diff options
-rw-r--r-- | CONTRIBUTORS | 16 | ||||
-rw-r--r-- | HISTORY | 55 | ||||
-rw-r--r-- | MANUAL | 25 | ||||
-rw-r--r-- | channels.conf | 8 | ||||
-rw-r--r-- | config.c | 5 | ||||
-rw-r--r-- | config.h | 7 | ||||
-rw-r--r-- | device.c | 6 | ||||
-rw-r--r-- | epg.c | 20 | ||||
-rw-r--r-- | epg.h | 14 | ||||
-rw-r--r-- | i18n.c | 68 | ||||
-rw-r--r-- | libsi/descriptor.c | 6 | ||||
-rw-r--r-- | libsi/util.h | 4 | ||||
-rw-r--r-- | menu.c | 90 | ||||
-rw-r--r-- | menu.h | 4 | ||||
-rw-r--r-- | osd.c | 20 | ||||
-rw-r--r-- | osd.h | 16 | ||||
-rw-r--r-- | recording.c | 38 | ||||
-rw-r--r-- | recording.h | 6 | ||||
-rw-r--r-- | timers.c | 133 | ||||
-rw-r--r-- | timers.h | 8 | ||||
-rw-r--r-- | vdr.5 | 38 |
21 files changed, 346 insertions, 241 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS index b3dc8e8..4b9f40b 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -73,6 +73,8 @@ Matthias Schniedermeyer <ms@citd.de> is currently recording for suggesting to make the SVDRP command LSTT optionally list the channels of the timers with their unique channel ids instead of their numbers + for suggesting to extend the 'event id' in EPG data to 32 bit, so that external tools + can generate ids that don't collide with those from the DVB data stream Miha Setina <mihasetina@softhome.net> for translating OSD texts to the Slovenian language @@ -961,6 +963,7 @@ Rolf Ahrenberg <rahrenbe@cc.hut.fi> for making the channel number be reset if the number entered through the numeric keys exceeds the maximum channel number for suggesting to also set the language codes when setting the audio track descriptions + for reporting a problem in setting the audio language codes in 'Transfer-Mode' Ralf Klueber <ralf.klueber@vodafone.com> for reporting a bug in cutting a recording if there is only a single editing mark @@ -977,6 +980,7 @@ Peter Bieringer <pb@bieringer.de> for reporting a leftover 'summary.vdr' in vdr.5 for adding more error messages and line numbers when reading EPG data and info.vdr for fixing handling "more than 3 byte" key sequences in cKbdRemote::ReadKeySequence() + for suggesting to ignore lines tagged with '#' in the 'info.vdr' file of a recording Alexander Damhuis <ad@phonedation.de> for reporting problems when deleting a timer that is currently recording @@ -1412,6 +1416,8 @@ Joachim Wilke <vdr@joachim-wilke.de> for reporting missing calls to cStatus::MsgOsdClear() in cSkins::Message() for fixing a NULL pointer access with the cUnbufferedFile when a replay session runs all the way until the end of the recording + for fixing removing the '-' when entering a channel number where there is no other + one that fits the input Sascha Klek <sklek@gmx.de> for reporting a problem with the '0' key in the "Day" item of the "Timers" menu @@ -1742,6 +1748,8 @@ Jaroslaw Swierczynski <swiergot@gmail.com> Alexander Hans <cleditor@arcor.de> for reporting a crash when pressing '0' in the "Schedule" menu on a channel that doesn't have any EPG data + for giving the DrawBitmap() function a new parameter 'Overlay' that allows a bitmap + to be drawn with a transparent background Daniel Karsubka <dkar@gmx.de> for suggesting to write the epg.data file when VDR exits @@ -1755,3 +1763,11 @@ Ronny Kornexl <ronny.kornexl@online.de> Bárta Vladimír <vladimir.barta@k2atmitec.cz> for translating OSD texts to the Czech language + +Christoph Haubrich <christoph1.haubrich@arcor.de> + for making the "Ok" key in the "Jump" mode of the replay progress display confirm + the jump instead of closing the display + +Pekka Mauno <pekka.mauno@iki.fi> + for fixing cSchedule::GetFollowingEvent() in case there is currently no present + event running @@ -4359,3 +4359,58 @@ Video Disk Recorder Revision History Reinhard Nissl). - Added a comment to tChannelID::nid, explaining that is is actually the "original" network id. + +2006-02-26: Version 1.3.44 + +- Fixed setting the audio language codes in 'Transfer-Mode' (reported by Rolf + Ahrenberg). The actual problem was the call to the Transferring() function in + cDevice::AttachPlayer() before assigning the player. +- Fixed removing the '-' when entering a channel number where there is no other + one that fits the input (thanks to Joachim Wilke). +- Fixed the 'libsi' function CharArray::checkSize(), which made a previous workaround + in libsi/descriptor.c obsolete (thanks to Marcel Wiesweg). +- The "Ok" key in the "Jump" mode of the replay progress display now confirms the + jump instead of closing the display (thanks to Christoph Haubrich). +- The 'summary' field of a timer definition has been renamed to 'aux', and is now + only used for external applications to store auxiliary information with a timer, + which has no meaning whatsoever to VDR itself. + The contents of the 'aux' field of a timer is copied into the recording's + 'info.vdr' file, using the tag character '@'. +- The description of a recording is now taken exclusively from its related EPG + data. If an application wants to use a different description it needs to set + it with SVDRP/PUTE and use table ID 0x00, so that it won't be overwritten (as + a side effect, however, this also disables VPS for such an event). +- There is no more "Summary" menu when pressing "Ok" in the "Timers" menu. + The "Ok" key now always opens the "Edit timer" menu. +- The upper 16 bit of a timer's "flags" are no longer treated specially when a timer + is modified in the "Edit timer" menu. If an external application needs to know if + a timer was modified, it has to keep a copy of the timer's data and compare that + to the actual data. +- The new function cRecordingInfo::ChannelID() can be used to retrieve the ID of + the channel a recording was made from. +- The 'info.vdr' file of a recording now also contains the 'E' and 'V' records of + the EPG event used when creating it. +- The option "Setup/OSD/Sort timers" has been removed. Timers are always sorted + by their start time and priority. +- The "Blue" key in the "Timers" menu now displays the EPG info of the event the + selected timer will record (if available). The "On/Off" function has been shifted + to the "Red" button. Editing a timer is done by pressing "Ok". +- When determining which event a timer is going to record, all available events + in the future are now taken into account (no more limit to 4 hours in the + future). This has been done so that the event info is available in the "Timers" + menu when pressing the "Blue" button. In order to avoid unnecessary work, each + timer now has its own timestamp to control whether its schedule has changed + since the last time its event has been set. +- Fixed setting events to timers in case a non-VPS event has expired. +- There is now a log message "timer ... set to event ..." when defining a timer + from the EPG menu. +- Lines tagged with '#' in the 'info.vdr' file of a recording are now silently + ignored when reading that file (suggested by Peter Bieringer). Such lines can + be used by external tools to store arbitrary information. +- The 'event id' in EPG data has been extended to 32 bit, so that external tools + can generate ids that don't collide with those from the DVB data stream + (suggested by Matthias Schniedermeyer). +- The DrawBitmap() function now has a new parameter 'Overlay' that allows a bitmap + to be drawn with a transparent background (thanks to Alexander Hans). +- Fixed cSchedule::GetFollowingEvent() in case there is currently no present event + running (thanks to Pekka Mauno). @@ -20,11 +20,11 @@ Version 1.3 Ok Ch display Select Switch Edit Accept Play Progress disp. Switch & Close Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu off Menu off Back - Menu off VDR menu VDR menu Discard VDR menu Recordings menu Close - Red - Record Edit Edit ABC/abc Play/Commands(2) Jump - + Red - Record Edit On/Off ABC/abc Play/Commands(1) Jump - Green - Audio New New Ins/Ovr Rewind Skip -60s - Yellow - Pause live Delete Delete Delete Delete Skip +60s - - Blue - Stop/Resume Mark On/Off(1) - Info Stop - - 0..9 Ch select - Sort(3) Day(4) Numeric inp. Exec cmd(2) Editing - + Blue - Stop/Resume Mark Info - Info Stop - + 0..9 Ch select - Sort(2) Day(3) Numeric inp. Exec cmd(1) Editing - In a numerical input field (like the response to a CAM enquiry) the keys 0..9 are used to enter the data, and the Left key can be used to delete the last @@ -75,18 +75,15 @@ Version 1.3 Yellow Info Blue Timers menu - (1) The "On/Off" button in the "Timers" menu only works if sorting the timers - has been enabled in the "Setup" menu. Otherwise the Blue button is used - to "mark" a timer for moving. - (2) See "Processing Recordings" below. - (3) In the "Channels" menu the '0' key switches the sort mode through "by number", + (1) See "Processing Recordings" below. + (2) In the "Channels" menu the '0' key switches the sort mode through "by number", "by name" and "by provider". Other numeric input positions the cursor to the channel with the number entered so far. If there is no channel with that number, nothing happens. While entering a channel number, the '0' key will be treated as part of that number, not as a sort mode toggle. If no numeric key has been pressed for more than one second, the number is reset and '0' functions as sort mode toggle again. - (4) In the "Timers" menu, when on the "Day" item, the '0' key toggles between + (3) In the "Timers" menu, when on the "Day" item, the '0' key toggles between a single shot and a repeating timer. If "Day" indicates a repeating timer, the keys '1'...'7' can be used to toggle the individual days ('1' is Monday). @@ -101,12 +98,10 @@ Version 1.3 any changes that might have been made in the current menu. In the "Timers" menu, the current timer can be enabled or disabled with - the "Blue" key (this is only possible if the "Timers" list is sorted, - otherwise the "Blue" key is used to mark a timer in order to move it to - another position in the list). Enabled timers are marked with '>', timers + the "Red" key. Enabled timers are marked with '>', timers that are currently recording are marked with '#'. If a timer has the "First day" set so that it will start recording only on the given date, - it is marked with '!'. The "Blue" key toggles through the "enabled" and + it is marked with '!'. The "Red" key toggles through the "enabled" and "disabled" states, and for repeating timers that are currently recording also a state that ends this recording prematurely and sets the "First day" date so that it will record again the next time the timer hits. @@ -539,10 +534,6 @@ Version 1.3 closing a temporary display, like, for instance, the channel display. - Sort timers = yes Turns sorting the timers in the "Timers" menu on/off. - Timers are sorted by ascending start times, with the - first one being the next timer that will start. - Recording directories = yes Turns displaying the Recordings menu as a hierarchical directory structure on or off. diff --git a/channels.conf b/channels.conf index a5f896e..50266e9 100644 --- a/channels.conf +++ b/channels.conf @@ -48,8 +48,8 @@ PREMIERE START,START;PREMIERE:11797:hC34:S19.2E:27500:255:256=deu:32:1801,1722,1 PREMIERE 1,PREM 1;PREMIERE:11797:hC34:S19.2E:27500:511:512=deu,513=deu;515=deu:32:1801,1722,1702:10:133:2:0 PREMIERE 2,PREM 2;PREMIERE:11797:hC34:S19.2E:27500:1791:1792=deu,1793=deu;1795=deu:32:1801,1722,1702:11:133:2:0 PREMIERE 3,PREM 3;PREMIERE:11797:hC34:S19.2E:27500:2303:2304=deu,2305=deu:32:1722,1702,1801:43:133:2:0 -PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu,769=deu:32:1801,1722,1702:9:133:2:0 -PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu,1281=deu:32:1722,1702,1801:29:133:2:0 +PREMIERE 4,PREM 4;PREMIERE:11797:hC34:S19.2E:27500:767:768=deu:32:1801,1722,1702:9:133:2:0 +PREMIERE 5,PREM 5;PREMIERE:11797:hC34:S19.2E:27500:1279:1280=deu:32:1722,1702,1801:29:133:2:0 PREMIERE 6,PREM 6;PREMIERE:11797:hC34:S19.2E:27500:1535:1536=deu:32:1801,1722,1702:41:133:2:0 PREMIERE 7,PREM 7;PREMIERE:11797:hC34:S19.2E:27500:1023:1024=deu:32:1801,1702,1722:20:133:2:0 DISNEY CHANNEL,DISNEY;PREMIERE:11758:hC34:S19.2E:27500:2559:2560=deu:32:1801,1722,1702:34:133:17:0 @@ -108,7 +108,7 @@ TPS Star:10757:vC34:S13.0E:27500:420:430=fra,431=eng:440:500,100:1204:176:11200: Sky One;BSkyB:12226:hC23:S28.2E:27500:515+8190:643=eng:579:960,961:4705:2:2027:0 Sky Two;BSkyB:12226:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:5104:2:2027:0 ITV2;BSkyB:10758:vC56:S28.2E:22000:2314:2315=eng,2363=NAR:2317:0:10070:2:2044:0 -Sci-Fi;BSkyB:12148:hC23:S28.2E:27500:512+8190:640=eng:576:960,961:4905:2:2023:0 +Sci-Fi;BSkyB:12148:hC23:S28.2E:27500:512+8190:640=eng,660=NAR:576:960,961:4905:2:2023:0 ParaComedy 1;BSkyB:12187:hC23:S28.2E:27500:518+8190:666=eng,686=NAR:582:960,961:5904:2:2025:0 Paramount;BSkyB:11526:vC23:S28.2E:27500:2317+2306:2318=eng:2319:960,961:50305:2:2404:0 ParaComedy 2;BSkyB:11914:hC23:S28.2E:27500:514+8190:642=eng,662=NAR:578:960,961:4504:2:2011:0 @@ -120,7 +120,7 @@ Sky Movies 4;BSkyB:11914:hC23:S28.2E:27500:512+8190:640=eng,655=NAR:576:960,961: Sky Movies 5;BSkyB:11914:hC23:S28.2E:27500:515+8190:643=eng,656=NAR:579:960,961:4503:2:2011:0 Sky Movies 6;BSkyB:11914:hC23:S28.2E:27500:513+8190:641=eng,657=NAR:577:960,961:4502:2:2011:0 Sky Movies 7;BSkyB:12285:vC23:S28.2E:27500:515+8190:643=eng,663=NAR:579:960,961:4603:2:2030:0 -Sky Movies 8;BSkyB:11836:hC23:S28.2E:27500:515+8190:643=eng,656=NAR:579:960,961:5502:2:2007:0 +Sky Movies 8;BSkyB:11836:hC23:S28.2E:27500:515+8190:643=eng,656=NAR;663=eng:579:960,961:5502:2:2007:0 Sky Movies 9;BSkyB:12285:vC23:S28.2E:27500:518+8190:646=eng,666=NAR:582:960,961:4602:2:2030:0 Sky Cinema 1;BSkyB:12285:vC23:S28.2E:27500:519+8190:647=eng,667=NAR:583:960,961:4809:2:2030:0 Sky Cinema 2;BSkyB:12285:vC23:S28.2E:27500:517+8190:645=eng,665=NAR:581:960,961:4802:2:2030:0 @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.c 1.141 2006/01/13 15:19:37 kls Exp $ + * $Id: config.c 1.142 2006/02/25 14:12:16 kls Exp $ */ #include "config.h" @@ -240,7 +240,6 @@ cSetup::cSetup(void) EPGLinger = 0; SVDRPTimeout = 300; ZapTimeout = 3; - SortTimers = 1; PrimaryLimit = 0; DefaultPriority = 50; DefaultLifetime = 99; @@ -400,7 +399,6 @@ bool cSetup::Parse(const char *Name, const char *Value) else if (!strcasecmp(Name, "EPGLinger")) EPGLinger = atoi(Value); 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, "PrimaryLimit")) PrimaryLimit = atoi(Value); else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value); else if (!strcasecmp(Name, "DefaultLifetime")) DefaultLifetime = atoi(Value); @@ -467,7 +465,6 @@ bool cSetup::Save(void) Store("EPGLinger", EPGLinger); Store("SVDRPTimeout", SVDRPTimeout); Store("ZapTimeout", ZapTimeout); - Store("SortTimers", SortTimers); Store("PrimaryLimit", PrimaryLimit); Store("DefaultPriority", DefaultPriority); Store("DefaultLifetime", DefaultLifetime); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: config.h 1.244 2006/02/12 10:07:44 kls Exp $ + * $Id: config.h 1.246 2006/02/25 14:12:20 kls Exp $ */ #ifndef __CONFIG_H @@ -19,8 +19,8 @@ #include "i18n.h" #include "tools.h" -#define VDRVERSION "1.3.43" -#define VDRVERSNUM 10343 // Version * 10000 + Major * 100 + Minor +#define VDRVERSION "1.3.44" +#define VDRVERSNUM 10344 // Version * 10000 + Major * 100 + Minor #define MAXPRIORITY 99 #define MAXLIFETIME 99 @@ -212,7 +212,6 @@ public: int EPGLinger; int SVDRPTimeout; int ZapTimeout; - int SortTimers; int PrimaryLimit; int DefaultPriority, DefaultLifetime; int PausePriority, PauseLifetime; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 1.123 2006/02/04 14:58:24 kls Exp $ + * $Id: device.c 1.124 2006/02/24 14:05:26 kls Exp $ */ #include "device.h" @@ -934,10 +934,10 @@ bool cDevice::AttachPlayer(cPlayer *Player) if (CanReplay()) { if (player) Detach(player); - if (!Transferring()) - ClrAvailableTracks(); pesAssembler->Reset(); player = Player; + if (!Transferring()) + ClrAvailableTracks(); SetPlayMode(player->playMode); player->device = this; player->Activate(true); @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * - * $Id: epg.c 1.61 2006/02/19 12:50:26 kls Exp $ + * $Id: epg.c 1.64 2006/02/26 15:07:17 kls Exp $ */ #include "epg.h" @@ -97,7 +97,7 @@ tComponent *cComponents::GetComponent(int Index, uchar Stream, uchar Type) // --- cEvent ---------------------------------------------------------------- -cEvent::cEvent(u_int16_t EventID) +cEvent::cEvent(tEventID EventID) { schedule = NULL; eventID = EventID; @@ -133,7 +133,7 @@ tChannelID cEvent::ChannelID(void) const return schedule ? schedule->ChannelID() : tChannelID(); } -void cEvent::SetEventID(u_int16_t EventID) +void cEvent::SetEventID(tEventID EventID) { if (eventID != EventID) { if (schedule) @@ -249,8 +249,7 @@ cString cEvent::GetVpsString(void) const void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const { if (InfoOnly || startTime + duration + Setup.EPGLinger * 60 >= time(NULL)) { - if (!InfoOnly) - fprintf(f, "%sE %u %ld %d %X %X\n", Prefix, eventID, startTime, duration, tableID, version); + fprintf(f, "%sE %u %ld %d %X %X\n", Prefix, eventID, startTime, duration, tableID, version); if (!isempty(title)) fprintf(f, "%sT %s\n", Prefix, title); if (!isempty(shortText)) @@ -268,7 +267,7 @@ void cEvent::Dump(FILE *f, const char *Prefix, bool InfoOnly) const fprintf(f, "%sX %s\n", Prefix, *p->ToString()); } } - if (!InfoOnly && vps) + if (vps) fprintf(f, "%sV %ld\n", Prefix, vps); if (!InfoOnly) fprintf(f, "%se\n", Prefix); @@ -692,10 +691,17 @@ const cEvent *cSchedule::GetFollowingEvent(void) const const cEvent *p = GetPresentEvent(); if (p) p = events.Next(p); + else { + time_t now = time(NULL); + for (p = events.First(); p; p = events.Next(p)) { + if (p->StartTime() >= now) + break; + } + } return p; } -const cEvent *cSchedule::GetEvent(u_int16_t EventID, time_t StartTime) const +const cEvent *cSchedule::GetEvent(tEventID EventID, time_t StartTime) const { // Returns either the event info with the given EventID or, if that one can't // be found, the one with the given StartTime (or NULL if neither can be found) @@ -7,7 +7,7 @@ * Original version (as used in VDR before 1.3.0) written by * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * - * $Id: epg.h 1.32 2006/02/19 12:51:41 kls Exp $ + * $Id: epg.h 1.33 2006/02/26 13:58:57 kls Exp $ */ #ifndef __EPG_H @@ -47,11 +47,13 @@ public: class cSchedule; +typedef u_int32_t tEventID; + class cEvent : public cListObject { friend class cSchedule; private: cSchedule *schedule; // The Schedule this event belongs to - u_int16_t eventID; // Event ID of this event + tEventID eventID; // Event ID of this event uchar tableID; // Table ID this event came from uchar version; // Version number of section this event came from int runningStatus; // 0=undefined, 1=not running, 2=starts in a few seconds, 3=pausing, 4=running @@ -64,12 +66,12 @@ private: time_t vps; // Video Programming Service timestamp (VPS, aka "Programme Identification Label", PIL) time_t seen; // When this event was last seen in the data stream public: - cEvent(u_int16_t EventID); + cEvent(tEventID EventID); ~cEvent(); virtual int Compare(const cListObject &ListObject) const; tChannelID ChannelID(void) const; const cSchedule *Schedule(void) const { return schedule; } - u_int16_t EventID(void) const { return eventID; } + tEventID EventID(void) const { return eventID; } uchar TableID(void) const { return tableID; } uchar Version(void) const { return version; } int RunningStatus(void) const { return runningStatus; } @@ -89,7 +91,7 @@ public: cString GetTimeString(void) const; cString GetEndTimeString(void) const; cString GetVpsString(void) const; - void SetEventID(u_int16_t EventID); + void SetEventID(tEventID EventID); void SetTableID(uchar TableID); void SetVersion(uchar Version); void SetRunningStatus(int RunningStatus, cChannel *Channel = NULL); @@ -140,7 +142,7 @@ public: const cList<cEvent> *Events(void) const { return &events; } const cEvent *GetPresentEvent(void) const; const cEvent *GetFollowingEvent(void) const; - const cEvent *GetEvent(u_int16_t EventID, time_t StartTime = 0) const; + const cEvent *GetEvent(tEventID EventID, time_t StartTime = 0) const; const cEvent *GetEventAround(time_t Time) const; void Dump(FILE *f, const char *Prefix = "", eDumpMode DumpMode = dmAll, time_t AtTime = 0) const; static bool Read(FILE *f, cSchedules *Schedules); @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: i18n.c 1.247 2006/02/04 14:17:54 kls Exp $ + * $Id: i18n.c 1.250 2006/02/25 14:21:28 kls Exp $ * * Translations provided by: * @@ -569,28 +569,6 @@ const tI18nPhrase Phrases[] = { "Hvad vises som det næste?", "Následující program", }, - { "Summary", - "Inhalt", - "Vsebina", - "Sommario", - "Inhoud", - "Resumo", - "Résumé", - "Sammendrag", - "Yhteenveto", - "Podsumowanie", - "Resumen", - "Ðåñéå÷üìåíï", - "Sammanfattning", - "Cuprins", - "Tartalom", - "Resum", - "¾ßØáÐÝØÕ", - "Sadr¾aj", - "Ülevaade", - "Omtale", - "Obsah", - }, // Button texts (should not be more than 10 characters!): { "Button$Edit", "Editieren", @@ -746,6 +724,28 @@ const tI18nPhrase Phrases[] = { "Optag", "Nahrát", }, + { "Button$Info", + "Info", + "Info", + "",//TODO + "Info", + "",//TODO + "Info", + "",//TODO + "Tiedot", + "Info", + "Info", + "Ðëçñïöïñßåò", + "Info", + "Info", + "",//TODO + "",//TODO + "¸ÝäÞ", + "Info", + "Info", + "Info", + "Info", + }, { "Button$Play", "Wiedergabe", "Predvajaj", @@ -3304,28 +3304,6 @@ const tI18nPhrase Phrases[] = { "Menu taste lukker", "Klávesa Menu zavírá", }, - { "Setup.OSD$Sort timers", - "Timer sortieren", - "Sortiraj termine", - "Ordinamento timer", - "Timers sorteren", - "Ordenar os timers", - "Trier les programmations", - "Sorter timere", - "Järjestä ajastimet", - "Sortuj timery", - "Ordenar programas de grabación", - "ÏñãÜíùóç ÷ñïíïðñïãñáììáôéóìþí", - "Sortera timers", - "Sortare timer-e", - "A beprogramozott felvételek elrendezése", - "Ordenar gravacions programades", - "ÁÞàâØàÞÒÚÐ âÐÙÜÕàÞÒ", - "Sortiraj termine", - "Taimeri sorteerimine", - "Sorter timere", - "Tøídìní èasovaèù", - }, { "Setup.OSD$Recording directories", "Aufnahmeverzeichnisse", "Direktoriji za posnetke", diff --git a/libsi/descriptor.c b/libsi/descriptor.c index 6a3af9f..b84e2c4 100644 --- a/libsi/descriptor.c +++ b/libsi/descriptor.c @@ -6,7 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: descriptor.c 1.17 2006/02/18 11:02:25 kls Exp $ + * $Id: descriptor.c 1.18 2006/02/25 10:06:05 kls Exp $ * * ***************************************************************************/ @@ -331,8 +331,6 @@ void CaDescriptor::Parse() { data.setPointerAndOffset<const descr_ca>(s, offset); if (checkSize(getLength()-offset)) privateData.assign(data.getData(offset), getLength()-offset); - else - privateData.assign(NULL, 0); } int StreamIdentifierDescriptor::getComponentTag() const { @@ -640,8 +638,6 @@ void LinkageDescriptor::Parse() { data.setPointerAndOffset<const descr_linkage>(s, offset); if (checkSize(getLength()-offset)) privateData.assign(data.getData(offset), getLength()-offset); - else - privateData.assign(NULL, 0); } int LinkageDescriptor::getTransportStreamId() const { diff --git a/libsi/util.h b/libsi/util.h index 91a4c32..08b1614 100644 --- a/libsi/util.h +++ b/libsi/util.h @@ -6,7 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * - * $Id: util.h 1.6 2006/02/18 10:38:20 kls Exp $ + * $Id: util.h 1.7 2006/02/25 10:13:28 kls Exp $ * * ***************************************************************************/ @@ -59,7 +59,7 @@ public: u_int32_t FourBytes(const int index) const { return data_->data ? data_->FourBytes(off+index) : 0; } bool isValid() const { return data_->valid; } - bool checkSize(int offset) { return (data_->valid && offset>=0 && (data_->valid=(off+offset < data_->size))); } + bool checkSize(int offset) { return (data_->valid && (data_->valid=(offset>=0 && off+offset < data_->size))); } void addOffset(int offset) { off+=offset; } private: @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.413 2006/02/19 10:18:28 kls Exp $ + * $Id: menu.c 1.422 2006/02/25 15:41:40 kls Exp $ */ #include "menu.h" @@ -686,14 +686,12 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key) if (!*data.file) strcpy(data.file, data.Channel()->ShortName(true)); if (timer) { - if (memcmp(timer, &data, sizeof(data)) != 0) { + if (memcmp(timer, &data, sizeof(data)) != 0) *timer = data; - if (timer->HasFlags(tfActive)) - timer->ClrFlags(~tfAll); // allows external programs to mark active timers with values > 0xFFFF and recognize if the user has modified them - } if (addIfConfirmed) Timers.Add(timer); timer->Matches(); + timer->SetEventFromSchedule(); Timers.SetModified(); isyslog("timer %s %s (%s)", *timer->ToDescr(), addIfConfirmed ? "added" : "modified", timer->HasFlags(tfActive) ? "active" : "inactive"); addIfConfirmed = false; @@ -771,13 +769,14 @@ void cMenuTimerItem::Set(void) class cMenuTimers : public cOsdMenu { private: + int helpKeys; eOSState Edit(void); eOSState New(void); eOSState Delete(void); eOSState OnOff(void); - virtual void Move(int From, int To); - eOSState Summary(void); + eOSState Info(void); cTimer *CurrentTimer(void); + void SetHelpKeys(void); public: cMenuTimers(void); virtual ~cMenuTimers(); @@ -787,11 +786,12 @@ public: cMenuTimers::cMenuTimers(void) :cOsdMenu(tr("Timers"), 2, CHNUMWIDTH, 10, 6, 6) { + helpKeys = -1; for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) Add(new cMenuTimerItem(timer)); - if (Setup.SortTimers) - Sort(); - SetHelp(tr("Button$Edit"), tr("Button$New"), tr("Button$Delete"), Setup.SortTimers ? tr("Button$On/Off") : tr("Button$Mark")); + Sort(); + SetCurrent(First()); + SetHelpKeys(); Timers.IncBeingEdited(); } @@ -806,11 +806,30 @@ cTimer *cMenuTimers::CurrentTimer(void) return item ? item->Timer() : NULL; } +void cMenuTimers::SetHelpKeys(void) +{ + int NewHelpKeys = 0; + cTimer *timer = CurrentTimer(); + if (timer) { + if (timer->Event()) + NewHelpKeys = 2; + else + NewHelpKeys = 1; + } + if (NewHelpKeys != helpKeys) { + helpKeys = NewHelpKeys; + SetHelp(helpKeys > 0 ? tr("Button$On/Off") : NULL, tr("Button$New"), helpKeys > 0 ? tr("Button$Delete") : NULL, helpKeys == 2 ? tr("Button$Info") : NULL); + } +} + eOSState cMenuTimers::OnOff(void) { + if (HasSubMenu()) + return osContinue; cTimer *timer = CurrentTimer(); if (timer) { timer->OnOff(); + timer->SetEventFromSchedule(); RefreshCurrent(); DisplayCurrent(true); if (timer->FirstDay()) @@ -861,23 +880,14 @@ eOSState cMenuTimers::Delete(void) return osContinue; } -void cMenuTimers::Move(int From, int To) -{ - Timers.Move(From, To); - cOsdMenu::Move(From, To); - Timers.SetModified(); - Display(); - isyslog("timer %d moved to %d", From + 1, To + 1); -} - -eOSState cMenuTimers::Summary(void) +eOSState cMenuTimers::Info(void) { if (HasSubMenu() || Count() == 0) return osContinue; cTimer *ti = CurrentTimer(); - if (ti && !isempty(ti->Summary())) - return AddSubMenu(new cMenuText(tr("Summary"), ti->Summary())); - return Edit(); // convenience for people not using the Summary feature ;-) + if (ti && ti->Event()) + return AddSubMenu(new cMenuEvent(ti->Event())); + return osContinue; } eOSState cMenuTimers::ProcessKey(eKeys Key) @@ -887,14 +897,11 @@ eOSState cMenuTimers::ProcessKey(eKeys Key) if (state == osUnknown) { switch (Key) { - case kOk: return Summary(); - case kRed: return Edit(); + case kOk: return Edit(); + case kRed: state = OnOff(); break; // must go through SetHelpKeys()! case kGreen: return New(); case kYellow: return Delete(); - case kBlue: if (Setup.SortTimers) - OnOff(); - else - Mark(); + case kBlue: return Info(); break; default: break; } @@ -904,12 +911,14 @@ eOSState cMenuTimers::ProcessKey(eKeys Key) Add(new cMenuTimerItem(Timers.Get(TimerNumber)), true); Display(); } + if (Key != kNone) + SetHelpKeys(); return state; } // --- cMenuEvent ------------------------------------------------------------ -cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch) +cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch, bool Buttons) :cOsdMenu(tr("Event")) { event = Event; @@ -919,7 +928,8 @@ cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch) SetTitle(channel->Name()); int TimerMatch = tmNone; Timers.GetMatch(event, &TimerMatch); - SetHelp(TimerMatch == tmFull ? tr("Button$Timer") : tr("Button$Record"), NULL, NULL, CanSwitch ? tr("Button$Switch") : NULL); + if (Buttons) + SetHelp(TimerMatch == tmFull ? tr("Button$Timer") : tr("Button$Record"), NULL, NULL, CanSwitch ? tr("Button$Switch") : NULL); } } } @@ -1173,7 +1183,7 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key) break; case kBlue: return Switch(); case kOk: if (Count()) - return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, true)); + return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, true, true)); break; default: break; } @@ -1442,7 +1452,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key) return Switch(); break; case kOk: if (Count()) - return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, otherChannel)); + return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, otherChannel, true)); break; default: break; } @@ -1850,7 +1860,7 @@ void cMenuRecordings::SetHelpKeys(void) case 0: SetHelp(NULL); break; case 1: SetHelp(tr("Button$Open")); break; case 2: - case 3: SetHelp(RecordingCommands.Count() ? tr("Commands") : tr("Button$Play"), tr("Button$Rewind"), tr("Button$Delete"), NewHelpKeys == 3 ? tr("Info") : NULL); + case 3: SetHelp(RecordingCommands.Count() ? tr("Commands") : tr("Button$Play"), tr("Button$Rewind"), tr("Button$Delete"), NewHelpKeys == 3 ? tr("Button$Info") : NULL); } helpKeys = NewHelpKeys; } @@ -2142,7 +2152,6 @@ void cMenuSetupOSD::Set(void) Add(new cMenuEditBoolItem(tr("Setup.OSD$Scroll pages"), &data.MenuScrollPage)); 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$Recording directories"), &data.RecordingDirs)); SetCurrent(Get(current)); Display(); @@ -3110,9 +3119,8 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key) else number = number * 10 + Key - k0; channel = Channels.GetByNumber(number); - displayChannel->SetEvents(NULL, NULL); + Refresh(); withInfo = false; - DisplayChannel(); // Lets see if there can be any useful further input: int n = channel ? number * 10 : 0; int m = 10; @@ -3131,10 +3139,10 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key) } if (n > 0) { // This channel is the only one that fits the input, so let's take it right away: - displayChannel->Flush(); // makes sure the user sees his last input NewChannel = channel; withInfo = true; number = 0; + Refresh(); } } break; @@ -3159,8 +3167,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key) group = SaveGroup; channel = Channels.Get(group); if (channel) { - displayChannel->SetEvents(NULL, NULL); - DisplayChannel(); + Refresh(); if (!channel->GroupSep()) group = -1; } @@ -3940,8 +3947,9 @@ void cReplayControl::TimeSearchProcess(eKeys Key) case kUp: case kPause: case kDown: + case kOk: Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds); - Goto(Seconds * FRAMESPERSEC, Key == kDown || Key == kPause); + Goto(Seconds * FRAMESPERSEC, Key == kDown || Key == kPause || Key == kOk); timeSearchActive = false; break; default: @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.h 1.83 2006/02/17 15:38:40 kls Exp $ + * $Id: menu.h 1.84 2006/02/25 13:41:21 kls Exp $ */ #ifndef __MENU_H @@ -49,7 +49,7 @@ class cMenuEvent : public cOsdMenu { private: const cEvent *event; public: - cMenuEvent(const cEvent *Event, bool CanSwitch = false); + cMenuEvent(const cEvent *Event, bool CanSwitch = false, bool Buttons = false); virtual void Display(void); virtual eOSState ProcessKey(eKeys Key); }; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.c 1.66 2006/02/05 13:46:37 kls Exp $ + * $Id: osd.c 1.67 2006/02/26 14:31:31 kls Exp $ */ #include "osd.h" @@ -344,7 +344,7 @@ void cBitmap::DrawPixel(int x, int y, tColor Color) SetIndex(x, y, Index(Color)); } -void cBitmap::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette) +void cBitmap::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay) { if (bitmap && Bitmap.bitmap && Intersects(x, y, x + Bitmap.Width() - 1, y + Bitmap.Height() - 1)) { if (Covers(x, y, x + Bitmap.Width() - 1, y + Bitmap.Height() - 1)) @@ -354,16 +354,20 @@ void cBitmap::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tC if (ReplacePalette && Covers(x + x0, y + y0, x + x0 + Bitmap.Width() - 1, y + y0 + Bitmap.Height() - 1)) { Replace(Bitmap); for (int ix = 0; ix < Bitmap.width; ix++) { - for (int iy = 0; iy < Bitmap.height; iy++) - SetIndex(x + ix, y + iy, Bitmap.bitmap[Bitmap.width * iy + ix]); + for (int iy = 0; iy < Bitmap.height; iy++) { + if (!Overlay || Bitmap.bitmap[Bitmap.width * iy + ix] != 0) + SetIndex(x + ix, y + iy, Bitmap.bitmap[Bitmap.width * iy + ix]); + } } } else { tIndexes Indexes; Take(Bitmap, &Indexes, ColorFg, ColorBg); for (int ix = 0; ix < Bitmap.width; ix++) { - for (int iy = 0; iy < Bitmap.height; iy++) - SetIndex(x + ix, y + iy, Indexes[int(Bitmap.bitmap[Bitmap.width * iy + ix])]); + for (int iy = 0; iy < Bitmap.height; iy++) { + if (!Overlay || Bitmap.bitmap[Bitmap.width * iy + ix] != 0) + SetIndex(x + ix, y + iy, Indexes[int(Bitmap.bitmap[Bitmap.width * iy + ix])]); + } } } } @@ -683,10 +687,10 @@ void cOsd::DrawPixel(int x, int y, tColor Color) bitmaps[i]->DrawPixel(x, y, Color); } -void cOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette) +void cOsd::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg, bool ReplacePalette, bool Overlay) { for (int i = 0; i < numBitmaps; i++) - bitmaps[i]->DrawBitmap(x, y, Bitmap, ColorFg, ColorBg, ReplacePalette); + bitmaps[i]->DrawBitmap(x, y, Bitmap, ColorFg, ColorBg, ReplacePalette, Overlay); } void cOsd::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment) @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: osd.h 1.51 2006/02/05 13:46:37 kls Exp $ + * $Id: osd.h 1.53 2006/02/26 14:45:05 kls Exp $ */ #ifndef __OSD_H @@ -157,13 +157,16 @@ public: ///< Sets the pixel at the given coordinates to the given Color, which is ///< a full 32 bit ARGB value. ///< If the coordinates are outside the bitmap area, no pixel will be set. - void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false); + void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false); ///< Sets the pixels in this bitmap with the data from the given ///< Bitmap, putting the upper left corner of the Bitmap at (x, y). ///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap ///< will be mapped to ColorBg and the second palette entry will be mapped to ///< ColorFg (palette indexes are defined so that 0 is the background and - ///< 1 is the foreground color). + ///< 1 is the foreground color). ReplacePalette controls whether the target + ///< area shall have its palette replaced with the one from Bitmap. + ///< If Overlay is true, any pixel in Bitmap that has color index 0 will + ///< not overwrite the corresponding pixel in the target area. void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); ///< Draws the given string at coordinates (x, y) with the given foreground ///< and background color and font. If Width and Height are given, the text @@ -278,13 +281,16 @@ public: ///< If the OSD area has been divided into separate sub-areas, and the ///< given coordinates don't fall into any of these sub-areas, no pixel will ///< be set. - virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false); + virtual void DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg = 0, tColor ColorBg = 0, bool ReplacePalette = false, bool Overlay = false); ///< Sets the pixels in the OSD with the data from the given ///< Bitmap, putting the upper left corner of the Bitmap at (x, y). ///< If ColorFg or ColorBg is given, the first palette entry of the Bitmap ///< will be mapped to ColorBg and the second palette entry will be mapped to ///< ColorFg (palette indexes are defined so that 0 is the background and - ///< 1 is the foreground color). + ///< 1 is the foreground color). ReplacePalette controls whether the target + ///< area shall have its palette replaced with the one from Bitmap. + ///< If Overlay is true, any pixel in Bitmap that has color index 0 will + ///< not overwrite the corresponding pixel in the target area. virtual void DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width = 0, int Height = 0, int Alignment = taDefault); ///< Draws the given string at coordinates (x, y) with the given foreground ///< and background color and font. If Width and Height are given, the text diff --git a/recording.c b/recording.c index 1efa3f6..b8db264 100644 --- a/recording.c +++ b/recording.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.c 1.137 2006/02/19 13:09:29 kls Exp $ + * $Id: recording.c 1.140 2006/02/26 11:59:59 kls Exp $ */ #include "recording.h" @@ -261,6 +261,7 @@ cRecordingInfo::cRecordingInfo(const cChannel *Channel, const cEvent *Event) channelID = Channel ? Channel->GetChannelID() : tChannelID::InvalidID; ownEvent = Event ? NULL : new cEvent(0); event = ownEvent ? ownEvent : Event; + aux = NULL; if (Channel) { // Since the EPG data's component records can carry only a single // language code, let's see whether the channel's PID data has @@ -299,6 +300,7 @@ cRecordingInfo::cRecordingInfo(const cChannel *Channel, const cEvent *Event) cRecordingInfo::~cRecordingInfo() { delete ownEvent; + free(aux); } void cRecordingInfo::SetData(const char *Title, const char *ShortText, const char *Description) @@ -311,6 +313,12 @@ void cRecordingInfo::SetData(const char *Title, const char *ShortText, const cha ((cEvent *)event)->SetDescription(Description); } +void cRecordingInfo::SetAux(const char *Aux) +{ + free(aux); + aux = Aux ? strdup(Aux) : NULL; +} + bool cRecordingInfo::Read(FILE *f) { if (ownEvent) { @@ -329,6 +337,26 @@ bool cRecordingInfo::Read(FILE *f) channelID = tChannelID::FromString(t); } break; + case 'E': { + unsigned int EventID; + time_t StartTime; + int Duration; + unsigned int TableID = 0; + unsigned int Version = 0xFF; + int n = sscanf(t, "%u %ld %d %X %X", &EventID, &StartTime, &Duration, &TableID, &Version); + if (n >= 3 && n <= 5) { + ownEvent->SetEventID(EventID); + ownEvent->SetStartTime(StartTime); + ownEvent->SetDuration(Duration); + ownEvent->SetTableID(TableID); + ownEvent->SetVersion(Version); + } + } + break; + case '@': free(aux); + aux = strdup(t); + break; + case '#': break; // comments are ignored default: if (!ownEvent->Parse(s)) { esyslog("ERROR: EPG data problem in line %d", line); return false; @@ -346,6 +374,8 @@ bool cRecordingInfo::Write(FILE *f, const char *Prefix) const if (channelID.Valid()) fprintf(f, "%sC %s\n", Prefix, *channelID.ToString()); event->Dump(f, Prefix, true); + if (aux) + fprintf(f, "%s@ %s\n", Prefix, aux); return true; } @@ -497,11 +527,7 @@ cRecording::cRecording(cTimer *Timer, const cEvent *Event) lifetime = Timer->Lifetime(); // handle info: info = new cRecordingInfo(Timer->Channel(), Event); - // this is a somewhat ugly hack to get the 'summary' information from the - // timer into the recording info, but it saves us from having to actually - // copy the entire event data: - if (!isempty(Timer->Summary())) - info->SetData(isempty(info->Title()) ? Timer->File() : NULL, NULL, Timer->Summary()); + info->SetAux(Timer->Aux()); } cRecording::cRecording(const char *FileName) diff --git a/recording.h b/recording.h index 5a18828..f0c3c0e 100644 --- a/recording.h +++ b/recording.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recording.h 1.51 2006/02/18 14:08:09 kls Exp $ + * $Id: recording.h 1.53 2006/02/25 12:24:46 kls Exp $ */ #ifndef __RECORDING_H @@ -44,14 +44,18 @@ private: tChannelID channelID; const cEvent *event; cEvent *ownEvent; + char *aux; cRecordingInfo(const cChannel *Channel = NULL, const cEvent *Event = NULL); void SetData(const char *Title, const char *ShortText, const char *Description); + void SetAux(const char *Aux); public: ~cRecordingInfo(); + tChannelID ChannelID(void) { return channelID; } const char *Title(void) const { return event->Title(); } const char *ShortText(void) const { return event->ShortText(); } const char *Description(void) const { return event->Description(); } const cComponents *Components(void) const { return event->Components(); } + const char *Aux(void) const { return aux; } bool Read(FILE *f); bool Write(FILE *f, const char *Prefix = "") const; }; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.46 2006/02/03 15:20:14 kls Exp $ + * $Id: timers.c 1.50 2006/02/26 10:50:47 kls Exp $ */ #include "timers.h" @@ -23,6 +23,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) { startTime = stopTime = 0; + lastSetEvent = 0; recording = pending = inVpsMargin = false; flags = tfNone; if (Instant) @@ -41,7 +42,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) priority = Pause ? Setup.PausePriority : Setup.DefaultPriority; lifetime = Pause ? Setup.PauseLifetime : Setup.DefaultLifetime; *file = 0; - summary = NULL; + aux = NULL; event = NULL; if (Instant && channel) snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); @@ -50,6 +51,7 @@ cTimer::cTimer(bool Instant, bool Pause, cChannel *Channel) cTimer::cTimer(const cEvent *Event) { startTime = stopTime = 0; + lastSetEvent = 0; recording = pending = inVpsMargin = false; flags = tfActive; if (Event->Vps() && Setup.UseVps) @@ -76,21 +78,22 @@ cTimer::cTimer(const cEvent *Event) const char *Title = Event->Title(); if (!isempty(Title)) strn0cpy(file, Event->Title(), sizeof(file)); - summary = NULL; - event = Event; + aux = NULL; + event = NULL; // let SetEvent() be called to get a log message } cTimer::~cTimer() { - free(summary); + free(aux); } cTimer& cTimer::operator= (const cTimer &Timer) { memcpy(this, &Timer, sizeof(*this)); - if (summary) - summary = strdup(summary); + if (aux) + aux = strdup(aux); event = NULL; + lastSetEvent = 0; return *this; } @@ -109,9 +112,7 @@ cString cTimer::ToText(bool UseChannelID) { char *buffer; strreplace(file, ':', '|'); - strreplace(summary, '\n', '|'); - asprintf(&buffer, "%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, summary ? summary : ""); - strreplace(summary, '|', '\n'); + asprintf(&buffer, "%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, aux ? aux : ""); strreplace(file, '|', ':'); return cString(buffer, true); } @@ -226,8 +227,8 @@ bool cTimer::Parse(const char *s) char *channelbuffer = NULL; char *daybuffer = NULL; char *filebuffer = NULL; - free(summary); - summary = NULL; + free(aux); + aux = NULL; //XXX Apparently sscanf() doesn't work correctly if the last %a argument //XXX results in an empty string (this first occured when the EIT gathering //XXX was put into a separate thread - don't know why this happens... @@ -244,17 +245,16 @@ bool cTimer::Parse(const char *s) s = s2; } bool result = false; - if (8 <= sscanf(s, "%u :%a[^:]:%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &flags, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &summary)) { + if (8 <= sscanf(s, "%u :%a[^:]:%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &flags, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &aux)) { ClrFlags(tfRecording); - if (summary && !*skipspace(summary)) { - free(summary); - summary = NULL; + if (aux && !*skipspace(aux)) { + free(aux); + aux = NULL; } //TODO add more plausibility checks result = ParseDay(daybuffer, day, weekdays); strn0cpy(file, filebuffer, MaxFileName); strreplace(file, '|', ':'); - strreplace(summary, '|', '\n'); if (isnumber(channelbuffer)) channel = Channels.GetByNumber(atoi(channelbuffer)); else @@ -426,6 +426,55 @@ time_t cTimer::StopTime(void) const return stopTime; } +#define EPGLIMITPAST (2 * 3600) // time in seconds in the past within which EPG events will be taken into consideration + +void cTimer::SetEventFromSchedule(const cSchedules *Schedules) +{ + cSchedulesLock SchedulesLock; + if (!Schedules) { + lastSetEvent = 0; // forces setting the event, even if the schedule hasn't been modified + if (!(Schedules = cSchedules::Schedules(SchedulesLock))) + return; + } + const cSchedule *Schedule = Schedules->GetSchedule(Channel()); + if (Schedule) { + if (!lastSetEvent || Schedule->Modified() >= lastSetEvent) { + const cEvent *Event = NULL; + int Overlap = 0; + int Distance = INT_MIN; + time_t now = time(NULL); + for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { + if (e->EndTime() < now - EPGLIMITPAST) + continue; // skip old events + int overlap = 0; + Matches(e, &overlap); + if (overlap && overlap >= Overlap) { + int distance = 0; + if (now < e->StartTime()) + distance = e->StartTime() - now; + else if (now > e->EndTime()) + distance = e->EndTime() - now; + if (Event && overlap == Overlap) { + if (Overlap > FULLMATCH) { // this means VPS + if (abs(Distance) < abs(distance)) + break; // we've already found the closest VPS event + } + else if (e->Duration() <= Event->Duration()) + continue; // if overlap is the same, we take the longer event + } + Overlap = overlap; + Distance = distance; + Event = e; + } + } + if (Event && Event->EndTime() < now - EXPIRELATENCY && Overlap > FULLMATCH && !Event->IsRunning()) + Event = NULL; + SetEvent(Event); + } + } + lastSetEvent = time(NULL); +} + void cTimer::SetEvent(const cEvent *Event) { if (event != Event) { //XXX TODO check event data, too??? @@ -491,7 +540,7 @@ bool cTimer::HasFlags(uint Flags) const void cTimer::Skip(void) { day = IncDay(SetTime(StartTime(), 0), 1); - event = NULL; + SetEvent(NULL); } void cTimer::OnOff(void) @@ -506,7 +555,7 @@ void cTimer::OnOff(void) Skip(); else SetFlags(tfActive); - event = NULL; + SetEvent(NULL); Matches(); // refresh start and end time } @@ -594,9 +643,6 @@ bool cTimers::Modified(int &State) return Result; } -#define EPGLIMITPAST (2 * 3600) // time in seconds around now, within which EPG events will be taken into consideration -#define EPGLIMITFUTURE (4 * 3600) - void cTimers::SetEvents(void) { if (time(NULL) - lastSetEvents < 5) @@ -606,46 +652,9 @@ void cTimers::SetEvents(void) if (Schedules) { if (!lastSetEvents || Schedules->Modified() >= lastSetEvents) { for (cTimer *ti = First(); ti; ti = Next(ti)) { - const cSchedule *Schedule = Schedules->GetSchedule(ti->Channel()); - if (Schedule) { - if (!lastSetEvents || Schedule->Modified() >= lastSetEvents) { - const cEvent *Event = NULL; - int Overlap = 0; - int Distance = INT_MIN; - time_t now = time(NULL); - for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { - if (cRemote::HasKeys()) - return; // react immediately on user input - if (e->EndTime() < now - EPGLIMITPAST) - continue; // skip old events - if (e->StartTime() > now + EPGLIMITFUTURE) - break; // no need to process events too far in the future - int overlap = 0; - ti->Matches(e, &overlap); - if (overlap && overlap >= Overlap) { - int distance = 0; - if (now < e->StartTime()) - distance = e->StartTime() - now; - else if (now > e->EndTime()) - distance = e->EndTime() - now; - if (Event && overlap == Overlap) { - if (Overlap > FULLMATCH) { // this means VPS - if (abs(Distance) < abs(distance)) - break; // we've already found the closest VPS event - } - else if (e->Duration() <= Event->Duration()) - continue; // if overlap is the same, we take the longer event - } - Overlap = overlap; - Distance = distance; - Event = e; - } - } - if (Event && Event->EndTime() < now - EXPIRELATENCY && !Event->IsRunning()) - Event = NULL; - ti->SetEvent(Event); - } - } + if (cRemote::HasKeys()) + return; // react immediately on user input + ti->SetEventFromSchedule(Schedules); } } } @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.h 1.24 2006/01/15 13:29:44 kls Exp $ + * $Id: timers.h 1.26 2006/02/25 15:05:09 kls Exp $ */ #ifndef __TIMERS_H @@ -28,6 +28,7 @@ class cTimer : public cListObject { friend class cMenuEditTimer; private: mutable time_t startTime, stopTime; + time_t lastSetEvent; bool recording, pending, inVpsMargin; uint flags; cChannel *channel; @@ -38,7 +39,7 @@ private: int priority; int lifetime; char file[MaxFileName]; - char *summary; + char *aux; const cEvent *event; public: cTimer(bool Instant = false, bool Pause = false, cChannel *Channel = NULL); @@ -59,7 +60,7 @@ public: int Lifetime(void) const { return lifetime; } const char *File(void) const { return file; } time_t FirstDay(void) const { return weekdays ? day : 0; } - const char *Summary(void) const { return summary; } + const char *Aux(void) const { return aux; } cString ToText(bool UseChannelID = false); cString ToDescr(void) const; const cEvent *Event(void) const { return event; } @@ -77,6 +78,7 @@ public: bool Expired(void) const; time_t StartTime(void) const; time_t StopTime(void) const; + void SetEventFromSchedule(const cSchedules *Schedules = NULL); void SetEvent(const cEvent *Event); void SetRecording(bool Recording); void SetPending(bool Pending); @@ -8,7 +8,7 @@ .\" License as specified in the file COPYING that comes with the .\" vdr distribution. .\" -.\" $Id: vdr.5 1.49 2006/02/19 15:04:21 kls Exp $ +.\" $Id: vdr.5 1.54 2006/02/26 14:10:00 kls Exp $ .\" .TH vdr 5 "19 Feb 2006" "1.3.43" "Video Disk Recorder Files" .SH NAME @@ -217,13 +217,8 @@ l l. \fB4\fR@this timer uses VPS \fB8\fR@this timer is currently recording (may only be up-to-date with SVDRP) .TE -Bits other than these can be used by external programs to mark active timers -and recognize if the user has modified them. When a user modifies an active -timer, the upper 16 bits of this unsigned 32 bit parameter will be explicitly set to 0. -Note: in order to allow future extensibility, external programs using the -\fBstatus\fR parameter should only use the upper 16 bit of this 32 bit parameter -and leave the lower 16 bit untouched. +All other bits are reserved for future use. .TP .B Channel The channel to record from. This is either the channel number as shown in the @@ -321,11 +316,11 @@ recording (if that data is available). If at the time of recording either of these cannot be determined, \fBTITLE\fR will default to the channel name, and \fBEPISODE\fR will default to a blank. .TP -.B Summary -Arbitrary text that describes the recording made by this timer. -Any newline characters in the summary have to be replaced by '|', and -the summary may contain ':' characters. If this field is not empty, its -contents will be written into the \fIinfo.vdr\fR file of the recording. +.B Auxiliary data +An arbitrary string that can be used by external applications to store any +kind of data related to this timer. The string must not contain any newline +characters. If this field is not empty, its contents will be written into the +\fIinfo.vdr\fR file of the recording with the '@' tag. .SS SOURCES The file \fIsources.conf\fR defines the codes to be used in the \fBSource\fR field of channels in \fIchannels.conf\fR and assigns descriptive texts to them. @@ -567,10 +562,13 @@ actual contents of this file. .SS INFO The file \fIinfo.vdr\fR (if present in a recording directory) contains a description of the recording, derived from the EPG data at recording time -(if such data was available) or the \fBSummary\fR field of the corresponding -timer. This is a plain ASCII file and contains tagged lines like the \fBEPG DATA\fR -file (see the description of the \fIepg.data\fR file). Note that the tags -c, E, e and V will not appear in an \fIinfo.vdr\fR file. +(if such data was available). The \fBAux\fR field of the corresponding +timer (if given) is copied into this file, using the '@' tag. +This is a plain ASCII file and contains tagged lines like the \fBEPG DATA\fR +file (see the description of the \fIepg.data\fR file). Note that the lowercase +tags ('c' and 'e') will not appear in an \fIinfo.vdr\fR file. +Lines tagged with '#' are ignored and can be used by external tools to +store arbitrary information. .SS RESUME The file \fIresume.vdr\fR (if present in a recording directory) contains the position within the recording where the last replay session left off. @@ -626,12 +624,15 @@ All other tags are optional (although every event should at least have a \fBT\fR entry). There may be several \fBX\fR tags, depending on the number of tracks (video, audio etc.) the event provides. +The special tag character \fB@\fR is used to mark the \fBauxiliary data\fR from +a timer definition in the \fIinfo.vdr\fR file. .TS tab (@); l l. <channel id> @is the "channel ID", made up from the parameters defined in 'channels.conf' <channel name> @is the "name" as in 'channels.conf' (for information only, may be left out) +<event id> @is a 32 bit unsigned int, uniquely identifying this event <start time> @is the time (as a time_t integer) in UTC when this event starts <duration> @is the time (in seconds) that this event will take <table id> @is a hex number that indicates the table this event is contained in (if this is left empty or 0 this event will not be overwritten or modified by data that comes from the DVB stream) @@ -648,6 +649,11 @@ l l. This file will be read at program startup in order to restore the results of previous EPG scans. + +Note that the \fBevent id\fR that comes from the DVB data stream is actually +just 16 bit wide. The internal representation in VDR allows for 32 bit to +be used, so that external tools can generate EPG data that is guaranteed +not to collide with the ids of existing data. .SH SEE ALSO .BR vdr (1) .SH AUTHOR |