diff options
author | Dave <vdr@pickles.me.uk> | 2012-07-19 10:23:27 +0100 |
---|---|---|
committer | Dave <vdr@pickles.me.uk> | 2012-07-19 10:23:27 +0100 |
commit | 4962076536f4b2509c21ce9561c2ddcd81a7b4f0 (patch) | |
tree | 08650c3a2b8e058830999d25ab4b5395099e59fd | |
parent | 6e11578e4e317b41497b89085efec58e9b8317f0 (diff) | |
download | vdrtva-0.3.0.tar.gz vdrtva-0.3.0.tar.bz2 |
Provide OSD to manage Series Links.v0.3.0
-rw-r--r-- | HISTORY | 9 | ||||
-rw-r--r-- | README | 20 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | vdr-1.7.29-rsvps.patch (renamed from vdr-1.7.28-rsvps.patch) | 30 | ||||
-rw-r--r-- | vdrtva.c | 225 | ||||
-rw-r--r-- | vdrtva.h | 52 |
6 files changed, 260 insertions, 78 deletions
@@ -71,3 +71,12 @@ VDR Plugin 'vdrtva' Revision History - Check for changed events now works without VPS. - Start CRID data collection at VDR startup. - Inhibit some functions if initial CRID capture still in progress. + +2012-07-19: Version 0.3.0 +- Manage series links via OSD. +- Delay CRID collection a few seconds to allow other plugins to start. +- Don't use "housekeeping" hook to trigger time-sensitive tasks. +- Deleting a series link now deletes any timers for the series. +- Remove leading 'crid://' from Default Authority if found (corrupts links file). +- Use builtin VDR function to sort timers, if available. +- Update VPS patch for VDR 1.7.29. @@ -102,6 +102,8 @@ LSTL Print the series links list LSTS Print the 'suggested' events list +LSTT Print the list of timers with suggestions for each event + LSTY Print the CRIDs for each event LSTZ Print the Default Authority data for each channel @@ -112,15 +114,27 @@ STRT UPDT Trigger an update of the series links. +OSD + +The plugin adds an entry to the VDR Main Menu called "Series Links". This shows +the title of the first programme in the series and the date (DD.MM) of the most +recent timer - if the series is still running this date will usually be in the +future. From this menu you can view further information on a selected series, or +delete a series together with any remaining timers. + +The configuration settings described above can also be set using the "Setup" +menu in the OSD. + + Files The plugin stores details of series links in the file links.data which is in the -VIDEODIR/plugins directory. Entries in this file have the format: +VIDEODIR/plugins/vdrtva directory. Entries in this file have the format: <scrid>,<modtime>;<icrids>;<path>;<title> scrid The series CRID. -modtime The start time of the last event in this series. +modtime The start time of the latest event in this series. icrids The CRIDS of the events in the series, separated by colons. path The subdirectory to store recordings in this series, taken from the first timer, or the string (NULL) if no subdirectory was given. @@ -142,7 +156,7 @@ Points to remember: - A series link is created for every timer whether you want one or not. - This plugin has not been tested with multiple tuner cards or with mixed DVB-T - and DVB-S setups. + and DVB-S setups. It will try to collect CRID data from the Primary DVB device. - The 'suggested' events list may have CRIDs which do not appear in the events list. @@ -12,8 +12,6 @@ Delete a series link if the only timer is manually deleted. Display suggestions for timers which don't have series CRIDs. -OSD for managing series links (work in progress). - Option to select which device to use for CRID collection. Remove reliance on VDR "Housekeeping" callback - causes problems when VDR is busy. diff --git a/vdr-1.7.28-rsvps.patch b/vdr-1.7.29-rsvps.patch index 5964764..0a7fa23 100644 --- a/vdr-1.7.28-rsvps.patch +++ b/vdr-1.7.29-rsvps.patch @@ -1,6 +1,6 @@ -diff -u vdr-1.7.28/config.c vdr-1.7/config.c ---- vdr-1.7.28/config.c 2012-05-11 12:06:57.000000000 +0100 -+++ vdr-1.7/config.c 2012-06-08 11:03:58.670418555 +0100 +diff -ur vdrtest/config.c vdr-1.7/config.c +--- vdrtest/config.c 2012-06-17 13:27:07.000000000 +0100 ++++ vdr-1.7/config.c 2012-07-14 15:06:41.138878534 +0100 @@ -415,6 +415,7 @@ UseSubtitle = 1; UseVps = 0; @@ -9,7 +9,7 @@ diff -u vdr-1.7.28/config.c vdr-1.7/config.c RecordingDirs = 1; FoldersInTimerMenu = 1; NumberKeysForChars = 1; -@@ -610,6 +611,7 @@ +@@ -611,6 +612,7 @@ else if (!strcasecmp(Name, "UseSubtitle")) UseSubtitle = atoi(Value); else if (!strcasecmp(Name, "UseVps")) UseVps = atoi(Value); else if (!strcasecmp(Name, "VpsMargin")) VpsMargin = atoi(Value); @@ -17,7 +17,7 @@ diff -u vdr-1.7.28/config.c vdr-1.7/config.c else if (!strcasecmp(Name, "RecordingDirs")) RecordingDirs = atoi(Value); else if (!strcasecmp(Name, "FoldersInTimerMenu")) FoldersInTimerMenu = atoi(Value); else if (!strcasecmp(Name, "NumberKeysForChars")) NumberKeysForChars = atoi(Value); -@@ -708,6 +710,7 @@ +@@ -710,6 +712,7 @@ Store("UseSubtitle", UseSubtitle); Store("UseVps", UseVps); Store("VpsMargin", VpsMargin); @@ -25,9 +25,9 @@ diff -u vdr-1.7.28/config.c vdr-1.7/config.c Store("RecordingDirs", RecordingDirs); Store("FoldersInTimerMenu", FoldersInTimerMenu); Store("NumberKeysForChars", NumberKeysForChars); -diff -u vdr-1.7.28/config.h vdr-1.7/config.h ---- vdr-1.7.28/config.h 2012-04-15 11:45:32.000000000 +0100 -+++ vdr-1.7/config.h 2012-06-08 11:03:58.672418431 +0100 +diff -ur vdrtest/config.h vdr-1.7/config.h +--- vdrtest/config.h 2012-06-17 12:14:50.000000000 +0100 ++++ vdr-1.7/config.h 2012-07-14 15:06:41.138878534 +0100 @@ -285,6 +285,7 @@ int UseSubtitle; int UseVps; @@ -36,10 +36,10 @@ diff -u vdr-1.7.28/config.h vdr-1.7/config.h int RecordingDirs; int FoldersInTimerMenu; int NumberKeysForChars; -diff -u vdr-1.7.28/menu.c vdr-1.7/menu.c ---- vdr-1.7.28/menu.c 2012-05-12 14:08:23.000000000 +0100 -+++ vdr-1.7/menu.c 2012-06-08 11:03:58.675418246 +0100 -@@ -3076,6 +3076,7 @@ +diff -ur vdrtest/menu.c vdr-1.7/menu.c +--- vdrtest/menu.c 2012-06-17 12:12:25.000000000 +0100 ++++ vdr-1.7/menu.c 2012-07-14 15:06:41.143878229 +0100 +@@ -3107,6 +3107,7 @@ Add(new cMenuEditBoolItem(tr("Setup.Recording$Use episode name"), &data.UseSubtitle)); Add(new cMenuEditBoolItem(tr("Setup.Recording$Use VPS"), &data.UseVps)); Add(new cMenuEditIntItem( tr("Setup.Recording$VPS margin (s)"), &data.VpsMargin, 0)); @@ -47,9 +47,9 @@ diff -u vdr-1.7.28/menu.c vdr-1.7/menu.c Add(new cMenuEditBoolItem(tr("Setup.Recording$Mark instant recording"), &data.MarkInstantRecord)); Add(new cMenuEditStrItem( tr("Setup.Recording$Name instant recording"), data.NameInstantRecord, sizeof(data.NameInstantRecord))); Add(new cMenuEditIntItem( tr("Setup.Recording$Instant rec. time (min)"), &data.InstantRecordTime, 1, MAXINSTANTRECTIME)); -diff -u vdr-1.7.28/timers.c vdr-1.7/timers.c ---- vdr-1.7.28/timers.c 2012-04-25 10:02:03.000000000 +0100 -+++ vdr-1.7/timers.c 2012-06-08 11:03:58.676418184 +0100 +diff -ur vdrtest/timers.c vdr-1.7/timers.c +--- vdrtest/timers.c 2012-06-09 15:37:24.000000000 +0100 ++++ vdr-1.7/timers.c 2012-07-14 15:06:41.144878168 +0100 @@ -431,7 +431,7 @@ deferred = 0; @@ -24,9 +24,9 @@ cLinks Links; cTvaLog tvalog; char *configDir; -static const char *VERSION = "0.2.2"; +static const char *VERSION = "0.3.0"; static const char *DESCRIPTION = "Series Record plugin"; -//static const char *MAINMENUENTRY = "Series Links"; +static const char *MAINMENUENTRY = "Series Links"; int collectionperiod; // Time to collect all CRID data (default 10 minutes) int lifetime; // Lifetime of series link recordings (default 99) @@ -36,7 +36,6 @@ int updatetime; // Time to carry out the series link update HHMM (default 03:0 bool captureComplete; // Flag set if initial CRID capture has completed. time_t startTime; // Time the plugin was initialised. - class cPluginvdrTva : public cPlugin { private: // Add any member variables or functions you may need here. @@ -76,7 +75,7 @@ public: virtual void MainThreadHook(void); virtual cString Active(void); virtual time_t WakeupTime(void); -// virtual const char *MainMenuEntry(void) { return tr(MAINMENUENTRY); } + virtual const char *MainMenuEntry(void) { return tr(MAINMENUENTRY); } virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); @@ -296,7 +295,7 @@ time_t cPluginvdrTva::WakeupTime(void) cOsdObject *cPluginvdrTva::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. - return NULL; + return new cMenuLinks; } cMenuSetupPage *cPluginvdrTva::SetupMenu(void) @@ -511,12 +510,14 @@ void cPluginvdrTva::Report() { if ((Timers.Count() == 0) || (!captureComplete)) return; REPORT(" \nTimers and Suggestions\n----------------------\n "); - cTvaTimers tvatimers; - for (cTvaTimerItem *ti = tvatimers.First(); ti; ti = tvatimers.Next(ti)) { - const cEvent *event = ti->Timer()->Event(); - if (event && ti->Timer()->HasFlags(tfActive)) { - REPORT("'%s' (%s %s)", event->Title(), ti->Timer()->Channel()->Name(), *DayDateTime(event->StartTime())); - FindSuggestions(event); + cSortedTimers SortedTimers; + for (int i = 0; i < SortedTimers.Size(); i++) { + if (const cTimer *ti = SortedTimers[i]) { + const cEvent *event = ti->Event(); + if (event && ti->HasFlags(tfActive)) { + REPORT("'%s' (%s %s)", event->Title(), ti->Channel()->Name(), *DayDateTime(event->StartTime())); + FindSuggestions(event); + } } } } @@ -1010,37 +1011,6 @@ char mailcmd[256]; /* - cTvaTimerItem - the things we need to do just to list the timers in order... -*/ - - -cTvaTimerItem::cTvaTimerItem(cTimer *Timer) -{ - timer = Timer; -} - -int cTvaTimerItem::Compare(const cListObject &ListObject) const -{ - return timer->Compare(*((cTvaTimerItem *)&ListObject)->timer); -} - - -/* - cTvaTimers -*/ - - -cTvaTimers::cTvaTimers(void) -{ - for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) { -// timer->SetEventFromSchedule(); // make sure the event is current - Add(new cTvaTimerItem(timer)); - } - Sort(); -} - - -/* cTvaFilter - capture the CRID data from EIT. */ @@ -1550,4 +1520,175 @@ void cLinks::SetUpdated(void) } + +/* + cMenuLinkItem - Series Link OSD menu item +*/ + +cMenuLinkItem::cMenuLinkItem(cLinkItem *LinkItem) +{ + linkitem = LinkItem; + Set(); +} + + +void cMenuLinkItem::Set(void) +{ + cString buffer; + char tim[32]; + struct tm tm_r; + time_t t = linkitem->ModTime(); + tm *tm = localtime_r(&t, &tm_r); + strftime(tim, sizeof(tim), "%d.%m", tm); + if (linkitem->Title()) { + buffer = cString::sprintf("%s\t%s", tim, linkitem->Title()); + } + else { + buffer = cString::sprintf("%s\t(No Title)", tim); + } + SetText(buffer); +} + +int cMenuLinkItem::Compare(const cListObject &ListObject) const +{ + cMenuLinkItem *p = (cMenuLinkItem *)&ListObject; + return linkitem->ModTime() - p->linkitem->ModTime(); +} + +// How many active timers are there for this series? + +int cMenuLinkItem::TimerCount(void) { + int count = 0; + if ((Timers.Count() == 0) || (!captureComplete)) return 99; + for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) { + const cEvent *event = ti->Event(); + if (event && ti->HasFlags(tfActive) && (ti->WeekDays() == 0)) { + cChannel *channel = Channels.GetByChannelID(event->ChannelID()); + cChanDA *chanda = ChanDAs.GetByChannelID(channel->Number()); + cEventCRID *eventcrid = EventCRIDs.GetByID(channel->Number(), event->EventID()); + if (eventcrid && chanda) { + cString scrid = cString::sprintf("%s%s", chanda->DA(),eventcrid->sCRID()); + if (!strcmp(scrid, sCRID())) count++; + } + } + } + return count; +} + + +/* + cMenuLinks - Series Link OSD menu +*/ + +cMenuLinks::cMenuLinks(void):cOsdMenu(tr("Series Links"), 6) +{ + Clear(); + for (cLinkItem *LinkItem = Links.First(); LinkItem; LinkItem = Links.Next(LinkItem)) { + cMenuLinkItem *item = new cMenuLinkItem(LinkItem); + Add(item); + } + Sort(); + SetHelp(tr("Delete"), tr("Info"), tr(""), tr("")); + Display(); +} + +void cMenuLinks::Propagate(void) +{ + for (cMenuLinkItem *ci = (cMenuLinkItem *)First(); ci; ci = (cMenuLinkItem *)ci->Next()) + ci->Set(); + Display(); +} + +eOSState cMenuLinks::ProcessKey(eKeys Key) +{ + eOSState state = cOsdMenu::ProcessKey(Key); + + if (state == osUnknown) { + switch (Key) { + case kRed: return Delete(); + case kGreen: return Info(); + case kYellow: + case kBlue: + case kOk: + default: state = osContinue; + } + } + return state; +} + +eOSState cMenuLinks::Delete(void) +{ + if (HasSubMenu() || Count() == 0) return osContinue; + if (!captureComplete) { + Skins.Message(mtError, tr("Data capture still in progress")); + return osContinue; + } + int Index = Current(); + cMenuLinkItem *item = (cMenuLinkItem *)Get(Index); + int timercount = item->TimerCount(); + cString prompt; + if (timercount > 1) { + prompt = cString::sprintf(tr("Delete series link & %d timers?"), timercount); + } + else if (timercount == 1) { + prompt = cString::sprintf(tr("Delete series link & 1 timer?")); + } + else { + prompt = cString::sprintf(tr("Delete series link?")); + } + if (Interface->Confirm(prompt)) { + char *linkCRID = item->sCRID(); + cOsdMenu::Del(Index); + Propagate(); + isyslog("vdrtva: series link %s deleted by OSD", linkCRID); + Links.DeleteItem(linkCRID); + } + return osContinue; +} + +eOSState cMenuLinks::Info(void) +{ + if (HasSubMenu() || Count() == 0) return osContinue; + if (!captureComplete) { + Skins.Message(mtError, tr("Data capture still in progress")); + return osContinue; + } + int Index = Current(); + cMenuLinkItem *menuitem = (cMenuLinkItem *)Get(Index); + cLinkItem *linkitem = menuitem->LinkItem(); + char *icrids = linkitem->iCRIDs(); + int eventcount = 1; + while (icrids = strchr(icrids, ':')) { + eventcount++; + icrids++; + } + cString message = cString::sprintf("Series CRID: %s\nTotal Events: %d\nActive Timers: %d", + menuitem->sCRID(), eventcount, menuitem->TimerCount()); + if (linkitem->Title()) { + return AddSubMenu(new cMenuText(linkitem->Title(), message, fontOsd)); + } + else { + return AddSubMenu(new cMenuText(tr("(No Title)"), message, fontOsd)); + } +} + + +#if VDRVERSNUM < 10728 + +// --- cSortedTimers (copied from timers.c v1.7.29) --- + +static int CompareTimers(const void *a, const void *b) +{ + return (*(const cTimer **)a)->Compare(**(const cTimer **)b); +} + +cSortedTimers::cSortedTimers(void) +:cVector<const cTimer *>(Timers.Count()) +{ + for (const cTimer *Timer = Timers.First(); Timer; Timer = Timers.Next(Timer)) + Append(Timer); + Sort(CompareTimers); +} +#endif + VDRPLUGINCREATOR(cPluginvdrTva); // Don't touch this! @@ -1,6 +1,9 @@ #include <vdr/filter.h> #include <vdr/device.h> #include <vdr/status.h> +#include <vdr/interface.h> +#include <vdr/menu.h> + class cTvaFilter : public cFilter { private: @@ -65,22 +68,6 @@ class cTvaLog { }; -class cTvaTimerItem : public cListObject { -private: - cTimer *timer; -public: - cTvaTimerItem(cTimer *Timer); - virtual int Compare(const cListObject &ListObject) const; - cTimer *Timer(void) { return timer; } -}; - - -class cTvaTimers : public cConfig<cTvaTimerItem> { -public: - cTvaTimers(void); -}; - - class cChanDA : public cListObject { private: int cid; @@ -195,3 +182,36 @@ class cLinks : public cRwLock, public cConfig<cLinkItem> { void SetUpdated(void); void DeleteTimersForSCRID(const char *sCRID); }; + + +class cMenuLinks : public cOsdMenu { +private: + void Propagate(void); + eOSState Delete(void); + eOSState Info(void); +public: + cMenuLinks(void); + virtual eOSState ProcessKey(eKeys Key); +}; + +class cMenuLinkItem : public cOsdItem { +private: + cLinkItem *linkitem; +public: + cMenuLinkItem(cLinkItem *LinkItem); + char * sCRID(void) { return linkitem->sCRID(); } + cLinkItem * LinkItem(void) { return linkitem; } + int TimerCount(void); + virtual void Set(void); + virtual int Compare(const cListObject &ListObject) const; +}; + +#if VDRVERSNUM < 10728 + +// Copied from timers.c v1.7.29 + +class cSortedTimers : public cVector<const cTimer *> { +public: + cSortedTimers(void); + }; +#endif |