mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented 'channel grouping'
This commit is contained in:
parent
d4eb96f725
commit
c00d4ea326
@ -10,6 +10,8 @@ Carsten Koch <Carsten.Koch@icem.de>
|
||||
Plamen Ganev <pganev@com-it.net>
|
||||
for fixing the frequency offset for Hotbird channels
|
||||
for adding the 'xtvrc2vdr' tool (see Tools/xtvrc2vdr)
|
||||
for adding the 'dvbrc2vdr' tool (see Tools/dvbrc2vdr)
|
||||
for implementing "channel grouping"
|
||||
|
||||
Heino Goldenstein <heino.goldenstein@microplex.de>
|
||||
for modifying scrolling through lists to make it page up and down
|
||||
@ -19,3 +21,6 @@ Guido Fiala <gfiala@s.netic.de>
|
||||
|
||||
Robert Schneider <Robert.Schneider@lotus.com>
|
||||
for implementing EIT support for displaying the current/next info
|
||||
|
||||
Niels de Carpentier <niels@casema.net>
|
||||
for adding a workaround for a driver timing problem in cDvbApi::Cmd().
|
||||
|
35
FORMATS
Normal file
35
FORMATS
Normal file
@ -0,0 +1,35 @@
|
||||
Video Disk Recorder File Formats
|
||||
--------------------------------
|
||||
|
||||
* channels.conf
|
||||
|
||||
This file contains the channel setup.
|
||||
It consists of two types of lines: "group delimiters" and "channel
|
||||
definitions".
|
||||
|
||||
A "group delimiter" is a line starting with a ':' as the very first
|
||||
character, followed by arbitrary text.
|
||||
Example: ":First group"
|
||||
|
||||
A "channel definition" is a line with channel data, where the fields
|
||||
are separated by ':' characters:
|
||||
Example: "RTL:12188:h:1:27500:163:104:0:12003"
|
||||
|
||||
The fields in a channel definition have the following meaning (from left
|
||||
to right):
|
||||
|
||||
- Name: the channel's name (if the name originally contains a ':' character
|
||||
it has to be replaced by '|')
|
||||
- Frequency in MHz (as an integer)
|
||||
- Polarization (one of 'h', 'H', 'v', 'V')
|
||||
- Diseqc number
|
||||
- Symbol rate
|
||||
- Video PID
|
||||
- Audio PID
|
||||
- Conditional Access (0 = Free To Air, 1 = can be decrypted by the first
|
||||
DVB card, 2 = can be decrypted by the second DVB card)
|
||||
- Program Number
|
||||
|
||||
* timers.conf
|
||||
|
||||
TODO
|
20
HISTORY
20
HISTORY
@ -138,3 +138,23 @@ Video Disk Recorder Revision History
|
||||
done for some of the channels in the default 'channels.conf'. Some other
|
||||
parameters in the default 'channels.conf' have also been updated, so please
|
||||
make sure your timers still use the correct channels!
|
||||
|
||||
2000-09-09: Version 0.63
|
||||
|
||||
- Workaround for a driver timing problem in cDvbApi::Cmd(), which sometimes caused
|
||||
the OSD to no longer be displayed (thanks to Niels de Carpentier).
|
||||
- Added the '-m486' option to the compiler call.
|
||||
- If a channel name contains a colon (':') it is now replaced with a '|' in
|
||||
channels.conf.
|
||||
- Not everybody appears to like the "page scrolling" mechanism introduced by
|
||||
Heino Goldenstein in version 0.61, so the Makefile now reacts on NO_PAGE_SCROLL=1
|
||||
to suppress that.
|
||||
- The new 'dvbrc2vdr' tool (thanks to Plamen Ganev!) can be used to convert
|
||||
'dvbrc' channel files into 'vdr' format.
|
||||
- Channels can now be "grouped" (thanks to Plamen Ganev!). See MANUAL for details.
|
||||
There is currently no mechanism to define and maintain "Channel groups" via
|
||||
the menu, so you'll have to insert "Channel group" control lines into your
|
||||
'channels.conf' file manually (for example with a text editor).
|
||||
XXX additional fields for 'preferred' etc???
|
||||
- Started a new file named FORMATS with a description of the various file
|
||||
formats used by VDR.
|
||||
|
16
MANUAL
16
MANUAL
@ -12,8 +12,8 @@ Video Disk Recorder User's Manual
|
||||
|
||||
Up Ch up Crsr up Crsr up Crsr up Crsr up Crsr up Play
|
||||
Down Ch down Crsr down Crsr down Crsr down Crsr down Crsr down Pause
|
||||
Left - - - Disable Decrement - Search back
|
||||
Right - - - Enable Increment - Search forward
|
||||
Left Prev group - - Disable Decrement - Search back
|
||||
Right Next group - - Enable Increment - Search forward
|
||||
Ok Ch display Select Switch Edit Accept Play Progress disp.
|
||||
Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on
|
||||
Back - Menu off Main menu Main menu Discard Main menu -
|
||||
@ -72,6 +72,18 @@ Video Disk Recorder User's Manual
|
||||
To bring up the channel display without switching channels you can press
|
||||
the "Ok" button.
|
||||
|
||||
* Switching through channel groups
|
||||
|
||||
If the 'channels.conf' file contains "group separators" you can switch
|
||||
through these groups by pressing the "Left" and "Right" key while no
|
||||
menu is being displayed. The channel display will show the name of the
|
||||
group, and if you press the "Ok" button while the group name is being
|
||||
displayed, you will switch to the first channel of that group.
|
||||
|
||||
Channel groups can be whatever you decide them to be. You can either
|
||||
group your channels by "Bouquet", by language, genre or whatever your
|
||||
preferences may be.
|
||||
|
||||
* Instant Recording
|
||||
|
||||
You can start recording the current channel by pressing the "Red" button
|
||||
|
8
Makefile
8
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 1.7 2000/09/03 09:26:24 kls Exp $
|
||||
# $Id: Makefile 1.8 2000/09/03 15:38:18 kls Exp $
|
||||
|
||||
DVBDIR = ../DVB
|
||||
|
||||
@ -21,8 +21,12 @@ ifdef DEBUG_OSD
|
||||
DEFINES += -DDEBUG_OSD
|
||||
endif
|
||||
|
||||
ifdef NO_PAGE_SCROLL
|
||||
DEFINES += -DNO_PAGE_SCROLL
|
||||
endif
|
||||
|
||||
%.o: %.c
|
||||
g++ -g -O2 -Wall -c $(DEFINES) $(INCLUDES) $<
|
||||
g++ -g -O2 -Wall -m486 -c $(DEFINES) $(INCLUDES) $<
|
||||
|
||||
all: vdr
|
||||
|
||||
|
152
config.c
152
config.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.c 1.18 2000/09/03 09:20:22 kls Exp $
|
||||
* $Id: config.c 1.19 2000/09/09 14:50:58 kls Exp $
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@ -196,11 +196,23 @@ cChannel::cChannel(const cChannel *Channel)
|
||||
apid = Channel ? Channel->apid : 256;
|
||||
ca = Channel ? Channel->ca : 0;
|
||||
pnr = Channel ? Channel->pnr : 0;
|
||||
preferred = Channel ? Channel->preferred : 0;
|
||||
groupSep = Channel ? Channel->groupSep : false;
|
||||
}
|
||||
|
||||
const char *cChannel::ToText(cChannel *Channel)
|
||||
{
|
||||
asprintf(&buffer, "%s:%d:%c:%d:%d:%d:%d:%d:%d\n", Channel->name, Channel->frequency, Channel->polarization, Channel->diseqc, Channel->srate, Channel->vpid, Channel->apid, Channel->ca, Channel->pnr);
|
||||
char buf[MaxChannelName * 2];
|
||||
char *s = Channel->name;
|
||||
if (strchr(s, ':')) {
|
||||
s = strcpy(buf, s);
|
||||
strreplace(s, ':', '|');
|
||||
}
|
||||
delete buffer;
|
||||
if (Channel->groupSep)
|
||||
asprintf(&buffer, ":%s\n", s);
|
||||
else
|
||||
asprintf(&buffer, "%s:%d:%c:%d:%d:%d:%d:%d:%d:%d\n", s, Channel->frequency, Channel->polarization, Channel->diseqc, Channel->srate, Channel->vpid, Channel->apid, Channel->ca, Channel->pnr, Channel->preferred);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -212,13 +224,32 @@ const char *cChannel::ToText(void)
|
||||
bool cChannel::Parse(const char *s)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
if (9 == sscanf(s, "%a[^:]:%d:%c:%d:%d:%d:%d:%d:%d", &buffer, &frequency, &polarization, &diseqc, &srate, &vpid, &apid, &ca, &pnr)) {
|
||||
strncpy(name, buffer, MaxChannelName - 1);
|
||||
name[strlen(buffer)] = 0;
|
||||
delete buffer;
|
||||
return true;
|
||||
if (*s == ':') {
|
||||
if (*++s) {
|
||||
strn0cpy(name, s, MaxChannelName);
|
||||
name[strlen(name) - 1] = 0; // strip the '\n'
|
||||
groupSep = true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
else {
|
||||
groupSep = false;
|
||||
int fields = sscanf(s, "%a[^:]:%d:%c:%d:%d:%d:%d:%d:%d:%d", &buffer, &frequency, &polarization, &diseqc, &srate, &vpid, &apid, &ca, &pnr, &preferred);
|
||||
#define VER062_FIELDS 9
|
||||
#define VER063_FIELDS 10
|
||||
if (fields == VER062_FIELDS || fields == VER063_FIELDS) {
|
||||
strn0cpy(name, buffer, MaxChannelName);
|
||||
delete buffer;
|
||||
if (fields == VER062_FIELDS) {
|
||||
preferred = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
strreplace(name, '|', ':');
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cChannel::Save(FILE *f)
|
||||
@ -230,9 +261,9 @@ bool cChannel::Switch(cDvbApi *DvbApi)
|
||||
{
|
||||
if (!DvbApi)
|
||||
DvbApi = cDvbApi::PrimaryDvbApi;
|
||||
if (!DvbApi->Recording()) {
|
||||
isyslog(LOG_INFO, "switching to channel %d", Index() + 1);
|
||||
CurrentChannel = Index();
|
||||
if (!DvbApi->Recording() && !groupSep) {
|
||||
isyslog(LOG_INFO, "switching to channel %d", number);
|
||||
CurrentChannel = number;
|
||||
for (int i = 3; i--;) {
|
||||
if (DvbApi->SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr)) {
|
||||
EIT.SetProgramNumber(pnr);
|
||||
@ -242,22 +273,10 @@ bool cChannel::Switch(cDvbApi *DvbApi)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Interface.Info("Channel locked (recording)!");
|
||||
Interface.Info(DvbApi->Recording() ? "Channel locked (recording)!" : name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cChannel::SwitchTo(int i, cDvbApi *DvbApi)
|
||||
{
|
||||
cChannel *channel = Channels.Get(i);
|
||||
return channel && channel->Switch(DvbApi);
|
||||
}
|
||||
|
||||
const char *cChannel::GetChannelName(int i)
|
||||
{
|
||||
cChannel *channel = Channels.Get(i);
|
||||
return channel ? channel->name : NULL;
|
||||
}
|
||||
|
||||
// -- cTimer -----------------------------------------------------------------
|
||||
|
||||
char *cTimer::buffer = NULL;
|
||||
@ -267,7 +286,8 @@ cTimer::cTimer(bool Instant)
|
||||
startTime = stopTime = 0;
|
||||
recording = false;
|
||||
active = Instant;
|
||||
channel = CurrentChannel + 1;
|
||||
cChannel *ch = Channels.GetByNumber(CurrentChannel);
|
||||
channel = ch ? ch->number : 0;
|
||||
time_t t = time(NULL);
|
||||
struct tm *now = localtime(&t);
|
||||
day = now->tm_mday;
|
||||
@ -280,8 +300,8 @@ cTimer::cTimer(bool Instant)
|
||||
lifetime = 99;
|
||||
*file = 0;
|
||||
summary = NULL;
|
||||
if (Instant)
|
||||
snprintf(file, sizeof(file), "@%s", cChannel::GetChannelName(CurrentChannel));
|
||||
if (Instant && ch)
|
||||
snprintf(file, sizeof(file), "@%s", ch->name);
|
||||
}
|
||||
|
||||
cTimer::~cTimer()
|
||||
@ -299,6 +319,7 @@ cTimer& cTimer::operator= (const cTimer &Timer)
|
||||
|
||||
const char *cTimer::ToText(cTimer *Timer)
|
||||
{
|
||||
delete buffer;
|
||||
asprintf(&buffer, "%d:%d:%s:%04d:%04d:%d:%d:%s:%s\n", Timer->active, Timer->channel, PrintDay(Timer->day), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file, Timer->summary ? Timer->summary : "");
|
||||
return buffer;
|
||||
}
|
||||
@ -368,11 +389,7 @@ bool cTimer::Parse(const char *s)
|
||||
if (8 <= sscanf(s, "%d:%d:%a[^:]:%d:%d:%d:%d:%a[^:\n]:%a[^\n]", &active, &channel, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
|
||||
//TODO add more plausibility checks
|
||||
day = ParseDay(buffer1);
|
||||
int l = strlen(buffer2);
|
||||
if (l >= MaxFileName)
|
||||
l = MaxFileName - 1;
|
||||
strncpy(file, buffer2, l);
|
||||
file[l] = 0;
|
||||
strn0cpy(file, buffer2, MaxFileName);
|
||||
delete buffer1;
|
||||
delete buffer2;
|
||||
return day != 0;
|
||||
@ -470,10 +487,79 @@ cKeys Keys;
|
||||
|
||||
// -- cChannels --------------------------------------------------------------
|
||||
|
||||
int CurrentChannel = 0;
|
||||
int CurrentChannel = 1;
|
||||
int CurrentGroup = -1;
|
||||
|
||||
cChannels Channels;
|
||||
|
||||
bool cChannels::Load(const char *FileName)
|
||||
{
|
||||
if (cConfig<cChannel>::Load(FileName)) {
|
||||
ReNumber();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int cChannels::GetNextGroup(int Idx)
|
||||
{
|
||||
cChannel *channel = Get(++Idx);
|
||||
while (channel && !channel->groupSep)
|
||||
channel = Get(++Idx);
|
||||
return channel ? Idx : -1;
|
||||
}
|
||||
|
||||
int cChannels::GetPrevGroup(int Idx)
|
||||
{
|
||||
cChannel *channel = Get(--Idx);
|
||||
while (channel && !channel->groupSep)
|
||||
channel = Get(--Idx);
|
||||
return channel ? Idx : -1;
|
||||
}
|
||||
|
||||
int cChannels::GetNextNormal(int Idx)
|
||||
{
|
||||
cChannel *channel = Get(++Idx);
|
||||
while (channel && channel->groupSep)
|
||||
channel = Get(++Idx);
|
||||
return channel ? Idx : -1;
|
||||
}
|
||||
|
||||
void cChannels::ReNumber( void )
|
||||
{
|
||||
int Number = 0;
|
||||
cChannel *ch = (cChannel *)First();
|
||||
while (ch) {
|
||||
if (!ch->groupSep)
|
||||
ch->number = ++Number;
|
||||
ch = (cChannel *)ch->Next();
|
||||
}
|
||||
maxNumber = Number;
|
||||
}
|
||||
|
||||
cChannel *cChannels::GetByNumber(int Number)
|
||||
{
|
||||
cChannel *channel = (cChannel *)First();
|
||||
while (channel) {
|
||||
if (channel->number == Number)
|
||||
return channel;
|
||||
channel = (cChannel *)channel->Next();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool cChannels::SwitchTo(int Number, cDvbApi *DvbApi)
|
||||
{
|
||||
cChannel *channel = GetByNumber(Number);
|
||||
return channel && channel->Switch(DvbApi);
|
||||
}
|
||||
|
||||
const char *cChannels::GetChannelNameByNumber(int Number)
|
||||
{
|
||||
cChannel *channel = GetByNumber(Number);
|
||||
return channel ? channel->name : NULL;
|
||||
}
|
||||
|
||||
// -- cTimers ----------------------------------------------------------------
|
||||
|
||||
cTimers Timers;
|
||||
|
30
config.h
30
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.15 2000/09/03 09:37:30 kls Exp $
|
||||
* $Id: config.h 1.16 2000/09/09 14:21:35 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -17,7 +17,7 @@
|
||||
#include "dvbapi.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "0.62"
|
||||
#define VDRVERSION "0.63"
|
||||
|
||||
#define MaxBuffer 10000
|
||||
|
||||
@ -75,14 +75,15 @@ public:
|
||||
int apid;
|
||||
int ca;
|
||||
int pnr;
|
||||
int preferred; //TODO implement "preferred channel" mechanism
|
||||
int number; // Sequence number assigned on load
|
||||
bool groupSep;
|
||||
cChannel(void);
|
||||
cChannel(const cChannel *Channel);
|
||||
const char *ToText(void);
|
||||
bool Parse(const char *s);
|
||||
bool Save(FILE *f);
|
||||
bool Switch(cDvbApi *DvbApi = NULL);
|
||||
static bool SwitchTo(int i, cDvbApi *DvbApi = NULL);
|
||||
static const char *GetChannelName(int i);
|
||||
};
|
||||
|
||||
class cTimer : public cListObject {
|
||||
@ -130,7 +131,7 @@ private:
|
||||
cList<T>::Clear();
|
||||
}
|
||||
public:
|
||||
bool Load(const char *FileName)
|
||||
virtual bool Load(const char *FileName)
|
||||
{
|
||||
isyslog(LOG_INFO, "loading %s", FileName);
|
||||
bool result = true;
|
||||
@ -182,14 +183,29 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class cChannels : public cConfig<cChannel> {};
|
||||
|
||||
class cChannels : public cConfig<cChannel> {
|
||||
protected:
|
||||
int maxNumber;
|
||||
public:
|
||||
cChannels(void) { maxNumber = 0; }
|
||||
virtual bool Load(const char *FileName);
|
||||
int GetNextGroup(int Idx); // Get next channel group
|
||||
int GetPrevGroup(int Idx); // Get previous channel group
|
||||
int GetNextNormal(int Idx); // Get next normal channel (not group)
|
||||
void ReNumber(void); // Recalculate 'number' based on channel type
|
||||
cChannel *GetByNumber(int Number);
|
||||
const char *GetChannelNameByNumber(int Number);
|
||||
bool SwitchTo(int Number, cDvbApi *DvbApi = NULL);
|
||||
int MaxNumber(void) { return maxNumber; }
|
||||
};
|
||||
|
||||
class cTimers : public cConfig<cTimer> {
|
||||
public:
|
||||
cTimer *GetTimer(cTimer *Timer);
|
||||
};
|
||||
|
||||
extern int CurrentChannel;
|
||||
extern int CurrentGroup;
|
||||
|
||||
extern cChannels Channels;
|
||||
extern cTimers Timers;
|
||||
|
6
dvbapi.c
6
dvbapi.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbapi.c 1.22 2000/08/06 14:06:14 kls Exp $
|
||||
* $Id: dvbapi.c 1.23 2000/09/09 12:13:55 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbapi.h"
|
||||
@ -1199,6 +1199,10 @@ void cDvbApi::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
|
||||
dc.y1 = y1;
|
||||
dc.data = (void *)data;
|
||||
ioctl(videoDev, VIDIOCSOSDCOMMAND, &dc);
|
||||
usleep(10); // XXX Workaround for a driver bug (cInterface::DisplayChannel() displayed texts at wrong places
|
||||
// XXX and sometimes the OSD was no longer displayed).
|
||||
// XXX Increase the value if the problem still persists on your particular system.
|
||||
// TODO Check if this is still necessary with driver versions after 0.6.
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
50
interface.c
50
interface.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.c 1.11 2000/09/03 10:17:21 kls Exp $
|
||||
* $Id: interface.c 1.12 2000/09/09 14:17:48 kls Exp $
|
||||
*/
|
||||
|
||||
#include "interface.h"
|
||||
@ -72,10 +72,10 @@ eKeys cInterface::GetKey(bool Wait)
|
||||
|
||||
eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||
{
|
||||
int t0 = time_ms();
|
||||
int t0 = time_ms() + Seconds * 1000;
|
||||
eKeys Key = kNone;
|
||||
|
||||
while (time_ms() - t0 < Seconds * 1000) {
|
||||
while (time_ms() < t0) {
|
||||
Key = GetKey();
|
||||
if (Key != kNone)
|
||||
break;
|
||||
@ -112,11 +112,9 @@ void cInterface::Write(int x, int y, const char *s, eDvbColor FgColor, eDvbColor
|
||||
cDvbApi::PrimaryDvbApi->Text(x, y, s, FgColor, BgColor);
|
||||
}
|
||||
|
||||
void cInterface::WriteText(int x, int y, const char *s, bool Current)
|
||||
void cInterface::WriteText(int x, int y, const char *s, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
if (open) {
|
||||
eDvbColor FgColor = Current ? clrBlack : clrWhite;
|
||||
eDvbColor BgColor = Current ? clrCyan : clrBackground;
|
||||
ClearEol(x, y, BgColor);
|
||||
int col = 0;
|
||||
for (;;) {
|
||||
@ -315,36 +313,42 @@ void cInterface::LearnKeys(void)
|
||||
}
|
||||
}
|
||||
|
||||
void cInterface::DisplayChannel(int Number, const char *Name)
|
||||
eKeys cInterface::DisplayChannel(int Number, const char *Name)
|
||||
{
|
||||
RcIo.Number(Number);
|
||||
// Number = 0 is used for channel group display and no EIT
|
||||
if (Number)
|
||||
RcIo.Number(Number);
|
||||
if (Name && !Recording()) {
|
||||
Open(MenuColumns, EIT.IsValid() ? 5 : 1);
|
||||
char buffer[MenuColumns + 1];
|
||||
snprintf(buffer, sizeof(buffer), "%d %s", Number, Name ? Name : "");
|
||||
//XXX Maybe show only those lines that have actual information???
|
||||
Open(MenuColumns, Number && EIT.IsValid() ? 5 : 1);
|
||||
int BufSize = MenuColumns + 1;
|
||||
char buffer[BufSize];
|
||||
if (Number)
|
||||
snprintf(buffer, BufSize, "%d %s", Number, Name ? Name : "");
|
||||
else
|
||||
snprintf(buffer, BufSize, "%s", Name ? Name : "");
|
||||
Write(0, 0, buffer);
|
||||
time_t t = time(NULL);
|
||||
struct tm *now = localtime(&t);
|
||||
snprintf(buffer, sizeof(buffer), "%02d:%02d", now->tm_hour, now->tm_min);
|
||||
snprintf(buffer, BufSize, "%02d:%02d", now->tm_hour, now->tm_min);
|
||||
Write(-5, 0, buffer);
|
||||
if (EIT.IsValid()) {
|
||||
const int t = 7;
|
||||
if (Number && EIT.IsValid()) {
|
||||
const int t = 6;
|
||||
int w = MenuColumns - t;
|
||||
Write(0, 1, EIT.GetRunningTime(), clrYellow, clrBackground);
|
||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetRunningTitle());
|
||||
Write(t, 1, buffer, clrCyan, clrBackground);
|
||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetRunningSubtitle());
|
||||
Write(t, 2, buffer, clrCyan, clrBackground);
|
||||
snprintf(buffer, BufSize, "%.*s", w, EIT.GetRunningTitle()); Write(t, 1, buffer, clrCyan, clrBackground);
|
||||
snprintf(buffer, BufSize, "%.*s", w, EIT.GetRunningSubtitle()); Write(t, 2, buffer, clrCyan, clrBackground);
|
||||
Write(0, 3, EIT.GetNextTime(), clrYellow, clrBackground);
|
||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetNextTitle());
|
||||
Write(t, 3, buffer, clrCyan, clrBackground);
|
||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetNextSubtitle());
|
||||
Write(t, 4, buffer, clrCyan, clrBackground);
|
||||
snprintf(buffer, BufSize, "%.*s", w, EIT.GetNextTitle()); Write(t, 3, buffer, clrCyan, clrBackground);
|
||||
snprintf(buffer, BufSize, "%.*s", w, EIT.GetNextSubtitle()); Write(t, 4, buffer, clrCyan, clrBackground);
|
||||
}
|
||||
if (Wait(5, true) == kOk)
|
||||
eKeys Key = Wait(5, true);
|
||||
if (Key == kOk)
|
||||
GetKey();
|
||||
Close();
|
||||
return Key;
|
||||
}
|
||||
return kNone;
|
||||
}
|
||||
|
||||
void cInterface::DisplayRecording(int Index, bool On)
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.h 1.9 2000/05/06 15:39:23 kls Exp $
|
||||
* $Id: interface.h 1.10 2000/09/03 14:34:24 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __INTERFACE_H
|
||||
@ -34,7 +34,7 @@ public:
|
||||
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
||||
void SetCols(int *c);
|
||||
void Write(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
void WriteText(int x, int y, const char *s, bool Current = false);
|
||||
void WriteText(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBlack);
|
||||
void Title(const char *s);
|
||||
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
|
||||
void Info(const char *s);
|
||||
@ -42,7 +42,7 @@ public:
|
||||
bool Confirm(const char *s);
|
||||
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||
void LearnKeys(void);
|
||||
void DisplayChannel(int Number, const char *Name = NULL);
|
||||
eKeys DisplayChannel(int Number, const char *Name = NULL);
|
||||
void DisplayRecording(int Index, bool On);
|
||||
bool Recording(void);
|
||||
};
|
||||
|
59
menu.c
59
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.22 2000/08/06 07:02:52 kls Exp $
|
||||
* $Id: menu.c 1.23 2000/09/09 14:43:37 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -145,7 +145,7 @@ public:
|
||||
};
|
||||
|
||||
cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
|
||||
:cMenuEditIntItem(Name, Value, 1, Channels.Count())
|
||||
:cMenuEditIntItem(Name, Value, 1, Channels.MaxNumber())
|
||||
{
|
||||
Set();
|
||||
}
|
||||
@ -153,7 +153,7 @@ cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
|
||||
void cMenuEditChanItem::Set(void)
|
||||
{
|
||||
char buf[255];
|
||||
cChannel *channel = Channels.Get(*value - 1);
|
||||
cChannel *channel = Channels.GetByNumber(*value);
|
||||
if (channel)
|
||||
snprintf(buf, sizeof(buf), "%d %s", *value, channel->name);
|
||||
else
|
||||
@ -513,6 +513,7 @@ cMenuEditChannel::cMenuEditChannel(int Index)
|
||||
Add(new cMenuEditIntItem( "Apid", &data.apid, 0, 10000)); //TODO exact limits???
|
||||
Add(new cMenuEditIntItem( "CA", &data.ca, 0, cDvbApi::NumDvbApis));
|
||||
Add(new cMenuEditIntItem( "Pnr", &data.pnr, 0));
|
||||
Add(new cMenuEditIntItem( "Preferred", &data.preferred, 0, 1)); //TODO implement "preferred channel" mechanism
|
||||
}
|
||||
}
|
||||
|
||||
@ -547,13 +548,18 @@ cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
|
||||
{
|
||||
index = Index;
|
||||
channel = Channel;
|
||||
if (channel->groupSep)
|
||||
SetColor(clrWhite, clrBlue);
|
||||
Set();
|
||||
}
|
||||
|
||||
void cMenuChannelItem::Set(void)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%d\t%s", index + 1, channel->name); // user visible channel numbers start with '1'
|
||||
if (!channel->groupSep)
|
||||
asprintf(&buffer, "%d\t%s", channel->number, channel->name );
|
||||
else
|
||||
asprintf(&buffer, "\t%s", channel->name);
|
||||
SetText(buffer, false);
|
||||
}
|
||||
|
||||
@ -583,9 +589,10 @@ cMenuChannels::cMenuChannels(void)
|
||||
//TODO
|
||||
int i = 0;
|
||||
cChannel *channel;
|
||||
int curr = ((channel = Channels.GetByNumber(CurrentChannel)) != NULL) ? channel->Index() : -1;
|
||||
|
||||
while ((channel = Channels.Get(i)) != NULL) {
|
||||
Add(new cMenuChannelItem(i, channel), i == CurrentChannel);
|
||||
Add(new cMenuChannelItem(i, channel), i == curr);
|
||||
i++;
|
||||
}
|
||||
SetHelp("Edit", "New", "Delete", "Mark");
|
||||
@ -613,9 +620,10 @@ eOSState cMenuChannels::New(void)
|
||||
return osContinue;
|
||||
cChannel *channel = new cChannel(Channels.Get(Current()));
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
Add(new cMenuChannelItem(channel->Index()/*XXX*/, channel), true);
|
||||
Channels.Save();
|
||||
isyslog(LOG_INFO, "channel %d added", channel->Index() + 1);
|
||||
isyslog(LOG_INFO, "channel %d added", channel->number);
|
||||
return AddSubMenu(new cMenuEditChannel(Current()));
|
||||
}
|
||||
|
||||
@ -623,28 +631,30 @@ eOSState cMenuChannels::Del(void)
|
||||
{
|
||||
if (Count() > 0) {
|
||||
int Index = Current();
|
||||
cChannel *channel = Channels.Get(Index);
|
||||
int DeletedChannel = channel->number;
|
||||
// Check if there is a timer using this channel:
|
||||
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||
if (ti->channel == Index + 1) {
|
||||
if (ti->channel == DeletedChannel) {
|
||||
Interface.Error("Channel is being used by a timer!");
|
||||
return osContinue;
|
||||
}
|
||||
}
|
||||
if (Interface.Confirm("Delete Channel?")) {
|
||||
// Move and renumber the channels:
|
||||
Channels.Del(Channels.Get(Index));
|
||||
Channels.Del(channel);
|
||||
Channels.ReNumber();
|
||||
cOsdMenu::Del(Index);
|
||||
int i = 0;
|
||||
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||
ci->SetIndex(i++);
|
||||
Channels.Save();
|
||||
isyslog(LOG_INFO, "channel %d deleted", Index + 1);
|
||||
isyslog(LOG_INFO, "channel %d deleted", DeletedChannel);
|
||||
// Fix the timers:
|
||||
bool TimersModified = false;
|
||||
Index++; // user visible channel numbers start with '1'
|
||||
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||
int OldChannel = ti->channel;
|
||||
if (ti->channel > Index)
|
||||
if (ti->channel > DeletedChannel)
|
||||
ti->channel--;
|
||||
if (ti->channel != OldChannel) {
|
||||
TimersModified = true;
|
||||
@ -661,25 +671,28 @@ eOSState cMenuChannels::Del(void)
|
||||
|
||||
void cMenuChannels::Move(int From, int To)
|
||||
{
|
||||
int FromNumber = Channels.Get(From)->number;
|
||||
int ToNumber = Channels.Get(To)->number;
|
||||
// Move and renumber the channels:
|
||||
Channels.Move(From, To);
|
||||
Channels.ReNumber();
|
||||
cOsdMenu::Move(From, To);
|
||||
int i = 0;
|
||||
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||
ci->SetIndex(i++);
|
||||
Channels.Save();
|
||||
isyslog(LOG_INFO, "channel %d moved to %d", From + 1, To + 1);
|
||||
isyslog(LOG_INFO, "channel %d moved to %d", FromNumber, ToNumber);
|
||||
// Fix the timers:
|
||||
bool TimersModified = false;
|
||||
From++; // user visible channel numbers start with '1'
|
||||
To++;
|
||||
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||
int OldChannel = ti->channel;
|
||||
if (ti->channel == From)
|
||||
ti->channel = To;
|
||||
else if (ti->channel > From && ti->channel <= To)
|
||||
if (ti->channel == FromNumber)
|
||||
ti->channel = ToNumber;
|
||||
else if (ti->channel > FromNumber && ti->channel <= ToNumber)
|
||||
ti->channel--;
|
||||
else if (ti->channel < From && ti->channel >= To)
|
||||
else if (ti->channel < FromNumber && ti->channel >= ToNumber)
|
||||
ti->channel++;
|
||||
if (ti->channel != OldChannel) {
|
||||
TimersModified = true;
|
||||
@ -791,7 +804,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||
if (state == osUnknown) {
|
||||
if (Key == kOk) {
|
||||
if (!*data.file)
|
||||
strcpy(data.file, cChannel::GetChannelName(data.channel - 1));
|
||||
strcpy(data.file, Channels.GetChannelNameByNumber(data.channel));
|
||||
if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
|
||||
*timer = data;
|
||||
Timers.Save();
|
||||
@ -1125,10 +1138,10 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
|
||||
timer = new cTimer(true);
|
||||
Timers.Add(timer);
|
||||
Timers.Save();
|
||||
asprintf(&instantId, cDvbApi::NumDvbApis > 1 ? "%s on %d" : "%s", cChannel::GetChannelName(timer->channel - 1), dvbApi->Index() + 1);
|
||||
asprintf(&instantId, cDvbApi::NumDvbApis > 1 ? "%s on %d" : "%s", Channels.GetChannelNameByNumber(timer->channel), dvbApi->Index() + 1);
|
||||
}
|
||||
timer->SetRecording(true);
|
||||
cChannel::SwitchTo(timer->channel - 1, dvbApi);
|
||||
Channels.SwitchTo(timer->channel, dvbApi);
|
||||
cRecording Recording(timer);
|
||||
if (dvbApi->StartRecord(Recording.FileName()))
|
||||
Recording.WriteSummary();
|
||||
@ -1172,8 +1185,8 @@ cRecordControl *cRecordControls::RecordControls[MAXDVBAPI] = { NULL };
|
||||
|
||||
bool cRecordControls::Start(cTimer *Timer)
|
||||
{
|
||||
int ch = Timer ? Timer->channel - 1 : CurrentChannel;
|
||||
cChannel *channel = Channels.Get(ch);
|
||||
int ch = Timer ? Timer->channel : CurrentChannel;
|
||||
cChannel *channel = Channels.GetByNumber(ch);
|
||||
|
||||
if (channel) {
|
||||
cDvbApi *dvbApi = cDvbApi::GetDvbApi(channel->ca);
|
||||
@ -1186,10 +1199,10 @@ bool cRecordControls::Start(cTimer *Timer)
|
||||
}
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: no free DVB device to record channel %d!", ch + 1);
|
||||
esyslog(LOG_ERR, "ERROR: no free DVB device to record channel %d!", ch);
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: channel %d not defined!", ch + 1);
|
||||
esyslog(LOG_ERR, "ERROR: channel %d not defined!", ch);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
100
osd.c
100
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.5 2000/07/26 17:35:09 kls Exp $
|
||||
* $Id: osd.c 1.6 2000/09/09 14:28:57 kls Exp $
|
||||
*/
|
||||
|
||||
#include "osd.h"
|
||||
@ -19,6 +19,9 @@ cOsdItem::cOsdItem(eOSState State)
|
||||
offset = -1;
|
||||
state = State;
|
||||
fresh = false;
|
||||
userColor = false;
|
||||
fgColor = clrWhite;
|
||||
bgColor = clrBackground;
|
||||
}
|
||||
|
||||
cOsdItem::cOsdItem(char *Text, eOSState State)
|
||||
@ -27,6 +30,9 @@ cOsdItem::cOsdItem(char *Text, eOSState State)
|
||||
offset = -1;
|
||||
state = State;
|
||||
fresh = false;
|
||||
userColor = false;
|
||||
fgColor = clrWhite;
|
||||
bgColor = clrBackground;
|
||||
SetText(Text);
|
||||
}
|
||||
|
||||
@ -41,15 +47,24 @@ void cOsdItem::SetText(const char *Text, bool Copy)
|
||||
text = Copy ? strdup(Text) : Text;
|
||||
}
|
||||
|
||||
void cOsdItem::Display(int Offset, bool Current)
|
||||
void cOsdItem::SetColor(eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
userColor = true;
|
||||
fgColor = FgColor;
|
||||
bgColor = BgColor;
|
||||
}
|
||||
|
||||
void cOsdItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
|
||||
{
|
||||
if (Offset < 0) {
|
||||
FgColor = clrBlack;
|
||||
BgColor = clrCyan;
|
||||
}
|
||||
fresh |= Offset >= 0;
|
||||
Current |= Offset < 0;
|
||||
if (Offset >= 0)
|
||||
offset = Offset;
|
||||
//TODO current if Offset == -1 ???
|
||||
if (offset >= 0)
|
||||
Interface.WriteText(0, offset + 2, text, Current);
|
||||
Interface.WriteText(0, offset + 2, text, userColor ? fgColor : FgColor, userColor ? bgColor : BgColor);
|
||||
}
|
||||
|
||||
eOSState cOsdItem::ProcessKey(eKeys Key)
|
||||
@ -100,6 +115,10 @@ void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, c
|
||||
helpGreen = Green;
|
||||
helpYellow = Yellow;
|
||||
helpBlue = Blue;
|
||||
if (visible)
|
||||
Display();
|
||||
//XXX Interface.Help(helpRed, helpGreen, helpYellow, helpBlue);
|
||||
//XXX must clear unused button areas!
|
||||
}
|
||||
|
||||
void cOsdMenu::Del(int Index)
|
||||
@ -140,7 +159,7 @@ void cOsdMenu::Display(void)
|
||||
for (int i = first; i < count; i++) {
|
||||
cOsdItem *item = Get(i);
|
||||
if (item)
|
||||
item->Display(i - first, i == current);
|
||||
item->Display(i - first, i == current ? clrBlack : clrWhite, i == current ? clrCyan : clrBackground);
|
||||
if (++n == MAXOSDITEMS) //TODO get this from Interface!!!
|
||||
break;
|
||||
}
|
||||
@ -159,49 +178,64 @@ void cOsdMenu::DisplayCurrent(bool Current)
|
||||
{
|
||||
cOsdItem *item = Get(current);
|
||||
if (item)
|
||||
item->Display(current - first, Current);
|
||||
item->Display(current - first, Current ? clrBlack : clrWhite, Current ? clrCyan : clrBackground);
|
||||
}
|
||||
|
||||
bool cOsdMenu::SpecialItem(int idx)
|
||||
{
|
||||
cOsdItem *item = Get(idx);
|
||||
return item && item->HasUserColor();
|
||||
}
|
||||
|
||||
void cOsdMenu::CursorUp(void)
|
||||
{
|
||||
if (current > 0) {
|
||||
DisplayCurrent(false);
|
||||
if (current == first) {
|
||||
first -= MAXOSDITEMS;
|
||||
if (first < 0)
|
||||
first = 0;
|
||||
if (current - MAXOSDITEMS > 0)
|
||||
current -= MAXOSDITEMS;
|
||||
else
|
||||
current--;
|
||||
int tmpCurrent = current;
|
||||
while (--tmpCurrent >= 0 && SpecialItem(tmpCurrent));
|
||||
if (tmpCurrent < 0)
|
||||
return;
|
||||
if (tmpCurrent >= first)
|
||||
DisplayCurrent(false);
|
||||
current = tmpCurrent;
|
||||
if (current < first) {
|
||||
first = first > MAXOSDITEMS - 1 ? first - (MAXOSDITEMS - 1) : 0;
|
||||
#ifndef NO_PAGE_SCROLL
|
||||
current = SpecialItem(first) ? first + 1 : first;
|
||||
#endif
|
||||
Display();
|
||||
}
|
||||
else {
|
||||
current--;
|
||||
else
|
||||
DisplayCurrent(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cOsdMenu::CursorDown(void)
|
||||
{
|
||||
int count = Count();
|
||||
if (current < count - 1) {
|
||||
DisplayCurrent(false);
|
||||
if (current == first + MAXOSDITEMS - 1) {
|
||||
first += MAXOSDITEMS;
|
||||
if (first > count - MAXOSDITEMS)
|
||||
first = count - MAXOSDITEMS;
|
||||
if (current + MAXOSDITEMS < count)
|
||||
current += MAXOSDITEMS;
|
||||
else
|
||||
current++;
|
||||
int last = Count() - 1;
|
||||
int lastOnScreen = first + MAXOSDITEMS - 1;
|
||||
|
||||
if (current < last) {
|
||||
int tmpCurrent = current;
|
||||
while (++tmpCurrent <= last && SpecialItem(tmpCurrent));
|
||||
if (tmpCurrent > last)
|
||||
return;
|
||||
if (tmpCurrent <= lastOnScreen)
|
||||
DisplayCurrent(false);
|
||||
current = tmpCurrent;
|
||||
if (current > lastOnScreen) {
|
||||
first += MAXOSDITEMS - 1;
|
||||
lastOnScreen = first + MAXOSDITEMS - 1;
|
||||
if (lastOnScreen > last) {
|
||||
first = last - (MAXOSDITEMS - 1);
|
||||
lastOnScreen = last;
|
||||
}
|
||||
#ifndef NO_PAGE_SCROLL
|
||||
current = SpecialItem(lastOnScreen) ? lastOnScreen - 1 : lastOnScreen;
|
||||
#endif
|
||||
Display();
|
||||
}
|
||||
else {
|
||||
current++;
|
||||
else
|
||||
DisplayCurrent(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
9
osd.h
9
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.9 2000/05/27 15:35:41 kls Exp $
|
||||
* $Id: osd.h 1.10 2000/09/03 14:50:22 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSD_H
|
||||
@ -37,13 +37,17 @@ private:
|
||||
eOSState state;
|
||||
protected:
|
||||
bool fresh;
|
||||
bool userColor;
|
||||
eDvbColor fgColor, bgColor;
|
||||
public:
|
||||
cOsdItem(eOSState State = osUnknown);
|
||||
cOsdItem(char *Text, eOSState State = osUnknown);
|
||||
virtual ~cOsdItem();
|
||||
bool HasUserColor(void) { return userColor; }
|
||||
void SetText(const char *Text, bool Copy = true);
|
||||
void SetColor(eDvbColor FgColor, eDvbColor BgColor = clrBackground);
|
||||
const char *Text(void) { return text; }
|
||||
void Display(int Offset = -1, bool Current = false);
|
||||
void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
||||
virtual void Set(void) {}
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
@ -68,6 +72,7 @@ private:
|
||||
const char *status;
|
||||
protected:
|
||||
bool visible;
|
||||
bool SpecialItem(int idx);
|
||||
void RefreshCurrent(void);
|
||||
void DisplayCurrent(bool Current);
|
||||
void CursorUp(void);
|
||||
|
57
svdrp.c
57
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.5 2000/08/26 12:51:51 kls Exp $
|
||||
* $Id: svdrp.c 1.6 2000/09/09 10:51:21 kls Exp $
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
@ -279,24 +279,24 @@ void cSVDRP::CmdChan(const char *Option)
|
||||
if (*Option) {
|
||||
int n = -1;
|
||||
if (isnumber(Option)) {
|
||||
int o = strtol(Option, NULL, 10) - 1;
|
||||
if (o >= 0 && o < Channels.Count())
|
||||
int o = strtol(Option, NULL, 10);
|
||||
if (o >= 1 && o <= Channels.MaxNumber())
|
||||
n = o;
|
||||
}
|
||||
else if (strcmp(Option, "-") == 0) {
|
||||
n = CurrentChannel;
|
||||
if (CurrentChannel > 0)
|
||||
if (CurrentChannel > 1)
|
||||
n--;
|
||||
}
|
||||
else if (strcmp(Option, "+") == 0) {
|
||||
n = CurrentChannel;
|
||||
if (CurrentChannel < Channels.Count() - 1)
|
||||
if (CurrentChannel < Channels.MaxNumber())
|
||||
n++;
|
||||
}
|
||||
else {
|
||||
int i = 0;
|
||||
int i = 1;
|
||||
cChannel *channel;
|
||||
while ((channel = Channels.Get(i)) != NULL) {
|
||||
while ((channel = Channels.GetByNumber(i)) != NULL) {
|
||||
if (strcasecmp(channel->name, Option) == 0) {
|
||||
n = i;
|
||||
break;
|
||||
@ -312,10 +312,10 @@ void cSVDRP::CmdChan(const char *Option)
|
||||
Reply(550, "Can't switch channel, interface is recording");
|
||||
return;
|
||||
}
|
||||
cChannel *channel = Channels.Get(n);
|
||||
cChannel *channel = Channels.GetByNumber(n);
|
||||
if (channel) {
|
||||
if (!channel->Switch()) {
|
||||
Reply(554, "Error switching to channel \"%d\"", channel->Index() + 1);
|
||||
Reply(554, "Error switching to channel \"%d\"", channel->number);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -324,9 +324,9 @@ void cSVDRP::CmdChan(const char *Option)
|
||||
return;
|
||||
}
|
||||
}
|
||||
cChannel *channel = Channels.Get(CurrentChannel);
|
||||
cChannel *channel = Channels.GetByNumber(CurrentChannel);
|
||||
if (channel)
|
||||
Reply(250, "%d %s", CurrentChannel + 1, channel->name);
|
||||
Reply(250, "%d %s", CurrentChannel, channel->name);
|
||||
else
|
||||
Reply(550, "Unable to find channel \"%d\"", CurrentChannel);
|
||||
}
|
||||
@ -394,41 +394,41 @@ void cSVDRP::CmdLstc(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
if (isnumber(Option)) {
|
||||
cChannel *channel = Channels.Get(strtol(Option, NULL, 10) - 1);
|
||||
cChannel *channel = Channels.GetByNumber(strtol(Option, NULL, 10));
|
||||
if (channel)
|
||||
Reply(250, "%d %s", channel->Index() + 1, channel->ToText());
|
||||
Reply(250, "%d %s", channel->number, channel->ToText());
|
||||
else
|
||||
Reply(501, "Channel \"%s\" not defined", Option);
|
||||
}
|
||||
else {
|
||||
int i = 0;
|
||||
int i = 1;
|
||||
cChannel *next = NULL;
|
||||
while (i < Channels.Count()) {
|
||||
cChannel *channel = Channels.Get(i);
|
||||
while (i <= Channels.MaxNumber()) {
|
||||
cChannel *channel = Channels.GetByNumber(i);
|
||||
if (channel) {
|
||||
if (strcasestr(channel->name, Option)) {
|
||||
if (next)
|
||||
Reply(-250, "%d %s", next->Index() + 1, next->ToText());
|
||||
Reply(-250, "%d %s", next->number, next->ToText());
|
||||
next = channel;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Reply(501, "Channel \"%d\" not found", i + 1);
|
||||
Reply(501, "Channel \"%d\" not found", i);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (next)
|
||||
Reply(250, "%d %s", next->Index() + 1, next->ToText());
|
||||
Reply(250, "%d %s", next->number, next->ToText());
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < Channels.Count(); i++) {
|
||||
cChannel *channel = Channels.Get(i);
|
||||
for (int i = 1; i <= Channels.MaxNumber(); i++) {
|
||||
cChannel *channel = Channels.GetByNumber(i);
|
||||
if (channel)
|
||||
Reply(i < Channels.Count() - 1 ? -250 : 250, "%d %s", channel->Index() + 1, channel->ToText());
|
||||
Reply(i < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->number, channel->ToText());
|
||||
else
|
||||
Reply(501, "Channel \"%d\" not found", i + 1);
|
||||
Reply(501, "Channel \"%d\" not found", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -464,7 +464,7 @@ void cSVDRP::CmdModc(const char *Option)
|
||||
int n = strtol(Option, &tail, 10);
|
||||
if (tail && tail != Option) {
|
||||
tail = skipspace(tail);
|
||||
cChannel *channel = Channels.Get(n - 1);
|
||||
cChannel *channel = Channels.GetByNumber(n);
|
||||
if (channel) {
|
||||
cChannel c = *channel;
|
||||
if (!c.Parse(tail)) {
|
||||
@ -473,8 +473,8 @@ void cSVDRP::CmdModc(const char *Option)
|
||||
}
|
||||
*channel = c;
|
||||
Channels.Save();
|
||||
isyslog(LOG_INFO, "channel %d modified", channel->Index() + 1);
|
||||
Reply(250, "%d %s", channel->Index() + 1, channel->ToText());
|
||||
isyslog(LOG_INFO, "channel %d modified", channel->number);
|
||||
Reply(250, "%d %s", channel->number, channel->ToText());
|
||||
}
|
||||
else
|
||||
Reply(501, "Channel \"%d\" not defined", n);
|
||||
@ -537,9 +537,10 @@ void cSVDRP::CmdNewc(const char *Option)
|
||||
cChannel *channel = new cChannel;
|
||||
if (channel->Parse(Option)) {
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
isyslog(LOG_INFO, "channel %d added", channel->Index() + 1);
|
||||
Reply(250, "%d %s", channel->Index() + 1, channel->ToText());
|
||||
isyslog(LOG_INFO, "channel %d added", channel->number);
|
||||
Reply(250, "%d %s", channel->number, channel->ToText());
|
||||
}
|
||||
else
|
||||
Reply(501, "Error in channel settings");
|
||||
|
12
tools.c
12
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.13 2000/07/29 18:41:45 kls Exp $
|
||||
* $Id: tools.c 1.14 2000/09/09 12:53:34 kls Exp $
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
@ -97,6 +97,14 @@ char *readline(FILE *f)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *strn0cpy(char *dest, const char *src, size_t n)
|
||||
{
|
||||
char *s = dest;
|
||||
for ( ; --n && (*dest = *src) != 0; dest++, src++) ;
|
||||
*dest = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
char *strreplace(char *s, char c1, char c2)
|
||||
{
|
||||
char *p = s;
|
||||
@ -418,6 +426,8 @@ void cListBase::Clear(void)
|
||||
|
||||
cListObject *cListBase::Get(int Index)
|
||||
{
|
||||
if (Index < 0)
|
||||
return NULL;
|
||||
cListObject *object = objects;
|
||||
while (object && Index-- > 0)
|
||||
object = object->Next();
|
||||
|
3
tools.h
3
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.12 2000/07/29 10:56:00 kls Exp $
|
||||
* $Id: tools.h 1.13 2000/09/09 12:53:10 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TOOLS_H
|
||||
@ -38,6 +38,7 @@ bool readint(int filedes, int &n);
|
||||
int readstring(int filedes, char *buffer, int size, bool wait = false);
|
||||
void purge(int filedes);
|
||||
char *readline(FILE *f);
|
||||
char *strn0cpy(char *dest, const char *src, size_t n);
|
||||
char *strreplace(char *s, char c1, char c2);
|
||||
char *skipspace(char *s);
|
||||
int time_ms(void);
|
||||
|
37
vdr.c
37
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.27 2000/07/29 19:01:57 kls Exp $
|
||||
* $Id: vdr.c 1.28 2000/09/09 14:18:25 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -53,6 +53,14 @@ void SignalHandler(int signum)
|
||||
Interrupted = signum;
|
||||
}
|
||||
|
||||
static eKeys ShowChannel(int Number, bool Group = false)
|
||||
{
|
||||
cChannel *channel = Group ? Channels.Get(Number) : Channels.GetByNumber(Number);
|
||||
if (channel)
|
||||
return Interface.DisplayChannel(channel->number, channel->name);
|
||||
return kNone;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Command line options:
|
||||
@ -166,7 +174,7 @@ int main(int argc, char *argv[])
|
||||
#endif
|
||||
Interface.Init();
|
||||
|
||||
cChannel::SwitchTo(CurrentChannel);
|
||||
Channels.SwitchTo(CurrentChannel);
|
||||
|
||||
// Signal handlers:
|
||||
|
||||
@ -185,16 +193,13 @@ int main(int argc, char *argv[])
|
||||
while (!Interrupted) {
|
||||
// Channel display:
|
||||
if (CurrentChannel != LastChannel) {
|
||||
if (!Menu) {
|
||||
cChannel *channel = Channels.Get(CurrentChannel);
|
||||
if (channel)
|
||||
Interface.DisplayChannel(CurrentChannel + 1, channel->name);
|
||||
}
|
||||
if (!Menu)
|
||||
ShowChannel(CurrentChannel);
|
||||
LastChannel = CurrentChannel;
|
||||
}
|
||||
// Direct Channel Select (action):
|
||||
if (dcNumber && time_ms() - dcTime > DIRECTCHANNELTIMEOUT) {
|
||||
cChannel::SwitchTo(dcNumber - 1);
|
||||
Channels.SwitchTo(dcNumber);
|
||||
dcNumber = 0;
|
||||
LastChannel = -1; // in case an invalid channel number was entered!
|
||||
}
|
||||
@ -246,11 +251,25 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Left/Right rotates trough channel groups:
|
||||
case kLeft:
|
||||
case kRight: if (!Interface.Recording()) {
|
||||
int SaveGroup = CurrentGroup;
|
||||
if (key == kRight)
|
||||
CurrentGroup = Channels.GetNextGroup(CurrentGroup) ;
|
||||
else
|
||||
CurrentGroup = Channels.GetPrevGroup(CurrentGroup < 1 ? 1 : CurrentGroup);
|
||||
if (CurrentGroup < 0)
|
||||
CurrentGroup = SaveGroup;
|
||||
if (ShowChannel(CurrentGroup, true) == kOk)
|
||||
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(CurrentGroup))->number);
|
||||
}
|
||||
break;
|
||||
// Up/Down Channel Select:
|
||||
case kUp:
|
||||
case kDown: if (!Interface.Recording()) {
|
||||
int n = CurrentChannel + (key == kUp ? 1 : -1);
|
||||
cChannel *channel = Channels.Get(n);
|
||||
cChannel *channel = Channels.GetByNumber(n);
|
||||
if (channel)
|
||||
channel->Switch();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user