diff options
author | louis <louis.braun@gmx.de> | 2014-10-18 16:50:33 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2014-10-18 16:50:33 +0200 |
commit | 3ef0db807d386553f1842ca0b8b0e931498237e1 (patch) | |
tree | 30f332068706af8f57715925c826fc39c92011a1 | |
parent | 762115bf818fb11b5f03525d115adad1f40c480d (diff) | |
download | vdr-plugin-skindesigner-3ef0db807d386553f1842ca0b8b0e931498237e1.tar.gz vdr-plugin-skindesigner-3ef0db807d386553f1842ca0b8b0e931498237e1.tar.bz2 |
added date of newest recording in a folder
-rw-r--r-- | HISTORY | 1 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | config.h | 3 | ||||
-rw-r--r-- | libcore/recfolderinfo.c | 201 | ||||
-rw-r--r-- | libcore/recfolderinfo.h | 42 | ||||
-rw-r--r-- | views/displaymenuitemcurrentview.c | 32 | ||||
-rw-r--r-- | views/displaymenuitemview.c | 34 |
7 files changed, 302 insertions, 12 deletions
@@ -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 @@ -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 \ @@ -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();
|