Description: Play after jump to next mark. Automatically jump over commercial breaks. See README.jumpplay and MANUAL for details. 2011-03-19: Remove marks reloading for VDR-1.7.17, by Udo Richter Author: Torsten Kunkel , Thomas Günther Origin: http://toms-cafe.de/vdr/download/vdr-jumpplay-1.0-1.7.6.diff --- a/MANUAL +++ b/MANUAL @@ -902,6 +902,25 @@ 0 resulting in a file named 'resume', and any other value resulting in 'resume.n'. + Jump&Play = no Turns playing on or off after jumping forward to the + next editing mark with the '9' key. + + Play&Jump = no Turns automatic jumping over commercial breaks on or + off. This includes jumping to the first mark, if the + replay starts at the beginning of a recording - and + stopping the replay at the last mark. + With this setting enabled, the behaviour of the '8' + key during replay is changed too. It moves the actual + replay position not only three seconds before the + next "start" mark, but also before the next "end" + mark. This can be used to test, if the editing marks + are correctly positioned for a "smooth" jump over a + commercial break. + + Pause at last mark = no + Turns pausing of replay at the last editing mark on or + off. + Miscellaneous: Min. event timeout = 30 --- /dev/null +++ b/README.jumpplay @@ -0,0 +1,92 @@ +JumpPlay patch for VDR +---------------------- + +This patch changes the replay behaviour for recordings that contain editing +marks. It allows to immediately continue the replay after jumping forward to +the next mark, and to automatically jump over the commercial break to the next +"start" mark, if an "end" mark is reached. + +The features of this patch can be turned on or off with parameters in the replay +setup. See MANUAL for description of this parameters: "Jump&Play", "Play&Jump", +"Pause at last mark" and "Reload marks". + + +* History + + 2003-07-04: jumpandrun.diff - the Noad + Jump&Play + + 2003-12-06: Version 0.0 - Torsten Kunkel + Play&Jump (only if progressbar is visible) + Setup parameters Jump&Play and Play&Jump in the replay setup + + 2004-01-20: Version 0.1 - Thomas Günther + Jump&Play: + - fixed speed after jump + - fixed removing of marks + Play&Jump: + - jump only on "end" marks + + 2004-01-27: Version 0.2 - Thomas Günther + Jump&Play: + - fixed double jump + Play&Jump: + - fixed mark detection: fuzzy detection (until 3 seconds after mark) + - jump without progressbar + - mode "progressbar only" for old behaviour + + 2004-01-31: Version 0.3 - Thomas Günther + Jump&Play: + - fixed display frames + Play&Jump: + - fixed end of playing at last mark + + 2004-07-11: Version 0.4 - Thomas Günther + Jump&Play: + - don't play after jump to end + Play&Jump: + - don't prevent jumping after hide or show + Less conflicts with other patches (Elchi/AutoPID) + + 2004-08-21: Version 0.5 - Thomas Günther + Play&Jump: + - exact jumps, replay like edited recording (no fuzzy mark detection) + - jump to first mark if replay starts at the beginning + - check jump marks with '8' key + - mode "progressbar only" removed + Description in README.jumpplay + + 2004-12-28: Version 0.6 - Thomas Günther + Adapted noad extensions (from the Noad ) to + jumpplay-0.5: + - cyclic reloading of marks found by noad online-scan + - don't stop after the last mark in case of live-recordings + New setup parameter "Load marks interval (s)" + Updated description in README.jumpplay + + 2006-04-14: Version 0.7 - Thomas Günther + Fixed jump to first mark (crashed with plugin extrecmenu-0.9) + Added version define JUMPPLAYVERSNUM + Added placeholders for Czech language texts + Cleaned up i18n entries (support only VDR >= 1.3.29) + Improved description of i18n placeholders - hoping for real language texts + + 2006-05-12: Version 0.8 - Thomas Günther + Fixed segfault in dvbplayer thread while the replaycontrol thread is + reloading the marks (thanks to horchi at vdrportal.de for reporting this - + see http://vdrportal.de/board/thread.php?postid=450463#post450463): + New class cMarksReload checks the timestamp of marks.vdr in 10 seconds + intervals, so the marks in the threads dvbplayer and replaycontrol can be + reloaded independently + Changed setup parameter "Load marks interval (s)" to "Reload marks" + Updated description in README.jumpplay + + 2006-05-28: Version 0.9 - Thomas Günther + New setup parameter "Pause at last mark" + Updated description in README.jumpplay + Moved parameters description to MANUAL + + 2009-03-31: Version 1.0 - Thomas Günther + Play&Jump: + - set resume position to 0 if replay stops at the first mark + Added French language texts (thanks to Michaël Nival) --- a/config.c +++ b/config.c @@ -465,6 +465,9 @@ ProgressDisplayTime = 0; PauseOnMarkSet = 0; ResumeID = 0; + JumpPlay = 0; + PlayJump = 0; + PauseLastMark = 0; CurrentChannel = -1; CurrentVolume = MAXVOLUME; CurrentDolby = 0; @@ -670,6 +673,9 @@ else if (!strcasecmp(Name, "ProgressDisplayTime")) ProgressDisplayTime= atoi(Value); else if (!strcasecmp(Name, "PauseOnMarkSet")) PauseOnMarkSet = atoi(Value); else if (!strcasecmp(Name, "ResumeID")) ResumeID = atoi(Value); + else if (!strcasecmp(Name, "JumpPlay")) JumpPlay = atoi(Value); + else if (!strcasecmp(Name, "PlayJump")) PlayJump = atoi(Value); + else if (!strcasecmp(Name, "PauseLastMark")) PauseLastMark = atoi(Value); else if (!strcasecmp(Name, "CurrentChannel")) CurrentChannel = atoi(Value); else if (!strcasecmp(Name, "CurrentVolume")) CurrentVolume = atoi(Value); else if (!strcasecmp(Name, "CurrentDolby")) CurrentDolby = atoi(Value); @@ -779,6 +785,9 @@ Store("ProgressDisplayTime",ProgressDisplayTime); Store("PauseOnMarkSet", PauseOnMarkSet); Store("ResumeID", ResumeID); + Store("JumpPlay", JumpPlay); + Store("PlayJump", PlayJump); + Store("PauseLastMark", PauseLastMark); Store("CurrentChannel", CurrentChannel); Store("CurrentVolume", CurrentVolume); Store("CurrentDolby", CurrentDolby); --- a/config.h +++ b/config.h @@ -36,6 +36,8 @@ // plugins to work with newer versions of the core VDR as long as no // VDR header files have changed. +#define JUMPPLAYVERSNUM 110 + #define MAXPRIORITY 99 #define MINPRIORITY (-MAXPRIORITY) #define LIVEPRIORITY 0 // priority used when selecting a device for live viewing @@ -328,6 +330,9 @@ int ProgressDisplayTime; int PauseOnMarkSet; int ResumeID; + int JumpPlay; + int PlayJump; + int PauseLastMark; int CurrentChannel; int CurrentVolume; int CurrentDolby; --- a/dvbplayer.c +++ b/dvbplayer.c @@ -211,6 +211,7 @@ cNonBlockingFileReader *nonBlockingFileReader; cRingBufferFrame *ringBuffer; cPtsIndex ptsIndex; + cMarks marks; cFileName *fileName; cIndexFile *index; cUnbufferedFile *replayFile; @@ -296,6 +297,7 @@ } else if (PauseLive) framesPerSecond = cRecording(FileName).FramesPerSecond(); // the fps rate might have changed from the default + marks.Load(FileName, framesPerSecond, isPesRecording); } cDvbPlayer::~cDvbPlayer() @@ -374,6 +376,10 @@ if (index) { int Index = ptsIndex.FindIndex(DeviceGetSTC()); if (Index >= 0) { + // set resume position to 0 if replay stops at the first mark + if (Setup.PlayJump && marks.First() && + abs(Index - marks.First()->Position()) <= int(round(RESUMEBACKUP * framesPerSecond))) + Index = 0; int backup = int(round(RESUMEBACKUP * framesPerSecond)); if (Index >= index->Last() - backup) Index = 0; @@ -405,11 +411,26 @@ { uchar *p = NULL; int pc = 0; + bool cutIn = false; + int total = -1; readIndex = Resume(); if (readIndex >= 0) isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true, framesPerSecond)); + if (Setup.PlayJump && readIndex <= 0 && marks.First() && index) { + int Index = marks.First()->Position(); + uint16_t FileNumber; + off_t FileOffset; + if (index->Get(Index, &FileNumber, &FileOffset) && + NextFile(FileNumber, FileOffset)) { + isyslog("PlayJump: start replay at first mark %d (%s)", + Index, *IndexToHMSF(Index, true, framesPerSecond)); + readIndex = Index; + } + } + + bool LastMarkPause = false; nonBlockingFileReader = new cNonBlockingFileReader; int Length = 0; bool Sleep = false; @@ -436,7 +457,7 @@ // Read the next frame from the file: - if (playMode != pmStill && playMode != pmPause) { + if (playMode != pmStill && playMode != pmPause && !LastMarkPause) { if (!readFrame && (replayFile || readIndex >= 0)) { if (!nonBlockingFileReader->Reading()) { if (!SwitchToPlayFrame && (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward))) { @@ -473,6 +494,44 @@ else if (index) { uint16_t FileNumber; off_t FileOffset; + if (Setup.PlayJump || Setup.PauseLastMark) { + // check for end mark - jump to next mark or pause + readIndex++; + marks.Update(); + cMark *m = marks.Get(readIndex); + if (m && (m->Index() & 0x01) != 0) { + m = marks.Next(m); + int Index; + if (m) + Index = m->Position(); + else if (Setup.PauseLastMark) { + // pause at last mark + isyslog("PauseLastMark: pause at position %d (%s)", + readIndex, *IndexToHMSF(readIndex, true, framesPerSecond)); + LastMarkPause = true; + Index = -1; + } + else if (total == index->Last()) + // at last mark jump to end of recording + Index = index->Last() - 1; + else + // jump but stay off end of live-recordings + Index = index->GetNextIFrame(index->Last() - int(round(MAXSTUCKATEOF * framesPerSecond)), true); + // don't jump in edited recordings + if (Setup.PlayJump && Index > readIndex && + Index > index->GetNextIFrame(readIndex, true)) { + isyslog("PlayJump: %d frames to %d (%s)", + Index - readIndex, Index, + *IndexToHMSF(Index, true, framesPerSecond)); + readIndex = Index; + cutIn = true; + } + } + readIndex--; + } + // for detecting growing length of live-recordings + if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent) && readIndependent) + total = index->Last(); if (index->Get(readIndex + 1, &FileNumber, &FileOffset, &readIndependent, &Length) && NextFile(FileNumber, FileOffset)) readIndex++; else @@ -517,6 +576,13 @@ // Store the frame in the buffer: if (readFrame) { + if (cutIn) { + if (isPesRecording) + cRemux::SetBrokenLink(readFrame->Data(), readFrame->Count()); + //else + // TsSetTeiOnBrokenPackets(readFrame->Data(), readFrame->Count()); + cutIn = false; + } if (ringBuffer->Put(readFrame)) readFrame = NULL; else @@ -583,8 +649,13 @@ p = NULL; } } - else + else { + if (LastMarkPause) { + LastMarkPause = false; + playMode = pmPause; + } Sleep = true; + } // Handle hitting begin/end of recording: --- a/menu.c +++ b/menu.c @@ -3352,6 +3352,9 @@ Add(new cMenuEditIntItem( tr("Setup.Replay$Progress display time (s)"), &data.ProgressDisplayTime, 0, 60)); Add(new cMenuEditBoolItem(tr("Setup.Replay$Pause replay when setting mark"), &data.PauseOnMarkSet)); Add(new cMenuEditIntItem(tr("Setup.Replay$Resume ID"), &data.ResumeID, 0, 99)); + Add(new cMenuEditBoolItem(tr("Setup.Replay$Jump&Play"), &data.JumpPlay)); + Add(new cMenuEditBoolItem(tr("Setup.Replay$Play&Jump"), &data.PlayJump)); + Add(new cMenuEditBoolItem(tr("Setup.Replay$Pause at last mark"), &data.PauseLastMark)); } void cMenuSetupReplay::Store(void) @@ -5006,8 +5009,17 @@ if (GetIndex(Current, Total)) { if (marks.Count()) { if (cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current)) { - Goto(m->Position(), true); - displayFrames = true; + bool Play2, Forward2; + int Speed; + if (Setup.JumpPlay && GetReplayMode(Play2, Forward2, Speed) && + Play2 && Forward && m->Position() < Total - SecondsToFrames(3, FramesPerSecond())) { + Goto(m->Position()); + Play(); + } + else { + Goto(m->Position(), true); + displayFrames = true; + } return; } } @@ -5068,7 +5080,7 @@ if (!m) m = marks.GetNext(Current); if (m) { - if ((m->Index() & 0x01) != 0) + if ((m->Index() & 0x01) != 0 && !Setup.PlayJump) m = marks.Next(m); if (m) { Goto(m->Position() - SecondsToFrames(3, FramesPerSecond())); --- a/po/de_DE.po +++ b/po/de_DE.po @@ -1095,6 +1095,15 @@ msgid "Replay" msgstr "Wiedergabe" +msgid "Setup.Replay$Jump&Play" +msgstr "Wiedergabe nach Sprung" + +msgid "Setup.Replay$Play&Jump" +msgstr "Sprung bei Schnittmarke" + +msgid "Setup.Replay$Pause at last mark" +msgstr "Pause bei letzter Marke" + msgid "Setup.Replay$Multi speed mode" msgstr "Mehrstufiger Vor-/Rücklauf" --- a/po/fr_FR.po +++ b/po/fr_FR.po @@ -1105,6 +1105,15 @@ msgid "Replay" msgstr "Lecture" +msgid "Setup.Replay$Jump&Play" +msgstr "Lecture après saut" + +msgid "Setup.Replay$Play&Jump" +msgstr "Saut sur les marques de découpes" + +msgid "Setup.Replay$Pause at last mark" +msgstr "Pause après la dernière marque" + msgid "Setup.Replay$Multi speed mode" msgstr "Mode multi-vitesses"