Implemented gaps in channel numbering

This commit is contained in:
Klaus Schmidinger 2002-10-19 15:33:37 +02:00
parent 16f3d3fc5d
commit ab4ceb29a0
10 changed files with 137 additions and 70 deletions

View File

@ -1619,3 +1619,8 @@ Video Disk Recorder Revision History
- Fixed a small glitch when switching channels (thanks to Dennis Noordsij for - Fixed a small glitch when switching channels (thanks to Dennis Noordsij for
reporting this one). reporting this one).
- Fixed handling multiple 'CaCaps' entries in 'setup.conf'. - Fixed handling multiple 'CaCaps' entries in 'setup.conf'.
- Group separators in 'channels.conf' may now be given like ':@201 My Channels',
where '@201' indicates the number to be given to the next channel. This can be
used to create 'gaps' in the channel numbering (see 'man 5 vdr'). BE CAREFUL
TO UPDATE YOUR 'timers.conf' ACCORDINGLY IF INSERTING THIS NEW FEATURE INTO YOUR
'channels.conf' FILE!

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: channels.c 1.3 2002/10/06 12:41:49 kls Exp $ * $Id: channels.c 1.4 2002/10/19 14:46:05 kls Exp $
*/ */
#include "channels.h" #include "channels.h"
@ -158,6 +158,7 @@ cChannel::cChannel(void)
tpid = 0; tpid = 0;
ca = 0; ca = 0;
sid = 0; sid = 0;
number = 0;
groupSep = false; groupSep = false;
//XXX //XXX
polarization = 'v'; polarization = 'v';
@ -282,8 +283,12 @@ const char *cChannel::ToText(cChannel *Channel)
strreplace(s, ':', '|'); strreplace(s, ':', '|');
} }
free(buffer); free(buffer);
if (Channel->groupSep) if (Channel->groupSep) {
asprintf(&buffer, ":%s\n", s); if (Channel->number)
asprintf(&buffer, ":@%d %s\n", Channel->number, s);
else
asprintf(&buffer, ":%s\n", s);
}
else { else {
char apidbuf[32]; char apidbuf[32];
char *q = apidbuf; char *q = apidbuf;
@ -308,13 +313,17 @@ const char *cChannel::ToText(void)
bool cChannel::Parse(const char *s) bool cChannel::Parse(const char *s)
{ {
if (*s == ':') { if (*s == ':') {
if (*++s) { groupSep = true;
strn0cpy(name, s, MaxChannelName); if (*++s == '@' && *++s) {
groupSep = true; char *p = NULL;
number = 0; errno = 0;
int n = strtol(s, &p, 10);
if (!errno && p != s && n > 0) {
number = n;
s = p;
}
} }
else strn0cpy(name, skipspace(s), MaxChannelName);
return false;
} }
else { else {
groupSep = false; groupSep = false;
@ -400,35 +409,39 @@ int cChannels::GetNextNormal(int Idx)
void cChannels::ReNumber( void ) void cChannels::ReNumber( void )
{ {
int Number = 0; int Number = 1;
cChannel *ch = (cChannel *)First(); for (cChannel *channel = First(); channel; channel = Next(channel)) {
while (ch) { if (channel->GroupSep()) {
if (!ch->GroupSep()) if (channel->Number() > Number)
ch->SetNumber(++Number); Number = channel->Number();
ch = (cChannel *)ch->Next(); }
} else
maxNumber = Number; channel->SetNumber(Number++);
}
maxNumber = Number - 1;
} }
cChannel *cChannels::GetByNumber(int Number) cChannel *cChannels::GetByNumber(int Number, int SkipGap)
{ {
cChannel *channel = (cChannel *)First(); cChannel *previous = NULL;
while (channel) { for (cChannel *channel = First(); channel; channel = Next(channel)) {
if (!channel->GroupSep() && channel->Number() == Number) if (!channel->GroupSep()) {
return channel; if (channel->Number() == Number)
channel = (cChannel *)channel->Next(); return channel;
} else if (SkipGap && channel->Number() > Number)
return SkipGap > 0 ? channel : previous;
previous = channel;
}
}
return NULL; return NULL;
} }
cChannel *cChannels::GetByServiceID(unsigned short ServiceId) cChannel *cChannels::GetByServiceID(unsigned short ServiceId)
{ {
cChannel *channel = (cChannel *)First(); for (cChannel *channel = First(); channel; channel = Next(channel)) {
while (channel) { if (!channel->GroupSep() && channel->Sid() == ServiceId)
if (!channel->GroupSep() && channel->Sid() == ServiceId) return channel;
return channel; }
channel = (cChannel *)channel->Next();
}
return NULL; return NULL;
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: channels.h 1.1 2002/10/05 13:53:15 kls Exp $ * $Id: channels.h 1.2 2002/10/19 11:48:02 kls Exp $
*/ */
#ifndef __CHANNELS_H #ifndef __CHANNELS_H
@ -112,7 +112,7 @@ public:
int GetPrevGroup(int Idx); // Get previous channel group int GetPrevGroup(int Idx); // Get previous channel group
int GetNextNormal(int Idx); // Get next normal channel (not group) int GetNextNormal(int Idx); // Get next normal channel (not group)
void ReNumber(void); // Recalculate 'number' based on channel type void ReNumber(void); // Recalculate 'number' based on channel type
cChannel *GetByNumber(int Number); cChannel *GetByNumber(int Number, int SkipGap = 0);
cChannel *GetByServiceID(unsigned short ServiceId); cChannel *GetByServiceID(unsigned short ServiceId);
const char *GetChannelNameByNumber(int Number); const char *GetChannelNameByNumber(int Number);
bool SwitchTo(int Number); bool SwitchTo(int Number);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.c 1.27 2002/10/12 13:24:37 kls Exp $ * $Id: device.c 1.28 2002/10/19 11:48:02 kls Exp $
*/ */
#include "device.h" #include "device.h"
@ -324,11 +324,11 @@ bool cDevice::SwitchChannel(int Direction)
int first = n; int first = n;
PrimaryDevice()->StopReplay(); // otherwise a running Transfer Mode would block channels PrimaryDevice()->StopReplay(); // otherwise a running Transfer Mode would block channels
cChannel *channel; cChannel *channel;
while ((channel = Channels.GetByNumber(n)) != NULL) { while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
// try only channels which are currently available // try only channels which are currently available
if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || GetDevice(channel, 0)) if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || GetDevice(channel, 0))
break; break;
n += Direction; n = channel->Number() + 1;
} }
if (channel) { if (channel) {
int d = n - first; int d = n - first;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: eitscan.c 1.8 2002/10/05 13:44:35 kls Exp $ * $Id: eitscan.c 1.9 2002/10/19 11:48:02 kls Exp $
*/ */
#include "eitscan.h" #include "eitscan.h"
@ -63,7 +63,7 @@ void cEITScanner::Process(void)
ch = 1; ch = 1;
numTransponders = 0; numTransponders = 0;
} }
cChannel *Channel = Channels.GetByNumber(ch); cChannel *Channel = Channels.GetByNumber(ch, 1);
if (Channel) { if (Channel) {
if (!Device->ProvidesChannel(Channel)) if (!Device->ProvidesChannel(Channel))
break; break;
@ -75,7 +75,7 @@ void cEITScanner::Process(void)
break; break;
} }
} }
ch++; ch = Channel->Number() + 1;
} }
} }
} }

