mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented sort mode for recordings
This commit is contained in:
parent
0b6c96a515
commit
440c119b0a
7
HISTORY
7
HISTORY
@ -7148,7 +7148,7 @@ Video Disk Recorder Revision History
|
|||||||
caching the information whether a recording is stored on the video directory file
|
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).
|
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
|
- Added a missing template specification to the c'tor of cSortedTimers (thanks to Udo
|
||||||
Richter).
|
Richter).
|
||||||
@ -7170,3 +7170,8 @@ Video Disk Recorder Revision History
|
|||||||
- Removed the gap from the main menu buttons in the LCARS skin.
|
- 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).
|
- 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.
|
- 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".
|
||||||
|
12
MANUAL
12
MANUAL
@ -24,7 +24,7 @@ Version 1.6
|
|||||||
Green - Audio New New Ins/Ovr Rewind Skip -60s -
|
Green - Audio New New Ins/Ovr Rewind Skip -60s -
|
||||||
Yellow - Pause live Delete Delete Delete Delete Skip +60s -
|
Yellow - Pause live Delete Delete Delete Delete Skip +60s -
|
||||||
Blue - Stop/Resume Mark Info - Info Stop -
|
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
|
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
|
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
|
Yellow Info
|
||||||
Blue Timers menu
|
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",
|
(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
|
"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
|
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"
|
A previously stopped playback session can be resumed by pressing the "Blue"
|
||||||
key in the "VDR" menu.
|
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
|
* Processing Recordings
|
||||||
|
|
||||||
The configuration file 'reccmds.conf' can be used to define system commands
|
The configuration file 'reccmds.conf' can be used to define system commands
|
||||||
|
38
menu.c
38
menu.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "menu.h"
|
||||||
@ -2247,6 +2247,7 @@ void cMenuRecordings::Set(bool Refresh)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Clear();
|
Clear();
|
||||||
|
GetRecordingsSortMode(DirectoryName());
|
||||||
Recordings.Sort();
|
Recordings.Sort();
|
||||||
for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
|
for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
|
||||||
if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == FOLDERDELIMCHAR)) {
|
if (!base || (strstr(recording->Name(), base) == recording->Name() && recording->Name()[strlen(base)] == FOLDERDELIMCHAR)) {
|
||||||
@ -2272,6 +2273,17 @@ void cMenuRecordings::Set(bool Refresh)
|
|||||||
Display();
|
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 *cMenuRecordings::GetRecording(cMenuRecordingItem *Item)
|
||||||
{
|
{
|
||||||
cRecording *recording = Recordings.GetByName(Item->FileName());
|
cRecording *recording = Recordings.GetByName(Item->FileName());
|
||||||
@ -2417,6 +2429,15 @@ eOSState cMenuRecordings::Commands(eKeys Key)
|
|||||||
return osContinue;
|
return osContinue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eOSState cMenuRecordings::Sort(void)
|
||||||
|
{
|
||||||
|
if (HasSubMenu())
|
||||||
|
return osContinue;
|
||||||
|
IncRecordingsSortMode(DirectoryName());
|
||||||
|
Set(true);
|
||||||
|
return osContinue;
|
||||||
|
}
|
||||||
|
|
||||||
eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
||||||
{
|
{
|
||||||
bool HadSubMenu = HasSubMenu();
|
bool HadSubMenu = HasSubMenu();
|
||||||
@ -2431,6 +2452,7 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
|||||||
case kYellow: return Delete();
|
case kYellow: return Delete();
|
||||||
case kInfo:
|
case kInfo:
|
||||||
case kBlue: return Info();
|
case kBlue: return Info();
|
||||||
|
case k0: return Sort();
|
||||||
case k1...k9: return Commands(Key);
|
case k1...k9: return Commands(Key);
|
||||||
case kNone: if (Recordings.StateChanged(recordingsState))
|
case kNone: if (Recordings.StateChanged(recordingsState))
|
||||||
Set(true);
|
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()
|
if (!Timer && !cReplayControl::LastReplayed()) // an instant recording, maybe from cRecordControls::PauseLiveVideo()
|
||||||
cReplayControl::SetRecording(fileName);
|
cReplayControl::SetRecording(fileName);
|
||||||
Recordings.AddByName(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;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
4
menu.h
4
menu.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __MENU_H
|
||||||
@ -203,8 +203,10 @@ private:
|
|||||||
eOSState Rewind(void);
|
eOSState Rewind(void);
|
||||||
eOSState Delete(void);
|
eOSState Delete(void);
|
||||||
eOSState Info(void);
|
eOSState Info(void);
|
||||||
|
eOSState Sort(void);
|
||||||
eOSState Commands(eKeys Key = kNone);
|
eOSState Commands(eKeys Key = kNone);
|
||||||
protected:
|
protected:
|
||||||
|
cString DirectoryName(void);
|
||||||
cRecording *GetRecording(cMenuRecordingItem *Item);
|
cRecording *GetRecording(cMenuRecordingItem *Item);
|
||||||
public:
|
public:
|
||||||
cMenuRecordings(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false);
|
cMenuRecordings(const char *Base = NULL, int Level = 0, bool OpenSubMenus = false);
|
||||||
|
66
recording.c
66
recording.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "recording.h"
|
||||||
@ -53,6 +53,8 @@
|
|||||||
#define INFOFILESUFFIX "/info"
|
#define INFOFILESUFFIX "/info"
|
||||||
#define MARKSFILESUFFIX "/marks"
|
#define MARKSFILESUFFIX "/marks"
|
||||||
|
|
||||||
|
#define SORTMODEFILE ".sort"
|
||||||
|
|
||||||
#define MINDISKSPACE 1024 // MB
|
#define MINDISKSPACE 1024 // MB
|
||||||
|
|
||||||
#define REMOVECHECKDELTA 60 // seconds between checks for removing deleted files
|
#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;
|
resume = RESUME_NOT_INITIALIZED;
|
||||||
titleBuffer = NULL;
|
titleBuffer = NULL;
|
||||||
sortBuffer = NULL;
|
sortBufferName = sortBufferTime = NULL;
|
||||||
fileName = NULL;
|
fileName = NULL;
|
||||||
name = NULL;
|
name = NULL;
|
||||||
fileSizeMB = -1; // unknown
|
fileSizeMB = -1; // unknown
|
||||||
@ -683,7 +685,7 @@ cRecording::cRecording(const char *FileName)
|
|||||||
numFrames = -1;
|
numFrames = -1;
|
||||||
deleted = 0;
|
deleted = 0;
|
||||||
titleBuffer = NULL;
|
titleBuffer = NULL;
|
||||||
sortBuffer = NULL;
|
sortBufferName = sortBufferTime = NULL;
|
||||||
FileName = fileName = strdup(FileName);
|
FileName = fileName = strdup(FileName);
|
||||||
if (*(fileName + strlen(fileName) - 1) == '/')
|
if (*(fileName + strlen(fileName) - 1) == '/')
|
||||||
*(fileName + strlen(fileName) - 1) = 0;
|
*(fileName + strlen(fileName) - 1) = 0;
|
||||||
@ -795,7 +797,8 @@ cRecording::cRecording(const char *FileName)
|
|||||||
cRecording::~cRecording()
|
cRecording::~cRecording()
|
||||||
{
|
{
|
||||||
free(titleBuffer);
|
free(titleBuffer);
|
||||||
free(sortBuffer);
|
free(sortBufferName);
|
||||||
|
free(sortBufferTime);
|
||||||
free(fileName);
|
free(fileName);
|
||||||
free(name);
|
free(name);
|
||||||
delete info;
|
delete info;
|
||||||
@ -816,22 +819,27 @@ char *cRecording::StripEpisodeName(char *s)
|
|||||||
}
|
}
|
||||||
t++;
|
t++;
|
||||||
}
|
}
|
||||||
if (s1 && s2)
|
if (s1 && s2) {
|
||||||
memmove(s1 + 1, s2, t - s2 + 1);
|
s1++;
|
||||||
|
memmove(s1, s2, t - s2 + 1);
|
||||||
|
*s1 = 0xFF; // sorts folders before plain recordings
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *cRecording::SortName(void) const
|
char *cRecording::SortName(void) const
|
||||||
{
|
{
|
||||||
if (!sortBuffer) {
|
char **sb = (RecordingsSortMode == rsmName) ? &sortBufferName : &sortBufferTime;
|
||||||
char *s = StripEpisodeName(strdup(FileName() + strlen(VideoDirectory) + 1));
|
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
|
strreplace(s, '/', 'a'); // some locales ignore '/' when sorting
|
||||||
int l = strxfrm(NULL, s, 0) + 1;
|
int l = strxfrm(NULL, s, 0) + 1;
|
||||||
sortBuffer = MALLOC(char, l);
|
*sb = MALLOC(char, l);
|
||||||
strxfrm(sortBuffer, s, l);
|
strxfrm(*sb, s, l);
|
||||||
free(s);
|
free(s);
|
||||||
}
|
}
|
||||||
return sortBuffer;
|
return *sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cRecording::GetResume(void) const
|
int cRecording::GetResume(void) const
|
||||||
@ -2133,3 +2141,39 @@ int ReadFrame(cUnbufferedFile *f, uchar *b, int Length, int Max)
|
|||||||
LOG_ERROR;
|
LOG_ERROR;
|
||||||
return r;
|
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);
|
||||||
|
}
|
||||||
|
12
recording.h
12
recording.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __RECORDING_H
|
||||||
@ -83,7 +83,8 @@ class cRecording : public cListObject {
|
|||||||
private:
|
private:
|
||||||
mutable int resume;
|
mutable int resume;
|
||||||
mutable char *titleBuffer;
|
mutable char *titleBuffer;
|
||||||
mutable char *sortBuffer;
|
mutable char *sortBufferName;
|
||||||
|
mutable char *sortBufferTime;
|
||||||
mutable char *fileName;
|
mutable char *fileName;
|
||||||
mutable char *name;
|
mutable char *name;
|
||||||
mutable int fileSizeMB;
|
mutable int fileSizeMB;
|
||||||
@ -333,4 +334,11 @@ char *ExchangeChars(char *s, bool ToFileSystem);
|
|||||||
|
|
||||||
bool GenerateIndex(const char *FileName);
|
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
|
#endif //__RECORDING_H
|
||||||
|
Loading…
Reference in New Issue
Block a user