#! /bin/sh /usr/share/dpatch/dpatch-run ## opt-41_timer-info.dpatch by Andreas Brugger , Thomas Günther ## http://toms-cafe.de/vdr/download/vdr-timer-info-0.2-1.3.38+.diff ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Shows info, if it is possible to record an event in the timer-info of ## DP: vdr - see README.timer-info for details. @DPATCH@ diff -Naur vdr-1.3.41/README.timer-info vdr-1.3.41-timer-info-0.2/README.timer-info --- vdr-1.3.41/README.timer-info 1970-01-01 01:00:00.000000000 +0100 +++ vdr-1.3.41-timer-info-0.2/README.timer-info 2006-01-30 00:28:11.000000000 +0100 @@ -0,0 +1,39 @@ ++------------------------------------------------------------------------------+ +| Info about the timer-info-patch by Brougs78 | +| brougs78@gmx.net / home.pages.at/brougs78 | ++------------------------------------------------------------------------------+ + + +README timer-info: +------------------ + +Features: + - Shows info, if it is possible to record an event in the timer-info of vdr. + For calculations the free space incl. the deleted recordings is used, + considering an average consumtion of 25.75 MB/min (also used by vdr itself). + The first column int the timer-list shows: + ( + ) recording will be most probably possible (enough space) + (+/-) recording may be possible + ( - ) recording will most probably fail (to less space) + The calculations also consider repeating timers. + - It is possible to deactivate the patch in the OSD-menu of VDR, if it slows + down the Timer-menu too much. + + +HISTORY timer-info: +------------------- + +25.11.2004: v0.1 + - Initial release + +11.01.2005: v0.1b + - Bugfixes for vdr-1.3.18 + - In the menu the free recording-time no longer includes the space of the + deleted recordings, because this slowed the vdr down to much. + +08.07.2005: v0.1c + - Made the patch configurable + +29.01.2006: v0.2 - Thomas Günther + - Rewritten great parts for vdr-1.3.38+ + http://toms-cafe.de/vdr/download/vdr-timer-info-0.2-1.3.38+.diff diff -Naur vdr-1.3.41/config.c vdr-1.3.41-timer-info-0.2/config.c --- vdr-1.3.41/config.c 2006-01-13 16:19:37.000000000 +0100 +++ vdr-1.3.41-timer-info-0.2/config.c 2006-01-29 20:42:56.000000000 +0100 @@ -241,6 +241,7 @@ SVDRPTimeout = 300; ZapTimeout = 3; SortTimers = 1; + ShowTimerInfo = 1; PrimaryLimit = 0; DefaultPriority = 50; DefaultLifetime = 99; @@ -401,6 +402,7 @@ else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value); else if (!strcasecmp(Name, "ZapTimeout")) ZapTimeout = atoi(Value); else if (!strcasecmp(Name, "SortTimers")) SortTimers = atoi(Value); + else if (!strcasecmp(Name, "ShowTimerInfo")) ShowTimerInfo = atoi(Value); else if (!strcasecmp(Name, "PrimaryLimit")) PrimaryLimit = atoi(Value); else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value); else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value); @@ -468,6 +470,7 @@ Store("SVDRPTimeout", SVDRPTimeout); Store("ZapTimeout", ZapTimeout); Store("SortTimers", SortTimers); + Store("ShowTimerInfo", ShowTimerInfo); Store("PrimaryLimit", PrimaryLimit); Store("DefaultPriority", DefaultPriority); Store("DefaultLifetime", DefaultLifetime); diff -Naur vdr-1.3.41/config.h vdr-1.3.41-timer-info-0.2/config.h --- vdr-1.3.41/config.h 2006-01-27 14:27:41.000000000 +0100 +++ vdr-1.3.41-timer-info-0.2/config.h 2006-01-29 20:42:56.000000000 +0100 @@ -213,6 +213,7 @@ int SVDRPTimeout; int ZapTimeout; int SortTimers; + int ShowTimerInfo; int PrimaryLimit; int DefaultPriority, DefaultLifetime; int PausePriority, PauseLifetime; diff -Naur vdr-1.3.41/i18n.c vdr-1.3.41-timer-info-0.2/i18n.c --- vdr-1.3.41/i18n.c 2006-01-28 11:38:33.000000000 +0100 +++ vdr-1.3.41-timer-info-0.2/i18n.c 2006-01-29 20:42:56.000000000 +0100 @@ -3178,6 +3178,27 @@ "Taimeri sorteerimine", "Sorter timere", }, + { "Setup.OSD$Show timer-info", + "Timerinfo anzeigen", + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + "",// TODO + }, { "Setup.OSD$Recording directories", "Aufnahmeverzeichnisse", "Direktoriji za posnetke", diff -Naur vdr-1.3.41/menu.c vdr-1.3.41-timer-info-0.2/menu.c --- vdr-1.3.41/menu.c 2006-01-29 15:04:37.000000000 +0100 +++ vdr-1.3.41-timer-info-0.2/menu.c 2006-01-30 18:15:00.000000000 +0100 @@ -41,6 +41,8 @@ #define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 1) +#define MB_PER_MINUTE 25.75 // this is just an estimate! + // --- cMenuEditCaItem ------------------------------------------------------- class cMenuEditCaItem : public cMenuEditIntItem { @@ -716,8 +718,10 @@ class cMenuTimerItem : public cOsdItem { private: cTimer *timer; + char diskStatus; public: cMenuTimerItem(cTimer *Timer); + void SetDiskStatus(char DiskStatus); virtual int Compare(const cListObject &ListObject) const; virtual void Set(void); cTimer *Timer(void) { return timer; } @@ -726,6 +730,7 @@ cMenuTimerItem::cMenuTimerItem(cTimer *Timer) { timer = Timer; + diskStatus = ' '; Set(); } @@ -763,9 +768,66 @@ timer->Stop() / 100, timer->Stop() % 100, timer->File()); + if (Setup.ShowTimerInfo) { + char *buffer2 = buffer; + buffer = NULL; + asprintf(&buffer, "%c%s", diskStatus, buffer2); + free(buffer2); + } SetText(buffer, false); } +void cMenuTimerItem::SetDiskStatus(char DiskStatus) +{ + diskStatus = DiskStatus; + Set(); +} + +// --- cTimerEntry ----------------------------------------------------------- + +class cTimerEntry : public cListObject { +private: + cMenuTimerItem *item; + const cTimer *timer; + time_t start; +public: + cTimerEntry(cMenuTimerItem *item) : item(item), timer(item->Timer()), start(timer->StartTime()) {} + cTimerEntry(const cTimer *timer, time_t start) : item(NULL), timer(timer), start(start) {} + virtual int Compare(const cListObject &ListObject) const; + bool active(void) const { return timer->HasFlags(tfActive); } + time_t startTime(void) const { return start; } + int priority(void) const { return timer->Priority(); } + int duration(void) const; + bool repTimer(void) const { return !timer->IsSingleEvent(); } + bool isDummy(void) const { return item == NULL; } + const cTimer *Timer(void) const { return timer; } + void SetDiskStatus(char DiskStatus); + }; + +int cTimerEntry::Compare(const cListObject &ListObject) const +{ + cTimerEntry *entry = (cTimerEntry *)&ListObject; + int r = startTime() - entry->startTime(); + if (r == 0) + r = entry->priority() - priority(); + return r; +} + +int cTimerEntry::duration(void) const +{ + int dur = (timer->Stop() / 100 * 60 + timer->Stop() % 100) - + (timer->Start() / 100 * 60 + timer->Start() % 100); + if (dur < 0) + dur += 24 * 60; + return dur; +} + +void cTimerEntry::SetDiskStatus(char DiskStatus) +{ + if (item) + item->SetDiskStatus(DiskStatus); +} + // --- cMenuTimers ----------------------------------------------------------- class cMenuTimers : public cOsdMenu { @@ -777,14 +839,17 @@ virtual void Move(int From, int To); eOSState Summary(void); cTimer *CurrentTimer(void); + void ActualiseDiskStatus(void); + bool actualiseDiskStatus; public: cMenuTimers(void); virtual ~cMenuTimers(); + virtual void Display(void); virtual eOSState ProcessKey(eKeys Key); }; cMenuTimers::cMenuTimers(void) -:cOsdMenu(tr("Timers"), 2, CHNUMWIDTH, 10, 6, 6) +:cOsdMenu(tr("Timers"), Setup.ShowTimerInfo ? 3 : 2, CHNUMWIDTH, 10, 6, 6) { for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) Add(new cMenuTimerItem(timer)); @@ -792,6 +857,7 @@ Sort(); SetHelp(tr("Button$Edit"), tr("Button$New"), tr("Button$Delete"), Setup.SortTimers ? tr("Button$On/Off") : tr("Button$Mark")); Timers.IncBeingEdited(); + actualiseDiskStatus = true; } cMenuTimers::~cMenuTimers() @@ -810,13 +876,12 @@ cTimer *timer = CurrentTimer(); if (timer) { timer->OnOff(); - RefreshCurrent(); - DisplayCurrent(true); if (timer->FirstDay()) isyslog("timer %s first day set to %s", *timer->ToDescr(), *timer->PrintFirstDay()); else isyslog("timer %s %sactivated", *timer->ToDescr(), timer->HasFlags(tfActive) ? "" : "de"); Timers.SetModified(); + Display(); } return osContinue; } @@ -879,6 +944,82 @@ return Edit(); // convenience for people not using the Summary feature ;-) } +void cMenuTimers::ActualiseDiskStatus(void) +{ + if (!actualiseDiskStatus || !Setup.ShowTimerInfo || !Count()) + return; + + // compute free disk space + int freeMB, freeMinutes, runshortMinutes; + VideoDiskSpace(&freeMB); + freeMinutes = int(double(freeMB) * 1.1 / MB_PER_MINUTE); // overestimate by 10 percent + runshortMinutes = freeMinutes / 5; // 20 Percent + + // fill entries list + cTimerEntry *entry; + cList entries; + for (cOsdItem *item = First(); item; item = Next(item)) + entries.Add(new cTimerEntry((cMenuTimerItem *)item)); + + // search first and latest start times + time_t firstStart = 0, latestStart = 0; + for (entry = entries.First(); entry; entry = entries.Next(entry)) { + if (firstStart == 0) + firstStart = entry->startTime(); + else + firstStart = min(entry->startTime(), firstStart); + latestStart = max(entry->startTime(), latestStart); + } + int nDays = (latestStart - firstStart) / SECSINDAY + 1; + + // add entries for repeating timers + for (entry = entries.First(); entry; entry = entries.Next(entry)) { + if (entry->repTimer() && !entry->isDummy()) { + cTimer timerDummy = *(entry->Timer()); + + for (int j = 0; j < nDays; j++) { + timerDummy.Skip(); + timerDummy.Matches(); // Actualise the timer + + if ( *(*timerDummy.PrintDay((timerDummy.Day() ), 0) + j) != '-') { + if (timerDummy.StartTime() > latestStart) + break; + entries.Add(new cTimerEntry(entry->Timer(), timerDummy.StartTime())); + } + } + } + } + + // set the disk-status + entries.Sort(); + for (entry = entries.First(); entry; entry = entries.Next(entry)) { + char status = ' '; + if (entry->active()) { + freeMinutes -= entry->duration(); + status = freeMinutes > runshortMinutes ? '+' : freeMinutes > 0 ? 177 /* +/- */ : '-'; + } + entry->SetDiskStatus(status); +/* + dsyslog("timer-info: %c | %d | %s | %s | %3d | %+5d -> %+5d", + status, + entry->startTime(), + entry->active() ? "aktiv " : "n.akt.", + entry->repTimer() ? entry->isDummy() ? " dummy " : "mehrmalig" : "einmalig ", + entry->duration(), + entry->active() ? freeMinutes + entry->duration() : freeMinutes, + freeMinutes); +*/ + } + + actualiseDiskStatus = false; +} + +void cMenuTimers::Display(void) +{ + ActualiseDiskStatus(); + cOsdMenu::Display(); +} + eOSState cMenuTimers::ProcessKey(eKeys Key) { int TimerNumber = HasSubMenu() ? Count() : -1; @@ -889,18 +1030,24 @@ case kOk: return Summary(); case kRed: return Edit(); case kGreen: return New(); - case kYellow: return Delete(); - case kBlue: if (Setup.SortTimers) + case kYellow: actualiseDiskStatus = true; + return Delete(); + case kBlue: if (Setup.SortTimers) { + actualiseDiskStatus = true; OnOff(); + } else Mark(); break; default: break; } } - if (TimerNumber >= 0 && !HasSubMenu() && Timers.Get(TimerNumber)) { - // a newly created timer was confirmed with Ok - Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true); + if (TimerNumber >= 0 && !HasSubMenu()) { + if (Timers.Get(TimerNumber)) // a newly created timer was confirmed with Ok + Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true); + if (Setup.SortTimers) + Sort(); + actualiseDiskStatus = true; Display(); } return state; @@ -2142,6 +2289,7 @@ Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll wraps"), &data.MenuScrollWrap)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Menu button closes"), &data.MenuButtonCloses)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Sort timers"), &data.SortTimers)); + Add(new cMenuEditBoolItem(tr("Setup.OSD$Show timer-info"), &data.ShowTimerInfo)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Recording directories"), &data.RecordingDirs)); SetCurrent(Get(current)); Display(); @@ -2804,8 +2952,6 @@ Display(); } -#define MB_PER_MINUTE 25.75 // this is just an estimate! - bool cMenuMain::Update(bool Force) { bool result = false;