59
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.217 2002/10/13 12:10:54 kls Exp $ * $Id: menu.c 1.218 2002/10/19 15:33:37 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -33,7 +33,7 @@
#define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS) #define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS)
#define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours #define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
#define CHNUMWIDTH (Channels.Count() > 999 ? 5 : 4) // there are people with more than 999 channels... #define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 1)
// --- cMenuEditChanItem ----------------------------------------------------- // --- cMenuEditChanItem -----------------------------------------------------
@ -42,6 +42,7 @@ protected:
virtual void Set(void); virtual void Set(void);
public: public:
cMenuEditChanItem(const char *Name, int *Value); cMenuEditChanItem(const char *Name, int *Value);
virtual eOSState ProcessKey(eKeys Key);
}; };
cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value) cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
@ -54,13 +55,32 @@ void cMenuEditChanItem::Set(void)
{ {
char buf[255]; char buf[255];
cChannel *channel = Channels.GetByNumber(*value); cChannel *channel = Channels.GetByNumber(*value);
if (channel) snprintf(buf, sizeof(buf), "%d %s", *value, channel ? channel->Name() : "");
snprintf(buf, sizeof(buf), "%d %s", *value, channel->Name());
else
*buf = 0;
SetValue(buf); SetValue(buf);
} }
eOSState cMenuEditChanItem::ProcessKey(eKeys Key)
{
int delta = 1;
switch (Key) {
case kLeft|k_Repeat:
case kLeft: delta = -1;
case kRight|k_Repeat:
case kRight:
{
cChannel *channel = Channels.GetByNumber(*value + delta, delta);
if (channel) {
*value = channel->Number();
Set();
}
}
break;
default : return cMenuEditIntItem::ProcessKey(Key);
}
return osContinue;
}
// --- cMenuEditTranItem ----------------------------------------------------- // --- cMenuEditTranItem -----------------------------------------------------
class cMenuEditTranItem : public cMenuEditChanItem { class cMenuEditTranItem : public cMenuEditChanItem {
@ -2383,10 +2403,17 @@ void cDisplayChannel::DisplayChannel(const cChannel *Channel)
{ {
int BufSize = Width() + 1; int BufSize = Width() + 1;
char buffer[BufSize]; char buffer[BufSize];
if (Channel && Channel->Number() > 0) *buffer = 0;
snprintf(buffer, BufSize, "%d%s %s", Channel->Number(), number ? "-" : "", Channel->Name()); if (Channel) {
if (Channel->Number() > 0)
snprintf(buffer, BufSize, "%d%s %s", Channel->Number(), number ? "-" : "", Channel->Name());
else if (Channel->Name())
snprintf(buffer, BufSize, "%s", Channel->Name());
}
else if (number)
snprintf(buffer, BufSize, "%d-", number);
else else
snprintf(buffer, BufSize, "%s", Channel ? Channel->Name() : tr("*** Invalid Channel ***")); snprintf(buffer, BufSize, "%s", tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, Setup.OSDwidth, 1, clrBackground); Interface->Fill(0, 0, Setup.OSDwidth, 1, clrBackground);
Interface->Write(0, 0, buffer); Interface->Write(0, 0, buffer);
const char *date = DayDateTime(); const char *date = DayDateTime();
@ -2468,10 +2495,6 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
cChannel *channel = Channels.GetByNumber(number); cChannel *channel = Channels.GetByNumber(number);
DisplayChannel(channel); DisplayChannel(channel);
lastTime = time_ms(); lastTime = time_ms();
if (!channel) {
number = -1;
lastTime += 1000;
}
} }
} }
break; break;
@ -2505,8 +2528,14 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
break; break;
case kNone: case kNone:
if (number && time_ms() - lastTime > DIRECTCHANNELTIMEOUT) { if (number && time_ms() - lastTime > DIRECTCHANNELTIMEOUT) {
if (number > 0 && !Channels.SwitchTo(number)) if (Channels.GetByNumber(number))
number = -1; Channels.SwitchTo(number);
else {
number = 0;
DisplayChannel(NULL);
lastTime = time_ms();
return osContinue;
}
return osEnd; return osEnd;
} }
break; break;

