summaryrefslogtreecommitdiff
path: root/media-video/vdr/files/vdr-2.6.1-patch-for-permashift.patch
diff options
context:
space:
mode:
Diffstat (limited to 'media-video/vdr/files/vdr-2.6.1-patch-for-permashift.patch')
-rw-r--r--media-video/vdr/files/vdr-2.6.1-patch-for-permashift.patch517
1 files changed, 517 insertions, 0 deletions
diff --git a/media-video/vdr/files/vdr-2.6.1-patch-for-permashift.patch b/media-video/vdr/files/vdr-2.6.1-patch-for-permashift.patch
new file mode 100644
index 000000000000..03b476f986bb
--- /dev/null
+++ b/media-video/vdr/files/vdr-2.6.1-patch-for-permashift.patch
@@ -0,0 +1,517 @@
+Adapted Patch from forum post
+https://www.vdr-portal.de/forum/index.php?thread/134171-permashift-1-0-4-f%C3%BCr-vdr-2-4-betaversion/&postID=1341243#post1341243
+
+SRC Url https://www.vdr-portal.de/index.php?attachment/45632-vdr-2-5-4-patch-for-permashift-diff-gz/ adapted for vdr-2.6.1
+
+Signed-off-by: Martin Dummer <martin.dummer@gmx.net>
+
+diff -Naur vdr-2.6.1.orig/device.c vdr-2.6.1/device.c
+--- vdr-2.6.1.orig/device.c 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/device.c 2022-02-06 18:05:26.452890690 +0100
+@@ -1880,6 +1880,17 @@
+ ReleaseCamSlot();
+ }
+
++cRecorder* cDevice::GetPreRecording(const cChannel *Channel)
++{
++ cMutexLock MutexLock(&mutexReceiver);
++ for (int i = 0; i < MAXRECEIVERS; i++) {
++ if (receiver[i])
++ if (receiver[i]->IsPreRecording(Channel))
++ return (cRecorder*)receiver[i];
++ }
++ return NULL;
++}
++
+ // --- cTSBuffer -------------------------------------------------------------
+
+ cTSBuffer::cTSBuffer(int File, int Size, int DeviceNumber)
+diff -Naur vdr-2.6.1.orig/device.h vdr-2.6.1/device.h
+--- vdr-2.6.1.orig/device.h 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/device.h 2022-02-06 18:05:51.541429884 +0100
+@@ -85,6 +85,7 @@
+
+ class cPlayer;
+ class cReceiver;
++class cRecorder;
+ class cLiveSubtitle;
+
+ class cDeviceHook : public cListObject {
+@@ -854,6 +855,8 @@
+ ///< Returns true if we are currently receiving. The parameter has no meaning (for backwards compatibility only).
+ bool AttachReceiver(cReceiver *Receiver);
+ ///< Attaches the given receiver to this device.
++ cRecorder* GetPreRecording(const cChannel *Channel);
++ ///< Get precocious recording for the channel if there is one.
+ void Detach(cReceiver *Receiver, bool ReleaseCam = true);
+ ///< Detaches the given receiver from this device.
+ ///< If ReleaseCam is true, the CAM slot will be released if it
+diff -Naur vdr-2.6.1.orig/dvbplayer.c vdr-2.6.1/dvbplayer.c
+--- vdr-2.6.1.orig/dvbplayer.c 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/dvbplayer.c 2022-02-06 18:05:26.452890690 +0100
+@@ -249,13 +249,14 @@
+ cUnbufferedFile *replayFile;
+ double framesPerSecond;
+ bool isPesRecording;
+- bool pauseLive;
++ ReplayState replayState;
+ bool eof;
+ bool firstPacket;
+ ePlayModes playMode;
+ ePlayDirs playDir;
+ int trickSpeed;
+ int readIndex;
++ int startIndex;
+ bool readIndependent;
+ cFrame *readFrame;
+ cFrame *playFrame;
+@@ -271,6 +272,8 @@
+ virtual void Action(void);
+ public:
+ cDvbPlayer(const char *FileName, bool PauseLive);
++ cDvbPlayer(const char *FileName, ReplayState newReplayState);
++ void Construct(const char *FileName, ReplayState newReplayState);
+ virtual ~cDvbPlayer();
+ void SetMarks(const cMarks *Marks);
+ bool Active(void) { return cThread::Running(); }
+@@ -297,6 +300,17 @@
+ cDvbPlayer::cDvbPlayer(const char *FileName, bool PauseLive)
+ :cThread("dvbplayer")
+ {
++ Construct(FileName, PauseLive? restPauseLive : restNormal);
++}
++
++cDvbPlayer::cDvbPlayer(const char *FileName, ReplayState newReplayState)
++:cThread("dvbplayer")
++{
++ Construct(FileName, newReplayState);
++}
++
++void cDvbPlayer::Construct(const char *FileName, ReplayState newReplayState)
++{
+ nonBlockingFileReader = NULL;
+ ringBuffer = NULL;
+ marks = NULL;
+@@ -304,7 +318,8 @@
+ cRecording Recording(FileName);
+ framesPerSecond = Recording.FramesPerSecond();
+ isPesRecording = Recording.IsPesRecording();
+- pauseLive = PauseLive;
++ replayState = newReplayState;
++ bool reuse = (replayState == restReusePause || replayState == restReuseRewind);
+ eof = false;
+ firstPacket = true;
+ playMode = pmPlay;
+@@ -323,15 +338,21 @@
+ return;
+ ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE);
+ // Create the index file:
+- index = new cIndexFile(FileName, false, isPesRecording, pauseLive);
++ index = new cIndexFile(FileName, false, isPesRecording, replayState == restPauseLive);
+ if (!index)
+ esyslog("ERROR: can't allocate index");
+ else if (!index->Ok()) {
+ delete index;
+ index = NULL;
+ }
+- else if (PauseLive)
++ else if (reuse)
+ framesPerSecond = cRecording(FileName).FramesPerSecond(); // the fps rate might have changed from the default
++ startIndex = 0;
++ if (replayState == restReuseRewind || replayState == restReusePause) {
++ int Current, Total;
++ GetIndex(Current, Total, false);
++ startIndex = max(Total - 1, 0);
++ }
+ }
+
+ cDvbPlayer::~cDvbPlayer()
+@@ -481,8 +502,21 @@
+ bool CutIn = false;
+ bool AtLastMark = false;
+
+- if (pauseLive)
+- Goto(0, true);
++ if (replayState == restPauseLive) {
++ Goto(0, true);
++ }
++ else if (replayState == restReuseRewind || replayState == restReusePause) {
++ readIndex = startIndex;
++ Goto(readIndex, true);
++ playMode = pmPlay;
++ if (replayState == restReuseRewind) {
++ Backward();
++ }
++ else if (replayState == restReusePause) {
++ Pause();
++ }
++ }
++
+ while (Running()) {
+ if (WaitingForData)
+ WaitingForData = !nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data
+@@ -985,6 +1019,11 @@
+ {
+ }
+
++cDvbPlayerControl::cDvbPlayerControl(const char *FileName, ReplayState replayState)
++:cControl(player = new cDvbPlayer(FileName, replayState))
++{
++}
++
+ cDvbPlayerControl::~cDvbPlayerControl()
+ {
+ Stop();
+diff -Naur vdr-2.6.1.orig/dvbplayer.h vdr-2.6.1/dvbplayer.h
+--- vdr-2.6.1.orig/dvbplayer.h 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/dvbplayer.h 2022-02-06 18:05:26.452890690 +0100
+@@ -16,6 +16,14 @@
+
+ class cDvbPlayer;
+
++enum ReplayState
++{
++ restNormal,
++ restPauseLive,
++ restReusePause,
++ restReuseRewind
++};
++
+ class cDvbPlayerControl : public cControl {
+ private:
+ cDvbPlayer *player;
+@@ -25,6 +33,8 @@
+ // If PauseLive is true, special care is taken to make sure the index
+ // file of the recording is long enough to allow the player to display
+ // the first frame in still picture mode.
++ cDvbPlayerControl(const char *FileName, ReplayState replayState);
++ // Sets up a player for the given file. replayState represents the initial state.
+ virtual ~cDvbPlayerControl();
+ void SetMarks(const cMarks *Marks);
+ bool Active(void);
+diff -Naur vdr-2.6.1.orig/menu.c vdr-2.6.1/menu.c
+--- vdr-2.6.1.orig/menu.c 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/menu.c 2022-02-06 18:05:26.452890690 +0100
+@@ -5303,6 +5303,16 @@
+
+ cRecordControl::cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer, bool Pause)
+ {
++ Construct(Device, Timers, Timer, Pause, NULL);
++}
++
++cRecordControl::cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer, bool Pause, bool* reused)
++{
++ Construct(Device, Timers, Timer, Pause, reused);
++}
++
++void cRecordControl::Construct(cDevice *Device, cTimers *Timers, cTimer *Timer, bool Pause, bool* reused)
++{
+ const char *LastReplayed = cReplayControl::LastReplayed(); // must do this before locking schedules!
+ // Whatever happens here, the timers will be modified in some way...
+ Timers->SetModified();
+@@ -5331,6 +5341,7 @@
+ timer->SetPending(true);
+ timer->SetRecording(true);
+ event = timer->Event();
++ if (reused != NULL) *reused = false;
+
+ if (event || GetEvent())
+ dsyslog("Title: '%s' Subtitle: '%s'", event->Title(), event->ShortText());
+@@ -5360,8 +5371,21 @@
+ if (MakeDirs(fileName, true)) {
+ Recording.WriteInfo(); // we write this *before* attaching the recorder to the device, to make sure the info file is present when the recorder needs to update the fps value!
+ const cChannel *ch = timer->Channel();
+- recorder = new cRecorder(fileName, ch, timer->Priority());
+- if (device->AttachReceiver(recorder)) {
++
++ if (!Timer) {
++ recorder = device->GetPreRecording(ch);
++ if (recorder != NULL) {
++ recorder->ActivatePreRecording(fileName, timer->Priority());
++ if (reused != NULL) *reused = true;
++ }
++ }
++
++ if (recorder == NULL) {
++ recorder = new cRecorder(fileName, ch, timer->Priority());
++ if (!device->AttachReceiver(recorder)) DELETENULL(recorder);
++ }
++
++ if (recorder != NULL) {
+ cStatus::MsgRecording(device, Recording.Name(), Recording.FileName(), true);
+ if (!Timer && !LastReplayed) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
+ cReplayControl::SetRecording(fileName);
+@@ -5371,8 +5395,6 @@
+ Recordings->AddByName(fileName);
+ return;
+ }
+- else
+- DELETENULL(recorder);
+ }
+ else
+ timer->SetDeferred(DEFERTIMER);
+@@ -5452,7 +5474,7 @@
+ cRecordControl *cRecordControls::RecordControls[MAXRECORDCONTROLS] = { NULL };
+ int cRecordControls::state = 0;
+
+-bool cRecordControls::Start(cTimers *Timers, cTimer *Timer, bool Pause)
++bool cRecordControls::Start(cTimers *Timers, cTimer *Timer, bool Pause, bool* reused)
+ {
+ static time_t LastNoDiskSpaceMessage = 0;
+ int FreeMB = 0;
+@@ -5490,7 +5512,7 @@
+ if (!Timer || Timer->Matches()) {
+ for (int i = 0; i < MAXRECORDCONTROLS; i++) {
+ if (!RecordControls[i]) {
+- RecordControls[i] = new cRecordControl(device, Timers, Timer, Pause);
++ RecordControls[i] = new cRecordControl(device, Timers, Timer, Pause, reused);
+ return RecordControls[i]->Process(time(NULL));
+ }
+ }
+@@ -5514,6 +5536,11 @@
+ return Start(Timers, NULL, Pause);
+ }
+
++bool cRecordControls::Start(cTimers *Timers, cTimer *Timer, bool Pause)
++{
++ return Start(Timers, Timer, Pause, NULL);
++}
++
+ void cRecordControls::Stop(const char *InstantId)
+ {
+ LOCK_TIMERS_WRITE;
+@@ -5549,10 +5576,17 @@
+
+ bool cRecordControls::PauseLiveVideo(void)
+ {
++ return PauseLiveVideo(false);
++}
++
++bool cRecordControls::PauseLiveVideo(bool rewind)
++{
+ Skins.Message(mtStatus, tr("Pausing live video..."));
++ bool reused = false;
+ cReplayControl::SetRecording(NULL); // make sure the new cRecordControl will set cReplayControl::LastReplayed()
+- if (Start(true)) {
+- cReplayControl *rc = new cReplayControl(true);
++ LOCK_TIMERS_WRITE;
++ if (Start(Timers, NULL, true, &reused)) {
++ cReplayControl *rc = new cReplayControl(rewind? restReuseRewind : reused? restReusePause : restPauseLive);
+ cControl::Launch(rc);
+ cControl::Attach();
+ Skins.Message(mtStatus, NULL);
+@@ -5695,7 +5729,18 @@
+ cReplayControl::cReplayControl(bool PauseLive)
+ :cDvbPlayerControl(fileName, PauseLive)
+ {
+- cDevice::PrimaryDevice()->SetKeepTracks(PauseLive);
++ Construct(PauseLive? restPauseLive : restNormal);
++}
++
++cReplayControl::cReplayControl(ReplayState replayState)
++:cDvbPlayerControl(fileName, replayState)
++{
++ Construct(replayState);
++}
++
++void cReplayControl::Construct(ReplayState replayState)
++{
++ cDevice::PrimaryDevice()->SetKeepTracks(replayState == restPauseLive);
+ currentReplayControl = this;
+ displayReplay = NULL;
+ marksModified = false;
+diff -Naur vdr-2.6.1.orig/menu.h vdr-2.6.1/menu.h
+--- vdr-2.6.1.orig/menu.h 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/menu.h 2022-02-06 18:05:26.452890690 +0100
+@@ -246,6 +246,8 @@
+ bool GetEvent(void);
+ public:
+ cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer = NULL, bool Pause = false);
++ cRecordControl(cDevice *Device, cTimers *Timers, cTimer *Timer, bool Pause, bool* reused);
++ void Construct(cDevice *Device, cTimers *Timers, cTimer *Timer, bool Pause, bool* reused);
+ virtual ~cRecordControl();
+ bool Process(time_t t);
+ cDevice *Device(void) { return device; }
+@@ -261,10 +263,12 @@
+ static int state;
+ public:
+ static bool Start(cTimers *Timers, cTimer *Timer, bool Pause = false);
++ static bool Start(cTimers *Timers, cTimer *Timer, bool Pause, bool* reused);
+ static bool Start(bool Pause = false);
+ static void Stop(const char *InstantId);
+ static void Stop(cTimer *Timer);
+ static bool PauseLiveVideo(void);
++ static bool PauseLiveVideo(bool rewind);
+ static const char *GetInstantId(const char *LastInstantId);
+ static cRecordControl *GetRecordControl(const char *FileName);
+ static cRecordControl *GetRecordControl(const cTimer *Timer);
+@@ -320,6 +324,8 @@
+ void EditTest(void);
+ public:
+ cReplayControl(bool PauseLive = false);
++ cReplayControl(ReplayState replayState);
++ void Construct(ReplayState replayState);
+ virtual ~cReplayControl();
+ void Stop(void);
+ virtual cOsdObject *GetInfo(void);
+diff -Naur vdr-2.6.1.orig/receiver.h vdr-2.6.1/receiver.h
+--- vdr-2.6.1.orig/receiver.h 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/receiver.h 2022-02-06 18:05:26.452890690 +0100
+@@ -85,6 +85,10 @@
+ ///< case the device is needed otherwise, so code that uses a cReceiver
+ ///< should repeatedly check whether it is still attached, and if
+ ///< it isn't, delete it (or take any other appropriate measures).
++ virtual bool IsPreRecording(const cChannel *Channel) { return false; }
++ ///< prerecords given channel; may be turned into a disc recording.
++ virtual bool ActivatePreRecording(const char* fileName, int Priority) { return false; }
++ ///< turn prerecording into a disc recording
+ };
+
+ #endif //__RECEIVER_H
+diff -Naur vdr-2.6.1.orig/recorder.c vdr-2.6.1/recorder.c
+--- vdr-2.6.1.orig/recorder.c 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/recorder.c 2022-02-06 18:05:26.452890690 +0100
+@@ -164,11 +164,25 @@
+ cRecorder::cRecorder(const char *FileName, const cChannel *Channel, int Priority)
+ :cReceiver(Channel, Priority)
+ ,cThread("recording")
++,tsChecker(NULL), frameChecker(NULL), recordingInfo(NULL), ringBuffer(NULL), frameDetector(NULL), fileName(NULL), index(NULL), recordFile(NULL), recordingName(NULL)
+ {
+- tsChecker = new cTsChecker;
+- frameChecker = new cFrameChecker;
++ if (FileName != NULL) {
++ InitializeFile(FileName, Channel);
++ }
++}
++
++void cRecorder::InitializeFile(const char *FileName, const cChannel *Channel)
++{
++ if (tsChecker == NULL) {
++ tsChecker = new cTsChecker;
++ }
++ if (frameChecker == NULL) {
++ frameChecker = new cFrameChecker;
++ }
+ recordingName = strdup(FileName);
+- recordingInfo = new cRecordingInfo(recordingName);
++ if (recordingInfo == NULL) {
++ recordingInfo = new cRecordingInfo(recordingName);
++ }
+ recordingInfo->Read();
+ oldErrors = max(0, recordingInfo->Errors()); // in case this is a re-started recording
+ errors = oldErrors;
+@@ -193,7 +207,9 @@
+ Pid = Channel->Dpid(0);
+ Type = 0x06;
+ }
+- frameDetector = new cFrameDetector(Pid, Type);
++ if (frameDetector == NULL) {
++ frameDetector = new cFrameDetector(Pid, Type);
++ }
+ index = NULL;
+ fileSize = 0;
+ lastDiskSpaceCheck = time(NULL);
+diff -Naur vdr-2.6.1.orig/recorder.h vdr-2.6.1/recorder.h
+--- vdr-2.6.1.orig/recorder.h 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/recorder.h 2022-02-06 18:05:26.452890690 +0100
+@@ -19,8 +19,8 @@
+ class cTsChecker;
+ class cFrameChecker;
+
+-class cRecorder : public cReceiver, cThread {
+-private:
++class cRecorder : public cReceiver, protected cThread {
++protected:
+ cTsChecker *tsChecker;
+ cFrameChecker *frameChecker;
+ cRingBufferLinear *ringBuffer;
+@@ -41,7 +41,6 @@
+ bool RunningLowOnDiskSpace(void);
+ bool NextFile(void);
+ void HandleErrors(bool Force = false);
+-protected:
+ virtual void Activate(bool On);
+ ///< If you override Activate() you need to call Detach() (which is a
+ ///< member of the cReceiver class) from your own destructor in order
+@@ -49,6 +48,9 @@
+ ///< destroyed.
+ virtual void Receive(const uchar *Data, int Length);
+ virtual void Action(void);
++ void InitializeFile(const char *FileName, const cChannel *Channel);
++ ///< Starts recording to file.
++ ///< Called in constructor if file name has been given.
+ public:
+ cRecorder(const char *FileName, const cChannel *Channel, int Priority);
+ ///< Creates a new recorder for the given Channel and
+diff -Naur vdr-2.6.1.orig/ringbuffer.c vdr-2.6.1/ringbuffer.c
+--- vdr-2.6.1.orig/ringbuffer.c 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/ringbuffer.c 2022-02-06 18:05:26.452890690 +0100
+@@ -368,6 +368,25 @@
+ return NULL;
+ }
+
++uchar *cRingBufferLinear::GetRest(int &Count)
++{
++ int Head = head;
++ if (getThreadTid <= 0)
++ getThreadTid = cThread::ThreadId();
++ int rest = Size() - tail;
++ int diff = Head - tail;
++ int cont = (diff >= 0) ? diff : Size() + diff - margin;
++ if (cont > rest)
++ cont = rest;
++ uchar *p = buffer + tail;
++ if (cont > 0) {
++ Count = gotten = cont;
++ return p;
++ }
++ WaitForGet();
++ return NULL;
++}
++
+ void cRingBufferLinear::Del(int Count)
+ {
+ if (Count > gotten) {
+diff -Naur vdr-2.6.1.orig/ringbuffer.h vdr-2.6.1/ringbuffer.h
+--- vdr-2.6.1.orig/ringbuffer.h 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/ringbuffer.h 2022-02-06 18:05:26.452890690 +0100
+@@ -98,6 +98,12 @@
+ ///< The data will remain in the buffer until a call to Del() deletes it.
+ ///< Returns a pointer to the data, and stores the number of bytes
+ ///< actually available in Count. If the returned pointer is NULL, Count has no meaning.
++ uchar *GetRest(int &Count);
++ ///< Gets data from the ring buffer disregarding the margin.
++ ///< Might have to be called several times to get all data.
++ ///< The data will remain in the buffer until a call to Del() deletes it.
++ ///< Returns a pointer to the data, and stores the number of bytes
++ ///< actually available in Count. If the returned pointer is NULL, Count has no meaning.
+ void Del(int Count);
+ ///< Deletes at most Count bytes from the ring buffer.
+ ///< Count must be less or equal to the number that was returned by a previous
+diff -Naur vdr-2.6.1.orig/vdr.c vdr-2.6.1/vdr.c
+--- vdr-2.6.1.orig/vdr.c 2022-02-02 10:56:43.000000000 +0100
++++ vdr-2.6.1/vdr.c 2022-02-06 18:05:26.452890690 +0100
+@@ -1352,13 +1352,22 @@
+ key = kNone;
+ break;
+ // Pausing live video:
++ case kFastRew:
++ {
++ // test if there's a live buffer to rewind into...
++ LOCK_CHANNELS_READ;
++ if (cDevice::ActualDevice()->GetPreRecording(Channels->GetByNumber(cDevice::CurrentChannel())) == NULL) {
++ break;
++ }
++ }
++ // fall through to pause
+ case kPlayPause:
+ case kPause:
+ if (!Control) {
+ DELETE_MENU;
+ if (Setup.PauseKeyHandling) {
+ if (Setup.PauseKeyHandling > 1 || Interface->Confirm(tr("Pause live video?"))) {
+- if (!cRecordControls::PauseLiveVideo())
++ if (!cRecordControls::PauseLiveVideo(int(key) == kFastRew))
+ Skins.QueueMessage(mtError, tr("No free DVB device to record!"));
+ }
+ }