diff --git a/HISTORY b/HISTORY index fed71e2a..43f3a983 100644 --- a/HISTORY +++ b/HISTORY @@ -7148,7 +7148,7 @@ Video Disk Recorder Revision History caching the information whether a recording is stored on the video directory file system within the cRecording data (based on a patch from Torsten Lang). -2012-06-08: Version 1.7.29 +2012-06-09: Version 1.7.29 - Added a missing template specification to the c'tor of cSortedTimers (thanks to Udo Richter). @@ -7170,3 +7170,8 @@ Video Disk Recorder Revision History - Removed the gap from the main menu buttons in the LCARS skin. - Fixed some copy&paste errors in PLUGINS.html (thanks to Winfried Köhler). - The LCARS skin's main menu now only displays timers that are actually activated. +- Within the "Recordings" menu, pressing the '0' key now toggles sorting between + "by time" and "by name". The selected sort mode is stored separately for each + folder (provided you have write access to that folder). + If a folder is newly created by a repeating timer, the sort mode for that + folder is initially set to "by time". diff --git a/MANUAL b/MANUAL index a33f3bf6..fdb7ab23 100644 --- a/MANUAL +++ b/MANUAL @@ -24,7 +24,7 @@ Version 1.6 Green - Audio New New Ins/Ovr Rewind Skip -60s - Yellow - Pause live Delete Delete Delete Delete Skip +60s - Blue - Stop/Resume Mark Info - Info Stop - - 0..9 Ch select - Sort(2) Day(3) Numeric inp. Exec cmd(1) Editing - + 0..9 Ch select - Sort(2) Day(3) Numeric inp. Sort/Exec cmd(1) Editing - In a numerical input field (like the response to a CAM enquiry) the keys 0..9 are used to enter the data, and the Left key can be used to delete the last @@ -81,7 +81,7 @@ Version 1.6 Yellow Info Blue Timers menu - (1) See "Processing Recordings" below. + (1) See "Sort Recordings" and "Processing Recordings" below. (2) In the "Channels" menu the '0' key switches the sort mode through "by number", "by name" and "by provider". Other numeric input positions the cursor to the channel with the number entered so far. If there is no channel with that @@ -301,6 +301,14 @@ Version 1.6 A previously stopped playback session can be resumed by pressing the "Blue" key in the "VDR" menu. +* Sort Recordings + + Within the "Recordings" menu, pressing the '0' key toggles sorting between + "by time" and "by name". The selected sort mode is stored separately for each + folder (provided you have write access to that folder). + If a folder is newly created by a repeating timer, the sort mode for that + folder is initially set to "by time". + * Processing Recordings The configuration file 'reccmds.conf' can be used to define system commands diff --git a/menu.c b/menu.c index ed07b7e2..45316fa7 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 2.54 2012/05/12 13:08:23 kls Exp $ + * $Id: menu.c 2.55 2012/06/09 14:27:02 kls Exp $ */ #include "menu.h" @@ -2247,6 +2247,7 @@ void cMenuRecordings::Set(bool Refresh) } } Clear(); + GetRecordingsSortMode(DirectoryName()); Recordings.Sort(); for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) { if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == FOLDERDELIMCHAR)) { @@ -2272,6 +2273,17 @@ void cMenuRecordings::Set(bool Refresh) Display(); } +cString cMenuRecordings::DirectoryName(void) +{ + cString d(VideoDirectory); + if (base) { + char *s = ExchangeChars(strdup(base), true); + d = AddDirectory(d, s); + free(s); + } + return d; +} + cRecording *cMenuRecordings::GetRecording(cMenuRecordingItem *Item) { cRecording *recording = Recordings.GetByName(Item->FileName()); @@ -2417,6 +2429,15 @@ eOSState cMenuRecordings::Commands(eKeys Key) return osContinue; } +eOSState cMenuRecordings::Sort(void) +{ + if (HasSubMenu()) + return osContinue; + IncRecordingsSortMode(DirectoryName()); + Set(true); + return osContinue; +} + eOSState cMenuRecordings::ProcessKey(eKeys Key) { bool HadSubMenu = HasSubMenu(); @@ -2431,6 +2452,7 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key) case kYellow: return Delete(); case kInfo: case kBlue: return Info(); + case k0: return Sort(); case k1...k9: return Commands(Key); case kNone: if (Recordings.StateChanged(recordingsState)) Set(true); @@ -4149,6 +4171,20 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo() cReplayControl::SetRecording(fileName); Recordings.AddByName(fileName); + if (!Timer->IsSingleEvent()) { + char *Directory = strdup(fileName); + // going up two directory levels to get the series folder + if (char *p = strrchr(Directory, '/')) { + while (p > Directory && *--p != '/') + ; + *p = 0; + if (!HasRecordingsSortMode(Directory)) { + dsyslog("setting %s to be sorted by time", Directory); + SetRecordingsSortMode(Directory, rsmTime); + } + } + free(Directory); + } return; } else diff --git a/menu.h b/menu.h index 99f88d0b..5202dd7e 100644 --- a/menu.h +++ b/menu.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.h 2.9 2012/05/12 11:48:04 kls Exp $ + * $Id: menu.h 2.10 2012/06/09 12:12:43 kls Exp $ */ #ifndef __MENU_H @@ -203,8 +203,10 @@ private: eOSState Rewind(void); eOSState Delete(void); eOSState Info(void); + eOSState Sort(void); eOSState Commands(eKeys Key = kNone); protected: + cString DirectoryName(void); cRecording *GetRecording(cMenuRecordingItem *Item); public: cMenuRecordings(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false); diff --git a/recording.c b/recording.c index 2a73645c..d13225be 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 2.56 2012/06/03 09:51:27 kls Exp $ + * $Id: recording.c 2.57 2012/06/09 13:57:30 kls Exp $ */ #include "recording.h" @@ -53,6 +53,8 @@ #define INFOFILESUFFIX "/info" #define MARKSFILESUFFIX "/marks" +#define SORTMODEFILE ".sort" + #define MINDISKSPACE 1024 // MB #define REMOVECHECKDELTA 60 // seconds between checks for removing deleted files @@ -610,7 +612,7 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event) { resume = RESUME_NOT_INITIALIZED; titleBuffer = NULL; - sortBuffer = NULL; + sortBufferName = sortBufferTime = NULL; fileName = NULL; name = NULL; fileSizeMB = -1; // unknown @@ -683,7 +685,7 @@ cRecording::cRecording(const char *FileName) numFrames = -1; deleted = 0; titleBuffer = NULL; - sortBuffer = NULL; + sortBufferName = sortBufferTime = NULL; FileName = fileName = strdup(FileName); if (*(fileName + strlen(fileName) - 1) == '/') *(fileName + strlen(fileName) - 1) = 0; @@ -795,7 +797,8 @@ cRecording::cRecording(const char *FileName) cRecording::~cRecording() { free(titleBuffer); - free(sortBuffer); + free(sortBufferName); + free(sortBufferTime); free(fileName); free(name); delete info; @@ -816,22 +819,27 @@ char *cRecording::StripEpisodeName(char *s) } t++; } - if (s1 && s2) - memmove(s1 + 1, s2, t - s2 + 1); + if (s1 && s2) { + s1++; + memmove(s1, s2, t - s2 + 1); + *s1 = 0xFF; // sorts folders before plain recordings + } return s; } char *cRecording::SortName(void) const { - if (!sortBuffer) { - char *s = StripEpisodeName(strdup(FileName() + strlen(VideoDirectory) + 1)); + char **sb = (RecordingsSortMode == rsmName) ? &sortBufferName : &sortBufferTime; + if (!*sb) { + char *s = (RecordingsSortMode == rsmName) ? strdup(FileName() + strlen(VideoDirectory) + 1) + : StripEpisodeName(strdup(FileName() + strlen(VideoDirectory) + 1)); strreplace(s, '/', 'a'); // some locales ignore '/' when sorting int l = strxfrm(NULL, s, 0) + 1; - sortBuffer = MALLOC(char, l); - strxfrm(sortBuffer, s, l); + *sb = MALLOC(char, l); + strxfrm(*sb, s, l); free(s); } - return sortBuffer; + return *sb; } int cRecording::GetResume(void) const @@ -2133,3 +2141,39 @@ int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max) LOG_ERROR; return r; } + +// --- Recordings Sort Mode -------------------------------------------------- + +eRecordingsSortMode RecordingsSortMode = rsmName; + +bool HasRecordingsSortMode(const char *Directory) +{ + return access(AddDirectory(Directory, SORTMODEFILE), R_OK) == 0; +} + +void GetRecordingsSortMode(const char *Directory) +{ + if (FILE *f = fopen(AddDirectory(Directory, SORTMODEFILE), "r")) { + char buf[8]; + if (fgets(buf, sizeof(buf), f)) + RecordingsSortMode = eRecordingsSortMode(constrain(atoi(buf), 0, int(rsmTime))); + fclose(f); + } +} + +void SetRecordingsSortMode(const char *Directory, eRecordingsSortMode SortMode) +{ + if (FILE *f = fopen(AddDirectory(Directory, SORTMODEFILE), "w")) { + fputs(cString::sprintf("%d\n", SortMode), f); + fclose(f); + } +} + +void IncRecordingsSortMode(const char *Directory) +{ + GetRecordingsSortMode(Directory); + RecordingsSortMode = eRecordingsSortMode(int(RecordingsSortMode) + 1); + if (RecordingsSortMode > rsmTime) + RecordingsSortMode = eRecordingsSortMode(0); + SetRecordingsSortMode(Directory, RecordingsSortMode); +} diff --git a/recording.h b/recording.h index 56659edc..8e712306 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.h 2.33 2012/06/03 09:49:09 kls Exp $ + * $Id: recording.h 2.34 2012/06/09 13:55:22 kls Exp $ */ #ifndef __RECORDING_H @@ -83,7 +83,8 @@ class cRecording : public cListObject { private: mutable int resume; mutable char *titleBuffer; - mutable char *sortBuffer; + mutable char *sortBufferName; + mutable char *sortBufferTime; mutable char *fileName; mutable char *name; mutable int fileSizeMB; @@ -333,4 +334,11 @@ char *ExchangeChars(char *s, bool ToFileSystem); bool GenerateIndex(const char *FileName); +enum eRecordingsSortMode { rsmName, rsmTime }; +extern eRecordingsSortMode RecordingsSortMode; +bool HasRecordingsSortMode(const char *Directory); +void GetRecordingsSortMode(const char *Directory); +void SetRecordingsSortMode(const char *Directory, eRecordingsSortMode SortMode); +void IncRecordingsSortMode(const char *Directory); + #endif //__RECORDING_H