diff options
-rw-r--r-- | HISTORY | 12 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | README | 24 | ||||
-rw-r--r-- | contrib/README | 14 | ||||
-rw-r--r-- | contrib/getlength.c (renamed from tools/getlength.c) | 0 | ||||
-rw-r--r-- | contrib/isodetect.c (renamed from tools/isodetect.c) | 0 | ||||
-rw-r--r-- | contrib/vdr-1.3.43-extrecmenu.diff (renamed from patches/vdr-1.3.43-extrecmenu.diff) | 0 | ||||
-rw-r--r-- | extrecmenu.c | 44 | ||||
-rw-r--r-- | extrecmenu.h | 2 | ||||
-rw-r--r-- | i18n.c | 78 | ||||
-rw-r--r-- | mydvbplayer.c | 824 | ||||
-rw-r--r-- | mydvbplayer.h | 45 | ||||
-rw-r--r-- | mymenumoverecording.h | 75 | ||||
-rw-r--r-- | mymenurecordingdetails.c | 48 | ||||
-rw-r--r-- | mymenurecordings.c | 163 | ||||
-rw-r--r-- | mymenurecordings.h | 14 | ||||
-rw-r--r-- | mymenurenamerecording.c | 25 | ||||
-rw-r--r-- | mymenusetup.c | 26 | ||||
-rw-r--r-- | mymenusetup.h | 6 | ||||
-rw-r--r-- | myreplaycontrol.c | 48 | ||||
-rw-r--r-- | myreplaycontrol.h | 8 | ||||
-rw-r--r-- | patchfont.c | 2 | ||||
-rwxr-xr-x | scripts/dvdarchive.sh | 26 | ||||
-rw-r--r-- | tools.c | 65 | ||||
-rw-r--r-- | tools.h | 18 |
25 files changed, 452 insertions, 1119 deletions
@@ -1,6 +1,18 @@ VDR Plugin 'extrecmenu' Revision History ---------------------------------------- +2006-04-10: Version 0.9 +- removed myDvbPlayer, use VDR's cDvbPlayer instead +- made adjustments to work with BigPatch-VDRs (JumpPlay-patch) +- added option for sort recordings +- moved editing of priority and lifetime to its own submenu +- removed option to select alternative dvd marker, the icon is now default +- added default values for setup options +- moved content of patches/ and tools/ to contrib/ and added a small README +- new version of 'dvdarchive.sh'; thanks to vejoun from vdr-portal.de +- fixed problem with archive dvd recordings at the base dir; thanks to Mase + from vdr-portal.de for reporting + 2006-03-31: Version 0.8a - fixed problem when open the plugin while replaying a archive dvd; thanks to Monroe from vdr-portal.de for reporting @@ -47,8 +47,8 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): OBJS = $(PLUGIN).o mymenurecordings.o myreplaycontrol.o mymenurenamerecording.o \ - mymenumoverecording.o i18n.o mydvbplayer.o mymenurecordinginfo.o mymenusetup.o \ - mymenucommands.o patchfont.o tools.o + mymenumoverecording.o i18n.o mymenurecordinginfo.o mymenusetup.o \ + mymenucommands.o patchfont.o tools.o mymenurecordingdetails.o ### Implicit rules: @@ -6,7 +6,7 @@ Project's homepage: http://martins-kabuff.de/extrecmenu.html See the file COPYING for license information. See top of *.c for additional copyright information. The script 'dvdarchive.sh' is provided by vejoun from -vdr-portal.de +vdr-portal.de. Description ------------------------------------------------------------------------------- @@ -25,7 +25,19 @@ base directory of the /video-directory-hierarchy. 'Ok' opens sub-directories, with 'Yellow' you can create new dirs. 'Blue' moves the recording to the selected directory. -DVDArchive-patch functionality +Sort recordings +------------------------------------------------------------------------------- +There are four options for sorting at the setup menu: +Sort recordings by: +- alphabet for main-, flexible for subdirectories +- date for main-, flexible for subdirectories +- alphabet for all directories +- date for all directories +Flexible means, if the directory name ends with "-",".","$" or "ª", the +recordings in this directory are sorted by name, else by date. + + +DVD-archive functionality ------------------------------------------------------------------------------- Burn the entire directory, that contains the recording, to a dvd and label it with an indentifier (a number or anything else). You can of cource burn more @@ -59,3 +71,11 @@ Check the options at the setup menu of the plugin. They are self-explaining. There is a patch for VDR in patches/ for replacing VDR's recordings menu with this plugin. You have to set the corresponding option at the setup menu of the plugin! + +There ist a patched TTF-Font for Enigma containing the dvd and alternative new +symbols. See this post at vdr-portal.de: +http://www.vdr-portal.de/board/thread.php?postid=447376#post447376 + + +Do you like this plugin? Support the developer! Go to the project homepage and +make a donation over the PayPal donation button. diff --git a/contrib/README b/contrib/README new file mode 100644 index 0000000..3ec797d --- /dev/null +++ b/contrib/README @@ -0,0 +1,14 @@ +getlength.c +------------------------------------------------------------------------------- +Creates a length.vdr from an index.vdr +Compile with 'gcc getlength.c -o getlength' + +isodetect.c +------------------------------------------------------------------------------- +Checks, if a dvd is in the drive. Used optionally by dvdarchive.sh +Compile with 'gcc isodetect.c -o isodetect' + +vdr-1.3.43-extrecmenu.diff +------------------------------------------------------------------------------- +A patch to replace VDR's recordings menu with the plugin +Apply with 'patch < vdr-1.3.43.extrecmenu.diff' diff --git a/tools/getlength.c b/contrib/getlength.c index 946e01c..946e01c 100644 --- a/tools/getlength.c +++ b/contrib/getlength.c diff --git a/tools/isodetect.c b/contrib/isodetect.c index 25c4c68..25c4c68 100644 --- a/tools/isodetect.c +++ b/contrib/isodetect.c diff --git a/patches/vdr-1.3.43-extrecmenu.diff b/contrib/vdr-1.3.43-extrecmenu.diff index 6e980f0..6e980f0 100644 --- a/patches/vdr-1.3.43-extrecmenu.diff +++ b/contrib/vdr-1.3.43-extrecmenu.diff diff --git a/extrecmenu.c b/extrecmenu.c index 622042b..c37ea64 100644 --- a/extrecmenu.c +++ b/extrecmenu.c @@ -10,63 +10,50 @@ cPluginExtrecmenu::cPluginExtrecmenu(void) { - // Initialize any member variables here. - // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL - // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! } cPluginExtrecmenu::~cPluginExtrecmenu() { - // Clean up after yourself! } const char *cPluginExtrecmenu::CommandLineHelp(void) { - // Return a string that describes all known command line options. - return NULL; + return NULL; } bool cPluginExtrecmenu::ProcessArgs(int argc, char *argv[]) { - // Implement command line argument processing here if applicable. - return true; + return true; } bool cPluginExtrecmenu::Initialize(void) { RegisterI18n(Phrases); - mysetup.wasdvd=false; - return true; } bool cPluginExtrecmenu::Start(void) { - // Start any background activities the plugin shall perform. - return true; + return true; } void cPluginExtrecmenu::Stop(void) { - // Stop any background activities the plugin shall perform. } void cPluginExtrecmenu::Housekeeping(void) { - // Perform any cleanup or other regular tasks. } cOsdObject *cPluginExtrecmenu::MainMenuAction(void) { - // Perform the action when selected from the main VDR menu. - return new myMenuRecordings(); + return new myMenuRecordings(); } cMenuSetupPage *cPluginExtrecmenu::SetupMenu(void) { - // Return a setup menu in case the plugin supports one. - return new myMenuSetup(); + return new myMenuSetup(); } bool cPluginExtrecmenu::SetupParse(const char *Name, const char *Value) @@ -92,14 +79,14 @@ bool cPluginExtrecmenu::SetupParse(const char *Name, const char *Value) if(!strcasecmp(Name,"PatchNew")) mysetup.PatchNew=atoi(Value); else - if(!strcasecmp(Name,"PatchDvd")) - mysetup.PatchDvd=atoi(Value); + if(!strcasecmp(Name,"ShowDvdNr")) + mysetup.ShowDvdNr=atoi(Value); else - if(!strcasecmp(Name,"ShowDvdNr")) - mysetup.ShowDvdNr=atoi(Value); + if(!strcasecmp(Name,"ShowNewRecs")) + mysetup.ShowNewRecs=atoi(Value); else - if(!strcasecmp(Name,"ShowNewRecs")) - mysetup.ShowNewRecs=atoi(Value); + if(!strcasecmp(Name,"SortRecords")) + mysetup.SortRecords=atoi(Value); else return false; return true; @@ -107,20 +94,17 @@ bool cPluginExtrecmenu::SetupParse(const char *Name, const char *Value) bool cPluginExtrecmenu::Service(const char *Id, void *Data) { - // Handle custom service requests from other plugins - return false; + return false; } const char **cPluginExtrecmenu::SVDRPHelpPages(void) { - // Return help text for SVDRP commands this plugin implements - return NULL; + return NULL; } cString cPluginExtrecmenu::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { - // Process SVDRP commands this plugin implements - return NULL; + return NULL; } VDRPLUGINCREATOR(cPluginExtrecmenu); // Don't touch this! diff --git a/extrecmenu.h b/extrecmenu.h index 687c445..d504ace 100644 --- a/extrecmenu.h +++ b/extrecmenu.h @@ -1,6 +1,6 @@ #include <vdr/plugin.h> -static const char *VERSION = "0.8a"; +static const char *VERSION = "0.9"; static const char *DESCRIPTION = "Extended recordings menu"; static const char *MAINMENUENTRY = "ExtRecMenu"; @@ -205,16 +205,6 @@ const tI18nPhrase Phrases[] = { "", "", }, - { "Show alternative dvd marker", - "Alternativen DVD-Marker anzeigen", - "", - "", - "", - "", - "Afficher les symbole DVD", - "", - "Näytä vaihtoehtoinen DVD:n merkintä", - }, { "Please insert DVD %s", "Bitte DVD %s einlegen", "", @@ -271,7 +261,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "[rép. parent]", + "[Dossier racine]", "", "[juurihakemisto]", }, @@ -281,7 +271,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "Pas de DVD dans le lecteur!", "", "Asemassa ei ole DVD-levyä!", }, @@ -291,7 +281,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "Erreur lors de la création des racourcis [0-9]*.vdr!", "", "Tiedostojen [0-9]*.vdr linkittäminen epäonnistui!", }, @@ -301,9 +291,69 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "\"Colone nouveaux enregistrements\" Afficher", "", "Näytä \"uudet tallenteet\"-sarake", }, + { "Sort recordings by", + "Aufnahme sortieren nach", + "", + "", + "", + "", + "Trier enregistrements par", + "", + "Järjestä tallenteet", + }, + { "alphabet for main-, flexible for subdirectories", + "Alphabet für Haupt-, flexibel für Unterverzeichnisse", + "", + "", + "", + "", + "Alphabet pour les dossiers, flexible pour les sous-dossiers", + "", + "juurihakemisto aakkosittain", + }, + { "date for main-, flexible for subdirectories", + "Datum für Haupt, flexibel für Unterverzeichnisse", + "", + "", + "", + "", + "Date pour les dossiers, flexible pour les sous-dossiers", + "", + "juurihakemisto päivämäärän mukaan", + }, + { "alphabet for all directories", + "Alphabet für alle Verzeichnisse", + "", + "", + "", + "", + "Alphabet pour tous les dossiers", + "", + "kaikki aakkosittain", + }, + { "date for all directories", + "Datum für alle Verzeichnisse", + "", + "", + "", + "", + "Date pour tous les dossiers", + "", + "kaikki päivämäärän mukaan", + }, + { "Details", + "Details", + "", + "", + "", + "", + "Détails", + "", + "Lisätiedot", + }, { NULL } }; diff --git a/mydvbplayer.c b/mydvbplayer.c deleted file mode 100644 index 2ef2b28..0000000 --- a/mydvbplayer.c +++ /dev/null @@ -1,824 +0,0 @@ -/* - * See the README file for copyright information and how to reach the author. - * - * This code is directly taken from VDR with some changes by me to work with this plugin - */ - -#include "mydvbplayer.h" -#include <stdlib.h> -#include <vdr/recording.h> -#include <vdr/remux.h> -#include <vdr/ringbuffer.h> -#include <vdr/thread.h> -#include <vdr/tools.h> - -// --- myBackTrace ---------------------------------------------------------- - -#define AVG_FRAME_SIZE 15000 // an assumption about the average frame size -#define DVB_BUF_SIZE (256 * 1024) // an assumption about the dvb firmware buffer size -#define BACKTRACE_ENTRIES (DVB_BUF_SIZE / AVG_FRAME_SIZE + 20) // how many entries are needed to backtrace buffer contents - -class myBackTrace { -private: - int index[BACKTRACE_ENTRIES]; - int length[BACKTRACE_ENTRIES]; - int pos, num; -public: - myBackTrace(void); - void Clear(void); - void Add(int Index, int Length); - int Get(bool Forward); - }; - -myBackTrace::myBackTrace(void) -{ - Clear(); -} - -void myBackTrace::Clear(void) -{ - pos = num = 0; -} - -void myBackTrace::Add(int Index, int Length) -{ - index[pos] = Index; - length[pos] = Length; - if (++pos >= BACKTRACE_ENTRIES) - pos = 0; - if (num < BACKTRACE_ENTRIES) - num++; -} - -int myBackTrace::Get(bool Forward) -{ - int p = pos; - int n = num; - int l = DVB_BUF_SIZE + (Forward ? 0 : 256 * 1024); //XXX (256 * 1024) == DVB_BUF_SIZE ??? - int i = -1; - - while (n && l > 0) { - if (--p < 0) - p = BACKTRACE_ENTRIES - 1; - i = index[p] - 1; - l -= length[p]; - n--; - } - return i; -} - -// --- myNonBlockingFileReader ------------------------------------------------ - -class myNonBlockingFileReader : public cThread { -private: - cUnbufferedFile *f; - uchar *buffer; - int wanted; - int length; - bool hasData; - cCondWait newSet; - cCondVar newDataCond; - cMutex newDataMutex; -protected: - void Action(void); -public: - myNonBlockingFileReader(void); - ~myNonBlockingFileReader(); - void Clear(void); - int Read(cUnbufferedFile *File, uchar *Buffer, int Length); - bool Reading(void) { return buffer; } - bool WaitForDataMs(int msToWait); - }; - -myNonBlockingFileReader::myNonBlockingFileReader(void) -:cThread("non blocking file reader") -{ - f = NULL; - buffer = NULL; - wanted = length = 0; - hasData = false; - Start(); -} - -myNonBlockingFileReader::~myNonBlockingFileReader() -{ - newSet.Signal(); - Cancel(3); - free(buffer); -} - -void myNonBlockingFileReader::Clear(void) -{ - Lock(); - f = NULL; - free(buffer); - buffer = NULL; - wanted = length = 0; - hasData = false; - Unlock(); - newSet.Signal(); -} - -int myNonBlockingFileReader::Read(cUnbufferedFile *File, uchar *Buffer, int Length) -{ - if (hasData && buffer) { - if (buffer != Buffer) { - esyslog("ERROR: myNonBlockingFileReader::Read() called with different buffer!"); - errno = EINVAL; - return -1; - } - buffer = NULL; - return length; - } - if (!buffer) { - f = File; - buffer = Buffer; - wanted = Length; - length = 0; - hasData = false; - newSet.Signal(); - } - errno = EAGAIN; - return -1; -} - -void myNonBlockingFileReader::Action(void) -{ - while (Running()) { - Lock(); - if (!hasData && f && buffer) { - int r = f->Read(buffer + length, wanted - length); - if (r >= 0) { - length += r; - if (!r || length == wanted) { // r == 0 means EOF - cMutexLock NewDataLock(&newDataMutex); - hasData = true; - newDataCond.Broadcast(); - } - } - else if (r < 0 && FATALERRNO) { - LOG_ERROR; - length = r; // this will forward the error status to the caller - hasData = true; - } - } - Unlock(); - newSet.Wait(1000); - } -} - -bool myNonBlockingFileReader::WaitForDataMs(int msToWait) -{ - cMutexLock NewDataLock(&newDataMutex); - if (hasData) - return true; - return newDataCond.TimedWait(newDataMutex, msToWait); -} - -// --- myDvbPlayer ------------------------------------------------------------ - -#define PLAYERBUFSIZE MEGABYTE(1) - -// The number of frames to back up when resuming an interrupted replay session: -#define RESUMEBACKUP (10 * FRAMESPERSEC) - -class myDvbPlayer : public cPlayer, cThread { -private: - enum ePlayModes { pmPlay, pmPause, pmSlow, pmFast, pmStill }; - enum ePlayDirs { pdForward, pdBackward }; - static int Speeds[]; - myNonBlockingFileReader *nonBlockingFileReader; - cRingBufferFrame *ringBuffer; - myBackTrace *backTrace; - cFileName *fileName; - cIndexFile *index; - cUnbufferedFile *replayFile; - bool eof; - bool firstPacket; - ePlayModes playMode; - ePlayDirs playDir; - int trickSpeed; - int readIndex, writeIndex; - cFrame *readFrame; - cFrame *playFrame; - void TrickSpeed(int Increment); - void Empty(void); - bool NextFile(uchar FileNumber = 0, int FileOffset = -1); - int Resume(void); - bool Save(void); -protected: - virtual void Activate(bool On); - virtual void Action(void); -public: - myDvbPlayer(const char *FileName); - virtual ~myDvbPlayer(); - bool Active(void) { return cThread::Running(); } - void Pause(void); - void Play(void); - void Forward(void); - void Backward(void); - int SkipFrames(int Frames); - void SkipSeconds(int Seconds); - void Goto(int Position, bool Still = false); - virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); - virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed); - }; - -#define MAX_VIDEO_SLOWMOTION 63 // max. arg to pass to VIDEO_SLOWMOTION // TODO is this value correct? -#define NORMAL_SPEED 4 // the index of the '1' entry in the following array -#define MAX_SPEEDS 3 // the offset of the maximum speed from normal speed in either direction -#define SPEED_MULT 12 // the speed multiplier -int myDvbPlayer::Speeds[] = { 0, -2, -4, -8, 1, 2, 4, 12, 0 }; - -myDvbPlayer::myDvbPlayer(const char *FileName) -:cThread("dvbplayer") -{ - nonBlockingFileReader = NULL; - ringBuffer = NULL; - backTrace = NULL; - index = NULL; - eof = false; - firstPacket = true; - playMode = pmPlay; - playDir = pdForward; - trickSpeed = NORMAL_SPEED; - readIndex = writeIndex = -1; - readFrame = NULL; - playFrame = NULL; - isyslog("replay %s", FileName); - fileName = new cFileName(FileName, false); - replayFile = fileName->Open(); - if (!replayFile) - return; - ringBuffer = new cRingBufferFrame(PLAYERBUFSIZE); - // Create the index file: - index = new cIndexFile(FileName, false); - if (!index) - esyslog("ERROR: can't allocate index"); - else if (!index->Ok()) { - delete index; - index = NULL; - } - backTrace = new myBackTrace; -} - -myDvbPlayer::~myDvbPlayer() -{ - Detach(); - Save(); - delete readFrame; // might not have been stored in the buffer in Action() - delete index; - delete fileName; - delete backTrace; - delete ringBuffer; -} - -void myDvbPlayer::TrickSpeed(int Increment) -{ - int nts = trickSpeed + Increment; - if (Speeds[nts] == 1) { - trickSpeed = nts; - if (playMode == pmFast) - Play(); - else - Pause(); - } - else if (Speeds[nts]) { - trickSpeed = nts; - int Mult = (playMode == pmSlow && playDir == pdForward) ? 1 : SPEED_MULT; - int sp = (Speeds[nts] > 0) ? Mult / Speeds[nts] : -Speeds[nts] * Mult; - if (sp > MAX_VIDEO_SLOWMOTION) - sp = MAX_VIDEO_SLOWMOTION; - DeviceTrickSpeed(sp); - } -} - -void myDvbPlayer::Empty(void) -{ - LOCK_THREAD; - if (nonBlockingFileReader) - nonBlockingFileReader->Clear(); - if ((readIndex = backTrace->Get(playDir == pdForward)) < 0) - readIndex = writeIndex; - delete readFrame; // might not have been stored in the buffer in Action() - readFrame = NULL; - playFrame = NULL; - ringBuffer->Clear(); - backTrace->Clear(); - DeviceClear(); - firstPacket = true; -} - -bool myDvbPlayer::NextFile(uchar FileNumber, int FileOffset) -{ - if (FileNumber > 0) - replayFile = fileName->SetOffset(FileNumber, FileOffset); - else if (replayFile && eof) - replayFile = fileName->NextFile(); - eof = false; - return replayFile != NULL; -} - -int myDvbPlayer::Resume(void) -{ - if (index) { - int Index = index->GetResume(); - if (Index >= 0) { - uchar FileNumber; - int FileOffset; - if (index->Get(Index, &FileNumber, &FileOffset) && NextFile(FileNumber, FileOffset)) - return Index; - } - } - return -1; -} - -bool myDvbPlayer::Save(void) -{ - if (index) { - int Index = writeIndex; - if (Index >= 0) { - Index -= RESUMEBACKUP; - if (Index > 0) - Index = index->GetNextIFrame(Index, false); - else - Index = 0; - if (Index >= 0) - return index->StoreResume(Index); - } - } - return false; -} - -void myDvbPlayer::Activate(bool On) -{ - if (On) { - if (replayFile) - Start(); - } - else - Cancel(9); -} - -void myDvbPlayer::Action(void) -{ - uchar *b = NULL; - uchar *p = NULL; - int pc = 0; - - readIndex = Resume(); - if (readIndex >= 0) - isyslog("resuming replay at index %d (%s)", readIndex, *IndexToHMSF(readIndex, true)); - - nonBlockingFileReader = new myNonBlockingFileReader; - int Length = 0; - bool Sleep = false; - bool WaitingForData = false; - - while (Running() && (NextFile() || readIndex >= 0 || ringBuffer->Available() || !DeviceFlush(100))) { - if (Sleep) { - if (WaitingForData) - nonBlockingFileReader->WaitForDataMs(3); // this keeps the CPU load low, but reacts immediately on new data - else - cCondWait::SleepMs(3); // this keeps the CPU load low - Sleep = false; - } - cPoller Poller; - if (DevicePoll(Poller, 100)) { - - LOCK_THREAD; - - // Read the next frame from the file: - - if (playMode != pmStill && playMode != pmPause) { - if (!readFrame && (replayFile || readIndex >= 0)) { - if (!nonBlockingFileReader->Reading()) { - if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) { - uchar FileNumber; - int FileOffset; - int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, true); - if (Index >= 0) { - if (!NextFile(FileNumber, FileOffset)) - continue; - } - else { - // hit begin of recording: wait for device buffers to drain - // before changing play mode: - if (!DeviceFlush(100)) - continue; - // can't call Play() here, because those functions may only be - // called from the foreground thread - and we also don't need - // to empty the buffer here - DevicePlay(); - playMode = pmPlay; - playDir = pdForward; - continue; - } - readIndex = Index; - } - else if (index) { - uchar FileNumber; - int FileOffset; - readIndex++; - if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) { - readIndex = -1; - eof = true; - continue; - } - } - else // allows replay even if the index file is missing - Length = MAXFRAMESIZE; - if (Length == -1) - Length = MAXFRAMESIZE; // this means we read up to EOF (see cIndex) - else if (Length > MAXFRAMESIZE) { - esyslog("ERROR: frame larger than buffer (%d > %d)", Length, MAXFRAMESIZE); - Length = MAXFRAMESIZE; - } - b = MALLOC(uchar, Length); - } - int r = nonBlockingFileReader->Read(replayFile, b, Length); - if (r > 0) { - WaitingForData = false; - readFrame = new cFrame(b, -r, ftUnknown, readIndex); // hands over b to the ringBuffer - b = NULL; - } - else if (r == 0) - eof = true; - else if (r < 0 && errno == EAGAIN) - WaitingForData = true; - else if (r < 0 && FATALERRNO) { - LOG_ERROR; - break; - } - } - - // Store the frame in the buffer: - - if (readFrame) { - if (ringBuffer->Put(readFrame)) - readFrame = NULL; - } - } - else - Sleep = true; - - // Get the next frame from the buffer: - - if (!playFrame) { - playFrame = ringBuffer->Get(); - p = NULL; - pc = 0; - } - - // Play the frame: - - if (playFrame) { - if (!p) { - p = playFrame->Data(); - pc = playFrame->Count(); - if (p) { - if (firstPacket) { - PlayPes(NULL, 0); - cRemux::SetBrokenLink(p, pc); - firstPacket = false; - } - } - } - if (p) { - int w = PlayPes(p, pc, playMode != pmPlay); - if (w > 0) { - p += w; - pc -= w; - } - else if (w < 0 && FATALERRNO) { - LOG_ERROR; - break; - } - } - if (pc == 0) { - writeIndex = playFrame->Index(); - backTrace->Add(playFrame->Index(), playFrame->Count()); - ringBuffer->Drop(playFrame); - playFrame = NULL; - p = NULL; - } - } - else - Sleep = true; - } - } - - myNonBlockingFileReader *nbfr = nonBlockingFileReader; - nonBlockingFileReader = NULL; - delete nbfr; -} - -void myDvbPlayer::Pause(void) -{ - if (playMode == pmPause || playMode == pmStill) - Play(); - else { - LOCK_THREAD; - if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) - Empty(); - DeviceFreeze(); - playMode = pmPause; - } -} - -void myDvbPlayer::Play(void) -{ - if (playMode != pmPlay) { - LOCK_THREAD; - if (playMode == pmStill || playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) - Empty(); - DevicePlay(); - playMode = pmPlay; - playDir = pdForward; - } -} - -void myDvbPlayer::Forward(void) -{ - if (index) { - switch (playMode) { - case pmFast: - if (Setup.MultiSpeedMode) { - TrickSpeed(playDir == pdForward ? 1 : -1); - break; - } - else if (playDir == pdForward) { - Play(); - break; - } - // run into pmPlay - case pmPlay: { - LOCK_THREAD; - Empty(); - DeviceMute(); - playMode = pmFast; - playDir = pdForward; - trickSpeed = NORMAL_SPEED; - TrickSpeed(Setup.MultiSpeedMode ? 1 : MAX_SPEEDS); - } - break; - case pmSlow: - if (Setup.MultiSpeedMode) { - TrickSpeed(playDir == pdForward ? -1 : 1); - break; - } - else if (playDir == pdForward) { - Pause(); - break; - } - // run into pmPause - case pmStill: - case pmPause: - DeviceMute(); - playMode = pmSlow; - playDir = pdForward; - trickSpeed = NORMAL_SPEED; - TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS); - break; - } - } -} - -void myDvbPlayer::Backward(void) -{ - if (index) { - switch (playMode) { - case pmFast: - if (Setup.MultiSpeedMode) { - TrickSpeed(playDir == pdBackward ? 1 : -1); - break; - } - else if (playDir == pdBackward) { - Play(); - break; - } - // run into pmPlay - case pmPlay: { - LOCK_THREAD; - Empty(); - DeviceMute(); - playMode = pmFast; - playDir = pdBackward; - trickSpeed = NORMAL_SPEED; - TrickSpeed(Setup.MultiSpeedMode ? 1 : MAX_SPEEDS); - } - break; - case pmSlow: - if (Setup.MultiSpeedMode) { - TrickSpeed(playDir == pdBackward ? -1 : 1); - break; - } - else if (playDir == pdBackward) { - Pause(); - break; - } - // run into pmPause - case pmStill: - case pmPause: { - LOCK_THREAD; - Empty(); - DeviceMute(); - playMode = pmSlow; - playDir = pdBackward; - trickSpeed = NORMAL_SPEED; - TrickSpeed(Setup.MultiSpeedMode ? -1 : -MAX_SPEEDS); - } - break; - } - } -} - -int myDvbPlayer::SkipFrames(int Frames) -{ - if (index && Frames) { - int Current, Total; - GetIndex(Current, Total, true); - int OldCurrent = Current; - // As GetNextIFrame() increments/decrements at least once, the - // destination frame (= Current + Frames) must be adjusted by - // -1/+1 respectively. - Current = index->GetNextIFrame(Current + Frames + (Frames > 0 ? -1 : 1), Frames > 0); - return Current >= 0 ? Current : OldCurrent; - } - return -1; -} - -void myDvbPlayer::SkipSeconds(int Seconds) -{ - if (index && Seconds) { - LOCK_THREAD; - Empty(); - int Index = writeIndex; - if (Index >= 0) { - Index = max(Index + Seconds * FRAMESPERSEC, 0); - if (Index > 0) - Index = index->GetNextIFrame(Index, false, NULL, NULL, NULL, true); - if (Index >= 0) - readIndex = writeIndex = Index - 1; // Action() will first increment it! - } - Play(); - } -} - -void myDvbPlayer::Goto(int Index, bool Still) -{ - if (index) { - LOCK_THREAD; - Empty(); - if (++Index <= 0) - Index = 1; // not '0', to allow GetNextIFrame() below to work! - uchar FileNumber; - int FileOffset, Length; - Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset, &Length); - if (Index >= 0 && NextFile(FileNumber, FileOffset) && Still) { - uchar b[MAXFRAMESIZE + 4 + 5 + 4]; - int r = ReadFrame(replayFile, b, Length, sizeof(b)); - if (r > 0) { - if (playMode == pmPause) - DevicePlay(); - // append sequence end code to get the image shown immediately with softdevices - if (r > 6 && (b[3] & 0xF0) == 0xE0) { // make sure to append it only to a video packet - b[r++] = 0x00; - b[r++] = 0x00; - b[r++] = 0x01; - b[r++] = b[3]; - if (b[6] & 0x80) { // MPEG 2 - b[r++] = 0x00; - b[r++] = 0x07; - b[r++] = 0x80; - b[r++] = 0x00; - b[r++] = 0x00; - } - else { // MPEG 1 - b[r++] = 0x00; - b[r++] = 0x05; - b[r++] = 0x0F; - } - b[r++] = 0x00; - b[r++] = 0x00; - b[r++] = 0x01; - b[r++] = 0xB7; - } - DeviceStillPicture(b, r); - } - playMode = pmStill; - } - readIndex = writeIndex = Index; - } -} - -bool myDvbPlayer::GetIndex(int &Current, int &Total, bool SnapToIFrame) -{ - if (index) { - if (playMode == pmStill) - Current = max(readIndex, 0); - else { - Current = max(writeIndex, 0); - if (SnapToIFrame) { - int i1 = index->GetNextIFrame(Current + 1, false); - int i2 = index->GetNextIFrame(Current, true); - Current = (abs(Current - i1) <= abs(Current - i2)) ? i1 : i2; - } - } - Total = index->Last(); - return true; - } - Current = Total = -1; - return false; -} - -bool myDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed) -{ - Play = (playMode == pmPlay || playMode == pmFast); - Forward = (playDir == pdForward); - if (playMode == pmFast || playMode == pmSlow) - Speed = Setup.MultiSpeedMode ? abs(trickSpeed - NORMAL_SPEED) : 0; - else - Speed = -1; - return true; -} - -// --- myDvbPlayerControl ----------------------------------------------------- - -myDvbPlayerControl::myDvbPlayerControl(const char *FileName) -:cControl(player = new myDvbPlayer(FileName)) -{ -} - -myDvbPlayerControl::~myDvbPlayerControl() -{ - Stop(); -} - -bool myDvbPlayerControl::Active(void) -{ - return player && player->Active(); -} - -void myDvbPlayerControl::Stop(void) -{ - delete player; - player = NULL; -} - -void myDvbPlayerControl::Pause(void) -{ - if (player) - player->Pause(); -} - -void myDvbPlayerControl::Play(void) -{ - if (player) - player->Play(); -} - -void myDvbPlayerControl::Forward(void) -{ - if (player) - player->Forward(); -} - -void myDvbPlayerControl::Backward(void) -{ - if (player) - player->Backward(); -} - -void myDvbPlayerControl::SkipSeconds(int Seconds) -{ - if (player) - player->SkipSeconds(Seconds); -} - -int myDvbPlayerControl::SkipFrames(int Frames) -{ - if (player) - return player->SkipFrames(Frames); - return -1; -} - -bool myDvbPlayerControl::GetIndex(int &Current, int &Total, bool SnapToIFrame) -{ - if (player) { - player->GetIndex(Current, Total, SnapToIFrame); - return true; - } - return false; -} - -bool myDvbPlayerControl::GetReplayMode(bool &Play, bool &Forward, int &Speed) -{ - return player && player->GetReplayMode(Play, Forward, Speed); -} - -void myDvbPlayerControl::Goto(int Position, bool Still) -{ - if (player) - player->Goto(Position, Still); -} diff --git a/mydvbplayer.h b/mydvbplayer.h deleted file mode 100644 index 989ec5d..0000000 --- a/mydvbplayer.h +++ /dev/null @@ -1,45 +0,0 @@ -#include <vdr/player.h> -#include <vdr/thread.h> - -class myDvbPlayer; - -class myDvbPlayerControl : public cControl { -private: - myDvbPlayer *player; -public: - myDvbPlayerControl(const char *FileName); - // Sets up a player for the given file. - virtual ~myDvbPlayerControl(); - bool Active(void); - void Stop(void); - // Stops the current replay session (if any). - void Pause(void); - // Pauses the current replay session, or resumes a paused session. - void Play(void); - // Resumes normal replay mode. - void Forward(void); - // Runs the current replay session forward at a higher speed. - void Backward(void); - // Runs the current replay session backwards at a higher speed. - int SkipFrames(int Frames); - // Returns the new index into the current replay session after skipping - // the given number of frames (no actual repositioning is done!). - // The sign of 'Frames' determines the direction in which to skip. - void SkipSeconds(int Seconds); - // Skips the given number of seconds in the current replay session. - // The sign of 'Seconds' determines the direction in which to skip. - // Use a very large negative value to go all the way back to the - // beginning of the recording. - bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); - // Returns the current and total frame index, optionally snapped to the - // nearest I-frame. - bool GetReplayMode(bool &Play, bool &Forward, int &Speed); - // Returns the current replay mode (if applicable). - // 'Play' tells whether we are playing or pausing, 'Forward' tells whether - // we are going forward or backward and 'Speed' is -1 if this is normal - // play/pause mode, 0 if it is single speed fast/slow forward/back mode - // and >0 if this is multi speed mode. - void Goto(int Index, bool Still = false); - // Positions to the given index and displays that frame as a still picture - // if Still is true. - }; diff --git a/mymenumoverecording.h b/mymenumoverecording.h deleted file mode 100644 index bc7b389..0000000 --- a/mymenumoverecording.h +++ /dev/null @@ -1,75 +0,0 @@ -extern bool clearall; // needed for myMenuMoveRecording - -// --- myMenuRecordingsItem --------------------------------------------------- -class myMenuRecordingsItem:public cOsdItem -{ - private: - int level,isdirectory; - int totalentries,newentries; - char *title; - char *name; - const char *filename; - public: - myMenuRecordingsItem(cRecording *Recording,int Level); - ~myMenuRecordingsItem(); - const char *FileName(){return filename;} - const char *Name(){return name;} - bool IsDirectory(){return name!=NULL;} - void IncrementCounter(bool IsNew); -}; - -// --- myMenuRecordings ------------------------------------------------------- -class myMenuRecordings:public cOsdMenu -{ - private: - bool edit; - int level,helpkeys; - int recordingsstate; - char *base; - bool Open(); - void SetHelpKeys(); - cRecording *GetRecording(myMenuRecordingsItem *Item); - eOSState Play(); - eOSState Rewind(); - eOSState Delete(); - eOSState Rename(); - eOSState MoveRec(); - eOSState Info(); - eOSState Commands(eKeys Key=kNone); - public: - myMenuRecordings(const char *Base=NULL,int Level=0); - ~myMenuRecordings(); - void Set(bool Refresh=false); - virtual eOSState ProcessKey(eKeys Key); -}; - -// --- myMenuRenameRecording -------------------------------------------------- -class myMenuRenameRecording:public cOsdMenu -{ - private: - char name[MaxFileName]; - char path[MaxFileName]; - cRecording *recording; - myMenuRecordings *menurecordings; - public: - myMenuRenameRecording(cRecording *Recording,myMenuRecordings *MenuRecordings); - virtual eOSState ProcessKey(eKeys Key); -}; - -// --- myMenuMoveRecording ---------------------------------------------------- -class myMenuMoveRecording:public cOsdMenu -{ - private: - int level; - char *base; - cRecording *recording; - myMenuRecordings *menurecordings; - void Set(); - eOSState Open(); - eOSState MoveRec(); - eOSState Create(); - public: - myMenuMoveRecording(cRecording *Recording,myMenuRecordings *MenuRecordings,const char *Base=NULL,int Level=0); - myMenuMoveRecording::~myMenuMoveRecording(); - virtual eOSState ProcessKey(eKeys Key); -}; diff --git a/mymenurecordingdetails.c b/mymenurecordingdetails.c new file mode 100644 index 0000000..def9a57 --- /dev/null +++ b/mymenurecordingdetails.c @@ -0,0 +1,48 @@ +/* + * See the README file for copyright information and how to reach the author. + * + */ + +#include <vdr/videodir.h> +#include <vdr/menu.h> +#include "mymenurecordings.h" +#include "tools.h" + +myMenuRecordingDetails::myMenuRecordingDetails(cRecording *Recording,myMenuRecordings *MenuRecordings):cOsdMenu(tr("Details"),12) +{ + recording=Recording; + menurecordings=MenuRecordings; + priority=recording->priority; + lifetime=recording->lifetime; + + Add(new cMenuEditIntItem(tr("Priority"),&priority,0,MAXPRIORITY)); + Add(new cMenuEditIntItem(tr("Lifetime"),&lifetime,0,MAXLIFETIME)); +} + +eOSState myMenuRecordingDetails::ProcessKey(eKeys Key) +{ + eOSState state=cOsdMenu::ProcessKey(Key); + if(state==osUnknown) + { + if(Key==kOk) + { + char *newfilename=strdup(recording->FileName()); + + sprintf(newfilename+strlen(newfilename)-9,"%02d.%02d.rec",priority,lifetime); + + if(MoveVideoFile(recording,newfilename)) + { + menurecordings->Set(true); + state=osBack; + } + else + { + Skins.Message(mtError,tr("Error while accessing recording!")); + state=osContinue; + } + + free(newfilename); + } + } + return state; +} diff --git a/mymenurecordings.c b/mymenurecordings.c index 1a9f860..bbdb4da 100644 --- a/mymenurecordings.c +++ b/mymenurecordings.c @@ -10,6 +10,7 @@ #include "mymenusetup.h" #include "mymenucommands.h" #include "patchfont.h" +#include "tools.h" // --- myMenuRecordingsItem --------------------------------------------------- myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level) @@ -51,7 +52,6 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level) *title='\t'; *(title+1)='\t'; strn0cpy(title+2,p,s-p+1); - name=strdup(title+2); } else @@ -121,7 +121,7 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level) char RecDate[9],RecTime[6],RecDelimiter[2]={'\t',0}; char New[2]={0,0}; if(isdvd) - New[0]=mysetup.PatchDvd?char(129):'~'; + New[0]=char(129); else if(isnew&&!mysetup.PatchNew) New[0]='*'; @@ -142,7 +142,7 @@ myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level) (mysetup.ShowDvdNr?dvdnr:""), // show dvd nummber ((isdvd&&mysetup.ShowDvdNr)?" ":""), // space for fancy looking s?s+1:Recording->Name()); // recording name - + asprintf(&id,"%s %s %s",RecDate,RecTime,Recording->Name()); } else @@ -172,6 +172,10 @@ void myMenuRecordingsItem::IncrementCounter(bool IsNew) else asprintf(&buffer,"%d\t%s",totalentries,name); + // don't show '-', '.', '$', 'ª' or '·' if the directory name ends with one of it + if(buffer[strlen(buffer)-1]=='.'||buffer[strlen(buffer)-1]=='-'||buffer[strlen(buffer)-1]=='$'||buffer[strlen(buffer)-1]==char(170)||buffer[strlen(buffer)-1]==char(183)) + buffer[strlen(buffer)-1]=0; + SetText(buffer,false); } @@ -179,7 +183,7 @@ void myMenuRecordingsItem::IncrementCounter(bool IsNew) myMenuRecordings::myMenuRecordings(const char *Base,int Level):cOsdMenu(Base?Base:tr("Extended recordings menu")) { // patch font - if(Level==0&&(mysetup.PatchNew||mysetup.PatchDvd)) + if(Level==0) { if(Setup.UseSmallFont==2) PatchFont(fontSml); @@ -209,31 +213,28 @@ myMenuRecordings::myMenuRecordings(const char *Base,int Level):cOsdMenu(Base?Bas Recordings.StateChanged(recordingsstate); Display(); - Set(); - if(Current()<0) - SetCurrent(First()); - else - if(myReplayControl::LastReplayed()) + + if(mysetup.wasdvd&&!cControl::Control()) + { + char *cmd; + asprintf(&cmd,"dvdarchive.sh umount \"%s\"",myReplayControl::LastReplayed()); + isyslog("[extrecmenu] calling %s to unmount dvd",cmd); + int result=SystemExec(cmd); + if(result) { - if(mysetup.wasdvd&&!cControl::Control()) - { - char *cmd; - asprintf(&cmd,"dvdarchive.sh umount \"%s\"",myReplayControl::LastReplayed()); - isyslog("[extrecmenu] calling %s to unmount dvd",cmd); - int result=SystemExec(cmd); - if(result) - { - result=result/256; - if(result==1) - Skins.Message(mtError,tr("Error while mounting DVD!")); - } - isyslog("[extrecmenu] dvdarchive.sh returns %d",result); - free(cmd); - - mysetup.wasdvd=false; - } - Open(); + result=result/256; + if(result==1) + Skins.Message(mtError,tr("Error while mounting DVD!")); } + isyslog("[extrecmenu] dvdarchive.sh returns %d",result); + free(cmd); + + mysetup.wasdvd=false; + } + + Set(); + if(myReplayControl::LastReplayed()) + Open(); Display(); SetHelpKeys(); @@ -243,7 +244,7 @@ myMenuRecordings::~myMenuRecordings() { free(base); - if(level==0&&(mysetup.PatchNew||mysetup.PatchDvd)) + if(level==0) { if(Setup.UseSmallFont==2) cFont::SetFont(fontSml); @@ -291,90 +292,49 @@ void myMenuRecordings::Set(bool Refresh) cThreadLock RecordingsLock(&Recordings); Clear(); + // create my own recordings list from VDR's + myRecList *list=new myRecList(); + for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) + list->Add(new myRecListItem(recording)); + // sort my recordings list + list->Sort(); + + // needed for move recording menu Recordings.Sort(); char *lastitemtext=NULL; myMenuRecordingsItem *lastitem=NULL; - bool inlist=false; - // add first the directories - for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) + for(myRecListItem *listitem=list->First();listitem;listitem=list->Next(listitem)) { - if(!base||(strstr(recording->Name(),base)==recording->Name()&&recording->Name()[strlen(base)]=='~')) + cRecording *recording=listitem->recording; + if(!base||(strstr(listitem->recording->Name(),base)==listitem->recording->Name()&&listitem->recording->Name()[strlen(base)]=='~')) { - myMenuRecordingsItem *item=new myMenuRecordingsItem(recording,level); - if(*item->Text()&&(!lastitem||strcmp(item->Text(),lastitemtext))) + myMenuRecordingsItem *recitem=new myMenuRecordingsItem(listitem->recording,level); + if(*recitem->Text()&&(!lastitem||strcmp(recitem->Text(),lastitemtext))) { - if(item->IsDirectory()) - { - Add(item); - inlist=true; - } - lastitem=item; + Add(recitem); + lastitem=recitem; free(lastitemtext); lastitemtext=strdup(lastitem->Text()); } else - delete item; - + delete recitem; + if(lastitem) { if(lastitem->IsDirectory()) - { - lastitem->IncrementCounter(recording->IsNew()); // counts the number of entries in a directory - if(lastreplayed&&!strcmp(lastreplayed,recording->FileName())) - SetCurrent(lastitem); - } - // delete items that are not in the list - if(!inlist) - { - delete lastitem; - lastitem=NULL; - inlist=false; - } - } - } - } - inlist=false; - lastitem=NULL; - // and now the recordings - for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) - { - if(!base||(strstr(recording->Name(),base)==recording->Name()&&recording->Name()[strlen(base)]=='~')) - { - myMenuRecordingsItem *item=new myMenuRecordingsItem(recording,level); - if(item->ID()&&(!lastitem||strcmp(lastitemtext,item->ID()))) - { - if(!item->IsDirectory()) - { - Add(item); - inlist=true; - } - lastitem=item; - free(lastitemtext); - lastitemtext=strdup(lastitem->ID()); - } - else - delete item; - - if(lastitem) - { - if(!item->IsDirectory()&&lastreplayed&&!strcmp(lastreplayed,recording->FileName())) + lastitem->IncrementCounter(recording->IsNew()); + if(lastreplayed&&!strcmp(lastreplayed,recording->FileName())) { SetCurrent(lastitem); - if(!cControl::Control()) + if(recitem&&!recitem->IsDirectory()&&!cControl::Control()) myReplayControl::ClearLastReplayed(recording->FileName()); } - // delete items that are not in the list - if(!inlist) - { - delete lastitem; - lastitem=NULL; - inlist=false; - } } } - } + } free(lastitemtext); + delete list; if(Refresh) Display(); } @@ -559,6 +519,22 @@ eOSState myMenuRecordings::Rename() return osContinue; } +// edit details of a recording +eOSState myMenuRecordings::Details() +{ + if(HasSubMenu()||Count()==0) + return osContinue; + + myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + if(item&&!item->IsDirectory()) + { + cRecording *recording=GetRecording(item); + if(recording) + return AddSubMenu(new myMenuRecordingDetails(recording,this)); + } + return osContinue; +} + // moves a recording eOSState myMenuRecordings::MoveRec() { @@ -635,6 +611,9 @@ eOSState myMenuRecordings::ProcessKey(eKeys Key) case kYellow: edit=false; helpkeys=-1; return Delete(); + case kBlue: edit=false; + helpkeys=-1; + return Details(); case kBack: edit=false; helpkeys=-1; SetHelpKeys(); @@ -658,7 +637,7 @@ eOSState myMenuRecordings::ProcessKey(eKeys Key) if(item&&!item->IsDirectory()) { edit=true; - SetHelp(tr("Button$Rename"),tr("Button$Move"),tr("Button$Delete")); + SetHelp(tr("Button$Rename"),tr("Button$Move"),tr("Button$Delete"),tr("Details")); } break; } diff --git a/mymenurecordings.h b/mymenurecordings.h index ebbf644..36e3f17 100644 --- a/mymenurecordings.h +++ b/mymenurecordings.h @@ -41,6 +41,7 @@ class myMenuRecordings:public cOsdMenu eOSState Rename(); eOSState MoveRec(); eOSState Info(); + eOSState Details(); eOSState Commands(eKeys Key=kNone); public: myMenuRecordings(const char *Base=NULL,int Level=0); @@ -53,7 +54,6 @@ class myMenuRecordings:public cOsdMenu class myMenuRenameRecording:public cOsdMenu { private: - int priority,lifetime; char name[MaxFileName]; char path[MaxFileName]; cRecording *recording; @@ -80,3 +80,15 @@ class myMenuMoveRecording:public cOsdMenu myMenuMoveRecording::~myMenuMoveRecording(); virtual eOSState ProcessKey(eKeys Key); }; + +// --- myMenuRenameRecording -------------------------------------------------- +class myMenuRecordingDetails:public cOsdMenu +{ + private: + int priority,lifetime; + cRecording *recording; + myMenuRecordings *menurecordings; + public: + myMenuRecordingDetails(cRecording *Recording,myMenuRecordings *MenuRecordings); + virtual eOSState ProcessKey(eKeys Key); +}; diff --git a/mymenurenamerecording.c b/mymenurenamerecording.c index 646813e..5259f3d 100644 --- a/mymenurenamerecording.c +++ b/mymenurenamerecording.c @@ -12,8 +12,6 @@ myMenuRenameRecording::myMenuRenameRecording(cRecording *Recording,myMenuRecordings *MenuRecordings):cOsdMenu(tr("Rename recording"),12) { recording=Recording; - priority=recording->priority; - lifetime=recording->lifetime; menurecordings=MenuRecordings; char *p=strrchr(recording->Name(),'~'); @@ -32,15 +30,13 @@ myMenuRenameRecording::myMenuRenameRecording(cRecording *Recording,myMenuRecordi strn0cpy(path,"",sizeof(path)); } Add(new cMenuEditStrItem(tr("Name"),name,sizeof(name),tr(FileNameChars))); - Add(new cMenuEditIntItem(tr("Priority"),&priority,0,MAXPRIORITY)); - Add(new cMenuEditIntItem(tr("Lifetime"),&lifetime,0,MAXLIFETIME)); -// cRemote::Put(kRight); + cRemote::Put(kRight); } eOSState myMenuRenameRecording::ProcessKey(eKeys Key) { eOSState state=cOsdMenu::ProcessKey(Key); - if(state==osUnknown) // ==osContinue) + if(state==osContinue) { if(Key==kOk) { @@ -52,18 +48,7 @@ eOSState myMenuRenameRecording::ProcessKey(eKeys Key) else asprintf(&buffer,"%s",name); -// asprintf(&newfilename,"%s/%s/%s",VideoDirectory,ExchangeChars(buffer,true),strrchr(recording->FileName(),'/')+1); - struct tm tm_r; - struct tm *t=localtime_r(&recording->start, &tm_r); - asprintf(&newfilename,"%s/%s/%d-%02d-%02d.%02d.%02d.%02d.%02d.rec", - VideoDirectory, - ExchangeChars(buffer,true), - t->tm_year+1900, - t->tm_mon+1, - t->tm_mday, - t->tm_hour, - t->tm_min, - priority,lifetime); + asprintf(&newfilename,"%s/%s/%s",VideoDirectory,ExchangeChars(buffer,true),strrchr(recording->FileName(),'/')+1); if(MoveVideoFile(recording,newfilename)) { @@ -78,8 +63,8 @@ eOSState myMenuRenameRecording::ProcessKey(eKeys Key) free(buffer); free(newfilename); } -// if(Key==kBack) -// return osBack; + if(Key==kBack) + return osBack; } return state; } diff --git a/mymenusetup.c b/mymenusetup.c index 2a3cc18..e5dec57 100644 --- a/mymenusetup.c +++ b/mymenusetup.c @@ -1,25 +1,45 @@ +#include <vdr/menu.h> #include "mymenusetup.h" +mySetup::mySetup() +{ + mysetup.HideMainMenuEntry=0; + mysetup.PatchNew=0; + mysetup.ShowDvdNr=0; + mysetup.ReplaceOrgRecMenu=0; + mysetup.ShowRecDate=1; + mysetup.ShowRecTime=1; + mysetup.ShowRecLength=0; + mysetup.ShowNewRecs=1; + mysetup.SortRecords=0; + mysetup.wasdvd=false; +} + mySetup mysetup; myMenuSetup::myMenuSetup() { + sortrecordstext[0]=tr("alphabet for main-, flexible for subdirectories"); + sortrecordstext[1]=tr("date for main-, flexible for subdirectories"); + sortrecordstext[2]=tr("alphabet for all directories"); + sortrecordstext[3]=tr("date for all directories"); + hidemainmenuentry=mysetup.HideMainMenuEntry; patchnew=mysetup.PatchNew; - patchdvd=mysetup.PatchDvd; replaceorgrecmenu=mysetup.ReplaceOrgRecMenu; showrecdate=mysetup.ShowRecDate; showrectime=mysetup.ShowRecTime; showreclength=mysetup.ShowRecLength; showdvdnr=mysetup.ShowDvdNr; shownewrecs=mysetup.ShowNewRecs; + sortrecords=mysetup.SortRecords; Add(new cMenuEditBoolItem(tr("Show recording date"),&showrecdate)); Add(new cMenuEditBoolItem(tr("Show recording time"),&showrectime)); Add(new cMenuEditBoolItem(tr("Show recording length"),&showreclength)); Add(new cMenuEditBoolItem(tr("Show \"new recordings column\""),&shownewrecs)); + Add(new cMenuEditStraItem(tr("Sort recordings by"),&sortrecords,4,sortrecordstext)); Add(new cMenuEditBoolItem(tr("Show alternative to new marker"),&patchnew)); - Add(new cMenuEditBoolItem(tr("Show alternative dvd marker"),&patchdvd)); Add(new cMenuEditBoolItem(tr("Show dvd number"),&showdvdnr)); Add(new cMenuEditBoolItem(tr("Hide main menu entry"),&hidemainmenuentry)); Add(new cMenuEditBoolItem(tr("Replace original recordings menu"),&replaceorgrecmenu)); @@ -29,11 +49,11 @@ void myMenuSetup::Store() { SetupStore("HideMainMenuEntry",mysetup.HideMainMenuEntry=hidemainmenuentry); SetupStore("PatchNew",mysetup.PatchNew=patchnew); - SetupStore("PatchDvd",mysetup.PatchDvd=patchdvd); SetupStore("ShowDvdNr",mysetup.ShowDvdNr=showdvdnr); SetupStore("ReplaceOrgRecMenu",mysetup.ReplaceOrgRecMenu=replaceorgrecmenu); SetupStore("ShowRecDate",mysetup.ShowRecDate=showrecdate); SetupStore("ShowRecTime",mysetup.ShowRecTime=showrectime); SetupStore("ShowRecLength",mysetup.ShowRecLength=showreclength); SetupStore("ShowNewRecs",mysetup.ShowNewRecs=shownewrecs); + SetupStore("SortRecords",mysetup.SortRecords=sortrecords); } diff --git a/mymenusetup.h b/mymenusetup.h index bd6f1a1..8813ac9 100644 --- a/mymenusetup.h +++ b/mymenusetup.h @@ -3,15 +3,16 @@ class mySetup { public: + mySetup(); int ShowRecDate; int ShowRecTime; int ShowRecLength; int HideMainMenuEntry; int ReplaceOrgRecMenu; int PatchNew; - int PatchDvd; int ShowDvdNr; int ShowNewRecs; + int SortRecords; bool wasdvd; // needed for dvdarchive-patch functionality }; @@ -20,15 +21,16 @@ extern mySetup mysetup; class myMenuSetup:public cMenuSetupPage { private: + const char *sortrecordstext[4]; int showrecdate; int showrectime; int showreclength; int hidemainmenuentry; int replaceorgrecmenu; int patchnew; - int patchdvd; int showdvdnr; int shownewrecs; + int sortrecords; protected: virtual void Store(); public: diff --git a/myreplaycontrol.c b/myreplaycontrol.c index fe5f2b6..fb7f50f 100644 --- a/myreplaycontrol.c +++ b/myreplaycontrol.c @@ -1,7 +1,8 @@ /* * See the README file for copyright information and how to reach the author. * - * This code is directly taken from VDR with some changes by me to work with this plugin + * This code is directly taken from VDR with some changes by me to work with this plugin. + * Also to JumpPlay-Patch is integrated using #ifdef's. */ #include <vdr/interface.h> @@ -13,7 +14,12 @@ char *myReplayControl::fileName = NULL; char *myReplayControl::title = NULL; myReplayControl::myReplayControl(void) -:myDvbPlayerControl(fileName) +#ifdef BIGPATCHVERSION +:cDvbPlayerControl(fileName,&marks) +#endif +#ifndef BIGPATCHVERSION +:cDvbPlayerControl(fileName) +#endif { displayReplay = NULL; visible = modeOnly = shown = displayFrames = false; @@ -23,6 +29,9 @@ myReplayControl::myReplayControl(void) timeoutShow = 0; timeSearchActive = false; marks.Load(fileName); +#ifdef BIGPACKVERSION + lastLoadMarks = time(NULL); +#endif cRecording Recording(fileName); cStatus::MsgReplaying(this, Recording.Name(), Recording.FileName(), true); } @@ -244,8 +253,16 @@ void myReplayControl::MarkToggle(void) ShowTimed(2); bool Play, Forward; int Speed; +#ifndef BIGPACKVERSION if (GetReplayMode(Play, Forward, Speed) && !Play) Goto(Current, true); +#endif +#ifdef BIGBACKVERSION + if (GetReplayMode(Play, Forward, Speed) && !Play) { + Goto(Current, true); + displayFrames = true; + } +#endif } marks.Save(); @@ -259,8 +276,23 @@ void myReplayControl::MarkJump(bool Forward) if (GetIndex(Current, Total)) { cMark *m = Forward ? marks.GetNext(Current) : marks.GetPrev(Current); if (m) { +#ifndef BIGPACKVERSION Goto(m->position, true); displayFrames = true; +#endif +#ifdef BIGPACKVERSION + bool Play2, Forward2; + int Speed; + if (Setup.JumpPlay && GetReplayMode(Play2, Forward2, Speed) && + Play2 && Forward && m->position < Total - SecondsToFrames(3)) { + Goto(m->position); + Play(); + } + else { + Goto(m->position, true); + displayFrames = true; + } +#endif } } } @@ -315,7 +347,12 @@ void myReplayControl::EditTest(void) if (!m) m = marks.GetNext(Current); if (m) { +#ifndef BIGPACKVERSION if ((m->Index() & 0x01) != 0) +#endif +#ifdef BIGPACKVERSION + if ((m->Index() & 0x01) != 0 && !Setup.PlayJump) +#endif m = marks.Next(m); if (m) { Goto(m->position - SecondsToFrames(3)); @@ -337,6 +374,13 @@ eOSState myReplayControl::ProcessKey(eKeys Key) { if (!Active()) return osEnd; +#ifdef BIGPACKVERSION + if (Setup.LoadMarksInterval && + time(NULL) >= lastLoadMarks + Setup.LoadMarksInterval) { + marks.Load(fileName, true); + lastLoadMarks = time(NULL); + } +#endif if (visible) { if (timeoutShow && time(NULL) > timeoutShow) { Hide(); diff --git a/myreplaycontrol.h b/myreplaycontrol.h index cd14c96..274737e 100644 --- a/myreplaycontrol.h +++ b/myreplaycontrol.h @@ -1,9 +1,8 @@ -#include "mydvbplayer.h" - +#include <vdr/dvbplayer.h> #define MODETIMEOUT 3 // seconds // --- myReplayControls ------------------------------------------------------- -class myReplayControl : public myDvbPlayerControl { +class myReplayControl : public cDvbPlayerControl { private: cSkinDisplayReplay *displayReplay; cMarks marks; @@ -12,6 +11,9 @@ private: bool lastPlay, lastForward; int lastSpeed; time_t timeoutShow; +#ifdef BIGPACKVERSION + time_t lastLoadMarks; +#endif bool timeSearchActive, timeSearchHide; int timeSearchTime, timeSearchPos; void TimeSearchDisplay(void); diff --git a/patchfont.c b/patchfont.c index 4f2ad2a..0a4c7db 100644 --- a/patchfont.c +++ b/patchfont.c @@ -87,7 +87,7 @@ void PatchFont(eDvbFont DvbFont) } } // dvd marker - else if(num_char==129&&mysetup.PatchDvd) + else if(num_char==129) { if(DvbFont==fontOsd) { diff --git a/scripts/dvdarchive.sh b/scripts/dvdarchive.sh index 3dc0c71..7f5b72b 100755 --- a/scripts/dvdarchive.sh +++ b/scripts/dvdarchive.sh @@ -1,6 +1,6 @@ #!/bin/bash # -# Version 1.2 2006-03-30 +# Version 1.4 2006-04-07 # # Exitcodes: # @@ -15,20 +15,35 @@ # For dvd-in-drive detection download isodetect.c, compile it and put it into the PATH, # usually /usr/local/bin/ # +# Tools needed: mount, awk, find, test +# Optional tools: isodetect #<Configuration> MOUNTCMD="/usr/bin/sudo /bin/mount" UMOUNTCMD="/usr/bin/sudo /bin/umount" + MOUNTPOINT="/media/cdrom" # no trailing '/'! +# Eject DVD for exit-codes 2 and 3 (no or wrong dvd). 1 = yes, 0 = no. +EJECTWRONG=0 +# Eject DVD after unmounting. 1 = yes, 0 = no. +EJECTUMOUNT=0 + #</Configuration> -DEVICE="$(awk '( $1 !~ /^#/ ) && ( $2 == "'$MOUNTPOINT'" ) { print $1; exit; }' /etc/fstab)" # dvd-device, used by isodetect if exists +DEVICE="$(awk '( $1 !~ /^#/ ) && ( $2 == "'$MOUNTPOINT'" ) { printf("%s", $1); exit; }' /etc/fstab)" # dvd-device, used by isodetect if exists REC="$2" NAME="$3" +call() { + echo -e "\nScript $0 needs three parameters. Action, rec and name. Action is mount or umount" + echo -e "Example: dvdarchive.sh mount '/video1.0/Music/%Riverdance/2004-06-06.00:10.50.99.rec' '2004-06-06.00:10.50.99.rec'\n" +} + +[ $# -ne 3 ] && { call; exit 10; } + case "$1" in mount) # check if dvd is in drive, only if isodetect exists @@ -36,6 +51,7 @@ mount) isodetect -d "$DEVICE" >/dev/null 2>&1 if [ $? -ne 0 ]; then echo "no dvd in drive" + [ $EJECTWRONG -eq 1 ] && { eject "$DEVICE"; } exit 2 fi fi @@ -50,6 +66,7 @@ mount) if [ -z "$DIR" ]; then $UMOUNTCMD "$MOUNTPOINT" || { echo "dvd umount error"; exit 1; } echo "wrong dvd in drive / recording not found on dvd" + [ $EJECTWRONG -eq 1 ] && { eject "$DEVICE"; } exit 3 fi # link index.vdr if not exist @@ -84,7 +101,12 @@ umount) rm "$LINK" fi done + [ $EJECTUMOUNT -eq 1 ] && { eject "$DEVICE"; } ;; + *) + echo -e "\nWrong action." + call + ;; esac exit 0 @@ -1,6 +1,14 @@ +/* + * See the README file for copyright information and how to reach the author. + * + * The code for sort recordings as adopted from the SortRecordings-patch + * copyright by FrankJepsen and FRank99 from vdr-portal.de + */ + #include <vdr/videodir.h> #include <vdr/recording.h> #include "tools.h" +#include "mymenusetup.h" bool MoveVideoFile(cRecording *Recording,char *NewName) { @@ -23,3 +31,60 @@ bool MoveVideoFile(cRecording *Recording,char *NewName) isyslog("[extrecmenu] moving failed"); return false; } + +// --- myRecListItem ---------------------------------------------------------- +myRecListItem::myRecListItem(cRecording *Recording) +{ + recording=Recording; + filename=recording->FileName(); + sortbuffer=NULL; +} + +myRecListItem::~myRecListItem() +{ + free(sortbuffer); +} + +char *myRecListItem::StripEpisodeName(char *s) +{ + char *t=s,*s1=NULL,*s2=NULL; + while(*t) + { + if(*t=='/') + { + if(s1) + { + if(s2) + s1=s2; + s2=t; + } + else + s1=t; + } + t++; + } + *s1=255; + if(s1&&s2&&(s1==s&&(mysetup.SortRecords&1)||s1!=s&&(mysetup.SortRecords==3||mysetup.SortRecords!=2&&!strchr(".-$ª·",*(s1-1))))) + memmove(s1+1,s2,t-s2+1); + return s; +} + +char *myRecListItem::SortName()const +{ + if(!sortbuffer) + { + char *s=StripEpisodeName(strdup(filename+strlen(VideoDirectory))); + strreplace(s,'/','a'); + int l=strxfrm(NULL,s,0)+1; + sortbuffer=MALLOC(char,l); + strxfrm(sortbuffer,s,l); + free(s); + } + return sortbuffer; +} + +int myRecListItem::Compare(const cListObject &ListObject)const +{ + myRecListItem *item=(myRecListItem*)&ListObject; + return strcasecmp(SortName(),item->SortName()); +} @@ -1 +1,19 @@ bool MoveVideoFile(cRecording *Recording,char *NewName); + +class myRecListItem:public cListObject +{ + private: + const char *filename; + mutable char *sortbuffer; + static char *StripEpisodeName(char *s); + char *SortName()const; + public: + myRecListItem(cRecording *Recording); + ~myRecListItem(); + virtual int Compare(const cListObject &ListObject)const; + cRecording *recording; +}; + +class myRecList:public cList<myRecListItem> +{ +}; |