added date of newest recording in a folder

This commit is contained in:
louis
2014-10-18 16:50:33 +02:00
parent 762115bf81
commit 3ef0db807d
7 changed files with 302 additions and 12 deletions

201
libcore/recfolderinfo.c Normal file
View 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
View 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