mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 17:58:31 +02:00
added date of newest recording in a folder
This commit is contained in:
parent
762115bf81
commit
3ef0db807d
1
HISTORY
1
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"
|
- 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 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
|
- 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
|
1
Makefile
1
Makefile
@ -75,6 +75,7 @@ OBJS = $(PLUGIN).o \
|
|||||||
libcore/imagescaler.o \
|
libcore/imagescaler.o \
|
||||||
libcore/helpers.o \
|
libcore/helpers.o \
|
||||||
libcore/imageloader.o \
|
libcore/imageloader.o \
|
||||||
|
libcore/recfolderinfo.o \
|
||||||
libcore/timers.o \
|
libcore/timers.o \
|
||||||
libtemplate/globals.o \
|
libtemplate/globals.o \
|
||||||
libtemplate/parameter.o \
|
libtemplate/parameter.o \
|
||||||
|
3
config.h
3
config.h
@ -9,6 +9,7 @@
|
|||||||
#include <vdr/plugin.h>
|
#include <vdr/plugin.h>
|
||||||
#include "libcore/fontmanager.h"
|
#include "libcore/fontmanager.h"
|
||||||
#include "libcore/imagecache.h"
|
#include "libcore/imagecache.h"
|
||||||
|
#include "libcore/recfolderinfo.h"
|
||||||
|
|
||||||
class cDesignerConfig {
|
class cDesignerConfig {
|
||||||
private:
|
private:
|
||||||
@ -67,12 +68,14 @@ public:
|
|||||||
cFontManager *fontManager = NULL;
|
cFontManager *fontManager = NULL;
|
||||||
cImageCache *imgCache = NULL;
|
cImageCache *imgCache = NULL;
|
||||||
cTheme Theme;
|
cTheme Theme;
|
||||||
|
cRecordingsFolderInfo recFolderInfo(Recordings);
|
||||||
#else
|
#else
|
||||||
extern bool firstDisplay;
|
extern bool firstDisplay;
|
||||||
extern cDesignerConfig config;
|
extern cDesignerConfig config;
|
||||||
extern cFontManager *fontManager;
|
extern cFontManager *fontManager;
|
||||||
extern cImageCache *imgCache;
|
extern cImageCache *imgCache;
|
||||||
extern cTheme Theme;
|
extern cTheme Theme;
|
||||||
|
extern cRecordingsFolderInfo recFolderInfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif //__DESIGNER_CONFIG_H
|
#endif //__DESIGNER_CONFIG_H
|
||||||
|
201
libcore/recfolderinfo.c
Normal file
201
libcore/recfolderinfo.c
Normal file
@ -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;
|
||||||
|
}
|
42
libcore/recfolderinfo.h
Normal file
42
libcore/recfolderinfo.h
Normal file
@ -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
|
@ -1,5 +1,6 @@
|
|||||||
#include "../services/scraper2vdr.h"
|
#include "../services/scraper2vdr.h"
|
||||||
#include "../libcore/helpers.h"
|
#include "../libcore/helpers.h"
|
||||||
|
#include "../libcore/recfolderinfo.h"
|
||||||
#include "displaymenuitemcurrentview.h"
|
#include "displaymenuitemcurrentview.h"
|
||||||
|
|
||||||
|
|
||||||
@ -508,12 +509,20 @@ void cDisplayMenuItemCurrentRecordingView::Render(void) {
|
|||||||
|
|
||||||
string name = recording->Name() ? recording->Name() : "";
|
string name = recording->Name() ? recording->Name() : "";
|
||||||
string buffer = "";
|
string buffer = "";
|
||||||
|
stringstream folderName;
|
||||||
try {
|
try {
|
||||||
vector<string> tokens;
|
vector<string> tokens;
|
||||||
istringstream f(name.c_str());
|
istringstream f(name.c_str());
|
||||||
string s;
|
string s;
|
||||||
|
int i=0;
|
||||||
while (getline(f, s, FOLDERDELIMCHAR)) {
|
while (getline(f, s, FOLDERDELIMCHAR)) {
|
||||||
tokens.push_back(s);
|
tokens.push_back(s);
|
||||||
|
if (isFolder && i <= level) {
|
||||||
|
if (i > 0)
|
||||||
|
folderName << FOLDERDELIMCHAR;
|
||||||
|
folderName << s;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buffer = tokens.at(level);
|
buffer = tokens.at(level);
|
||||||
if (!isFolder && recording->IsEdited()) {
|
if (!isFolder && recording->IsEdited()) {
|
||||||
@ -539,13 +548,24 @@ void cDisplayMenuItemCurrentRecordingView::Render(void) {
|
|||||||
const cEvent *event = info->GetEvent();
|
const cEvent *event = info->GetEvent();
|
||||||
if (!event) return;
|
if (!event) return;
|
||||||
|
|
||||||
string recDate = *(event->GetDateString());
|
string recDate = "";
|
||||||
string recTime = *(event->GetTimeString());
|
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) {
|
if (recDate.find("1970") != string::npos) {
|
||||||
time_t start = recording->Start();
|
time_t start = recording->Start();
|
||||||
recDate = *DateString(start);
|
recDate = *DateString(start);
|
||||||
recTime = *TimeString(start);
|
recTime = *TimeString(start);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
time_t startTime = event->StartTime();
|
time_t startTime = event->StartTime();
|
||||||
struct tm * sStartTime = localtime(&startTime);
|
struct tm * sStartTime = localtime(&startTime);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "../services/scraper2vdr.h"
|
#include "../services/scraper2vdr.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
#include "../libcore/helpers.h"
|
#include "../libcore/helpers.h"
|
||||||
|
#include "../libcore/recfolderinfo.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@ -611,12 +612,20 @@ void cDisplayMenuItemRecordingView::SetTokens(void) {
|
|||||||
|
|
||||||
string name = recording->Name() ? recording->Name() : "";
|
string name = recording->Name() ? recording->Name() : "";
|
||||||
string buffer = "";
|
string buffer = "";
|
||||||
|
stringstream folderName;
|
||||||
try {
|
try {
|
||||||
vector<string> tokens;
|
vector<string> tokens;
|
||||||
istringstream f(name.c_str());
|
istringstream f(name.c_str());
|
||||||
string s;
|
string s;
|
||||||
|
int i=0;
|
||||||
while (getline(f, s, FOLDERDELIMCHAR)) {
|
while (getline(f, s, FOLDERDELIMCHAR)) {
|
||||||
tokens.push_back(s);
|
tokens.push_back(s);
|
||||||
|
if (isFolder && i <= level) {
|
||||||
|
if (i > 0)
|
||||||
|
folderName << FOLDERDELIMCHAR;
|
||||||
|
folderName << s;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
buffer = tokens.at(level);
|
buffer = tokens.at(level);
|
||||||
if (!isFolder && recording->IsEdited()) {
|
if (!isFolder && recording->IsEdited()) {
|
||||||
@ -625,6 +634,7 @@ void cDisplayMenuItemRecordingView::SetTokens(void) {
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
buffer = name.c_str();
|
buffer = name.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
stringTokens.insert(pair<string,string>("name", buffer.c_str()));
|
stringTokens.insert(pair<string,string>("name", buffer.c_str()));
|
||||||
intTokens.insert(pair<string,int>("new", recording->IsNew()));
|
intTokens.insert(pair<string,int>("new", recording->IsNew()));
|
||||||
intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs));
|
intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs));
|
||||||
@ -637,13 +647,25 @@ void cDisplayMenuItemRecordingView::SetTokens(void) {
|
|||||||
event = info->GetEvent();
|
event = info->GetEvent();
|
||||||
if (!event) return;
|
if (!event) return;
|
||||||
|
|
||||||
string recDate = *(event->GetDateString());
|
|
||||||
string recTime = *(event->GetTimeString());
|
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) {
|
if (recDate.find("1970") != string::npos) {
|
||||||
time_t start = recording->Start();
|
time_t start = recording->Start();
|
||||||
recDate = *DateString(start);
|
recDate = *DateString(start);
|
||||||
recTime = *TimeString(start);
|
recTime = *TimeString(start);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
time_t startTime = event->StartTime();
|
time_t startTime = event->StartTime();
|
||||||
struct tm * sStartTime = localtime(&startTime);
|
struct tm * sStartTime = localtime(&startTime);
|
||||||
|
Loading…
Reference in New Issue
Block a user