From 5a4eb3f1041b8a53826cebe570f9d201f3d35826 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 29 Feb 2004 18:00:00 +0100 Subject: =?UTF-8?q?Version=201.3.5=20-=20Fixed=20reading=20the=20EPG=20pre?= =?UTF-8?q?ferred=20language=20parameter=20from=20'setup.conf'.=20-=20Fixe?= =?UTF-8?q?d=20switching=20to=20a=20visible=20programme=20in=20case=20the?= =?UTF-8?q?=20current=20channel=20has=20neither=20=20=20a=20video=20nor=20?= =?UTF-8?q?an=20audio=20PID.=20-=20Fixed=20editing=20channels=20(SID=20now?= =?UTF-8?q?=20range=20checked)=20and=20creating=20new=20channels=20(NID,?= =?UTF-8?q?=20=20=20TID=20and=20RID=20are=20now=20set=20to=200).=20-=20Fix?= =?UTF-8?q?ed=20transponder=20handling=20to=20make=20it=20work=20with=20sa?= =?UTF-8?q?tellites=20that=20provide=20two=20=20=20transponders=20on=20the?= =?UTF-8?q?=20same=20frequency,=20with=20different=20polarization,=20like?= =?UTF-8?q?=20Hispasat=20=20=20at=20S30.0W=20(thanks=20to=20Thomas=20Bergw?= =?UTF-8?q?inkl=20for=20pointing=20this=20out).=20See=20man=20vdr(5)=20=20?= =?UTF-8?q?=20for=20details=20about=20the=20enhanced=20channel=20ID=20form?= =?UTF-8?q?at.=20-=20Since=20there=20appears=20to=20be=20no=20general=20so?= =?UTF-8?q?lution=20for=20the=20UPT=20error=20yet,=20a=20recording=20=20?= =?UTF-8?q?=20now=20initiates=20an=20"emergency=20exit"=20if=20the=20numbe?= =?UTF-8?q?r=20of=20UPT=20errors=20during=20one=20=20=20recording=20exceed?= =?UTF-8?q?s=2010=20(suggested=20by=20Gregoire=20Favre).=20Since=20the=20U?= =?UTF-8?q?PT=20error=20doesn't=20=20=20happen=20on=20my=20system,=20this?= =?UTF-8?q?=20has=20not=20been=20explicitly=20tested.=20=20=20The=20"preli?= =?UTF-8?q?minary=20fix"=20for=20the=20UPT=20error=20in=20VDR/dvbdevice.c?= =?UTF-8?q?=20has=20been=20disabled=20=20=20by=20default,=20since=20it=20m?= =?UTF-8?q?akes=20channel=20switching=20unpleasently=20slow.=20If=20you=20?= =?UTF-8?q?want=20=20=20to=20have=20that=20workaround=20back,=20you=20can?= =?UTF-8?q?=20uncomment=20the=20line=20=20=20//#define=20WAIT=5FFOR=5FLOCK?= =?UTF-8?q?=5FAFTER=5FTUNING=201=20=20=20in=20VDR/dvbdevice.c.=20-=20Adapt?= =?UTF-8?q?ed=20the=20'sky'=20plugin=20to=20use=20the=20actual=20channel?= =?UTF-8?q?=20IDs,=20and=20to=20fetch=20EPG=20data=20=20=20from=20www.bleb?= =?UTF-8?q?.org.=20-=20Limited=20automatic=20retuning=20to=20devices=20tha?= =?UTF-8?q?t=20actually=20provide=20the=20transponder=20=20=20(necessary?= =?UTF-8?q?=20for=20the=20'sky'=20plugin).=20-=20Fixed=20handling=20receiv?= =?UTF-8?q?ers=20in=20the=20'sky'=20plugin,=20so=20that=20a=20recording=20?= =?UTF-8?q?on=20the=20same=20=20=20channel=20won't=20interrupt=20an=20ongo?= =?UTF-8?q?ing=20Transfer=20Mode.=20-=20Added=20subtable=20ID=20and=20TSDT?= =?UTF-8?q?=20handling=20to=20'libsi'=20(thanks=20to=20Marcel=20Wiesweg).?= =?UTF-8?q?=20-=20Fixed=20some=20Russian=20OSD=20texts=20(thanks=20to=20Vy?= =?UTF-8?q?acheslav=20Dikonov).=20-=20Added=20the=20'running=20status'=20t?= =?UTF-8?q?o=20the=20EPG=20events.=20This=20is=20necessary=20for=20impleme?= =?UTF-8?q?nting=20=20=20the=20VPS=20function=20for=20recording.=20-=20Rem?= =?UTF-8?q?oved=20the=20obsolete=20'present'=20and=20'following'=20handlin?= =?UTF-8?q?g=20from=20the=20EPG=20data.=20-=20The=20EPG=20data=20is=20now?= =?UTF-8?q?=20always=20kept=20sorted=20chronologically=20in=20the=20intern?= =?UTF-8?q?al=20data=20=20=20structures.=20This=20also=20means=20that=20an?= =?UTF-8?q?y=20EPG=20data=20retrieved=20through=20the=20SVRDP=20=20=20comm?= =?UTF-8?q?and=20LSTE=20is=20guaranteed=20to=20be=20sorted=20by=20start=20?= =?UTF-8?q?time.=20-=20Now=20using=20the=20'running=20status'=20in=20the?= =?UTF-8?q?=20channel=20display,=20so=20that=20a=20programme=20=20=20that?= =?UTF-8?q?=20has=20an=20end=20time=20that=20is=20before=20the=20current?= =?UTF-8?q?=20time,=20but=20is=20still=20running,=20=20=20will=20still=20b?= =?UTF-8?q?e=20shown=20in=20the=20display=20(provided=20the=20broadcasters?= =?UTF-8?q?=20handle=20the=20=20=20'running=20status'=20flag=20correctly).?= =?UTF-8?q?=20This=20also=20applies=20to=20programmes=20that=20have=20=20?= =?UTF-8?q?=20a=20start=20time=20that=20is=20in=20the=20future,=20but=20ar?= =?UTF-8?q?e=20already=20running.=20-=20Implemented=20an=20"EPG=20linger?= =?UTF-8?q?=20time",=20which=20can=20be=20set=20to=20have=20older=20EPG=20?= =?UTF-8?q?information=20=20=20still=20displayed=20in=20the=20"Schedule"?= =?UTF-8?q?=20menu=20(thanks=20to=20Jaakko=20Hyv=C3=A4tti).=20-=20Added=20?= =?UTF-8?q?PDCDescriptor=20handling=20to=20'libsi'.=20-=20Implemented=20ha?= =?UTF-8?q?ndling=20the=20VPS=20timestamps=20(aka=20"Programme=20Identific?= =?UTF-8?q?ation=20Label")=20=20=20for=20full=20VPS=20support=20for=20time?= =?UTF-8?q?rs=20(provided=20the=20tv=20stations=20actually=20broadcast=20?= =?UTF-8?q?=20=20this=20information).=20The=20VPS=20time=20is=20displayed?= =?UTF-8?q?=20in=20the=20event=20info=20page=20if=20it=20exists=20=20=20an?= =?UTF-8?q?d=20is=20different=20than=20the=20event's=20start=20time.=20-?= =?UTF-8?q?=20Extended=20the=20SVDRP=20command=20LSTE=20to=20allow=20limit?= =?UTF-8?q?ing=20the=20listed=20data=20to=20a=20given=20=20=20channel,=20t?= =?UTF-8?q?he=20present=20or=20following=20events,=20or=20events=20at=20a?= =?UTF-8?q?=20given=20time=20(thanks=20to=20=20=20Thomas=20Heiligenmann).?= =?UTF-8?q?=20-=20Fixed=20a=20typo=20in=20libsi/si.h=20(thanks=20to=20St?= =?UTF-8?q?=C3=A9phane=20Est=C3=A9-Gracias).=20-=20Timers=20can=20now=20be?= =?UTF-8?q?=20set=20to=20use=20the=20VPS=20information=20to=20control=20re?= =?UTF-8?q?cording=20a=20programme.=20=20=20The=20new=20setup=20options=20?= =?UTF-8?q?"Recording/Use=20VPS"=20and=20"Recording/VPS=20margin",=20as=20?= =?UTF-8?q?well=20as=20=20=20the=20"VPS"=20option=20in=20the=20individual?= =?UTF-8?q?=20timers,=20can=20be=20used=20to=20control=20this=20feature=20?= =?UTF-8?q?=20=20(see=20MANUAL=20for=20details).=20=20=20Note=20that=20thi?= =?UTF-8?q?s=20feature=20will=20certainly=20need=20a=20lot=20of=20testing?= =?UTF-8?q?=20before=20it=20can=20be=20=20=20called=20"safe"!=20-=20The=20?= =?UTF-8?q?"Schedule"=20and=20"What's=20on=20now/next=3F"=20menus=20now=20?= =?UTF-8?q?have=20an=20additional=20column=20=20=20which=20displays=20info?= =?UTF-8?q?rmation=20on=20whether=20there=20is=20a=20timer=20defined=20for?= =?UTF-8?q?=20an=20event,=20=20=20whether=20an=20event=20has=20a=20VPS=20t?= =?UTF-8?q?ime=20that's=20different=20than=20its=20start=20time,=20and=20?= =?UTF-8?q?=20=20whether=20an=20event=20is=20currently=20running=20(see=20?= =?UTF-8?q?MANUAL=20under=20"The=20"Schedule"=20Menu"=20=20=20for=20detail?= =?UTF-8?q?s).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- timers.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 142 insertions(+), 21 deletions(-) (limited to 'timers.c') diff --git a/timers.c b/timers.c index 1db88a0..b29d6c8 100644 --- a/timers.c +++ b/timers.c @@ -4,13 +4,14 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: timers.c 1.8 2003/12/27 13:10:04 kls Exp $ + * $Id: timers.c 1.9 2004/02/13 15:37:49 kls Exp kls $ */ #include "timers.h" #include #include "channels.h" #include "i18n.h" +#include "libsi/si.h" // IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d' // format characters in order to allow any number of blanks after a numeric @@ -23,8 +24,10 @@ char *cTimer::buffer = NULL; cTimer::cTimer(bool Instant, bool Pause) { startTime = stopTime = 0; - recording = pending = false; - active = Instant ? taActInst : taInactive; + recording = pending = inVpsMargin = false; + flags = tfNone; + if (Instant) + SetFlags(tfActive | tfInstant); channel = Channels.GetByNumber(cDevice::CurrentChannel()); time_t t = time(NULL); struct tm tm_r; @@ -40,6 +43,7 @@ cTimer::cTimer(bool Instant, bool Pause) *file = 0; firstday = 0; summary = NULL; + event = NULL; if (Instant && channel) snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name()); } @@ -47,12 +51,17 @@ cTimer::cTimer(bool Instant, bool Pause) cTimer::cTimer(const cEvent *Event) { startTime = stopTime = 0; - recording = pending = false; - active = true; + recording = pending = inVpsMargin = false; + flags = tfActive; + if (Event->Vps() && Setup.UseVps) + SetFlags(tfVps); channel = Channels.GetByChannelID(Event->ChannelID(), true); - time_t tstart = Event->StartTime(); - time_t tstop = tstart + Event->Duration() + Setup.MarginStop * 60; - tstart -= Setup.MarginStart * 60; + time_t tstart = (flags & tfVps) ? Event->Vps() : Event->StartTime(); + time_t tstop = tstart + Event->Duration(); + if (!(HasFlags(tfVps))) { + tstop += Setup.MarginStop * 60; + tstart -= Setup.MarginStart * 60; + } struct tm tm_r; struct tm *time = localtime_r(&tstart, &tm_r); day = time->tm_mday; @@ -69,6 +78,7 @@ cTimer::cTimer(const cEvent *Event) strn0cpy(file, Event->Title(), sizeof(file)); firstday = 0; summary = NULL; + event = Event; } cTimer::~cTimer() @@ -81,6 +91,7 @@ cTimer& cTimer::operator= (const cTimer &Timer) memcpy(this, &Timer, sizeof(*this)); if (summary) summary = strdup(summary); + event = NULL; return *this; } @@ -97,7 +108,7 @@ const char *cTimer::ToText(bool UseChannelID) free(buffer); strreplace(file, ':', '|'); strreplace(summary, '\n', '|'); - asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", active, UseChannelID ? Channel()->GetChannelID().ToString() : itoa(Channel()->Number()), PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : ""); + asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? Channel()->GetChannelID().ToString() : itoa(Channel()->Number()), PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : ""); strreplace(summary, '|', '\n'); strreplace(file, '|', ':'); return buffer; @@ -205,7 +216,7 @@ bool cTimer::Parse(const char *s) s = s2; } bool result = false; - if (8 <= sscanf(s, "%d :%a[^:]:%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &active, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &summary)) { + if (8 <= sscanf(s, "%d :%a[^:]:%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &flags, &channelbuffer, &daybuffer, &start, &stop, &priority, &lifetime, &filebuffer, &summary)) { if (summary && !*skipspace(summary)) { free(summary); summary = NULL; @@ -219,7 +230,7 @@ bool cTimer::Parse(const char *s) if (isnumber(channelbuffer)) channel = Channels.GetByNumber(atoi(channelbuffer)); else - channel = Channels.GetByChannelID(tChannelID::FromString(channelbuffer), true); + channel = Channels.GetByChannelID(tChannelID::FromString(channelbuffer), true, true); if (!channel) { esyslog("ERROR: channel %s not defined", channelbuffer); result = false; @@ -290,7 +301,7 @@ char *cTimer::SetFile(const char *File) return file; } -bool cTimer::Matches(time_t t) +bool cTimer::Matches(time_t t, bool Directly) { startTime = stopTime = 0; if (t == 0) @@ -316,9 +327,35 @@ bool cTimer::Matches(time_t t) } if (!startTime) startTime = firstday; // just to have something that's more than a week in the future - else if (t > startTime || t > firstday + SECSINDAY + 3600) // +3600 in case of DST change + else if (!Directly && (t > startTime || t > firstday + SECSINDAY + 3600)) // +3600 in case of DST change firstday = 0; - return active && startTime <= t && t < stopTime; // must stop *before* stopTime to allow adjacent timers + + if (HasFlags(tfActive)) { + if (HasFlags(tfVps) && !Directly && event && event->Vps()) { + startTime = event->StartTime(); + stopTime = startTime + event->Duration(); + return event->RunningStatus() > SI::RunningStatusNotRunning; + } + return startTime <= t && t < stopTime; // must stop *before* stopTime to allow adjacent timers + } + return false; +} + +int cTimer::Matches(const cEvent *Event) +{ + if (channel->GetChannelID() == Event->ChannelID()) { + bool UseVps = HasFlags(tfVps) && Event->Vps(); + time_t t1 = UseVps ? Event->Vps() : Event->StartTime(); + time_t t2 = t1 + Event->Duration(); + bool m1 = Matches(t1, true); + bool m2 = UseVps ? m1 : Matches(t2, true); + startTime = stopTime = 0; + if (m1 && m2) + return tmFull; + if (m1 || m2) + return tmPartial; + } + return tmNone; } time_t cTimer::StartTime(void) @@ -335,6 +372,19 @@ time_t cTimer::StopTime(void) return stopTime; } +void cTimer::SetEvent(const cEvent *Event) +{ + if (event != Event) { //XXX TODO check event data, too??? + if (Event) { + char vpsbuf[64] = ""; + if (Event->Vps()) + sprintf(vpsbuf, "(VPS: %s) ", Event->GetVpsString()); + isyslog("timer %d (%d %04d-%04d '%s') set to event %s %s-%s %s'%s'", Index() + 1, Channel()->Number(), start, stop, file, Event->GetDateString(), Event->GetTimeString(), Event->GetEndTimeString(), vpsbuf, Event->Title()); + } + event = Event; + } +} + void cTimer::SetRecording(bool Recording) { recording = Recording; @@ -346,28 +396,52 @@ void cTimer::SetPending(bool Pending) pending = Pending; } -void cTimer::SetActive(int Active) +void cTimer::SetInVpsMargin(bool InVpsMargin) +{ + if (InVpsMargin && !inVpsMargin) + isyslog("timer %d (%d %04d-%04d '%s') entered VPS margin", Index() + 1, Channel()->Number(), start, stop, file); + inVpsMargin = InVpsMargin; +} + +void cTimer::SetFlags(int Flags) +{ + flags |= Flags; +} + +void cTimer::ClrFlags(int Flags) { - active = Active; + flags &= ~Flags; +} + +void cTimer::InvFlags(int Flags) +{ + flags ^= Flags; +} + +bool cTimer::HasFlags(int Flags) +{ + return (flags & Flags) == Flags; } void cTimer::Skip(void) { firstday = IncDay(SetTime(StartTime(), 0), 1); + event = NULL; } void cTimer::OnOff(void) { if (IsSingleEvent()) - active = !active; + InvFlags(tfActive); else if (firstday) { firstday = 0; - active = false; + ClrFlags(tfActive); } - else if (active) + else if (HasFlags(tfActive)) Skip(); else - active = true; + SetFlags(tfActive); + event = NULL; Matches(); // refresh start and end time } @@ -396,12 +470,59 @@ cTimer *cTimers::GetMatch(time_t t) return t0; } +cTimer *cTimers::GetMatch(const cEvent *Event, int *Match) +{ + cTimer *t = NULL; + int m = tmNone; + for (cTimer *ti = First(); ti; ti = Next(ti)) { + int tm = ti->Matches(Event); + if (tm > m) { + t = ti; + m = tm; + if (m == tmFull) + break; + } + } + if (Match) + *Match = m; + return t; +} + cTimer *cTimers::GetNextActiveTimer(void) { cTimer *t0 = NULL; for (cTimer *ti = First(); ti; ti = Next(ti)) { - if (ti->Active() && (!t0 || *ti < *t0)) + if ((ti->HasFlags(tfActive)) && (!t0 || *ti < *t0)) t0 = ti; } return t0; } + +void cTimers::SetEvents(void) +{ + cSchedulesLock SchedulesLock; + const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); + if (Schedules) { + for (cTimer *ti = First(); ti; ti = Next(ti)) { + const cSchedule *Schedule = Schedules->GetSchedule(ti->Channel()->GetChannelID()); + const cEvent *Event = NULL; + if (Schedule) { + //XXX what if the Schedule doesn't have any VPS??? + const cEvent *e; + int Match = tmNone; + int i = 0; + while ((e = Schedule->GetEventNumber(i++)) != NULL) { + int m = ti->Matches(e); + if (m > Match) { + Match = m; + Event = e; + if (Match == tmFull) + break; + //XXX what if there's another event with the same VPS time??? + } + } + } + ti->SetEvent(Event); + } + } +} -- cgit v1.2.3