26
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * graphical interface that sits on top of an SVDRP connection.
* *
* $Id: svdrp.c 1.45 2002/10/13 09:31:31 kls Exp $ * $Id: svdrp.c 1.46 2002/10/19 11:48:02 kls Exp $
*/ */
#include "svdrp.h" #include "svdrp.h"
@ -413,12 +413,12 @@ void cSVDRP::CmdCHAN(const char *Option)
else { else {
int i = 1; int i = 1;
cChannel *channel; cChannel *channel;
while ((channel = Channels.GetByNumber(i)) != NULL) { while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
if (strcasecmp(channel->Name(), Option) == 0) { if (strcasecmp(channel->Name(), Option) == 0) {
n = i; n = i;
break; break;
} }
i++; i = channel->Number() + 1;
} }
} }
if (n < 0) { if (n < 0) {
@ -640,7 +640,7 @@ void cSVDRP::CmdLSTC(const char *Option)
int i = 1; int i = 1;
cChannel *next = NULL; cChannel *next = NULL;
while (i <= Channels.MaxNumber()) { while (i <= Channels.MaxNumber()) {
cChannel *channel = Channels.GetByNumber(i); cChannel *channel = Channels.GetByNumber(i, 1);
if (channel) { if (channel) {
if (strcasestr(channel->Name(), Option)) { if (strcasestr(channel->Name(), Option)) {
if (next) if (next)
@ -652,7 +652,7 @@ void cSVDRP::CmdLSTC(const char *Option)
Reply(501, "Channel \"%d\" not found", i); Reply(501, "Channel \"%d\" not found", i);
return; return;
} }
i++; i = channel->Number() + 1;
} }
if (next) if (next)
Reply(250, "%d %s", next->Number(), next->ToText()); Reply(250, "%d %s", next->Number(), next->ToText());
@ -661,13 +661,15 @@ void cSVDRP::CmdLSTC(const char *Option)
} }
} }
else if (Channels.MaxNumber() >= 1) { else if (Channels.MaxNumber() >= 1) {
for (int i = 1; i <= Channels.MaxNumber(); i++) { int i = 1;
cChannel *channel = Channels.GetByNumber(i); while (i <= Channels.MaxNumber()) {
if (channel) cChannel *channel = Channels.GetByNumber(i, 1);
Reply(i < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->Number(), channel->ToText()); if (channel)
else Reply(channel->Number() < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->Number(), channel->ToText());
Reply(501, "Channel \"%d\" not found", i); else
} Reply(501, "Channel \"%d\" not found", i);
i = channel->Number() + 1;
}
} }
else else
Reply(550, "No channels defined"); Reply(550, "No channels defined");

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 1.71 2002/09/09 21:35:49 kls Exp $ * $Id: tools.c 1.72 2002/10/19 12:32:53 kls Exp $
*/ */
#include "tools.h" #include "tools.h"
@ -207,6 +207,13 @@ bool isempty(const char *s)
return !(s && *skipspace(s)); return !(s && *skipspace(s));
} }
int numdigits(int n)
{
char buf[16];
snprintf(buf, sizeof(buf), "%d", n);
return strlen(buf);
}
int time_ms(void) int time_ms(void)
{ {
static time_t t0 = 0; static time_t t0 = 0;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.50 2002/09/08 10:22:29 kls Exp $ * $Id: tools.h 1.51 2002/10/19 12:31:50 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -64,6 +64,7 @@ const char *strescape(const char *s, const char *chars); // returns a statically
bool startswith(const char *s, const char *p); bool startswith(const char *s, const char *p);
bool endswith(const char *s, const char *p); bool endswith(const char *s, const char *p);
bool isempty(const char *s); bool isempty(const char *s);
int numdigits(int n);
int time_ms(void); int time_ms(void);
void delay_ms(int ms); void delay_ms(int ms);
bool isnumber(const char *s); bool isnumber(const char *s);

16
vdr.5
View File

@ -8,9 +8,9 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 1.8 2002/10/13 12:14:49 kls Exp $ .\" $Id: vdr.5 1.9 2002/10/19 12:45:23 kls Exp $
.\" .\"
.TH vdr 5 "7 Sep 2002" "1.2.0" "Video Disk Recorder Files" .TH vdr 5 "7 Oct 2002" "1.2.0" "Video Disk Recorder Files"
.SH NAME .SH NAME
vdr file formats - the Video Disk Recorder Files vdr file formats - the Video Disk Recorder Files
.SH DESCRIPTION .SH DESCRIPTION
@ -26,12 +26,22 @@ character, followed by arbitrary text. Example:
\fB:First group\fR \fB:First group\fR
Group delimiters may also be used to specify the number of the next channel.
To do this, the character '@' and a number must immediately follow the ':',
as in
\fB:@201 First group\fR
The given number must be larger than the number of any previous channel
(otherwise it is silently ignored).
A \fBchannel definition\fR is a line with channel data, where the fields A \fBchannel definition\fR is a line with channel data, where the fields
are separated by ':' characters. Example: are separated by ':' characters. Example:
\fBRTL:12188:h:S19.2E:27500:163:104:105:0:12003\fR \fBRTL:12188:h:S19.2E:27500:163:104:105:0:12003\fR
The line number of a channel definition (not counting group separators!) The line number of a channel definition (not counting group separators,
and based on a possible previous '@...' parameter)
defines the channel's number in OSD menus and the \fItimers.conf\fR file. defines the channel's number in OSD menus and the \fItimers.conf\fR file.
The fields in a channel definition have the following meaning (from left The fields in a channel definition have the following meaning (from left