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>
|
Plamen Ganev <pganev@com-it.net>
|
||||||
for fixing the frequency offset for Hotbird channels
|
for fixing the frequency offset for Hotbird channels
|
||||||
for adding the 'xtvrc2vdr' tool (see Tools/xtvrc2vdr)
|
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>
|
Heino Goldenstein <heino.goldenstein@microplex.de>
|
||||||
for modifying scrolling through lists to make it page up and down
|
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>
|
Robert Schneider <Robert.Schneider@lotus.com>
|
||||||
for implementing EIT support for displaying the current/next info
|
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
|
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
|
parameters in the default 'channels.conf' have also been updated, so please
|
||||||
make sure your timers still use the correct channels!
|
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
|
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
|
Down Ch down Crsr down Crsr down Crsr down Crsr down Crsr down Pause
|
||||||
Left - - - Disable Decrement - Search back
|
Left Prev group - - Disable Decrement - Search back
|
||||||
Right - - - Enable Increment - Search forward
|
Right Next group - - Enable Increment - Search forward
|
||||||
Ok Ch display Select Switch Edit Accept Play Progress disp.
|
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
|
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 -
|
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
|
To bring up the channel display without switching channels you can press
|
||||||
the "Ok" button.
|
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
|
* Instant Recording
|
||||||
|
|
||||||
You can start recording the current channel by pressing the "Red" button
|
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
|
# See the main source file 'vdr.c' for copyright information and
|
||||||
# how to reach the author.
|
# 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
|
DVBDIR = ../DVB
|
||||||
|
|
||||||
@ -21,8 +21,12 @@ ifdef DEBUG_OSD
|
|||||||
DEFINES += -DDEBUG_OSD
|
DEFINES += -DDEBUG_OSD
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef NO_PAGE_SCROLL
|
||||||
|
DEFINES += -DNO_PAGE_SCROLL
|
||||||
|
endif
|
||||||
|
|
||||||
%.o: %.c
|
%.o: %.c
|
||||||
g++ -g -O2 -Wall -c $(DEFINES) $(INCLUDES) $<
|
g++ -g -O2 -Wall -m486 -c $(DEFINES) $(INCLUDES) $<
|
||||||
|
|
||||||
all: vdr
|
all: vdr
|
||||||
|
|
||||||
|
150
config.c
150
config.c
@ -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: 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"
|
#include "config.h"
|
||||||
@ -196,11 +196,23 @@ cChannel::cChannel(const cChannel *Channel)
|
|||||||
apid = Channel ? Channel->apid : 256;
|
apid = Channel ? Channel->apid : 256;
|
||||||
ca = Channel ? Channel->ca : 0;
|
ca = Channel ? Channel->ca : 0;
|
||||||
pnr = Channel ? Channel->pnr : 0;
|
pnr = Channel ? Channel->pnr : 0;
|
||||||
|
preferred = Channel ? Channel->preferred : 0;
|
||||||
|
groupSep = Channel ? Channel->groupSep : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *cChannel::ToText(cChannel *Channel)
|
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;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,13 +224,32 @@ const char *cChannel::ToText(void)
|
|||||||
bool cChannel::Parse(const char *s)
|
bool cChannel::Parse(const char *s)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
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)) {
|
if (*s == ':') {
|
||||||
strncpy(name, buffer, MaxChannelName - 1);
|
if (*++s) {
|
||||||
name[strlen(buffer)] = 0;
|
strn0cpy(name, s, MaxChannelName);
|
||||||
delete buffer;
|
name[strlen(name) - 1] = 0; // strip the '\n'
|
||||||
return true;
|
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)
|
bool cChannel::Save(FILE *f)
|
||||||
@ -230,9 +261,9 @@ bool cChannel::Switch(cDvbApi *DvbApi)
|
|||||||
{
|
{
|
||||||
if (!DvbApi)
|
if (!DvbApi)
|
||||||
DvbApi = cDvbApi::PrimaryDvbApi;
|
DvbApi = cDvbApi::PrimaryDvbApi;
|
||||||
if (!DvbApi->Recording()) {
|
if (!DvbApi->Recording() && !groupSep) {
|
||||||
isyslog(LOG_INFO, "switching to channel %d", Index() + 1);
|
isyslog(LOG_INFO, "switching to channel %d", number);
|
||||||
CurrentChannel = Index();
|
CurrentChannel = number;
|
||||||
for (int i = 3; i--;) {
|
for (int i = 3; i--;) {
|
||||||
if (DvbApi->SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr)) {
|
if (DvbApi->SetChannel(frequency, polarization, diseqc, srate, vpid, apid, ca, pnr)) {
|
||||||
EIT.SetProgramNumber(pnr);
|
EIT.SetProgramNumber(pnr);
|
||||||
@ -242,22 +273,10 @@ bool cChannel::Switch(cDvbApi *DvbApi)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Interface.Info("Channel locked (recording)!");
|
Interface.Info(DvbApi->Recording() ? "Channel locked (recording)!" : name);
|
||||||
return false;
|
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 -----------------------------------------------------------------
|
// -- cTimer -----------------------------------------------------------------
|
||||||
|
|
||||||
char *cTimer::buffer = NULL;
|
char *cTimer::buffer = NULL;
|
||||||
@ -267,7 +286,8 @@ cTimer::cTimer(bool Instant)
|
|||||||
startTime = stopTime = 0;
|
startTime = stopTime = 0;
|
||||||
recording = false;
|
recording = false;
|
||||||
active = Instant;
|
active = Instant;
|
||||||
channel = CurrentChannel + 1;
|
cChannel *ch = Channels.GetByNumber(CurrentChannel);
|
||||||
|
channel = ch ? ch->number : 0;
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm *now = localtime(&t);
|
struct tm *now = localtime(&t);
|
||||||
day = now->tm_mday;
|
day = now->tm_mday;
|
||||||
@ -280,8 +300,8 @@ cTimer::cTimer(bool Instant)
|
|||||||
lifetime = 99;
|
lifetime = 99;
|
||||||
*file = 0;
|
*file = 0;
|
||||||
summary = NULL;
|
summary = NULL;
|
||||||
if (Instant)
|
if (Instant && ch)
|
||||||
snprintf(file, sizeof(file), "@%s", cChannel::GetChannelName(CurrentChannel));
|
snprintf(file, sizeof(file), "@%s", ch->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
cTimer::~cTimer()
|
cTimer::~cTimer()
|
||||||
@ -299,6 +319,7 @@ cTimer& cTimer::operator= (const cTimer &Timer)
|
|||||||
|
|
||||||
const char *cTimer::ToText(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 : "");
|
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;
|
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)) {
|
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
|
//TODO add more plausibility checks
|
||||||
day = ParseDay(buffer1);
|
day = ParseDay(buffer1);
|
||||||
int l = strlen(buffer2);
|
strn0cpy(file, buffer2, MaxFileName);
|
||||||
if (l >= MaxFileName)
|
|
||||||
l = MaxFileName - 1;
|
|
||||||
strncpy(file, buffer2, l);
|
|
||||||
file[l] = 0;
|
|
||||||
delete buffer1;
|
delete buffer1;
|
||||||
delete buffer2;
|
delete buffer2;
|
||||||
return day != 0;
|
return day != 0;
|
||||||
@ -470,10 +487,79 @@ cKeys Keys;
|
|||||||
|
|
||||||
// -- cChannels --------------------------------------------------------------
|
// -- cChannels --------------------------------------------------------------
|
||||||
|
|
||||||
int CurrentChannel = 0;
|
int CurrentChannel = 1;
|
||||||
|
int CurrentGroup = -1;
|
||||||
|
|
||||||
cChannels Channels;
|
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 ----------------------------------------------------------------
|
||||||
|
|
||||||
cTimers Timers;
|
cTimers Timers;
|
||||||
|
28
config.h
28
config.h
@ -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: 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
|
#ifndef __CONFIG_H
|
||||||
@ -17,7 +17,7 @@
|
|||||||
#include "dvbapi.h"
|
#include "dvbapi.h"
|
||||||
#include "tools.h"
|
#include "tools.h"
|
||||||
|
|
||||||
#define VDRVERSION "0.62"
|
#define VDRVERSION "0.63"
|
||||||
|
|
||||||
#define MaxBuffer 10000
|
#define MaxBuffer 10000
|
||||||
|
|
||||||
@ -75,14 +75,15 @@ public:
|
|||||||
int apid;
|
int apid;
|
||||||
int ca;
|
int ca;
|
||||||
int pnr;
|
int pnr;
|
||||||
|
int preferred; //TODO implement "preferred channel" mechanism
|
||||||
|
int number; // Sequence number assigned on load
|
||||||
|
bool groupSep;
|
||||||
cChannel(void);
|
cChannel(void);
|
||||||
cChannel(const cChannel *Channel);
|
cChannel(const cChannel *Channel);
|
||||||
const char *ToText(void);
|
const char *ToText(void);
|
||||||
bool Parse(const char *s);
|
bool Parse(const char *s);
|
||||||
bool Save(FILE *f);
|
bool Save(FILE *f);
|
||||||
bool Switch(cDvbApi *DvbApi = NULL);
|
bool Switch(cDvbApi *DvbApi = NULL);
|
||||||
static bool SwitchTo(int i, cDvbApi *DvbApi = NULL);
|
|
||||||
static const char *GetChannelName(int i);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class cTimer : public cListObject {
|
class cTimer : public cListObject {
|
||||||
@ -130,7 +131,7 @@ private:
|
|||||||
cList<T>::Clear();
|
cList<T>::Clear();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
bool Load(const char *FileName)
|
virtual bool Load(const char *FileName)
|
||||||
{
|
{
|
||||||
isyslog(LOG_INFO, "loading %s", FileName);
|
isyslog(LOG_INFO, "loading %s", FileName);
|
||||||
bool result = true;
|
bool result = true;
|
||||||
@ -182,7 +183,21 @@ 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> {
|
class cTimers : public cConfig<cTimer> {
|
||||||
public:
|
public:
|
||||||
@ -190,6 +205,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern int CurrentChannel;
|
extern int CurrentChannel;
|
||||||
|
extern int CurrentGroup;
|
||||||
|
|
||||||
extern cChannels Channels;
|
extern cChannels Channels;
|
||||||
extern cTimers Timers;
|
extern cTimers Timers;
|
||||||
|
6
dvbapi.c
6
dvbapi.c
@ -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: 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"
|
#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.y1 = y1;
|
||||||
dc.data = (void *)data;
|
dc.data = (void *)data;
|
||||||
ioctl(videoDev, VIDIOCSOSDCOMMAND, &dc);
|
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
|
#endif
|
||||||
|
48
interface.c
48
interface.c
@ -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: 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"
|
#include "interface.h"
|
||||||
@ -72,10 +72,10 @@ eKeys cInterface::GetKey(bool Wait)
|
|||||||
|
|
||||||
eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
eKeys cInterface::Wait(int Seconds, bool KeepChar)
|
||||||
{
|
{
|
||||||
int t0 = time_ms();
|
int t0 = time_ms() + Seconds * 1000;
|
||||||
eKeys Key = kNone;
|
eKeys Key = kNone;
|
||||||
|
|
||||||
while (time_ms() - t0 < Seconds * 1000) {
|
while (time_ms() < t0) {
|
||||||
Key = GetKey();
|
Key = GetKey();
|
||||||
if (Key != kNone)
|
if (Key != kNone)
|
||||||
break;
|
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);
|
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) {
|
if (open) {
|
||||||
eDvbColor FgColor = Current ? clrBlack : clrWhite;
|
|
||||||
eDvbColor BgColor = Current ? clrCyan : clrBackground;
|
|
||||||
ClearEol(x, y, BgColor);
|
ClearEol(x, y, BgColor);
|
||||||
int col = 0;
|
int col = 0;
|
||||||
for (;;) {
|
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)
|
||||||
{
|
{
|
||||||
|
// Number = 0 is used for channel group display and no EIT
|
||||||
|
if (Number)
|
||||||
RcIo.Number(Number);
|
RcIo.Number(Number);
|
||||||
if (Name && !Recording()) {
|
if (Name && !Recording()) {
|
||||||
Open(MenuColumns, EIT.IsValid() ? 5 : 1);
|
//XXX Maybe show only those lines that have actual information???
|
||||||
char buffer[MenuColumns + 1];
|
Open(MenuColumns, Number && EIT.IsValid() ? 5 : 1);
|
||||||
snprintf(buffer, sizeof(buffer), "%d %s", Number, Name ? Name : "");
|
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);
|
Write(0, 0, buffer);
|
||||||
time_t t = time(NULL);
|
time_t t = time(NULL);
|
||||||
struct tm *now = localtime(&t);
|
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);
|
Write(-5, 0, buffer);
|
||||||
if (EIT.IsValid()) {
|
if (Number && EIT.IsValid()) {
|
||||||
const int t = 7;
|
const int t = 6;
|
||||||
int w = MenuColumns - t;
|
int w = MenuColumns - t;
|
||||||
Write(0, 1, EIT.GetRunningTime(), clrYellow, clrBackground);
|
Write(0, 1, EIT.GetRunningTime(), clrYellow, clrBackground);
|
||||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetRunningTitle());
|
snprintf(buffer, BufSize, "%.*s", w, EIT.GetRunningTitle()); Write(t, 1, buffer, clrCyan, clrBackground);
|
||||||
Write(t, 1, buffer, clrCyan, clrBackground);
|
snprintf(buffer, BufSize, "%.*s", w, EIT.GetRunningSubtitle()); Write(t, 2, buffer, clrCyan, clrBackground);
|
||||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetRunningSubtitle());
|
|
||||||
Write(t, 2, buffer, clrCyan, clrBackground);
|
|
||||||
Write(0, 3, EIT.GetNextTime(), clrYellow, clrBackground);
|
Write(0, 3, EIT.GetNextTime(), clrYellow, clrBackground);
|
||||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetNextTitle());
|
snprintf(buffer, BufSize, "%.*s", w, EIT.GetNextTitle()); Write(t, 3, buffer, clrCyan, clrBackground);
|
||||||
Write(t, 3, buffer, clrCyan, clrBackground);
|
snprintf(buffer, BufSize, "%.*s", w, EIT.GetNextSubtitle()); Write(t, 4, buffer, clrCyan, clrBackground);
|
||||||
snprintf(buffer, sizeof(buffer), "%.*s", w, EIT.GetNextSubtitle());
|
|
||||||
Write(t, 4, buffer, clrCyan, clrBackground);
|
|
||||||
}
|
}
|
||||||
if (Wait(5, true) == kOk)
|
eKeys Key = Wait(5, true);
|
||||||
|
if (Key == kOk)
|
||||||
GetKey();
|
GetKey();
|
||||||
Close();
|
Close();
|
||||||
|
return Key;
|
||||||
}
|
}
|
||||||
|
return kNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cInterface::DisplayRecording(int Index, bool On)
|
void cInterface::DisplayRecording(int Index, bool On)
|
||||||
|
@ -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: 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
|
#ifndef __INTERFACE_H
|
||||||
@ -34,7 +34,7 @@ public:
|
|||||||
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
|
||||||
void SetCols(int *c);
|
void SetCols(int *c);
|
||||||
void Write(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
|
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 Title(const char *s);
|
||||||
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
|
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
|
||||||
void Info(const char *s);
|
void Info(const char *s);
|
||||||
@ -42,7 +42,7 @@ public:
|
|||||||
bool Confirm(const char *s);
|
bool Confirm(const char *s);
|
||||||
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
void Help(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
|
||||||
void LearnKeys(void);
|
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);
|
void DisplayRecording(int Index, bool On);
|
||||||
bool Recording(void);
|
bool Recording(void);
|
||||||
};
|
};
|
||||||
|
59
menu.c
59
menu.c
@ -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.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"
|
#include "menu.h"
|
||||||
@ -145,7 +145,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
|
cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
|
||||||
:cMenuEditIntItem(Name, Value, 1, Channels.Count())
|
:cMenuEditIntItem(Name, Value, 1, Channels.MaxNumber())
|
||||||
{
|
{
|
||||||
Set();
|
Set();
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
|
|||||||
void cMenuEditChanItem::Set(void)
|
void cMenuEditChanItem::Set(void)
|
||||||
{
|
{
|
||||||
char buf[255];
|
char buf[255];
|
||||||
cChannel *channel = Channels.Get(*value - 1);
|
cChannel *channel = Channels.GetByNumber(*value);
|
||||||
if (channel)
|
if (channel)
|
||||||
snprintf(buf, sizeof(buf), "%d %s", *value, channel->name);
|
snprintf(buf, sizeof(buf), "%d %s", *value, channel->name);
|
||||||
else
|
else
|
||||||
@ -513,6 +513,7 @@ cMenuEditChannel::cMenuEditChannel(int Index)
|
|||||||
Add(new cMenuEditIntItem( "Apid", &data.apid, 0, 10000)); //TODO exact limits???
|
Add(new cMenuEditIntItem( "Apid", &data.apid, 0, 10000)); //TODO exact limits???
|
||||||
Add(new cMenuEditIntItem( "CA", &data.ca, 0, cDvbApi::NumDvbApis));
|
Add(new cMenuEditIntItem( "CA", &data.ca, 0, cDvbApi::NumDvbApis));
|
||||||
Add(new cMenuEditIntItem( "Pnr", &data.pnr, 0));
|
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;
|
index = Index;
|
||||||
channel = Channel;
|
channel = Channel;
|
||||||
|
if (channel->groupSep)
|
||||||
|
SetColor(clrWhite, clrBlue);
|
||||||
Set();
|
Set();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cMenuChannelItem::Set(void)
|
void cMenuChannelItem::Set(void)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
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);
|
SetText(buffer, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,9 +589,10 @@ cMenuChannels::cMenuChannels(void)
|
|||||||
//TODO
|
//TODO
|
||||||
int i = 0;
|
int i = 0;
|
||||||
cChannel *channel;
|
cChannel *channel;
|
||||||
|
int curr = ((channel = Channels.GetByNumber(CurrentChannel)) != NULL) ? channel->Index() : -1;
|
||||||
|
|
||||||
while ((channel = Channels.Get(i)) != NULL) {
|
while ((channel = Channels.Get(i)) != NULL) {
|
||||||
Add(new cMenuChannelItem(i, channel), i == CurrentChannel);
|
Add(new cMenuChannelItem(i, channel), i == curr);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
SetHelp("Edit", "New", "Delete", "Mark");
|
SetHelp("Edit", "New", "Delete", "Mark");
|
||||||
@ -613,9 +620,10 @@ eOSState cMenuChannels::New(void)
|
|||||||
return osContinue;
|
return osContinue;
|
||||||
cChannel *channel = new cChannel(Channels.Get(Current()));
|
cChannel *channel = new cChannel(Channels.Get(Current()));
|
||||||
Channels.Add(channel);
|
Channels.Add(channel);
|
||||||
|
Channels.ReNumber();
|
||||||
Add(new cMenuChannelItem(channel->Index()/*XXX*/, channel), true);
|
Add(new cMenuChannelItem(channel->Index()/*XXX*/, channel), true);
|
||||||
Channels.Save();
|
Channels.Save();
|
||||||
isyslog(LOG_INFO, "channel %d added", channel->Index() + 1);
|
isyslog(LOG_INFO, "channel %d added", channel->number);
|
||||||
return AddSubMenu(new cMenuEditChannel(Current()));
|
return AddSubMenu(new cMenuEditChannel(Current()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,28 +631,30 @@ eOSState cMenuChannels::Del(void)
|
|||||||
{
|
{
|
||||||
if (Count() > 0) {
|
if (Count() > 0) {
|
||||||
int Index = Current();
|
int Index = Current();
|
||||||
|
cChannel *channel = Channels.Get(Index);
|
||||||
|
int DeletedChannel = channel->number;
|
||||||
// Check if there is a timer using this channel:
|
// Check if there is a timer using this channel:
|
||||||
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
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!");
|
Interface.Error("Channel is being used by a timer!");
|
||||||
return osContinue;
|
return osContinue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Interface.Confirm("Delete Channel?")) {
|
if (Interface.Confirm("Delete Channel?")) {
|
||||||
// Move and renumber the channels:
|
// Move and renumber the channels:
|
||||||
Channels.Del(Channels.Get(Index));
|
Channels.Del(channel);
|
||||||
|
Channels.ReNumber();
|
||||||
cOsdMenu::Del(Index);
|
cOsdMenu::Del(Index);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||||
ci->SetIndex(i++);
|
ci->SetIndex(i++);
|
||||||
Channels.Save();
|
Channels.Save();
|
||||||
isyslog(LOG_INFO, "channel %d deleted", Index + 1);
|
isyslog(LOG_INFO, "channel %d deleted", DeletedChannel);
|
||||||
// Fix the timers:
|
// Fix the timers:
|
||||||
bool TimersModified = false;
|
bool TimersModified = false;
|
||||||
Index++; // user visible channel numbers start with '1'
|
|
||||||
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||||
int OldChannel = ti->channel;
|
int OldChannel = ti->channel;
|
||||||
if (ti->channel > Index)
|
if (ti->channel > DeletedChannel)
|
||||||
ti->channel--;
|
ti->channel--;
|
||||||
if (ti->channel != OldChannel) {
|
if (ti->channel != OldChannel) {
|
||||||
TimersModified = true;
|
TimersModified = true;
|
||||||
@ -661,25 +671,28 @@ eOSState cMenuChannels::Del(void)
|
|||||||
|
|
||||||
void cMenuChannels::Move(int From, int To)
|
void cMenuChannels::Move(int From, int To)
|
||||||
{
|
{
|
||||||
|
int FromNumber = Channels.Get(From)->number;
|
||||||
|
int ToNumber = Channels.Get(To)->number;
|
||||||
// Move and renumber the channels:
|
// Move and renumber the channels:
|
||||||
Channels.Move(From, To);
|
Channels.Move(From, To);
|
||||||
|
Channels.ReNumber();
|
||||||
cOsdMenu::Move(From, To);
|
cOsdMenu::Move(From, To);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||||
ci->SetIndex(i++);
|
ci->SetIndex(i++);
|
||||||
Channels.Save();
|
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:
|
// Fix the timers:
|
||||||
bool TimersModified = false;
|
bool TimersModified = false;
|
||||||
From++; // user visible channel numbers start with '1'
|
From++; // user visible channel numbers start with '1'
|
||||||
To++;
|
To++;
|
||||||
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
|
||||||
int OldChannel = ti->channel;
|
int OldChannel = ti->channel;
|
||||||
if (ti->channel == From)
|
if (ti->channel == FromNumber)
|
||||||
ti->channel = To;
|
ti->channel = ToNumber;
|
||||||
else if (ti->channel > From && ti->channel <= To)
|
else if (ti->channel > FromNumber && ti->channel <= ToNumber)
|
||||||
ti->channel--;
|
ti->channel--;
|
||||||
else if (ti->channel < From && ti->channel >= To)
|
else if (ti->channel < FromNumber && ti->channel >= ToNumber)
|
||||||
ti->channel++;
|
ti->channel++;
|
||||||
if (ti->channel != OldChannel) {
|
if (ti->channel != OldChannel) {
|
||||||
TimersModified = true;
|
TimersModified = true;
|
||||||
@ -791,7 +804,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
|||||||
if (state == osUnknown) {
|
if (state == osUnknown) {
|
||||||
if (Key == kOk) {
|
if (Key == kOk) {
|
||||||
if (!*data.file)
|
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) {
|
if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
|
||||||
*timer = data;
|
*timer = data;
|
||||||
Timers.Save();
|
Timers.Save();
|
||||||
@ -1125,10 +1138,10 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
|
|||||||
timer = new cTimer(true);
|
timer = new cTimer(true);
|
||||||
Timers.Add(timer);
|
Timers.Add(timer);
|
||||||
Timers.Save();
|
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);
|
timer->SetRecording(true);
|
||||||
cChannel::SwitchTo(timer->channel - 1, dvbApi);
|
Channels.SwitchTo(timer->channel, dvbApi);
|
||||||
cRecording Recording(timer);
|
cRecording Recording(timer);
|
||||||
if (dvbApi->StartRecord(Recording.FileName()))
|
if (dvbApi->StartRecord(Recording.FileName()))
|
||||||
Recording.WriteSummary();
|
Recording.WriteSummary();
|
||||||
@ -1172,8 +1185,8 @@ cRecordControl *cRecordControls::RecordControls[MAXDVBAPI] = { NULL };
|
|||||||
|
|
||||||
bool cRecordControls::Start(cTimer *Timer)
|
bool cRecordControls::Start(cTimer *Timer)
|
||||||
{
|
{
|
||||||
int ch = Timer ? Timer->channel - 1 : CurrentChannel;
|
int ch = Timer ? Timer->channel : CurrentChannel;
|
||||||
cChannel *channel = Channels.Get(ch);
|
cChannel *channel = Channels.GetByNumber(ch);
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
cDvbApi *dvbApi = cDvbApi::GetDvbApi(channel->ca);
|
cDvbApi *dvbApi = cDvbApi::GetDvbApi(channel->ca);
|
||||||
@ -1186,10 +1199,10 @@ bool cRecordControls::Start(cTimer *Timer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
esyslog(LOG_ERR, "ERROR: channel %d not defined!", ch + 1);
|
esyslog(LOG_ERR, "ERROR: channel %d not defined!", ch);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
96
osd.c
96
osd.c
@ -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: 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"
|
#include "osd.h"
|
||||||
@ -19,6 +19,9 @@ cOsdItem::cOsdItem(eOSState State)
|
|||||||
offset = -1;
|
offset = -1;
|
||||||
state = State;
|
state = State;
|
||||||
fresh = false;
|
fresh = false;
|
||||||
|
userColor = false;
|
||||||
|
fgColor = clrWhite;
|
||||||
|
bgColor = clrBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
cOsdItem::cOsdItem(char *Text, eOSState State)
|
cOsdItem::cOsdItem(char *Text, eOSState State)
|
||||||
@ -27,6 +30,9 @@ cOsdItem::cOsdItem(char *Text, eOSState State)
|
|||||||
offset = -1;
|
offset = -1;
|
||||||
state = State;
|
state = State;
|
||||||
fresh = false;
|
fresh = false;
|
||||||
|
userColor = false;
|
||||||
|
fgColor = clrWhite;
|
||||||
|
bgColor = clrBackground;
|
||||||
SetText(Text);
|
SetText(Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,15 +47,24 @@ void cOsdItem::SetText(const char *Text, bool Copy)
|
|||||||
text = Copy ? strdup(Text) : Text;
|
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;
|
fresh |= Offset >= 0;
|
||||||
Current |= Offset < 0;
|
|
||||||
if (Offset >= 0)
|
if (Offset >= 0)
|
||||||
offset = Offset;
|
offset = Offset;
|
||||||
//TODO current if Offset == -1 ???
|
|
||||||
if (offset >= 0)
|
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)
|
eOSState cOsdItem::ProcessKey(eKeys Key)
|
||||||
@ -100,6 +115,10 @@ void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, c
|
|||||||
helpGreen = Green;
|
helpGreen = Green;
|
||||||
helpYellow = Yellow;
|
helpYellow = Yellow;
|
||||||
helpBlue = Blue;
|
helpBlue = Blue;
|
||||||
|
if (visible)
|
||||||
|
Display();
|
||||||
|
//XXX Interface.Help(helpRed, helpGreen, helpYellow, helpBlue);
|
||||||
|
//XXX must clear unused button areas!
|
||||||
}
|
}
|
||||||
|
|
||||||
void cOsdMenu::Del(int Index)
|
void cOsdMenu::Del(int Index)
|
||||||
@ -140,7 +159,7 @@ void cOsdMenu::Display(void)
|
|||||||
for (int i = first; i < count; i++) {
|
for (int i = first; i < count; i++) {
|
||||||
cOsdItem *item = Get(i);
|
cOsdItem *item = Get(i);
|
||||||
if (item)
|
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!!!
|
if (++n == MAXOSDITEMS) //TODO get this from Interface!!!
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -159,50 +178,65 @@ void cOsdMenu::DisplayCurrent(bool Current)
|
|||||||
{
|
{
|
||||||
cOsdItem *item = Get(current);
|
cOsdItem *item = Get(current);
|
||||||
if (item)
|
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)
|
void cOsdMenu::CursorUp(void)
|
||||||
{
|
{
|
||||||
if (current > 0) {
|
if (current > 0) {
|
||||||
|
int tmpCurrent = current;
|
||||||
|
while (--tmpCurrent >= 0 && SpecialItem(tmpCurrent));
|
||||||
|
if (tmpCurrent < 0)
|
||||||
|
return;
|
||||||
|
if (tmpCurrent >= first)
|
||||||
DisplayCurrent(false);
|
DisplayCurrent(false);
|
||||||
if (current == first) {
|
current = tmpCurrent;
|
||||||
first -= MAXOSDITEMS;
|
if (current < first) {
|
||||||
if (first < 0)
|
first = first > MAXOSDITEMS - 1 ? first - (MAXOSDITEMS - 1) : 0;
|
||||||
first = 0;
|
#ifndef NO_PAGE_SCROLL
|
||||||
if (current - MAXOSDITEMS > 0)
|
current = SpecialItem(first) ? first + 1 : first;
|
||||||
current -= MAXOSDITEMS;
|
#endif
|
||||||
else
|
|
||||||
current--;
|
|
||||||
Display();
|
Display();
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
current--;
|
|
||||||
DisplayCurrent(true);
|
DisplayCurrent(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cOsdMenu::CursorDown(void)
|
void cOsdMenu::CursorDown(void)
|
||||||
{
|
{
|
||||||
int count = Count();
|
int last = Count() - 1;
|
||||||
if (current < 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);
|
DisplayCurrent(false);
|
||||||
if (current == first + MAXOSDITEMS - 1) {
|
current = tmpCurrent;
|
||||||
first += MAXOSDITEMS;
|
if (current > lastOnScreen) {
|
||||||
if (first > count - MAXOSDITEMS)
|
first += MAXOSDITEMS - 1;
|
||||||
first = count - MAXOSDITEMS;
|
lastOnScreen = first + MAXOSDITEMS - 1;
|
||||||
if (current + MAXOSDITEMS < count)
|
if (lastOnScreen > last) {
|
||||||
current += MAXOSDITEMS;
|
first = last - (MAXOSDITEMS - 1);
|
||||||
else
|
lastOnScreen = last;
|
||||||
current++;
|
}
|
||||||
|
#ifndef NO_PAGE_SCROLL
|
||||||
|
current = SpecialItem(lastOnScreen) ? lastOnScreen - 1 : lastOnScreen;
|
||||||
|
#endif
|
||||||
Display();
|
Display();
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
current++;
|
|
||||||
DisplayCurrent(true);
|
DisplayCurrent(true);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cOsdMenu::Mark(void)
|
void cOsdMenu::Mark(void)
|
||||||
|
9
osd.h
9
osd.h
@ -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: 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
|
#ifndef __OSD_H
|
||||||
@ -37,13 +37,17 @@ private:
|
|||||||
eOSState state;
|
eOSState state;
|
||||||
protected:
|
protected:
|
||||||
bool fresh;
|
bool fresh;
|
||||||
|
bool userColor;
|
||||||
|
eDvbColor fgColor, bgColor;
|
||||||
public:
|
public:
|
||||||
cOsdItem(eOSState State = osUnknown);
|
cOsdItem(eOSState State = osUnknown);
|
||||||
cOsdItem(char *Text, eOSState State = osUnknown);
|
cOsdItem(char *Text, eOSState State = osUnknown);
|
||||||
virtual ~cOsdItem();
|
virtual ~cOsdItem();
|
||||||
|
bool HasUserColor(void) { return userColor; }
|
||||||
void SetText(const char *Text, bool Copy = true);
|
void SetText(const char *Text, bool Copy = true);
|
||||||
|
void SetColor(eDvbColor FgColor, eDvbColor BgColor = clrBackground);
|
||||||
const char *Text(void) { return text; }
|
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 void Set(void) {}
|
||||||
virtual eOSState ProcessKey(eKeys Key);
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
};
|
};
|
||||||
@ -68,6 +72,7 @@ private:
|
|||||||
const char *status;
|
const char *status;
|
||||||
protected:
|
protected:
|
||||||
bool visible;
|
bool visible;
|
||||||
|
bool SpecialItem(int idx);
|
||||||
void RefreshCurrent(void);
|
void RefreshCurrent(void);
|
||||||
void DisplayCurrent(bool Current);
|
void DisplayCurrent(bool Current);
|
||||||
void CursorUp(void);
|
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
|
* 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.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
|
#define _GNU_SOURCE
|
||||||
@ -279,24 +279,24 @@ void cSVDRP::CmdChan(const char *Option)
|
|||||||
if (*Option) {
|
if (*Option) {
|
||||||
int n = -1;
|
int n = -1;
|
||||||
if (isnumber(Option)) {
|
if (isnumber(Option)) {
|
||||||
int o = strtol(Option, NULL, 10) - 1;
|
int o = strtol(Option, NULL, 10);
|
||||||
if (o >= 0 && o < Channels.Count())
|
if (o >= 1 && o <= Channels.MaxNumber())
|
||||||
n = o;
|
n = o;
|
||||||
}
|
}
|
||||||
else if (strcmp(Option, "-") == 0) {
|
else if (strcmp(Option, "-") == 0) {
|
||||||
n = CurrentChannel;
|
n = CurrentChannel;
|
||||||
if (CurrentChannel > 0)
|
if (CurrentChannel > 1)
|
||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
else if (strcmp(Option, "+") == 0) {
|
else if (strcmp(Option, "+") == 0) {
|
||||||
n = CurrentChannel;
|
n = CurrentChannel;
|
||||||
if (CurrentChannel < Channels.Count() - 1)
|
if (CurrentChannel < Channels.MaxNumber())
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i = 0;
|
int i = 1;
|
||||||
cChannel *channel;
|
cChannel *channel;
|
||||||
while ((channel = Channels.Get(i)) != NULL) {
|
while ((channel = Channels.GetByNumber(i)) != NULL) {
|
||||||
if (strcasecmp(channel->name, Option) == 0) {
|
if (strcasecmp(channel->name, Option) == 0) {
|
||||||
n = i;
|
n = i;
|
||||||
break;
|
break;
|
||||||
@ -312,10 +312,10 @@ void cSVDRP::CmdChan(const char *Option)
|
|||||||
Reply(550, "Can't switch channel, interface is recording");
|
Reply(550, "Can't switch channel, interface is recording");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cChannel *channel = Channels.Get(n);
|
cChannel *channel = Channels.GetByNumber(n);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
if (!channel->Switch()) {
|
if (!channel->Switch()) {
|
||||||
Reply(554, "Error switching to channel \"%d\"", channel->Index() + 1);
|
Reply(554, "Error switching to channel \"%d\"", channel->number);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,9 +324,9 @@ void cSVDRP::CmdChan(const char *Option)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cChannel *channel = Channels.Get(CurrentChannel);
|
cChannel *channel = Channels.GetByNumber(CurrentChannel);
|
||||||
if (channel)
|
if (channel)
|
||||||
Reply(250, "%d %s", CurrentChannel + 1, channel->name);
|
Reply(250, "%d %s", CurrentChannel, channel->name);
|
||||||
else
|
else
|
||||||
Reply(550, "Unable to find channel \"%d\"", CurrentChannel);
|
Reply(550, "Unable to find channel \"%d\"", CurrentChannel);
|
||||||
}
|
}
|
||||||
@ -394,41 +394,41 @@ void cSVDRP::CmdLstc(const char *Option)
|
|||||||
{
|
{
|
||||||
if (*Option) {
|
if (*Option) {
|
||||||
if (isnumber(Option)) {
|
if (isnumber(Option)) {
|
||||||
cChannel *channel = Channels.Get(strtol(Option, NULL, 10) - 1);
|
cChannel *channel = Channels.GetByNumber(strtol(Option, NULL, 10));
|
||||||
if (channel)
|
if (channel)
|
||||||
Reply(250, "%d %s", channel->Index() + 1, channel->ToText());
|
Reply(250, "%d %s", channel->number, channel->ToText());
|
||||||
else
|
else
|
||||||
Reply(501, "Channel \"%s\" not defined", Option);
|
Reply(501, "Channel \"%s\" not defined", Option);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int i = 0;
|
int i = 1;
|
||||||
cChannel *next = NULL;
|
cChannel *next = NULL;
|
||||||
while (i < Channels.Count()) {
|
while (i <= Channels.MaxNumber()) {
|
||||||
cChannel *channel = Channels.Get(i);
|
cChannel *channel = Channels.GetByNumber(i);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
if (strcasestr(channel->name, Option)) {
|
if (strcasestr(channel->name, Option)) {
|
||||||
if (next)
|
if (next)
|
||||||
Reply(-250, "%d %s", next->Index() + 1, next->ToText());
|
Reply(-250, "%d %s", next->number, next->ToText());
|
||||||
next = channel;
|
next = channel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Reply(501, "Channel \"%d\" not found", i + 1);
|
Reply(501, "Channel \"%d\" not found", i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (next)
|
if (next)
|
||||||
Reply(250, "%d %s", next->Index() + 1, next->ToText());
|
Reply(250, "%d %s", next->number, next->ToText());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < Channels.Count(); i++) {
|
for (int i = 1; i <= Channels.MaxNumber(); i++) {
|
||||||
cChannel *channel = Channels.Get(i);
|
cChannel *channel = Channels.GetByNumber(i);
|
||||||
if (channel)
|
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
|
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);
|
int n = strtol(Option, &tail, 10);
|
||||||
if (tail && tail != Option) {
|
if (tail && tail != Option) {
|
||||||
tail = skipspace(tail);
|
tail = skipspace(tail);
|
||||||
cChannel *channel = Channels.Get(n - 1);
|
cChannel *channel = Channels.GetByNumber(n);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
cChannel c = *channel;
|
cChannel c = *channel;
|
||||||
if (!c.Parse(tail)) {
|
if (!c.Parse(tail)) {
|
||||||
@ -473,8 +473,8 @@ void cSVDRP::CmdModc(const char *Option)
|
|||||||
}
|
}
|
||||||
*channel = c;
|
*channel = c;
|
||||||
Channels.Save();
|
Channels.Save();
|
||||||
isyslog(LOG_INFO, "channel %d modified", channel->Index() + 1);
|
isyslog(LOG_INFO, "channel %d modified", channel->number);
|
||||||
Reply(250, "%d %s", channel->Index() + 1, channel->ToText());
|
Reply(250, "%d %s", channel->number, channel->ToText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Reply(501, "Channel \"%d\" not defined", n);
|
Reply(501, "Channel \"%d\" not defined", n);
|
||||||
@ -537,9 +537,10 @@ void cSVDRP::CmdNewc(const char *Option)
|
|||||||
cChannel *channel = new cChannel;
|
cChannel *channel = new cChannel;
|
||||||
if (channel->Parse(Option)) {
|
if (channel->Parse(Option)) {
|
||||||
Channels.Add(channel);
|
Channels.Add(channel);
|
||||||
|
Channels.ReNumber();
|
||||||
Channels.Save();
|
Channels.Save();
|
||||||
isyslog(LOG_INFO, "channel %d added", channel->Index() + 1);
|
isyslog(LOG_INFO, "channel %d added", channel->number);
|
||||||
Reply(250, "%d %s", channel->Index() + 1, channel->ToText());
|
Reply(250, "%d %s", channel->number, channel->ToText());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Reply(501, "Error in channel settings");
|
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
|
* 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.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
|
#define _GNU_SOURCE
|
||||||
@ -97,6 +97,14 @@ char *readline(FILE *f)
|
|||||||
return NULL;
|
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 *strreplace(char *s, char c1, char c2)
|
||||||
{
|
{
|
||||||
char *p = s;
|
char *p = s;
|
||||||
@ -418,6 +426,8 @@ void cListBase::Clear(void)
|
|||||||
|
|
||||||
cListObject *cListBase::Get(int Index)
|
cListObject *cListBase::Get(int Index)
|
||||||
{
|
{
|
||||||
|
if (Index < 0)
|
||||||
|
return NULL;
|
||||||
cListObject *object = objects;
|
cListObject *object = objects;
|
||||||
while (object && Index-- > 0)
|
while (object && Index-- > 0)
|
||||||
object = object->Next();
|
object = object->Next();
|
||||||
|
3
tools.h
3
tools.h
@ -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.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
|
#ifndef __TOOLS_H
|
||||||
@ -38,6 +38,7 @@ bool readint(int filedes, int &n);
|
|||||||
int readstring(int filedes, char *buffer, int size, bool wait = false);
|
int readstring(int filedes, char *buffer, int size, bool wait = false);
|
||||||
void purge(int filedes);
|
void purge(int filedes);
|
||||||
char *readline(FILE *f);
|
char *readline(FILE *f);
|
||||||
|
char *strn0cpy(char *dest, const char *src, size_t n);
|
||||||
char *strreplace(char *s, char c1, char c2);
|
char *strreplace(char *s, char c1, char c2);
|
||||||
char *skipspace(char *s);
|
char *skipspace(char *s);
|
||||||
int time_ms(void);
|
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
|
* 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>
|
#include <getopt.h>
|
||||||
@ -53,6 +53,14 @@ void SignalHandler(int signum)
|
|||||||
Interrupted = 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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
// Command line options:
|
// Command line options:
|
||||||
@ -166,7 +174,7 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
Interface.Init();
|
Interface.Init();
|
||||||
|
|
||||||
cChannel::SwitchTo(CurrentChannel);
|
Channels.SwitchTo(CurrentChannel);
|
||||||
|
|
||||||
// Signal handlers:
|
// Signal handlers:
|
||||||
|
|
||||||
@ -185,16 +193,13 @@ int main(int argc, char *argv[])
|
|||||||
while (!Interrupted) {
|
while (!Interrupted) {
|
||||||
// Channel display:
|
// Channel display:
|
||||||
if (CurrentChannel != LastChannel) {
|
if (CurrentChannel != LastChannel) {
|
||||||
if (!Menu) {
|
if (!Menu)
|
||||||
cChannel *channel = Channels.Get(CurrentChannel);
|
ShowChannel(CurrentChannel);
|
||||||
if (channel)
|
|
||||||
Interface.DisplayChannel(CurrentChannel + 1, channel->name);
|
|
||||||
}
|
|
||||||
LastChannel = CurrentChannel;
|
LastChannel = CurrentChannel;
|
||||||
}
|
}
|
||||||
// Direct Channel Select (action):
|
// Direct Channel Select (action):
|
||||||
if (dcNumber && time_ms() - dcTime > DIRECTCHANNELTIMEOUT) {
|
if (dcNumber && time_ms() - dcTime > DIRECTCHANNELTIMEOUT) {
|
||||||
cChannel::SwitchTo(dcNumber - 1);
|
Channels.SwitchTo(dcNumber);
|
||||||
dcNumber = 0;
|
dcNumber = 0;
|
||||||
LastChannel = -1; // in case an invalid channel number was entered!
|
LastChannel = -1; // in case an invalid channel number was entered!
|
||||||
}
|
}
|
||||||
@ -246,11 +251,25 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
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:
|
// Up/Down Channel Select:
|
||||||
case kUp:
|
case kUp:
|
||||||
case kDown: if (!Interface.Recording()) {
|
case kDown: if (!Interface.Recording()) {
|
||||||
int n = CurrentChannel + (key == kUp ? 1 : -1);
|
int n = CurrentChannel + (key == kUp ? 1 : -1);
|
||||||
cChannel *channel = Channels.Get(n);
|
cChannel *channel = Channels.GetByNumber(n);
|
||||||
if (channel)
|
if (channel)
|
||||||
channel->Switch();
|
channel->Switch();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user