summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2014-10-18 16:50:33 +0200
committerlouis <louis.braun@gmx.de>2014-10-18 16:50:33 +0200
commit3ef0db807d386553f1842ca0b8b0e931498237e1 (patch)
tree30f332068706af8f57715925c826fc39c92011a1
parent762115bf818fb11b5f03525d115adad1f40c480d (diff)
downloadvdr-plugin-skindesigner-3ef0db807d386553f1842ca0b8b0e931498237e1.tar.gz
vdr-plugin-skindesigner-3ef0db807d386553f1842ca0b8b0e931498237e1.tar.bz2
added date of newest recording in a folder
-rw-r--r--HISTORY1
-rw-r--r--Makefile1
-rw-r--r--config.h3
-rw-r--r--libcore/recfolderinfo.c201
-rw-r--r--libcore/recfolderinfo.h42
-rw-r--r--views/displaymenuitemcurrentview.c32
-rw-r--r--views/displaymenuitemview.c34
7 files changed, 302 insertions, 12 deletions
diff --git a/HISTORY b/HISTORY
index 2ec76d5..b3e135f 100644
--- a/HISTORY
+++ b/HISTORY
@@ -26,3 +26,4 @@ Version 0.0.2
- added setup option to choose Menu Item display method between "at one go" and "after one another"
- fixed bug that new skin was not properly loaded sometimes when skin was changed in OSD Setup menu
- fixed bug that new font was displayed first after VDR restart when font was changed in OSD Setup menu
+- added date of newest recording in a folder, thanks@ Lars Hanisch for providing the patch \ No newline at end of file
diff --git a/Makefile b/Makefile
index d3d35d5..171cf53 100644
--- a/Makefile
+++ b/Makefile
@@ -75,6 +75,7 @@ OBJS = $(PLUGIN).o \
libcore/imagescaler.o \
libcore/helpers.o \
libcore/imageloader.o \
+ libcore/recfolderinfo.o \
libcore/timers.o \
libtemplate/globals.o \
libtemplate/parameter.o \
diff --git a/config.h b/config.h
index 3763bf9..9d10588 100644
--- a/config.h
+++ b/config.h
@@ -9,6 +9,7 @@
#include <vdr/plugin.h>
#include "libcore/fontmanager.h"
#include "libcore/imagecache.h"
+#include "libcore/recfolderinfo.h"
class cDesignerConfig {
private:
@@ -67,12 +68,14 @@ public:
cFontManager *fontManager = NULL;
cImageCache *imgCache = NULL;
cTheme Theme;
+ cRecordingsFolderInfo recFolderInfo(Recordings);
#else
extern bool firstDisplay;
extern cDesignerConfig config;
extern cFontManager *fontManager;
extern cImageCache *imgCache;
extern cTheme Theme;
+ extern cRecordingsFolderInfo recFolderInfo;
#endif
#endif //__DESIGNER_CONFIG_H
diff --git a/libcore/recfolderinfo.c b/libcore/recfolderinfo.c
new file mode 100644
index 0000000..debc309
--- /dev/null
+++ b/libcore/recfolderinfo.c
@@ -0,0 +1,201 @@
+#include "recfolderinfo.h"
+
+
+class cFolderInfoInternList;
+
+class cRecordingsFolderInfo::cFolderInfoIntern:public cListObject {
+private:
+ cFolderInfoIntern *_parent;
+ cList<cFolderInfoIntern> *_subFolders;
+
+ cString _name;
+ time_t _latest;
+ int _count;
+
+ void UpdateData(cRecording *Recording);
+ cFolderInfoIntern *FindSubFolder(const char *Name) const;
+
+public:
+ cFolderInfoIntern(cFolderInfoIntern *Parent, const char *Name);
+ virtual ~cFolderInfoIntern(void);
+
+ // split Name and find folder-info in tree
+ // if "Add", missing folders are created
+ cFolderInfoIntern *Find(const char *Name, bool Add);
+
+ void Add(cRecording *Recording);
+
+ cRecordingsFolderInfo::cFolderInfo *GetInfo(void) const;
+
+ cString FullName(void) const;
+ cString ToText(void) const;
+ cString DebugOutput(void) const;
+};
+
+
+cRecordingsFolderInfo::cFolderInfo::cFolderInfo(const char *Name, const char *FullName, time_t Latest, int Count)
+{
+ this->Name = Name;
+ this->FullName = FullName;
+ this->Latest = Latest;
+ this->Count = Count;
+}
+
+
+cRecordingsFolderInfo::cRecordingsFolderInfo(cRecordings &Recordings)
+:_recordings(Recordings)
+,_root(NULL)
+{
+ Rebuild();
+}
+
+cRecordingsFolderInfo::~cRecordingsFolderInfo(void)
+{
+ delete _root;
+ _root = NULL;
+}
+
+void cRecordingsFolderInfo::Rebuild(void)
+{
+ delete _root;
+ _root = new cFolderInfoIntern(NULL, "");
+
+ cThreadLock RecordingsLock(&_recordings);
+ // re-get state with lock held
+ _recordings.StateChanged(_recState);
+ cFolderInfoIntern *info;
+ for (cRecording *rec = _recordings.First(); rec; rec = _recordings.Next(rec)) {
+ info = _root->Find(*rec->Folder(), true);
+ info->Add(rec);
+ }
+}
+
+cRecordingsFolderInfo::cFolderInfo *cRecordingsFolderInfo::Get(const char *Folder)
+{
+ cMutexLock lock(&_rootLock);
+
+ if (_recordings.StateChanged(_recState) || (_root == NULL))
+ Rebuild();
+
+ cFolderInfoIntern *info = _root->Find(Folder, false);
+ if (info == NULL)
+ return NULL;
+
+ return info->GetInfo();
+}
+
+cString cRecordingsFolderInfo::DebugOutput(void) const
+{
+ cMutexLock lock(&_rootLock);
+
+ return _root->DebugOutput();
+}
+
+
+cRecordingsFolderInfo::cFolderInfoIntern::cFolderInfoIntern(cFolderInfoIntern *Parent, const char *Name)
+:_parent(Parent)
+,_name(Name)
+,_latest(0)
+,_count(0)
+{
+ _subFolders = new cList<cFolderInfoIntern>();
+}
+
+cRecordingsFolderInfo::cFolderInfoIntern::~cFolderInfoIntern(void)
+{
+ delete _subFolders;
+ _subFolders = NULL;
+}
+
+cRecordingsFolderInfo::cFolderInfoIntern *cRecordingsFolderInfo::cFolderInfoIntern::Find(const char *Name, bool Add)
+{
+ cFolderInfoIntern *info = NULL;
+ if (Add)
+ info = this;
+
+ if (Name && *Name) {
+ static char delim[2] = { FOLDERDELIMCHAR, 0 };
+ char *strtok_next;
+ cFolderInfoIntern *next;
+ char *folder = strdup(Name);
+ info = this;
+ for (char *t = strtok_r(folder, delim, &strtok_next); t; t = strtok_r(NULL, delim, &strtok_next)) {
+ next = info->FindSubFolder(t);
+ if (next == NULL) {
+ if (!Add) {
+ info = NULL;
+ break;
+ }
+
+ next = new cFolderInfoIntern(info, t);
+ info->_subFolders->Add(next);
+ }
+ info = next;
+ }
+ free(folder);
+ }
+
+ return info;
+}
+
+void cRecordingsFolderInfo::cFolderInfoIntern::UpdateData(cRecording *Recording)
+{
+ // count every recording
+ _count++;
+
+ // update date if newer
+ time_t recdate = Recording->Start();
+ if (_latest < recdate)
+ _latest = recdate;
+}
+
+cRecordingsFolderInfo::cFolderInfoIntern *cRecordingsFolderInfo::cFolderInfoIntern::FindSubFolder(const char *Name) const
+{
+ for (cRecordingsFolderInfo::cFolderInfoIntern *info = _subFolders->First(); info; info = _subFolders->Next(info)) {
+ if (strcmp(info->_name, Name) == 0)
+ return info;
+ }
+ return NULL;
+}
+
+void cRecordingsFolderInfo::cFolderInfoIntern::Add(cRecording *Recording)
+{
+ if (Recording == NULL)
+ return;
+
+ // update this and all parent folders
+ for (cFolderInfoIntern *p = this; p; p = p->_parent)
+ p->UpdateData(Recording);
+}
+
+cRecordingsFolderInfo::cFolderInfo *cRecordingsFolderInfo::cFolderInfoIntern::GetInfo(void) const
+{
+ return new cRecordingsFolderInfo::cFolderInfo(*_name, *FullName(), _latest, _count);
+}
+
+cString cRecordingsFolderInfo::cFolderInfoIntern::FullName(void) const
+{
+ static char delim[2] = { FOLDERDELIMCHAR, 0 };
+
+ cString name = _name;
+ for (cFolderInfoIntern *p = _parent; p; p = p->_parent) {
+ // don't add FOLDERDELIMCHAR at start of FullName
+ if (p->_parent == NULL)
+ break;
+ name = cString::sprintf("%s%s%s", *p->_name, delim, *name);
+ }
+ return name;
+}
+
+cString cRecordingsFolderInfo::cFolderInfoIntern::ToText(void) const
+{
+ return cString::sprintf("%s (%d recordings, latest: %s)\n", *FullName(), _count, *ShortDateString(_latest));
+}
+
+cString cRecordingsFolderInfo::cFolderInfoIntern::DebugOutput(void) const
+{
+ cString output = ToText();
+ for (cFolderInfoIntern *i = _subFolders->First(); i; i = _subFolders->Next(i))
+ output = cString::sprintf("%s%s", *output, *i->DebugOutput());
+ return output;
+} \ No newline at end of file
diff --git a/libcore/recfolderinfo.h b/libcore/recfolderinfo.h
new file mode 100644
index 0000000..65d0c70
--- /dev/null
+++ b/libcore/recfolderinfo.h
@@ -0,0 +1,42 @@
+#ifndef __RECFOLDERINFO_H
+#define __RECFOLDERINFO_H
+
+#include <vdr/recording.h>
+
+
+class cRecordingsFolderInfo {
+public:
+ class cFolderInfoIntern;
+
+private:
+ cRecordings &_recordings;
+ int _recState;
+ cFolderInfoIntern *_root;
+ mutable cMutex _rootLock;
+
+ void Rebuild(void);
+
+public:
+ class cFolderInfo {
+ public:
+ cString Name;
+ cString FullName;
+ time_t Latest;
+ int Count;
+
+ cFolderInfo(const char *Name, const char *FullName, time_t Latest, int Count);
+ };
+
+ cRecordingsFolderInfo(cRecordings &Recordings);
+ ~cRecordingsFolderInfo(void);
+
+ // caller must delete the cInfo object!
+ // returns NULL if folder doesn't exists
+ // will rebuild tree if recordings' state has changed
+ // is thread-safe
+ cFolderInfo *Get(const char *Folder);
+
+ cString DebugOutput(void) const;
+};
+
+#endif // __RECFOLDERINFO_H \ No newline at end of file
diff --git a/views/displaymenuitemcurrentview.c b/views/displaymenuitemcurrentview.c
index 7ef9cc0..7304aee 100644
--- a/views/displaymenuitemcurrentview.c
+++ b/views/displaymenuitemcurrentview.c
@@ -1,5 +1,6 @@
#include "../services/scraper2vdr.h"
#include "../libcore/helpers.h"
+#include "../libcore/recfolderinfo.h"
#include "displaymenuitemcurrentview.h"
@@ -508,12 +509,20 @@ void cDisplayMenuItemCurrentRecordingView::Render(void) {
string name = recording->Name() ? recording->Name() : "";
string buffer = "";
+ stringstream folderName;
try {
vector<string> tokens;
istringstream f(name.c_str());
string s;
+ int i=0;
while (getline(f, s, FOLDERDELIMCHAR)) {
tokens.push_back(s);
+ if (isFolder && i <= level) {
+ if (i > 0)
+ folderName << FOLDERDELIMCHAR;
+ folderName << s;
+ i++;
+ }
}
buffer = tokens.at(level);
if (!isFolder && recording->IsEdited()) {
@@ -539,12 +548,23 @@ void cDisplayMenuItemCurrentRecordingView::Render(void) {
const cEvent *event = info->GetEvent();
if (!event) return;
- string recDate = *(event->GetDateString());
- string recTime = *(event->GetTimeString());
- if (recDate.find("1970") != string::npos) {
- time_t start = recording->Start();
- recDate = *DateString(start);
- recTime = *TimeString(start);
+ string recDate = "";
+ string recTime = "";
+
+ if (isFolder) {
+ cRecordingsFolderInfo::cFolderInfo *folderInfo = recFolderInfo.Get(folderName.str().c_str());
+ if (folderInfo) {
+ recDate = *DateString(folderInfo->Latest);
+ recTime = *TimeString(folderInfo->Latest);
+ }
+ } else {
+ recDate = *(event->GetDateString());
+ recTime = *(event->GetTimeString());
+ if (recDate.find("1970") != string::npos) {
+ time_t start = recording->Start();
+ recDate = *DateString(start);
+ recTime = *TimeString(start);
+ }
}
time_t startTime = event->StartTime();
diff --git a/views/displaymenuitemview.c b/views/displaymenuitemview.c
index 64e8eab..2309d0a 100644
--- a/views/displaymenuitemview.c
+++ b/views/displaymenuitemview.c
@@ -2,6 +2,7 @@
#include "../services/scraper2vdr.h"
#include "../config.h"
#include "../libcore/helpers.h"
+#include "../libcore/recfolderinfo.h"
#include <sstream>
#include <algorithm>
@@ -611,12 +612,20 @@ void cDisplayMenuItemRecordingView::SetTokens(void) {
string name = recording->Name() ? recording->Name() : "";
string buffer = "";
+ stringstream folderName;
try {
vector<string> tokens;
istringstream f(name.c_str());
string s;
+ int i=0;
while (getline(f, s, FOLDERDELIMCHAR)) {
tokens.push_back(s);
+ if (isFolder && i <= level) {
+ if (i > 0)
+ folderName << FOLDERDELIMCHAR;
+ folderName << s;
+ i++;
+ }
}
buffer = tokens.at(level);
if (!isFolder && recording->IsEdited()) {
@@ -625,6 +634,7 @@ void cDisplayMenuItemRecordingView::SetTokens(void) {
} catch (...) {
buffer = name.c_str();
}
+
stringTokens.insert(pair<string,string>("name", buffer.c_str()));
intTokens.insert(pair<string,int>("new", recording->IsNew()));
intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs));
@@ -637,12 +647,24 @@ void cDisplayMenuItemRecordingView::SetTokens(void) {
event = info->GetEvent();
if (!event) return;
- string recDate = *(event->GetDateString());
- string recTime = *(event->GetTimeString());
- if (recDate.find("1970") != string::npos) {
- time_t start = recording->Start();
- recDate = *DateString(start);
- recTime = *TimeString(start);
+
+ string recDate = "";
+ string recTime = "";
+
+ if (isFolder) {
+ cRecordingsFolderInfo::cFolderInfo *folderInfo = recFolderInfo.Get(folderName.str().c_str());
+ if (folderInfo) {
+ recDate = *DateString(folderInfo->Latest);
+ recTime = *TimeString(folderInfo->Latest);
+ }
+ } else {
+ recDate = *(event->GetDateString());
+ recTime = *(event->GetTimeString());
+ if (recDate.find("1970") != string::npos) {
+ time_t start = recording->Start();
+ recDate = *DateString(start);
+ recTime = *TimeString(start);
+ }
}
time_t startTime = event->StartTime();