mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
First step towards a 'unique channel ID'
This commit is contained in:
parent
c67fe26e66
commit
9fee2b67ab
45
HISTORY
45
HISTORY
@ -249,7 +249,7 @@ Video Disk Recorder Revision History
|
||||
- The EIT information is now gathered in a separate thread.
|
||||
- The sytem time can now be synchronized to the time broadcast in the DVB data
|
||||
stream. This can be enabled in the "Setup" menu by setting "SetSystemTime" to
|
||||
1. Note that this works only if VDR is running under a user id that has
|
||||
1. Note that this works only if VDR is running under a user ID that has
|
||||
permisson to set the system time.
|
||||
- The new item "Schedule" in the "Main" menu opens VDR's EPG (thanks to Robert
|
||||
Schneider). See the MANUAL file for a detailed description.
|
||||
@ -1722,9 +1722,46 @@ Video Disk Recorder Revision History
|
||||
which can be used to disable simultaneous recording and replaying on the primary
|
||||
DVB device in case there are problems with this.
|
||||
|
||||
2002-11-08: Version 1.1.16
|
||||
2002-11-10: Version 1.1.16
|
||||
|
||||
- Fixed saving the polarization parameter of channels that have a number in the
|
||||
'source' parameter (thanks to Peter Seyringer for reporting this one).
|
||||
- Updated channels.conf.terr (thanks to Andy Carter).
|
||||
- Updated channels.conf.cable (thanks to Achim Lange).
|
||||
- Updated 'channels.conf.terr' (thanks to Andy Carter).
|
||||
- Updated 'channels.conf.cable' (thanks to Achim Lange).
|
||||
- First step towards a "unique channel ID". The channel ID is a human readable
|
||||
string, made up from several parameters of the channel's definition in the file
|
||||
'channels.conf' (see man vdr(5) for details).
|
||||
In order for the "unique channel ID" to work, all channel definitions now must
|
||||
be unique with respect to the combination of their Source, Frequency and SID
|
||||
parameters. You may have to fix your 'channels.conf' manually if there are error
|
||||
messages in the log file when loading it. BE SURE TO MAKE A BACKUP COPY OF YOUR
|
||||
'channels.conf' AND 'timers.conf' FILE BEFORE SWITCHING TO THIS VERSION, AND CHECK
|
||||
VERY CAREFULLY WHETHER YOUR TIMERS ARE STILL SET TO THE RIGHT CHANNELS!
|
||||
When reading an existing 'timers.conf', the channels will be identified as before
|
||||
by their numbers. As soon as this file is written back, the channel numbers will
|
||||
be replaced by the channel IDs. After that it is possible to manually edit the
|
||||
'channels.conf' file and rearrange the channels without breaking the timers.
|
||||
Note that you can still define new timers manually by using the channel number.
|
||||
VDR will correctly identify the 'channel' parameter in a timer definition and
|
||||
use it as a channel number or a channel ID, respectively. Also, the SVDRP commands
|
||||
that return timer definitions will list them with channel numbers in order to
|
||||
stay compatible with existing applications.
|
||||
The channel ID is also used in the 'epg.data' file to allow EPG information from
|
||||
different sources to be stored, which would previously have been mixed up in case
|
||||
they were using the same 'service ID'. Note that the contents of an existing
|
||||
'epg.data' file from a previous version will be silently ignored, since it doesn't
|
||||
contain the new channel IDs. When inserting EPG data into VDR via SVDRP you now also
|
||||
need to use the channel IDs.
|
||||
Currently the EPG data received from the DVB data stream only uses the 'Source'
|
||||
and 'Service ID' part of the channel ID. This makes it work for channels with
|
||||
the same service IDs on different sources (like satellites, cable or terrestrial).
|
||||
However, it doesn't work yet if the service IDs are not unique within a specific
|
||||
source. This will be fixed later.
|
||||
- Added missing SID parameters to 'channels.conf'. Some channels have been removed
|
||||
since they are apparently no longer broadcasted.
|
||||
- Removed dropping EPG events from "other" streams that have a duration of 86400
|
||||
seconds or more (was introduced in version 1.1.10). This has become obsolete by
|
||||
the modification in version 1.1.13, which fixed fetching the current/next information
|
||||
to handle cases where the duration of an event is set wrongly and would last beyond
|
||||
the start time of the next event. Besides, the change in 1.1.10 broke handling EPG
|
||||
data for NVOD channels.
|
||||
|
106
channels.c
106
channels.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.c 1.7 2002/11/08 13:21:16 kls Exp $
|
||||
* $Id: channels.c 1.8 2002/11/10 13:01:55 kls Exp $
|
||||
*/
|
||||
|
||||
#include "channels.h"
|
||||
@ -126,19 +126,18 @@ char *cChannel::buffer = NULL;
|
||||
|
||||
cChannel::cChannel(void)
|
||||
{
|
||||
*name = 0;
|
||||
frequency = 0;
|
||||
strcpy(name, "Pro7");
|
||||
frequency = 12480;
|
||||
source = cSource::FromString("S19.2E");
|
||||
srate = 0;
|
||||
vpid = 0;
|
||||
apid1 = 0;
|
||||
srate = 27500;
|
||||
vpid = 255;
|
||||
apid1 = 256;
|
||||
apid2 = 0;
|
||||
dpid1 = 0;
|
||||
dpid1 = 257;
|
||||
dpid2 = 0;
|
||||
tpid = 0;
|
||||
tpid = 32;
|
||||
ca = 0;
|
||||
sid = 0;
|
||||
number = 0;
|
||||
groupSep = false;
|
||||
polarization = 'v';
|
||||
inversion = INVERSION_AUTO;
|
||||
@ -151,30 +150,44 @@ cChannel::cChannel(void)
|
||||
hierarchy = HIERARCHY_AUTO;
|
||||
}
|
||||
|
||||
cChannel::cChannel(const cChannel *Channel)
|
||||
cChannel& cChannel::operator= (const cChannel &Channel)
|
||||
{
|
||||
strcpy(name, Channel ? Channel->name : "Pro7");
|
||||
frequency = Channel ? Channel->frequency : 12480;
|
||||
source = Channel ? Channel->source : cSource::FromString("S19.2E");
|
||||
srate = Channel ? Channel->srate : 27500;
|
||||
vpid = Channel ? Channel->vpid : 255;
|
||||
apid1 = Channel ? Channel->apid1 : 256;
|
||||
apid2 = Channel ? Channel->apid2 : 0;
|
||||
dpid1 = Channel ? Channel->dpid1 : 257;
|
||||
dpid2 = Channel ? Channel->dpid2 : 0;
|
||||
tpid = Channel ? Channel->tpid : 32;
|
||||
ca = Channel ? Channel->ca : 0;
|
||||
sid = Channel ? Channel->sid : 0;
|
||||
groupSep = Channel ? Channel->groupSep : false;
|
||||
polarization = Channel ? Channel->polarization : 'v';
|
||||
inversion = Channel ? Channel->inversion : INVERSION_AUTO;
|
||||
bandwidth = Channel ? Channel->bandwidth : BANDWIDTH_AUTO;
|
||||
coderateH = Channel ? Channel->coderateH : FEC_AUTO;
|
||||
coderateL = Channel ? Channel->coderateL : FEC_AUTO;
|
||||
modulation = Channel ? Channel->modulation : QAM_AUTO;
|
||||
transmission = Channel ? Channel->transmission : TRANSMISSION_MODE_AUTO;
|
||||
guard = Channel ? Channel->guard : GUARD_INTERVAL_AUTO;
|
||||
hierarchy = Channel ? Channel->hierarchy : HIERARCHY_AUTO;
|
||||
memcpy(&__BeginData__, &Channel.__BeginData__, (char *)&Channel.__EndData__ - (char *)&Channel.__BeginData__);
|
||||
return *this;
|
||||
}
|
||||
|
||||
static int MHz(int frequency)
|
||||
{
|
||||
while (frequency > 20000) {
|
||||
frequency /= 1000;
|
||||
}
|
||||
return frequency;
|
||||
}
|
||||
|
||||
uint64 cChannel::GetChannelID(void) const
|
||||
{
|
||||
return (uint64(source) << 48) | (uint64(0) << 32) | ((MHz(frequency)) << 16) | sid;
|
||||
}
|
||||
|
||||
const char *cChannel::GetChannelIDStr(void) const
|
||||
{
|
||||
static char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), "%s-%d-%d-%d", cSource::ToString(source), 0, MHz(frequency), sid);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint64 cChannel::StringToChannelID(const char *s)
|
||||
{
|
||||
char *sourcebuf = NULL;
|
||||
int reserved;
|
||||
int frequency;
|
||||
int sid;
|
||||
if (4 == sscanf(s, "%a[^-]-%d-%d-%d", &sourcebuf, &reserved, &frequency, &sid)) {
|
||||
int source = cSource::FromString(sourcebuf);
|
||||
if (source >= 0)
|
||||
return (uint64(source) << 48) | (uint64(reserved) << 32) | (frequency << 16) | sid;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int PrintParameter(char *p, char Name, int Value)
|
||||
@ -278,7 +291,7 @@ const char *cChannel::ToText(void)
|
||||
return ToText(this);
|
||||
}
|
||||
|
||||
bool cChannel::Parse(const char *s)
|
||||
bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
|
||||
{
|
||||
if (*s == ':') {
|
||||
groupSep = true;
|
||||
@ -324,6 +337,10 @@ bool cChannel::Parse(const char *s)
|
||||
free(sourcebuf);
|
||||
free(apidbuf);
|
||||
free(namebuf);
|
||||
if (!AllowNonUniqueID && Channels.GetByChannelID(GetChannelID())) {
|
||||
esyslog("ERROR: channel data not unique!");
|
||||
return false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
else
|
||||
@ -404,15 +421,34 @@ cChannel *cChannels::GetByNumber(int Number, int SkipGap)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cChannel *cChannels::GetByServiceID(unsigned short ServiceId)
|
||||
cChannel *cChannels::GetByServiceID(int Source, unsigned short ServiceID)
|
||||
{
|
||||
for (cChannel *channel = First(); channel; channel = Next(channel)) {
|
||||
if (!channel->GroupSep() && channel->Sid() == ServiceId)
|
||||
if (!channel->GroupSep() && channel->Source() == Source && channel->Sid() == ServiceID)
|
||||
return channel;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cChannel *cChannels::GetByChannelID(uint64 ChannelID)
|
||||
{
|
||||
for (cChannel *channel = First(); channel; channel = Next(channel)) {
|
||||
if (!channel->GroupSep() && channel->GetChannelID() == ChannelID)
|
||||
return channel;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cChannels::HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel)
|
||||
{
|
||||
uint64 NewChannelID = NewChannel->GetChannelID();
|
||||
for (cChannel *channel = First(); channel; channel = Next(channel)) {
|
||||
if (!channel->GroupSep() && channel != OldChannel && channel->GetChannelID() == NewChannelID)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cChannels::SwitchTo(int Number)
|
||||
{
|
||||
cChannel *channel = GetByNumber(Number);
|
||||
|
18
channels.h
18
channels.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.h 1.3 2002/10/20 11:50:36 kls Exp $
|
||||
* $Id: channels.h 1.4 2002/11/10 13:01:23 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CHANNELS_H
|
||||
@ -41,6 +41,7 @@ private:
|
||||
static char *buffer;
|
||||
static const char *ToText(cChannel *Channel);
|
||||
enum { MaxChannelName = 32 }; // 31 chars + terminating 0!
|
||||
int __BeginData__;
|
||||
char name[MaxChannelName];
|
||||
int frequency; // MHz
|
||||
int source;
|
||||
@ -53,7 +54,6 @@ private:
|
||||
int sid;
|
||||
int number; // Sequence number assigned on load
|
||||
bool groupSep;
|
||||
//XXX
|
||||
char polarization;
|
||||
int inversion;
|
||||
int bandwidth;
|
||||
@ -63,13 +63,14 @@ private:
|
||||
int transmission;
|
||||
int guard;
|
||||
int hierarchy;
|
||||
int __EndData__;
|
||||
const char *ParametersToString(void);
|
||||
bool StringToParameters(const char *s);
|
||||
public:
|
||||
cChannel(void);
|
||||
cChannel(const cChannel *Channel);
|
||||
cChannel& operator= (const cChannel &Channel);
|
||||
const char *ToText(void);
|
||||
bool Parse(const char *s);
|
||||
bool Parse(const char *s, bool AllowNonUniqueID = false);
|
||||
bool Save(FILE *f);
|
||||
const char *Name(void) const { return name; }
|
||||
int Frequency(void) const { return frequency; }
|
||||
@ -86,7 +87,6 @@ public:
|
||||
int Number(void) const { return number; }
|
||||
void SetNumber(int Number) { number = Number; }
|
||||
bool GroupSep(void) const { return groupSep; }
|
||||
//XXX
|
||||
char Polarization(void) const { return polarization; }
|
||||
int Inversion(void) const { return inversion; }
|
||||
int Bandwidth(void) const { return bandwidth; }
|
||||
@ -96,10 +96,12 @@ public:
|
||||
int Transmission(void) const { return transmission; }
|
||||
int Guard(void) const { return guard; }
|
||||
int Hierarchy(void) const { return hierarchy; }
|
||||
//XXX
|
||||
bool IsCable(void) { return (source & cSource::st_Mask) == cSource::stCable; }
|
||||
bool IsSat(void) { return (source & cSource::st_Mask) == cSource::stSat; }
|
||||
bool IsTerr(void) { return (source & cSource::st_Mask) == cSource::stTerr; }
|
||||
uint64 GetChannelID(void) const;
|
||||
const char *GetChannelIDStr(void) const;
|
||||
static uint64 StringToChannelID(const char *s);
|
||||
};
|
||||
|
||||
class cChannels : public cConfig<cChannel> {
|
||||
@ -113,7 +115,9 @@ public:
|
||||
int GetNextNormal(int Idx); // Get next normal channel (not group)
|
||||
void ReNumber(void); // Recalculate 'number' based on channel type
|
||||
cChannel *GetByNumber(int Number, int SkipGap = 0);
|
||||
cChannel *GetByServiceID(unsigned short ServiceId);
|
||||
cChannel *GetByServiceID(int Source, unsigned short ServiceID);
|
||||
cChannel *GetByChannelID(uint64 ChannelID);
|
||||
bool HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel = NULL);
|
||||
bool SwitchTo(int Number);
|
||||
int MaxNumber(void) { return maxNumber; }
|
||||
};
|
||||
|
4
device.c
4
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 1.34 2002/11/03 11:51:24 kls Exp $
|
||||
* $Id: device.c 1.35 2002/11/10 10:17:57 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -379,7 +379,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
||||
|
||||
if (Result == scrOk) {
|
||||
if (LiveView && IsPrimaryDevice()) {
|
||||
cSIProcessor::SetCurrentServiceID(Channel->Sid());
|
||||
cSIProcessor::SetCurrentChannelID(Channel->GetChannelID());
|
||||
currentChannel = Channel->Number();
|
||||
}
|
||||
cStatus::MsgChannelSwitch(this, Channel->Number()); // only report status if channel switch successfull
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 1.34 2002/11/03 12:31:11 kls Exp $
|
||||
* $Id: dvbdevice.c 1.35 2002/11/10 12:57:17 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -412,7 +412,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
// Stop setting system time:
|
||||
|
||||
if (siProcessor)
|
||||
siProcessor->SetCurrentTransponder(0);
|
||||
siProcessor->SetCurrentTransponder(0, 0);
|
||||
|
||||
// Turn off live PIDs if necessary:
|
||||
|
||||
@ -585,7 +585,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
// Start setting system time:
|
||||
|
||||
if (siProcessor)
|
||||
siProcessor->SetCurrentTransponder(Channel->Frequency());
|
||||
siProcessor->SetCurrentTransponder(Channel->Source(), Channel->Frequency());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
122
eit.c
122
eit.c
@ -16,7 +16,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: eit.c 1.59 2002/11/02 12:46:53 kls Exp $
|
||||
* $Id: eit.c 1.60 2002/11/10 15:50:21 kls Exp $
|
||||
***************************************************************************/
|
||||
|
||||
#include "eit.h"
|
||||
@ -180,7 +180,7 @@ bool cTDT::SetSystemTime()
|
||||
|
||||
// --- cEventInfo ------------------------------------------------------------
|
||||
|
||||
cEventInfo::cEventInfo(unsigned short serviceid, unsigned short eventid)
|
||||
cEventInfo::cEventInfo(uint64 channelid, unsigned short eventid)
|
||||
{
|
||||
pTitle = NULL;
|
||||
pSubtitle = NULL;
|
||||
@ -190,7 +190,7 @@ cEventInfo::cEventInfo(unsigned short serviceid, unsigned short eventid)
|
||||
tTime = 0;
|
||||
uTableID = 0;
|
||||
uEventID = eventid;
|
||||
uServiceID = serviceid;
|
||||
uChannelID = channelid;
|
||||
nChannelNumber = 0;
|
||||
}
|
||||
|
||||
@ -325,15 +325,15 @@ void cEventInfo::SetEventID(unsigned short evid)
|
||||
uEventID = evid;
|
||||
}
|
||||
/** */
|
||||
void cEventInfo::SetServiceID(unsigned short servid)
|
||||
void cEventInfo::SetChannelID(uint64 channelid)
|
||||
{
|
||||
uServiceID = servid;
|
||||
uChannelID = channelid;
|
||||
}
|
||||
|
||||
/** */
|
||||
unsigned short cEventInfo::GetServiceID() const
|
||||
uint64 cEventInfo::GetChannelID() const
|
||||
{
|
||||
return uServiceID;
|
||||
return uChannelID;
|
||||
}
|
||||
|
||||
/** */
|
||||
@ -368,7 +368,7 @@ bool cEventInfo::Read(FILE *f, cSchedule *Schedule)
|
||||
if (n == 3 || n == 4) {
|
||||
pEvent = (cEventInfo *)Schedule->GetEvent(uEventID, tTime);
|
||||
if (!pEvent)
|
||||
pEvent = Schedule->AddEvent(new cEventInfo(Schedule->GetServiceID(), uEventID));
|
||||
pEvent = Schedule->AddEvent(new cEventInfo(Schedule->GetChannelID(), uEventID));
|
||||
if (pEvent) {
|
||||
pEvent->SetTableID(uTableID);
|
||||
pEvent->SetTime(tTime);
|
||||
@ -404,24 +404,24 @@ bool cEventInfo::Read(FILE *f, cSchedule *Schedule)
|
||||
struct tEpgBugFixStats {
|
||||
int hits;
|
||||
int n;
|
||||
unsigned short serviceIDs[MAXEPGBUGFIXCHANS];
|
||||
uint64 channelIDs[MAXEPGBUGFIXCHANS];
|
||||
tEpgBugFixStats(void) { hits = n = 0; }
|
||||
};
|
||||
|
||||
tEpgBugFixStats EpgBugFixStats[MAXEPGBUGFIXSTATS];
|
||||
|
||||
static void EpgBugFixStat(int Number, unsigned int ServiceID)
|
||||
static void EpgBugFixStat(int Number, uint64 ChannelID)
|
||||
{
|
||||
if (0 <= Number && Number < MAXEPGBUGFIXSTATS) {
|
||||
tEpgBugFixStats *p = &EpgBugFixStats[Number];
|
||||
p->hits++;
|
||||
int i = 0;
|
||||
for (; i < p->n; i++) {
|
||||
if (p->serviceIDs[i] == ServiceID)
|
||||
if (p->channelIDs[i] == ChannelID)
|
||||
break;
|
||||
}
|
||||
if (i == p->n && p->n < MAXEPGBUGFIXCHANS)
|
||||
p->serviceIDs[p->n++] = ServiceID;
|
||||
p->channelIDs[p->n++] = ChannelID;
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,7 +448,7 @@ static void ReportEpgBugFixStats(bool Reset = false)
|
||||
char *q = buffer;
|
||||
q += snprintf(q, sizeof(buffer) - (q - buffer), "%d\t%d", i, p->hits);
|
||||
for (int c = 0; c < p->n; c++) {
|
||||
cChannel *channel = Channels.GetByServiceID(p->serviceIDs[c]);
|
||||
cChannel *channel = Channels.GetByChannelID(p->channelIDs[c]);
|
||||
if (channel) {
|
||||
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s%s", delim, channel->Name());
|
||||
delim = ", ";
|
||||
@ -499,7 +499,7 @@ void cEventInfo::FixEpgBugs(void)
|
||||
char *s = e ? strdup(e) : NULL;
|
||||
free(pSubtitle);
|
||||
pSubtitle = s;
|
||||
EpgBugFixStat(0, GetServiceID());
|
||||
EpgBugFixStat(0, GetChannelID());
|
||||
// now the fixes #1 and #2 below will handle the rest
|
||||
}
|
||||
}
|
||||
@ -524,7 +524,7 @@ void cEventInfo::FixEpgBugs(void)
|
||||
free(pExtendedDescription);
|
||||
pSubtitle = s;
|
||||
pExtendedDescription = d;
|
||||
EpgBugFixStat(1, GetServiceID());
|
||||
EpgBugFixStat(1, GetChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -541,7 +541,7 @@ void cEventInfo::FixEpgBugs(void)
|
||||
memmove(pSubtitle, pSubtitle + 1, strlen(pSubtitle));
|
||||
pExtendedDescription = pSubtitle;
|
||||
pSubtitle = NULL;
|
||||
EpgBugFixStat(2, GetServiceID());
|
||||
EpgBugFixStat(2, GetChannelID());
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,7 +553,7 @@ void cEventInfo::FixEpgBugs(void)
|
||||
if (pSubtitle && strcmp(pTitle, pSubtitle) == 0) {
|
||||
free(pSubtitle);
|
||||
pSubtitle = NULL;
|
||||
EpgBugFixStat(3, GetServiceID());
|
||||
EpgBugFixStat(3, GetChannelID());
|
||||
}
|
||||
|
||||
// ZDF.info puts the Subtitle between double quotes, which is nothing
|
||||
@ -569,7 +569,7 @@ void cEventInfo::FixEpgBugs(void)
|
||||
char *p = strrchr(pSubtitle, '"');
|
||||
if (p)
|
||||
*p = 0;
|
||||
EpgBugFixStat(4, GetServiceID());
|
||||
EpgBugFixStat(4, GetChannelID());
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,7 +590,7 @@ void cEventInfo::FixEpgBugs(void)
|
||||
if (*p == '-' && *(p + 1) == ' ' && *(p + 2) && islower(*(p - 1)) && islower(*(p + 2))) {
|
||||
if (!startswith(p + 2, "und ")) { // special case in German, as in "Lach- und Sachgeschichten"
|
||||
memmove(p, p + 2, strlen(p + 2) + 1);
|
||||
EpgBugFixStat(5, GetServiceID());
|
||||
EpgBugFixStat(5, GetChannelID());
|
||||
}
|
||||
}
|
||||
p++;
|
||||
@ -608,10 +608,10 @@ void cEventInfo::FixEpgBugs(void)
|
||||
|
||||
// --- cSchedule -------------------------------------------------------------
|
||||
|
||||
cSchedule::cSchedule(unsigned short servid)
|
||||
cSchedule::cSchedule(uint64 channelid)
|
||||
{
|
||||
pPresent = pFollowing = NULL;
|
||||
uServiceID = servid;
|
||||
uChannelID = channelid;
|
||||
}
|
||||
|
||||
|
||||
@ -645,14 +645,14 @@ const cEventInfo *cSchedule::GetFollowingEvent(void) const
|
||||
return pe;
|
||||
}
|
||||
|
||||
void cSchedule::SetServiceID(unsigned short servid)
|
||||
void cSchedule::SetChannelID(uint64 channelid)
|
||||
{
|
||||
uServiceID = servid;
|
||||
uChannelID = channelid;
|
||||
}
|
||||
/** */
|
||||
unsigned short cSchedule::GetServiceID() const
|
||||
uint64 cSchedule::GetChannelID() const
|
||||
{
|
||||
return uServiceID;
|
||||
return uChannelID;
|
||||
}
|
||||
/** */
|
||||
const cEventInfo * cSchedule::GetEvent(unsigned short uEventID, time_t tTime) const
|
||||
@ -735,10 +735,10 @@ void cSchedule::Cleanup(time_t tTime)
|
||||
/** */
|
||||
void cSchedule::Dump(FILE *f, const char *Prefix) const
|
||||
{
|
||||
cChannel *channel = Channels.GetByServiceID(uServiceID);
|
||||
cChannel *channel = Channels.GetByChannelID(uChannelID);
|
||||
if (channel)
|
||||
{
|
||||
fprintf(f, "%sC %u %s\n", Prefix, uServiceID, channel->Name());
|
||||
fprintf(f, "%sC %s %s\n", Prefix, channel->GetChannelIDStr(), channel->Name());
|
||||
for (cEventInfo *p = Events.First(); p; p = Events.Next(p))
|
||||
p->Dump(f, Prefix);
|
||||
fprintf(f, "%sc\n", Prefix);
|
||||
@ -751,14 +751,24 @@ bool cSchedule::Read(FILE *f, cSchedules *Schedules)
|
||||
char *s;
|
||||
while ((s = readline(f)) != NULL) {
|
||||
if (*s == 'C') {
|
||||
unsigned int uServiceID;
|
||||
if (1 == sscanf(s + 1, "%u", &uServiceID)) {
|
||||
cSchedule *p = (cSchedule *)Schedules->AddServiceID(uServiceID);
|
||||
s = skipspace(s + 1);
|
||||
char *p = strchr(s, ' ');
|
||||
if (p)
|
||||
*p = 0; // strips optional channel name
|
||||
if (*s) {
|
||||
uint64 uChannelID = cChannel::StringToChannelID(s);
|
||||
if (uChannelID) {
|
||||
cSchedule *p = (cSchedule *)Schedules->AddChannelID(uChannelID);
|
||||
if (p) {
|
||||
if (!cEventInfo::Read(f, p))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: illegal channel ID: %s", s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: unexpected tag while reading EPG data: %s", s);
|
||||
@ -775,28 +785,28 @@ bool cSchedule::Read(FILE *f, cSchedules *Schedules)
|
||||
cSchedules::cSchedules()
|
||||
{
|
||||
pCurrentSchedule = NULL;
|
||||
uCurrentServiceID = 0;
|
||||
uCurrentChannelID = 0;
|
||||
}
|
||||
|
||||
cSchedules::~cSchedules()
|
||||
{
|
||||
}
|
||||
/** */
|
||||
const cSchedule *cSchedules::AddServiceID(unsigned short servid)
|
||||
const cSchedule *cSchedules::AddChannelID(uint64 channelid)
|
||||
{
|
||||
const cSchedule *p = GetSchedule(servid);
|
||||
const cSchedule *p = GetSchedule(channelid);
|
||||
if (!p) {
|
||||
Add(new cSchedule(servid));
|
||||
p = GetSchedule(servid);
|
||||
Add(new cSchedule(channelid));
|
||||
p = GetSchedule(channelid);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
/** */
|
||||
const cSchedule *cSchedules::SetCurrentServiceID(unsigned short servid)
|
||||
const cSchedule *cSchedules::SetCurrentChannelID(uint64 channelid)
|
||||
{
|
||||
pCurrentSchedule = AddServiceID(servid);
|
||||
pCurrentSchedule = AddChannelID(channelid);
|
||||
if (pCurrentSchedule)
|
||||
uCurrentServiceID = servid;
|
||||
uCurrentChannelID = channelid;
|
||||
return pCurrentSchedule;
|
||||
}
|
||||
/** */
|
||||
@ -805,14 +815,14 @@ const cSchedule * cSchedules::GetSchedule() const
|
||||
return pCurrentSchedule;
|
||||
}
|
||||
/** */
|
||||
const cSchedule * cSchedules::GetSchedule(unsigned short servid) const
|
||||
const cSchedule * cSchedules::GetSchedule(uint64 channelid) const
|
||||
{
|
||||
cSchedule *p;
|
||||
|
||||
p = First();
|
||||
while (p != NULL)
|
||||
{
|
||||
if (p->GetServiceID() == servid)
|
||||
if (p->GetChannelID() == channelid)
|
||||
return p;
|
||||
p = Next(p);
|
||||
}
|
||||
@ -856,7 +866,7 @@ public:
|
||||
cEIT(unsigned char *buf, int length, cSchedules *Schedules);
|
||||
~cEIT();
|
||||
/** */
|
||||
int ProcessEIT(unsigned char *buffer);
|
||||
int ProcessEIT(unsigned char *buffer, int CurrentSource);
|
||||
|
||||
protected: // Protected methods
|
||||
/** returns true if this EIT covers a
|
||||
@ -879,7 +889,7 @@ cEIT::~cEIT()
|
||||
}
|
||||
|
||||
/** */
|
||||
int cEIT::ProcessEIT(unsigned char *buffer)
|
||||
int cEIT::ProcessEIT(unsigned char *buffer, int CurrentSource)
|
||||
{
|
||||
cEventInfo *pEvent, *rEvent = NULL;
|
||||
cSchedule *pSchedule, *rSchedule = NULL;
|
||||
@ -893,18 +903,19 @@ int cEIT::ProcessEIT(unsigned char *buffer)
|
||||
|
||||
if (VdrProgramInfos) {
|
||||
for (VdrProgramInfo = (struct VdrProgramInfo *) VdrProgramInfos->Head; VdrProgramInfo; VdrProgramInfo = (struct VdrProgramInfo *) xSucc (VdrProgramInfo)) {
|
||||
// Drop events that belong to an "other TS" and are very long (some stations broadcast bogus data for "other" channels):
|
||||
if (VdrProgramInfo->Duration >= 86400 && (tid == 0x4F || tid == 0x60 || tid == 0x61))
|
||||
continue;
|
||||
pSchedule = (cSchedule *)schedules->GetSchedule(VdrProgramInfo->ServiceID);
|
||||
//XXX TODO use complete channel ID
|
||||
cChannel *channel = Channels.GetByServiceID(CurrentSource, VdrProgramInfo->ServiceID);
|
||||
uint64 channelID = channel ? channel->GetChannelID() : (uint64(CurrentSource) << 48) | VdrProgramInfo->ServiceID;
|
||||
//XXX
|
||||
pSchedule = (cSchedule *)schedules->GetSchedule(channelID);
|
||||
if (!pSchedule) {
|
||||
schedules->Add(new cSchedule(VdrProgramInfo->ServiceID));
|
||||
pSchedule = (cSchedule *)schedules->GetSchedule(VdrProgramInfo->ServiceID);
|
||||
schedules->Add(new cSchedule(channelID));
|
||||
pSchedule = (cSchedule *)schedules->GetSchedule(channelID);
|
||||
if (!pSchedule)
|
||||
break;
|
||||
}
|
||||
if (VdrProgramInfo->ReferenceServiceID) {
|
||||
rSchedule = (cSchedule *)schedules->GetSchedule(VdrProgramInfo->ReferenceServiceID);
|
||||
rSchedule = (cSchedule *)schedules->GetSchedule((uint64(CurrentSource) << 48) | VdrProgramInfo->ReferenceServiceID);
|
||||
if (!rSchedule)
|
||||
break;
|
||||
rEvent = (cEventInfo *)rSchedule->GetEvent((unsigned short)VdrProgramInfo->ReferenceEventID);
|
||||
@ -915,7 +926,7 @@ int cEIT::ProcessEIT(unsigned char *buffer)
|
||||
if (!pEvent) {
|
||||
// If we don't have that event ID yet, we create a new one.
|
||||
// Otherwise we copy the information into the existing event anyway, because the data might have changed.
|
||||
pEvent = pSchedule->AddEvent(new cEventInfo(VdrProgramInfo->ServiceID, VdrProgramInfo->EventID));
|
||||
pEvent = pSchedule->AddEvent(new cEventInfo(channelID, VdrProgramInfo->EventID));
|
||||
if (!pEvent)
|
||||
break;
|
||||
pEvent->SetTableID(tid);
|
||||
@ -988,6 +999,8 @@ cSIProcessor::cSIProcessor(const char *FileName)
|
||||
{
|
||||
fileName = strdup(FileName);
|
||||
masterSIProcessor = numSIProcessors == 0; // the first one becomes the 'master'
|
||||
currentSource = 0;
|
||||
currentTransponder = 0;
|
||||
filters = NULL;
|
||||
if (!numSIProcessors++) // the first one creates it
|
||||
schedules = new cSchedules;
|
||||
@ -1167,7 +1180,7 @@ void cSIProcessor::Action()
|
||||
{
|
||||
cMutexLock MutexLock(&schedulesMutex);
|
||||
cEIT ceit(buf, seclen, schedules);
|
||||
ceit.ProcessEIT(buf);
|
||||
ceit.ProcessEIT(buf, currentSource);
|
||||
}
|
||||
else
|
||||
dsyslog("Received stuffing section in EIT\n");
|
||||
@ -1250,16 +1263,17 @@ bool cSIProcessor::ShutDownFilters(void)
|
||||
}
|
||||
|
||||
/** */
|
||||
void cSIProcessor::SetCurrentTransponder(int CurrentTransponder)
|
||||
void cSIProcessor::SetCurrentTransponder(int CurrentSource, int CurrentTransponder)
|
||||
{
|
||||
currentSource = CurrentSource;
|
||||
currentTransponder = CurrentTransponder;
|
||||
}
|
||||
|
||||
/** */
|
||||
bool cSIProcessor::SetCurrentServiceID(unsigned short servid)
|
||||
bool cSIProcessor::SetCurrentChannelID(uint64 channelid)
|
||||
{
|
||||
cMutexLock MutexLock(&schedulesMutex);
|
||||
return schedules ? schedules->SetCurrentServiceID(servid) : false;
|
||||
return schedules ? schedules->SetCurrentChannelID(channelid) : false;
|
||||
}
|
||||
|
||||
void cSIProcessor::TriggerDump(void)
|
||||
|
31
eit.h
31
eit.h
@ -16,7 +16,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: eit.h 1.20 2002/11/02 12:36:36 kls Exp $
|
||||
* $Id: eit.h 1.21 2002/11/10 12:58:27 kls Exp $
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __EIT_H
|
||||
@ -32,7 +32,7 @@ class cEventInfo : public cListObject {
|
||||
friend class cEIT;
|
||||
private:
|
||||
unsigned char uTableID; // Table ID this event came from
|
||||
unsigned short uServiceID; // Service ID of program for that event
|
||||
uint64 uChannelID; // Channel ID of program for that event
|
||||
bool bIsFollowing; // true if this is the next event on this channel
|
||||
bool bIsPresent; // true if this is the present event running
|
||||
char *pExtendedDescription; // Extended description of this event
|
||||
@ -47,13 +47,13 @@ protected:
|
||||
void SetFollowing(bool foll);
|
||||
void SetPresent(bool pres);
|
||||
void SetTitle(const char *string);
|
||||
void SetServiceID(unsigned short servid);
|
||||
void SetChannelID(uint64 channelid);
|
||||
void SetEventID(unsigned short evid);
|
||||
void SetDuration(long l);
|
||||
void SetTime(time_t t);
|
||||
void SetExtendedDescription(const char *string);
|
||||
void SetSubtitle(const char *string);
|
||||
cEventInfo(unsigned short serviceid, unsigned short eventid);
|
||||
cEventInfo(uint64 channelid, unsigned short eventid);
|
||||
public:
|
||||
~cEventInfo();
|
||||
const unsigned char GetTableID(void) const;
|
||||
@ -68,7 +68,7 @@ public:
|
||||
unsigned short GetEventID(void) const;
|
||||
long GetDuration(void) const;
|
||||
time_t GetTime(void) const;
|
||||
unsigned short GetServiceID(void) const;
|
||||
uint64 GetChannelID(void) const;
|
||||
int GetChannelNumber(void) const { return nChannelNumber; }
|
||||
void SetChannelNumber(int ChannelNumber) const { ((cEventInfo *)this)->nChannelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const'
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
@ -82,21 +82,21 @@ class cSchedule : public cListObject {
|
||||
private:
|
||||
cEventInfo *pPresent;
|
||||
cEventInfo *pFollowing;
|
||||
unsigned short uServiceID;
|
||||
uint64 uChannelID;
|
||||
cList<cEventInfo> Events;
|
||||
protected:
|
||||
void SetServiceID(unsigned short servid);
|
||||
void SetChannelID(uint64 channelid);
|
||||
bool SetFollowingEvent(cEventInfo *pEvent);
|
||||
bool SetPresentEvent(cEventInfo *pEvent);
|
||||
void Cleanup(time_t tTime);
|
||||
void Cleanup(void);
|
||||
cSchedule(unsigned short servid = 0);
|
||||
cSchedule(uint64 channelid = 0);
|
||||
public:
|
||||
~cSchedule();
|
||||
cEventInfo *AddEvent(cEventInfo *EventInfo);
|
||||
const cEventInfo *GetPresentEvent(void) const;
|
||||
const cEventInfo *GetFollowingEvent(void) const;
|
||||
unsigned short GetServiceID(void) const;
|
||||
uint64 GetChannelID(void) const;
|
||||
const cEventInfo *GetEvent(unsigned short uEventID, time_t tTime = 0) const;
|
||||
const cEventInfo *GetEventAround(time_t tTime) const;
|
||||
const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
|
||||
@ -110,15 +110,15 @@ class cSchedules : public cList<cSchedule> {
|
||||
friend class cSIProcessor;
|
||||
private:
|
||||
const cSchedule *pCurrentSchedule;
|
||||
unsigned short uCurrentServiceID;
|
||||
uint64 uCurrentChannelID;
|
||||
protected:
|
||||
const cSchedule *AddServiceID(unsigned short servid);
|
||||
const cSchedule *SetCurrentServiceID(unsigned short servid);
|
||||
const cSchedule *AddChannelID(uint64 channelid);
|
||||
const cSchedule *SetCurrentChannelID(uint64 channelid);
|
||||
void Cleanup();
|
||||
public:
|
||||
cSchedules(void);
|
||||
~cSchedules();
|
||||
const cSchedule *GetSchedule(unsigned short servid) const;
|
||||
const cSchedule *GetSchedule(uint64 channelid) const;
|
||||
const cSchedule *GetSchedule(void) const;
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
static bool Read(FILE *f);
|
||||
@ -141,6 +141,7 @@ private:
|
||||
static const char *epgDataFileName;
|
||||
static time_t lastDump;
|
||||
bool masterSIProcessor;
|
||||
int currentSource;
|
||||
int currentTransponder;
|
||||
SIP_FILTER *filters;
|
||||
char *fileName;
|
||||
@ -160,8 +161,8 @@ public:
|
||||
static bool Read(FILE *f = NULL);
|
||||
static void Clear(void);
|
||||
void SetStatus(bool On);
|
||||
void SetCurrentTransponder(int CurrentTransponder);
|
||||
static bool SetCurrentServiceID(unsigned short servid);
|
||||
void SetCurrentTransponder(int CurrentSource, int CurrentTransponder);
|
||||
static bool SetCurrentChannelID(uint64 channelid);
|
||||
static void TriggerDump(void);
|
||||
};
|
||||
|
||||
|
18
i18n.c
18
i18n.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.99 2002/10/27 14:24:00 kls Exp $
|
||||
* $Id: i18n.c 1.100 2002/11/10 12:32:30 kls Exp $
|
||||
*
|
||||
* Translations provided by:
|
||||
*
|
||||
@ -1468,6 +1468,22 @@ const tI18nPhrase Phrases[] = {
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
},
|
||||
{ "Channel settings are not unique!",
|
||||
"Kanaleinstellungen sind nicht eindeutig!",
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
"",//TODO
|
||||
},
|
||||
{ "Channel locked (recording)!",
|
||||
"Kanal blockiert (zeichnet auf)!",
|
||||
"Zaklenjen kanal (snemanje)!",
|
||||
|
69
menu.c
69
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.222 2002/11/01 12:15:45 kls Exp $
|
||||
* $Id: menu.c 1.223 2002/11/10 12:32:42 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -546,16 +546,18 @@ private:
|
||||
cChannel data;
|
||||
void Setup(void);
|
||||
public:
|
||||
cMenuEditChannel(int Index);
|
||||
cMenuEditChannel(cChannel *Channel, bool New = false);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuEditChannel::cMenuEditChannel(int Index)
|
||||
cMenuEditChannel::cMenuEditChannel(cChannel *Channel, bool New)
|
||||
:cOsdMenu(tr("Edit channel"), 14)
|
||||
{
|
||||
channel = Channels.Get(Index);
|
||||
channel = Channel;
|
||||
if (channel) {
|
||||
data = *channel;
|
||||
if (New)
|
||||
channel = NULL;
|
||||
Setup();
|
||||
}
|
||||
}
|
||||
@ -603,11 +605,27 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
|
||||
|
||||
if (state == osUnknown) {
|
||||
if (Key == kOk) {
|
||||
if (channel)
|
||||
if (Channels.HasUniqueChannelID(&data, channel)) {
|
||||
if (channel) {
|
||||
*channel = data;
|
||||
Channels.Save();
|
||||
isyslog("edited channel %d %s", channel->Number(), data.ToText());
|
||||
state = osBack;
|
||||
}
|
||||
else {
|
||||
channel = new cChannel;
|
||||
*channel = data;
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
isyslog("added channel %d %s", channel->Number(), data.ToText());
|
||||
state = osUser1;
|
||||
}
|
||||
Channels.Save();
|
||||
}
|
||||
else {
|
||||
Interface->Error(tr("Channel settings are not unique!"));
|
||||
state = osContinue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Key != kNone && (data.source & cSource::st_Mask) != (oldSource & cSource::st_Mask))
|
||||
Setup();
|
||||
@ -696,10 +714,8 @@ eOSState cMenuChannels::Edit(void)
|
||||
if (HasSubMenu() || Count() == 0)
|
||||
return osContinue;
|
||||
cChannel *ch = Channels.Get(Current());
|
||||
if (ch) {
|
||||
isyslog("editing channel %d", ch->Number());
|
||||
return AddSubMenu(new cMenuEditChannel(Current()));
|
||||
}
|
||||
if (ch)
|
||||
return AddSubMenu(new cMenuEditChannel(ch));
|
||||
return osContinue;
|
||||
}
|
||||
|
||||
@ -707,13 +723,7 @@ eOSState cMenuChannels::New(void)
|
||||
{
|
||||
if (HasSubMenu())
|
||||
return osContinue;
|
||||
cChannel *channel = new cChannel(Channels.Get(Current()));
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
Add(new cMenuChannelItem(channel), true);
|
||||
Channels.Save();
|
||||
isyslog("channel %d added", channel->Number());
|
||||
return AddSubMenu(new cMenuEditChannel(Current()));
|
||||
return AddSubMenu(new cMenuEditChannel(Channels.Get(Current()), true));
|
||||
}
|
||||
|
||||
eOSState cMenuChannels::Del(void)
|
||||
@ -753,6 +763,16 @@ eOSState cMenuChannels::ProcessKey(eKeys Key)
|
||||
{
|
||||
eOSState state = cOsdMenu::ProcessKey(Key);
|
||||
|
||||
switch (state) {
|
||||
case osUser1: {
|
||||
cChannel *channel = Channels.Last();
|
||||
if (channel) {
|
||||
Add(new cMenuChannelItem(channel), true);
|
||||
return CloseSubMenu();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: return Switch();
|
||||
@ -763,6 +783,7 @@ eOSState cMenuChannels::ProcessKey(eKeys Key)
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -1068,7 +1089,7 @@ cMenuEvent::cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch)
|
||||
{
|
||||
eventInfo = EventInfo;
|
||||
if (eventInfo) {
|
||||
cChannel *channel = Channels.GetByServiceID(eventInfo->GetServiceID());
|
||||
cChannel *channel = Channels.GetByChannelID(eventInfo->GetChannelID());
|
||||
if (channel) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->Name(), 5, eventInfo->GetDate(), eventInfo->GetTimeString(), eventInfo->GetEndTimeString());
|
||||
@ -1162,7 +1183,7 @@ cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentCha
|
||||
|
||||
pArray[num] = Now ? Schedule->GetPresentEvent() : Schedule->GetFollowingEvent();
|
||||
if (pArray[num]) {
|
||||
cChannel *channel = Channels.GetByServiceID(pArray[num]->GetServiceID());
|
||||
cChannel *channel = Channels.GetByChannelID(pArray[num]->GetChannelID());
|
||||
if (channel) {
|
||||
pArray[num]->SetChannelNumber(channel->Number());
|
||||
num++;
|
||||
@ -1192,7 +1213,7 @@ eOSState cMenuWhatsOn::Switch(void)
|
||||
{
|
||||
cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current());
|
||||
if (item) {
|
||||
cChannel *channel = Channels.GetByServiceID(item->eventInfo->GetServiceID());
|
||||
cChannel *channel = Channels.GetByChannelID(item->eventInfo->GetChannelID());
|
||||
if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
|
||||
return osEnd;
|
||||
}
|
||||
@ -1313,7 +1334,7 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel)
|
||||
SetTitle(buffer);
|
||||
free(buffer);
|
||||
if (schedules) {
|
||||
const cSchedule *Schedule = Channel->Sid() ? schedules->GetSchedule(Channel->Sid()) : schedules->GetSchedule();
|
||||
const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID());
|
||||
int num = Schedule->NumEvents();
|
||||
const cEventInfo **pArray = MALLOC(const cEventInfo *, num);
|
||||
if (pArray) {
|
||||
@ -1376,7 +1397,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
|
||||
if (!now && !next) {
|
||||
int ChannelNr = 0;
|
||||
if (Count()) {
|
||||
cChannel *channel = Channels.GetByServiceID(((cMenuScheduleItem *)Get(Current()))->eventInfo->GetServiceID());
|
||||
cChannel *channel = Channels.GetByChannelID(((cMenuScheduleItem *)Get(Current()))->eventInfo->GetChannelID());
|
||||
if (channel)
|
||||
ChannelNr = channel->Number();
|
||||
}
|
||||
@ -1403,7 +1424,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
|
||||
now = next = false;
|
||||
const cEventInfo *ei = cMenuWhatsOn::ScheduleEventInfo();
|
||||
if (ei) {
|
||||
cChannel *channel = Channels.GetByServiceID(ei->GetServiceID());
|
||||
cChannel *channel = Channels.GetByChannelID(ei->GetChannelID());
|
||||
if (channel) {
|
||||
PrepareSchedule(channel);
|
||||
if (channel->Number() != cDevice::CurrentChannel()) {
|
||||
@ -2713,7 +2734,7 @@ bool cRecordControl::GetEventInfo(void)
|
||||
cMutexLock MutexLock;
|
||||
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(channel->Sid());
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
eventInfo = Schedule->GetEventAround(Time);
|
||||
if (eventInfo) {
|
||||
|
22
osd.c
22
osd.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osd.c 1.36 2002/10/13 10:31:28 kls Exp $
|
||||
* $Id: osd.c 1.37 2002/11/10 12:30:09 kls Exp $
|
||||
*/
|
||||
|
||||
#include "osd.h"
|
||||
@ -599,20 +599,24 @@ eOSState cOsdMenu::AddSubMenu(cOsdMenu *SubMenu)
|
||||
delete subMenu;
|
||||
subMenu = SubMenu;
|
||||
subMenu->Display();
|
||||
return osContinue; // convenience return value (see cMenuMain)
|
||||
return osContinue; // convenience return value
|
||||
}
|
||||
|
||||
eOSState cOsdMenu::CloseSubMenu()
|
||||
{
|
||||
delete subMenu;
|
||||
subMenu = NULL;
|
||||
RefreshCurrent();
|
||||
Display();
|
||||
return osContinue; // convenience return value
|
||||
}
|
||||
|
||||
eOSState cOsdMenu::ProcessKey(eKeys Key)
|
||||
{
|
||||
if (subMenu) {
|
||||
eOSState state = subMenu->ProcessKey(Key);
|
||||
if (state == osBack) {
|
||||
delete subMenu;
|
||||
subMenu = NULL;
|
||||
RefreshCurrent();
|
||||
Display();
|
||||
state = osContinue;
|
||||
}
|
||||
if (state == osBack)
|
||||
return CloseSubMenu();
|
||||
return state;
|
||||
}
|
||||
|
||||
|
3
osd.h
3
osd.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osd.h 1.35 2002/11/03 18:03:55 kls Exp $
|
||||
* $Id: osd.h 1.36 2002/11/10 12:28:57 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSD_H
|
||||
@ -147,6 +147,7 @@ protected:
|
||||
void Mark(void);
|
||||
eOSState HotKey(eKeys Key);
|
||||
eOSState AddSubMenu(cOsdMenu *SubMenu);
|
||||
eOSState CloseSubMenu();
|
||||
bool HasSubMenu(void) { return subMenu; }
|
||||
void SetStatus(const char *s);
|
||||
void SetTitle(const char *Title, bool ShowDate = true);
|
||||
|
4
remote.h
4
remote.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: remote.h 1.19 2002/11/01 10:48:11 kls Exp $
|
||||
* $Id: remote.h 1.20 2002/11/09 11:07:33 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __REMOTE_H
|
||||
@ -16,8 +16,6 @@
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
typedef unsigned long long int uint64;
|
||||
|
||||
class cRemote : public cListObject {
|
||||
private:
|
||||
enum { MaxKeys = MAXKEYSINMACRO };
|
||||
|
31
svdrp.c
31
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 1.48 2002/10/20 12:45:03 kls Exp $
|
||||
* $Id: svdrp.c 1.49 2002/11/10 12:09:56 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -776,16 +776,21 @@ void cSVDRP::CmdMODC(const char *Option)
|
||||
tail = skipspace(tail);
|
||||
cChannel *channel = Channels.GetByNumber(n);
|
||||
if (channel) {
|
||||
cChannel c = *channel;
|
||||
if (!c.Parse(tail)) {
|
||||
Reply(501, "Error in channel settings");
|
||||
return;
|
||||
}
|
||||
*channel = c;
|
||||
cChannel ch;
|
||||
if (ch.Parse(tail, true)) {
|
||||
if (Channels.HasUniqueChannelID(&ch, channel)) {
|
||||
*channel = ch;
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
isyslog("channel %d modified", channel->Number());
|
||||
isyslog("modifed channel %d %s", channel->Number(), channel->ToText());
|
||||
Reply(250, "%d %s", channel->Number(), channel->ToText());
|
||||
}
|
||||
else
|
||||
Reply(501, "Channel settings are not unique");
|
||||
}
|
||||
else
|
||||
Reply(501, "Error in channel settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Channel \"%d\" not defined", n);
|
||||
}
|
||||
@ -844,14 +849,20 @@ void cSVDRP::CmdMOVT(const char *Option)
|
||||
void cSVDRP::CmdNEWC(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
cChannel ch;
|
||||
if (ch.Parse(Option, true)) {
|
||||
if (Channels.HasUniqueChannelID(&ch)) {
|
||||
cChannel *channel = new cChannel;
|
||||
if (channel->Parse(Option)) {
|
||||
*channel = ch;
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
isyslog("channel %d added", channel->Number());
|
||||
isyslog("new channel %d %s", channel->Number(), channel->ToText());
|
||||
Reply(250, "%d %s", channel->Number(), channel->ToText());
|
||||
}
|
||||
else
|
||||
Reply(501, "Channel settings are not unique");
|
||||
}
|
||||
else
|
||||
Reply(501, "Error in channel settings");
|
||||
}
|
||||
|
53
timers.c
53
timers.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.c 1.1 2002/10/20 12:28:55 kls Exp $
|
||||
* $Id: timers.c 1.2 2002/11/10 10:19:12 kls Exp $
|
||||
*/
|
||||
|
||||
#include "timers.h"
|
||||
@ -49,7 +49,7 @@ cTimer::cTimer(const cEventInfo *EventInfo)
|
||||
startTime = stopTime = 0;
|
||||
recording = pending = false;
|
||||
active = true;
|
||||
channel = Channels.GetByServiceID(EventInfo->GetServiceID());
|
||||
channel = Channels.GetByChannelID(EventInfo->GetChannelID());
|
||||
time_t tstart = EventInfo->GetTime();
|
||||
time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
|
||||
tstart -= Setup.MarginStart * 60;
|
||||
@ -92,22 +92,17 @@ bool cTimer::operator< (const cListObject &ListObject)
|
||||
return t1 < t2 || (t1 == t2 && priority > ti->priority);
|
||||
}
|
||||
|
||||
const char *cTimer::ToText(cTimer *Timer)
|
||||
const char *cTimer::ToText(bool UseChannelID)
|
||||
{
|
||||
free(buffer);
|
||||
strreplace(Timer->file, ':', '|');
|
||||
strreplace(Timer->summary, '\n', '|');
|
||||
asprintf(&buffer, "%d:%d:%s:%04d:%04d:%d:%d:%s:%s\n", Timer->active, Timer->Channel()->Number(), PrintDay(Timer->day, Timer->firstday), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file, Timer->summary ? Timer->summary : "");
|
||||
strreplace(Timer->summary, '|', '\n');
|
||||
strreplace(Timer->file, '|', ':');
|
||||
strreplace(file, ':', '|');
|
||||
strreplace(summary, '\n', '|');
|
||||
asprintf(&buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s\n", active, UseChannelID ? Channel()->GetChannelIDStr() : itoa(Channel()->Number()), PrintDay(day, firstday), start, stop, priority, lifetime, file, summary ? summary : "");
|
||||
strreplace(summary, '|', '\n');
|
||||
strreplace(file, '|', ':');
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *cTimer::ToText(void)
|
||||
{
|
||||
return ToText(this);
|
||||
}
|
||||
|
||||
int cTimer::TimeToInt(int t)
|
||||
{
|
||||
return (t / 100 * 60 + t % 100) * 60;
|
||||
@ -189,8 +184,9 @@ const char *cTimer::PrintFirstDay(void)
|
||||
|
||||
bool cTimer::Parse(const char *s)
|
||||
{
|
||||
char *buffer1 = NULL;
|
||||
char *buffer2 = NULL;
|
||||
char *channelbuffer = NULL;
|
||||
char *daybuffer = NULL;
|
||||
char *filebuffer = NULL;
|
||||
free(summary);
|
||||
summary = NULL;
|
||||
//XXX Apparently sscanf() doesn't work correctly if the last %a argument
|
||||
@ -208,34 +204,35 @@ bool cTimer::Parse(const char *s)
|
||||
strcat(strn0cpy(s2, s, l2 + 1), " \n");
|
||||
s = s2;
|
||||
}
|
||||
int ch = 0;
|
||||
if (8 <= sscanf(s, "%d :%d :%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &active, &ch, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
|
||||
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 (summary && !*skipspace(summary)) {
|
||||
free(summary);
|
||||
summary = NULL;
|
||||
}
|
||||
//TODO add more plausibility checks
|
||||
day = ParseDay(buffer1, &firstday);
|
||||
strn0cpy(file, buffer2, MaxFileName);
|
||||
day = ParseDay(daybuffer, &firstday);
|
||||
result = day != 0;
|
||||
strn0cpy(file, filebuffer, MaxFileName);
|
||||
strreplace(file, '|', ':');
|
||||
strreplace(summary, '|', '\n');
|
||||
free(buffer1);
|
||||
free(buffer2);
|
||||
free(s2);
|
||||
channel = Channels.GetByNumber(ch);
|
||||
uint64 cid = cChannel::StringToChannelID(channelbuffer);
|
||||
channel = cid ? Channels.GetByChannelID(cid) : Channels.GetByNumber(atoi(channelbuffer));
|
||||
if (!channel) {
|
||||
esyslog("ERROR: channel %d not defined", ch);
|
||||
return false;
|
||||
esyslog("ERROR: channel %s not defined", channelbuffer);
|
||||
result = false;
|
||||
}
|
||||
return day != 0;
|
||||
}
|
||||
free(channelbuffer);
|
||||
free(daybuffer);
|
||||
free(filebuffer);
|
||||
free(s2);
|
||||
return false;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cTimer::Save(FILE *f)
|
||||
{
|
||||
return fprintf(f, ToText()) > 0;
|
||||
return fprintf(f, ToText(true)) > 0;
|
||||
}
|
||||
|
||||
bool cTimer::IsSingleEvent(void)
|
||||
|
5
timers.h
5
timers.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.h 1.1 2002/10/20 11:52:23 kls Exp $
|
||||
* $Id: timers.h 1.2 2002/11/10 10:17:05 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TIMERS_H
|
||||
@ -36,7 +36,6 @@ private:
|
||||
char file[MaxFileName];
|
||||
time_t firstday;
|
||||
char *summary;
|
||||
static const char *ToText(cTimer *Timer);
|
||||
public:
|
||||
cTimer(bool Instant = false);
|
||||
cTimer(const cEventInfo *EventInfo);
|
||||
@ -55,7 +54,7 @@ public:
|
||||
const char *File(void) { return file; }
|
||||
time_t FirstDay(void) { return firstday; }
|
||||
const char *Summary(void) { return summary; }
|
||||
const char *ToText(void);
|
||||
const char *ToText(bool UseChannelID = false);
|
||||
bool Parse(const char *s);
|
||||
bool Save(FILE *f);
|
||||
bool IsSingleEvent(void);
|
||||
|
9
tools.c
9
tools.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.c 1.72 2002/10/19 12:32:53 kls Exp $
|
||||
* $Id: tools.c 1.73 2002/11/09 15:33:47 kls Exp $
|
||||
*/
|
||||
|
||||
#include "tools.h"
|
||||
@ -243,6 +243,13 @@ bool isnumber(const char *s)
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *itoa(int n)
|
||||
{
|
||||
static char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%d", n);
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *AddDirectory(const char *DirName, const char *FileName)
|
||||
{
|
||||
static char *buf = NULL;
|
||||
|
4
tools.h
4
tools.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: tools.h 1.51 2002/10/19 12:31:50 kls Exp $
|
||||
* $Id: tools.h 1.52 2002/11/09 15:32:36 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TOOLS_H
|
||||
@ -20,6 +20,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned long long int uint64;
|
||||
|
||||
extern int SysLogLevel;
|
||||
|
||||
@ -68,6 +69,7 @@ int numdigits(int n);
|
||||
int time_ms(void);
|
||||
void delay_ms(int ms);
|
||||
bool isnumber(const char *s);
|
||||
const char *itoa(int n); // returns a statically allocated string!
|
||||
const char *AddDirectory(const char *DirName, const char *FileName); // returns a statically allocated string!
|
||||
int FreeDiskSpaceMB(const char *Directory, int *UsedMB = NULL);
|
||||
bool DirectoryOk(const char *DirName, bool LogErrors = false);
|
||||
|
30
vdr.5
30
vdr.5
@ -8,9 +8,9 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 1.11 2002/10/27 15:36:44 kls Exp $
|
||||
.\" $Id: vdr.5 1.12 2002/11/10 10:10:15 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "7 Oct 2002" "1.2.0" "Video Disk Recorder Files"
|
||||
.TH vdr 5 "10 Nov 2002" "1.2.0" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
vdr file formats - the Video Disk Recorder Files
|
||||
.SH DESCRIPTION
|
||||
@ -120,6 +120,18 @@ l l.
|
||||
.TP
|
||||
.B SID
|
||||
The service ID of this channel.
|
||||
.PP
|
||||
A particular channel can be uniquely identified by its \fBchannel\ ID\fR,
|
||||
which is a string that looks like this:
|
||||
|
||||
\fBS19.2E-0-12188-12003\fR
|
||||
|
||||
The components of this string are the \fBSource\fR (S19.2E), \fBFrequency\fR
|
||||
(12188, MHz) and \fBSID\fR (12003) as defined above. The part that is currently
|
||||
\fB0\fR is reserved for future use.
|
||||
.br
|
||||
The \fBchannel\ ID\fR is used in the \fItimers.conf\fR and \fIepg.data\fR
|
||||
files to properly identify the channels.
|
||||
.SS TIMERS
|
||||
The file \fItimers.conf\fR contains the timer setup.
|
||||
Each line contains one timer definition, with individual fields
|
||||
@ -143,7 +155,13 @@ Note: in order to allow future extensibility, external programs using the
|
||||
and leave the lower 16 bit untouched.
|
||||
.TP
|
||||
.B Channel
|
||||
The number of the channel to record.
|
||||
The channel to record from. This is either the channel number as shown in the
|
||||
on-screen menus, or a complete channel ID. When reading \fItimers.conf\fR
|
||||
any channel numbers will be mapped to the respective channel ids and when
|
||||
the file is written again, there will only be channel ids. Channel numbers
|
||||
are accepted as input in order to allow easier creation of timers when
|
||||
manually editing \fItimers.conf\fR. Also, when timers are listed via SVDRP
|
||||
commands, the channels are given as numbers.
|
||||
.TP
|
||||
.B Day
|
||||
The day when this timer shall record.
|
||||
@ -472,7 +490,7 @@ The following tag characters are defined:
|
||||
.TS
|
||||
tab (@);
|
||||
l l.
|
||||
\fBC\fR@<service id> <channel name>
|
||||
\fBC\fR@<channel id> <channel name>
|
||||
\fBE\fR@<event id> <start time> <duration> <table id>
|
||||
\fBT\fR@<title>
|
||||
\fBS\fR@<subtitle>
|
||||
@ -491,8 +509,8 @@ should at least have a \fBT\fR entry).
|
||||
.TS
|
||||
tab (@);
|
||||
l l.
|
||||
<service id> @is the "program number" as defined in 'channels.conf'
|
||||
<channel name> @is the "name" as in 'channels.conf' (for information only)
|
||||
<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)
|
||||
<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\
|
||||
|
Loading…
Reference in New Issue
Block a user