Modified channel handling; full DiSEqC support

This commit is contained in:
Klaus Schmidinger 2002-10-06 10:25:42 +02:00
parent b7615a7ae1
commit 962596f4ab
26 changed files with 1818 additions and 486 deletions

View File

@ -185,6 +185,7 @@ Wolfgang Henselmann-Weiss <Wolfgang_Henselmann@betaresearch.de>
Uwe Scheffler <UweScheffler@t-online.de>
for his help in keeping 'channels.conf.cable' up to date
for helping to test new DVB-T handling
Matjaz Thaler <matjaz.thaler@guest.arnes.si>
for improving AC3 decoding when replaying DVDs
@ -407,3 +408,10 @@ Jeremy Hall <jhall@UU.NET>
Oliver Endriss <o.endriss@gmx.de>
for fixing a missing Flush() call in the remote control learning procedure
for helping to test and debug the new channel source and DiSEqC handling
Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf'
Lauri Tischler <lauri.tischler@efore.fi>
for helping to test and debug the new channel source and DiSEqC handling

33
HISTORY
View File

@ -1536,7 +1536,38 @@ Video Disk Recorder Revision History
- Avoiding restarts due to 'panic level' when switching channels on the primary
device during EPG scan.
2002-09-30: Version 1.1.12
2002-10-06: Version 1.1.12
- Fixed a missing Flush() call in the remote control learning procedure (thanks
to Oliver Endriss).
- Modified channel handling to cover all parameters necessary for DVB-C and DVB-T
(see man vdr(5) for the meaning of the additional parameters stored in the field
previously named 'polarisation'). Thanks to Uwe Scheffler for testing.
If you have a system with different kinds of DVB cards, like DVB-T and DVB-C,
for instance, there is no more need to distinguish the channels through the
'Ca' parameter in order to assign them to the various DVB cards. This is now
taken care of by the "source" parameter. So a channel marked as "terrestrial",
for example, will only be received on DVB-T cards.
Note that the cChannel class has been moved into a separate file (channels.[ch]),
and that all data members have been made private and are now only accessible
through member functions. You may have to change any plugin code that accesses
cChannel data accordingly.
- The new configuration file 'sources.conf' contains the various signal sources
(satellites, cable and terrestrial) which are used in 'channels.conf' and
'diseqc.conf' (thanks to Reinhard Walter Buchner for adding some satellites to
'sources.conf' and Oliver Endriss and Lauri Tischler for testing and debugging).
- The 'diseqc' parameter in the channel definitions has been redefined to hold the
"source" of the given channel (which can be either a satellite, cable or terrestrial).
For compatibility with channels.conf files from older versions, numeric values in
this parameter will be tolerated, but they have no meaning. If you want to use
DiSEqC you will need to replace these old values with the proper source identifiers
defined in the new configuration file 'sources.conf'. See how this is done in the
'channels.conf' file that comes with the VDR package.
- The new configuration file 'diseqc.conf' can be used to set up the individual
diseqc configuration (see man vdr(5) for a description of the file format).
- The "Edit channel" menu has a new entry "Source:" in which the source of this
channel can be selected (either a satellite, cable or terrestrial). The set of
parameters at the end of this menu will change according to the type of source.
- The "Use DiSEqC" parameter in the "Setup/LNB" menu has been moved to the beginning
of the list and disables the rest of the parameters when set to "yes", since these
are now only meaningful if DiSEqC is _not_ used.

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
# $Id: Makefile 1.47 2002/09/28 14:12:43 kls Exp $
# $Id: Makefile 1.48 2002/10/04 14:29:14 kls Exp $
.DELETE_ON_ERROR:
@ -32,10 +32,11 @@ endif
DTVLIB = $(DTVDIR)/libdtv.a
OBJS = audio.o config.o cutter.o device.o dvbdevice.o dvbosd.o dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o\
interface.o keys.o lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o receiver.o\
recorder.o recording.o remote.o remux.o ringbuffer.o spu.o status.o svdrp.o thread.o\
tools.o transfer.o vdr.o videodir.o
OBJS = audio.o channels.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd.o\
dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o interface.o keys.o\
lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o\
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sources.o\
spu.o status.o svdrp.o thread.o tools.o transfer.o vdr.o videodir.o
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1

View File

@ -21,18 +21,18 @@ VDR program and present itself to the user.
The <i>inside</i> interface provides the plugin code access to VDR's internal data
structures and allows it to hook itself into specific areas to perform special actions.
<p>
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.7 are marked like this.
<!--X1.1.7--></td></tr></table>
<!--X1.1.8--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
<!--X1.1.8--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.8 are marked like this.
<!--X1.1.8--></td></tr></table>
<!--X1.1.9--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<!--X1.1.9--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.9 are marked like this.
<!--X1.1.9--></td></tr></table>
<!--X1.1.11--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
<!--X1.1.11--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.11 are marked like this.
<!--X1.1.11--></td></tr></table>
<!--X1.1.12--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.12 are marked like this.
<!--X1.1.12--></td></tr></table>
<a name="Part I - The Outside Interface"><hr><center><h1>Part I - The Outside Interface</h1></center>
@ -957,7 +957,6 @@ stream. There are no prerequisites regarding the length or alignment of an
individual block of data. The sum of all blocks must simply result in the
desired video data stream, and it must be delivered fast enough so that the
DVB device doesn't run out of data.
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
To avoid busy loops the player should call its member function
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
@ -965,7 +964,6 @@ bool DevicePoll(cPoller &amp;Poller, int TimeoutMs = 0);
</pre></td></tr></table><p>
to determine whether the device is ready for further data.
<!--X1.1.7--></td></tr></table>
<p>
TODO: PlayAudio()???
<p>
@ -1184,14 +1182,17 @@ the <tt>cDvbDevice</tt>, which is used to access the DVB PCI cards.
If the new device can receive, it most likely needs to provide a way of
selecting which channel it shall tune to:
<!--X1.1.9--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<!--X1.1.9--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
<!--X1.1.12--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
virtual bool ProvidesSource(int Source) const;
<!--X1.1.12--></td></tr></table>
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
</pre></td></tr></table><p>
These functions will be called with the desired channel and shall return whether
this device can provide the requested channel and whether tuning to it was successful,
These functions will be called with the desired source or channel and shall return whether
this device can provide the requested source or channel and whether tuning to it was successful,
repectively.
<!--X1.1.9--></td></tr></table>
<p>
@ -1203,7 +1204,7 @@ A device that can be used for recording must implement the functions
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
virtual bool OpenDvr(void);
virtual void CloseDvr(void);
<!--X1.1.9--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<!--X1.1.9--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
virtual bool GetTSPacket(uchar *&amp;Data);
<!--X1.1.9--></td></tr></table>
</pre></td></tr></table><p>
@ -1227,7 +1228,6 @@ to indicate this to VDR.
<p>
The functions to implement replaying capabilites are
<!--X1.1.7--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
virtual bool HasDecoder(void) const;
virtual bool SetPlayMode(ePlayMode PlayMode);
@ -1240,7 +1240,6 @@ virtual void StillPicture(const uchar *Data, int Length);
virtual bool Poll(cPoller &amp;Poller, int TimeoutMs = 0);
virtual int PlayVideo(const uchar *Data, int Length);
</pre></td></tr></table><p>
<!--X1.1.7--></td></tr></table>
In addition, the following functions may be implemented to provide further
functionality:
@ -1251,7 +1250,7 @@ virtual void SetVideoFormat(bool VideoFormat16_9);
virtual void SetVolumeDevice(int Volume);
</pre></td></tr></table><p>
<!--X1.1.8--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
<!--X1.1.8--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<p>
<b>On Screen Display</b>
<p>
@ -1292,7 +1291,7 @@ shut down (delete) all devices when the program terminates. It is therefore
important that the devices are created on the heap, using the <tt>new</tt>
operator!
<!--X1.1.11--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
<!--X1.1.11--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<hr><h2>Remote Control</h2>
<center><i><b>The joy of zapping!</b></i></center><p>

433
channels.c Normal file
View File

@ -0,0 +1,433 @@
/*
* channels.c: Channel handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: channels.c 1.1 2002/10/05 13:22:28 kls Exp $
*/
#include "channels.h"
#ifdef NEWSTRUCT
#include <linux/dvb/frontend.h>
#else
#include <ost/frontend.h>
#endif
#include <ctype.h>
// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
// format characters in order to allow any number of blanks after a numeric
// value!
// -- Channel Parameter Maps -------------------------------------------------
const tChannelParameterMap InversionValues[] = {
{ 0, INVERSION_OFF },
{ 1, INVERSION_ON },
{ 999, INVERSION_AUTO },
{ -1 }
};
const tChannelParameterMap BandwidthValues[] = {
{ 6, BANDWIDTH_6_MHZ },
{ 7, BANDWIDTH_7_MHZ },
{ 8, BANDWIDTH_8_MHZ },
#ifdef NEWSTRUCT
{ 999, BANDWIDTH_AUTO },
#endif
{ -1 }
};
const tChannelParameterMap CoderateValues[] = {
{ 0, FEC_NONE },
{ 12, FEC_1_2 },
{ 23, FEC_2_3 },
{ 34, FEC_3_4 },
#ifdef NEWSTRUCT
{ 45, FEC_4_5 },
#endif
{ 56, FEC_5_6 },
#ifdef NEWSTRUCT
{ 67, FEC_6_7 },
#endif
{ 78, FEC_7_8 },
#ifdef NEWSTRUCT
{ 89, FEC_8_9 },
#endif
{ 999, FEC_AUTO },
{ -1 }
};
const tChannelParameterMap ModulationValues[] = {
{ 0, QPSK },
{ 16, QAM_16 },
{ 32, QAM_32 },
{ 64, QAM_64 },
{ 128, QAM_128 },
{ 256, QAM_256 },
#ifdef NEWSTRUCT
{ 999, QAM_AUTO },
#endif
{ -1 }
};
const tChannelParameterMap TransmissionValues[] = {
{ 2, TRANSMISSION_MODE_2K },
{ 8, TRANSMISSION_MODE_8K },
#ifdef NEWSTRUCT
{ 999, TRANSMISSION_MODE_AUTO },
#endif
{ -1 }
};
const tChannelParameterMap GuardValues[] = {
{ 4, GUARD_INTERVAL_1_4 },
{ 8, GUARD_INTERVAL_1_8 },
{ 16, GUARD_INTERVAL_1_16 },
{ 32, GUARD_INTERVAL_1_32 },
#ifdef NEWSTRUCT
{ 999, GUARD_INTERVAL_AUTO },
#endif
{ -1 }
};
const tChannelParameterMap HierarchyValues[] = {
{ 0, HIERARCHY_NONE },
{ 1, HIERARCHY_1 },
{ 2, HIERARCHY_2 },
{ 4, HIERARCHY_4 },
#ifdef NEWSTRUCT
{ 999, HIERARCHY_AUTO },
#endif
{ -1 }
};
int UserIndex(int Value, const tChannelParameterMap *Map)
{
const tChannelParameterMap *map = Map;
while (map && map->userValue != -1) {
if (map->userValue == Value)
return map - Map;
map++;
}
return -1;
}
int DriverIndex(int Value, const tChannelParameterMap *Map)
{
const tChannelParameterMap *map = Map;
while (map && map->userValue != -1) {
if (map->driverValue == Value)
return map - Map;
map++;
}
return -1;
}
int MapToUser(int Value, const tChannelParameterMap *Map)
{
int n = DriverIndex(Value, Map);
if (n >= 0)
return Map[n].userValue;
return -1;
}
int MapToDriver(int Value, const tChannelParameterMap *Map)
{
int n = UserIndex(Value, Map);
if (n >= 0)
return Map[n].driverValue;
return -1;
}
// -- cChannel ---------------------------------------------------------------
char *cChannel::buffer = NULL;
cChannel::cChannel(void)
{
*name = 0;
frequency = 0;
source = 0;
srate = 0;
vpid = 0;
apid1 = 0;
apid2 = 0;
dpid1 = 0;
dpid2 = 0;
tpid = 0;
ca = 0;
sid = 0;
groupSep = false;
//XXX
polarization = 'v';
inversion = INVERSION_AUTO;
bandwidth = BANDWIDTH_8_MHZ;
coderateH = FEC_AUTO;//XXX FEC_2_3
coderateL = FEC_1_2;//XXX
modulation = QAM_64;
transmission = TRANSMISSION_MODE_2K;
guard = GUARD_INTERVAL_1_32;
hierarchy = HIERARCHY_NONE;
}
cChannel::cChannel(const cChannel *Channel)
{
strcpy(name, Channel ? Channel->name : "Pro7");
frequency = Channel ? Channel->frequency : 12480;
source = Channel ? Channel->source : 0;
srate = Channel ? Channel->srate : 27500;
vpid = Channel ? Channel->vpid : 255;
apid1 = Channel ? Channel->apid1 : 256;
apid2 = Channel ? Channel->apid2 : 0;
dpid1 = Channel ? Channel->dpid1 : 257;
dpid2 = Channel ? Channel->dpid2 : 0;
tpid = Channel ? Channel->tpid : 32;
ca = Channel ? Channel->ca : 0;
sid = Channel ? Channel->sid : 0;
groupSep = Channel ? Channel->groupSep : false;
//XXX
polarization = Channel ? Channel->polarization : 'v';
inversion = Channel ? Channel->inversion : INVERSION_AUTO;
bandwidth = Channel ? Channel->bandwidth : BANDWIDTH_8_MHZ;
coderateH = Channel ? Channel->coderateH : FEC_AUTO;//XXX FEC_2_3
coderateL = Channel ? Channel->coderateL : FEC_1_2;//XXX
modulation = Channel ? Channel->modulation : QAM_64;
transmission = Channel ? Channel->transmission : TRANSMISSION_MODE_2K;
guard = Channel ? Channel->guard : GUARD_INTERVAL_1_32;
hierarchy = Channel ? Channel->hierarchy : HIERARCHY_NONE;
}
static int PrintParameter(char *p, char Name, int Value)
{
return Value > 0 && Value != 999 ? sprintf(p, "%c%d", Name, Value) : 0;
}
const char *cChannel::ParametersToString(void)
{
char type = *cSource::ToString(source);
#define ST(s) if (strchr(s, type))
static char buffer[64];
char *q = buffer;
*q = 0;
ST(" S ") q += sprintf(q, "%c", polarization);
ST("CST") q += PrintParameter(q, 'I', MapToUser(inversion, InversionValues));
ST("CST") q += PrintParameter(q, 'C', MapToUser(coderateH, CoderateValues));
ST(" T") q += PrintParameter(q, 'D', MapToUser(coderateL, CoderateValues));
ST("C T") q += PrintParameter(q, 'M', MapToUser(modulation, ModulationValues));
ST(" T") q += PrintParameter(q, 'B', MapToUser(bandwidth, BandwidthValues));
ST(" T") q += PrintParameter(q, 'T', MapToUser(transmission, TransmissionValues));
ST(" T") q += PrintParameter(q, 'G', MapToUser(guard, GuardValues));
ST(" T") q += PrintParameter(q, 'Y', MapToUser(hierarchy, HierarchyValues));
return buffer;
}
static const char *ParseParameter(const char *s, int &Value, const tChannelParameterMap *Map)
{
if (*++s) {
char *p = NULL;
errno = 0;
int n = strtol(s, &p, 10);
if (!errno && p != s) {
Value = MapToDriver(n, Map);
if (Value >= 0)
return p;
}
}
esyslog("ERROR: illegal value for parameter '%c'", *(s - 1));
return NULL;
}
bool cChannel::StringToParameters(const char *s)
{
while (s && *s) {
switch (toupper(*s)) {
case 'B': s = ParseParameter(s, bandwidth, BandwidthValues); break;
case 'C': s = ParseParameter(s, coderateH, CoderateValues); break;
case 'D': s = ParseParameter(s, coderateL, CoderateValues); break;
case 'G': s = ParseParameter(s, guard, GuardValues); break;
case 'H': polarization = *s++; break;
case 'I': s = ParseParameter(s, inversion, InversionValues); break;
// 'L' reserved for possible circular polarization
case 'M': s = ParseParameter(s, modulation, ModulationValues); break;
// 'R' reserved for possible circular polarization
case 'T': s = ParseParameter(s, transmission, TransmissionValues); break;
case 'V': polarization = *s++; break;
case 'Y': s = ParseParameter(s, hierarchy, HierarchyValues); break;
default: esyslog("ERROR: unknown parameter key '%c'", *s);
return false;
}
}
return true;
}
const char *cChannel::ToText(cChannel *Channel)
{
char buf[MaxChannelName * 2];
char *s = Channel->name;
if (strchr(s, ':')) {
s = strcpy(buf, s);
strreplace(s, ':', '|');
}
free(buffer);
if (Channel->groupSep)
asprintf(&buffer, ":%s\n", s);
else {
char apidbuf[32];
char *q = apidbuf;
q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1);
if (Channel->apid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->apid2);
if (Channel->dpid1 || Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ";%d", Channel->dpid1);
if (Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2);
*q = 0;
asprintf(&buffer, "%s:%d:%s:%s:%d:%d:%s:%d:%d:%d\n", s, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, Channel->vpid, apidbuf, Channel->tpid, Channel->ca, Channel->sid);
}
return buffer;
}
const char *cChannel::ToText(void)
{
return ToText(this);
}
bool cChannel::Parse(const char *s)
{
if (*s == ':') {
if (*++s) {
strn0cpy(name, s, MaxChannelName);
groupSep = true;
number = 0;
}
else
return false;
}
else {
groupSep = false;
char *namebuf = NULL;
char *sourcebuf = NULL;
char *parambuf = NULL;
char *apidbuf = NULL;
int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%d :%a[^:]:%d :%d :%d ", &namebuf, &frequency, &parambuf, &sourcebuf, &srate, &vpid, &apidbuf, &tpid, &ca, &sid);
if (fields >= 9) {
if (fields == 9) {
// allow reading of old format
sid = ca;
ca = tpid;
tpid = 0;
}
apid1 = apid2 = 0;
dpid1 = dpid2 = 0;
bool ok = false;
if (parambuf && sourcebuf && apidbuf) {
ok = StringToParameters(parambuf) && (source = cSource::FromString(sourcebuf)) >= 0;
char *p = strchr(apidbuf, ';');
if (p)
*p++ = 0;
sscanf(apidbuf, "%d ,%d ", &apid1, &apid2);
if (p)
sscanf(p, "%d ,%d ", &dpid1, &dpid2);
}
strn0cpy(name, namebuf, MaxChannelName);
free(parambuf);
free(sourcebuf);
free(apidbuf);
free(namebuf);
return ok;
}
else
return false;
}
strreplace(name, '|', ':');
return true;
}
bool cChannel::Save(FILE *f)
{
return fprintf(f, ToText()) > 0;
}
// -- cChannels --------------------------------------------------------------
cChannels Channels;
bool cChannels::Load(const char *FileName, bool AllowComments)
{
if (cConfig<cChannel>::Load(FileName, AllowComments)) {
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->SetNumber(++Number);
ch = (cChannel *)ch->Next();
}
maxNumber = Number;
}
cChannel *cChannels::GetByNumber(int Number)
{
cChannel *channel = (cChannel *)First();
while (channel) {
if (!channel->GroupSep() && channel->Number() == Number)
return channel;
channel = (cChannel *)channel->Next();
}
return NULL;
}
cChannel *cChannels::GetByServiceID(unsigned short ServiceId)
{
cChannel *channel = (cChannel *)First();
while (channel) {
if (!channel->GroupSep() && channel->Sid() == ServiceId)
return channel;
channel = (cChannel *)channel->Next();
}
return NULL;
}
bool cChannels::SwitchTo(int Number)
{
cChannel *channel = GetByNumber(Number);
return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
}
const char *cChannels::GetChannelNameByNumber(int Number)
{
cChannel *channel = GetByNumber(Number);
return channel ? channel->Name() : NULL;
}

124
channels.h Normal file
View File

@ -0,0 +1,124 @@
/*
* channels.h: Channel handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: channels.h 1.1 2002/10/05 13:53:15 kls Exp $
*/
#ifndef __CHANNELS_H
#define __CHANNELS_H
#include "config.h"
#include "sources.h"
#include "tools.h"
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4) //XXX
struct tChannelParameterMap {
int userValue;
int driverValue;
};
//XXX into cChannel???
int MapToUser(int Value, const tChannelParameterMap *Map);
int MapToDriver(int Value, const tChannelParameterMap *Map);
int UserIndex(int Value, const tChannelParameterMap *Map);
int DriverIndex(int Value, const tChannelParameterMap *Map);
extern const tChannelParameterMap InversionValues[];
extern const tChannelParameterMap BandwidthValues[];
extern const tChannelParameterMap CoderateValues[];
extern const tChannelParameterMap ModulationValues[];
extern const tChannelParameterMap TransmissionValues[];
extern const tChannelParameterMap GuardValues[];
extern const tChannelParameterMap HierarchyValues[];
class cChannel : public cListObject {
friend class cMenuEditChannel;
private:
static char *buffer;
static const char *ToText(cChannel *Channel);
enum { MaxChannelName = 32 }; // 31 chars + terminating 0!
char name[MaxChannelName];
int frequency; // MHz
int source;
int srate;
int vpid;
int apid1, apid2;
int dpid1, dpid2;
int tpid;
int ca;
int sid;
int number; // Sequence number assigned on load
bool groupSep;
//XXX
char polarization;
int inversion;
int bandwidth;
int coderateH;
int coderateL;
int modulation;
int transmission;
int guard;
int hierarchy;
const char *ParametersToString(void);
bool StringToParameters(const char *s);
public:
cChannel(void);
cChannel(const cChannel *Channel);
const char *ToText(void);
bool Parse(const char *s);
bool Save(FILE *f);
const char *Name(void) const { return name; }
int Frequency(void) const { return frequency; }
int Source(void) const { return source; }
int Srate(void) const { return srate; }
int Vpid(void) const { return vpid; }
int Apid1(void) const { return apid1; }
int Apid2(void) const { return apid2; }
int Dpid1(void) const { return dpid1; }
int Dpid2(void) const { return dpid2; }
int Tpid(void) const { return tpid; }
int Ca(void) const { return ca; }
int Sid(void) const { return sid; }
int Number(void) const { return number; }
void SetNumber(int Number) { number = Number; }
bool GroupSep(void) const { return groupSep; }
//XXX
char Polarization(void) const { return polarization; }
int Inversion(void) const { return inversion; }
int Bandwidth(void) const { return bandwidth; }
int CoderateH(void) const { return coderateH; }
int CoderateL(void) const { return coderateL; }
int Modulation(void) const { return modulation; }
int Transmission(void) const { return transmission; }
int Guard(void) const { return guard; }
int Hierarchy(void) const { return hierarchy; }
//XXX
bool IsCable(void) { return (source & cSource::st_Mask) == cSource::stCable; }
bool IsSat(void) { return (source & cSource::st_Mask) == cSource::stSat; }
bool IsTerr(void) { return (source & cSource::st_Mask) == cSource::stTerr; }
};
class cChannels : public cConfig<cChannel> {
protected:
int maxNumber;
public:
cChannels(void) { maxNumber = 0; }
virtual bool Load(const char *FileName, bool AllowComments = false);
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);
cChannel *GetByServiceID(unsigned short ServiceId);
const char *GetChannelNameByNumber(int Number);
bool SwitchTo(int Number);
int MaxNumber(void) { return maxNumber; }
};
extern cChannels Channels;
#endif //__CHANNELS_H

202
config.c
View File

@ -4,12 +4,13 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.106 2002/09/28 09:43:41 kls Exp $
* $Id: config.c 1.107 2002/10/03 10:06:55 kls Exp $
*/
#include "config.h"
#include <ctype.h>
#include <stdlib.h>
#include "channels.h" //XXX timers!
#include "i18n.h"
#include "interface.h"
#include "plugin.h"
@ -19,116 +20,6 @@
// format characters in order to allow any number of blanks after a numeric
// value!
// -- cChannel ---------------------------------------------------------------
char *cChannel::buffer = NULL;
cChannel::cChannel(void)
{
*name = 0;
}
cChannel::cChannel(const cChannel *Channel)
{
strcpy(name, Channel ? Channel->name : "Pro7");
frequency = Channel ? Channel->frequency : 12480;
polarization = Channel ? Channel->polarization : 'v';
diseqc = Channel ? Channel->diseqc : 0;
srate = Channel ? Channel->srate : 27500;
vpid = Channel ? Channel->vpid : 255;
apid1 = Channel ? Channel->apid1 : 256;
apid2 = Channel ? Channel->apid2 : 0;
dpid1 = Channel ? Channel->dpid1 : 257;
dpid2 = Channel ? Channel->dpid2 : 0;
tpid = Channel ? Channel->tpid : 32;
ca = Channel ? Channel->ca : 0;
pnr = Channel ? Channel->pnr : 0;
groupSep = Channel ? Channel->groupSep : false;
}
const char *cChannel::ToText(cChannel *Channel)
{
char buf[MaxChannelName * 2];
char *s = Channel->name;
if (strchr(s, ':')) {
s = strcpy(buf, s);
strreplace(s, ':', '|');
}
free(buffer);
if (Channel->groupSep)
asprintf(&buffer, ":%s\n", s);
else {
char apidbuf[32];
char *q = apidbuf;
q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1);
if (Channel->apid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->apid2);
if (Channel->dpid1 || Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ";%d", Channel->dpid1);
if (Channel->dpid2)
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2);
*q = 0;
asprintf(&buffer, "%s:%d:%c:%d:%d:%d:%s:%d:%d:%d\n", s, Channel->frequency, Channel->polarization, Channel->diseqc, Channel->srate, Channel->vpid, apidbuf, Channel->tpid, Channel->ca, Channel->pnr);
}
return buffer;
}
const char *cChannel::ToText(void)
{
return ToText(this);
}
bool cChannel::Parse(const char *s)
{
char *buffer = NULL;
if (*s == ':') {
if (*++s) {
strn0cpy(name, s, MaxChannelName);
groupSep = true;
number = 0;
}
else
return false;
}
else {
groupSep = false;
char *apidbuf = NULL;
int fields = sscanf(s, "%a[^:]:%d :%c:%d :%d :%d :%a[^:]:%d :%d :%d ", &buffer, &frequency, &polarization, &diseqc, &srate, &vpid, &apidbuf, &tpid, &ca, &pnr);
apid1 = apid2 = 0;
dpid1 = dpid2 = 0;
if (apidbuf) {
char *p = strchr(apidbuf, ';');
if (p)
*p++ = 0;
sscanf(apidbuf, "%d ,%d ", &apid1, &apid2);
if (p)
sscanf(p, "%d ,%d ", &dpid1, &dpid2);
free(apidbuf);
}
else
return false;
if (fields >= 9) {
if (fields == 9) {
// allow reading of old format
pnr = ca;
ca = tpid;
tpid = 0;
}
strn0cpy(name, buffer, MaxChannelName);
free(buffer);
}
else
return false;
}
strreplace(name, '|', ':');
return true;
}
bool cChannel::Save(FILE *f)
{
return fprintf(f, ToText()) > 0;
}
// -- cTimer -----------------------------------------------------------------
char *cTimer::buffer = NULL;
@ -139,7 +30,7 @@ cTimer::cTimer(bool Instant)
recording = pending = false;
active = Instant ? taActInst : taInactive;
cChannel *ch = Channels.GetByNumber(cDevice::CurrentChannel());
channel = ch ? ch->number : 0;
channel = ch ? ch->Number() : 0;
time_t t = time(NULL);
struct tm tm_r;
struct tm *now = localtime_r(&t, &tm_r);
@ -156,7 +47,7 @@ cTimer::cTimer(bool Instant)
firstday = 0;
summary = NULL;
if (Instant && ch)
snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : ch->name);
snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : ch->Name());
}
cTimer::cTimer(const cEventInfo *EventInfo)
@ -165,7 +56,7 @@ cTimer::cTimer(const cEventInfo *EventInfo)
recording = pending = false;
active = true;
cChannel *ch = Channels.GetByServiceID(EventInfo->GetServiceID());
channel = ch ? ch->number : 0;
channel = ch ? ch->Number() : 0;
time_t tstart = EventInfo->GetTime();
time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
tstart -= Setup.MarginStart * 60;
@ -573,89 +464,6 @@ bool cCaDefinition::Parse(const char *s)
cCommands Commands;
// -- cChannels --------------------------------------------------------------
cChannels Channels;
bool cChannels::Load(const char *FileName, bool AllowComments)
{
if (cConfig<cChannel>::Load(FileName, AllowComments)) {
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->groupSep && channel->number == Number)
return channel;
channel = (cChannel *)channel->Next();
}
return NULL;
}
cChannel *cChannels::GetByServiceID(unsigned short ServiceId)
{
cChannel *channel = (cChannel *)First();
while (channel) {
if (!channel->groupSep && channel->pnr == ServiceId)
return channel;
channel = (cChannel *)channel->Next();
}
return NULL;
}
bool cChannels::SwitchTo(int Number)
{
cChannel *channel = GetByNumber(Number);
return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
}
const char *cChannels::GetChannelNameByNumber(int Number)
{
cChannel *channel = GetByNumber(Number);
return channel ? channel->name : NULL;
}
// -- cTimers ----------------------------------------------------------------
cTimers Timers;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 1.130 2002/09/30 15:57:23 kls Exp $
* $Id: config.h 1.131 2002/10/05 09:58:58 kls Exp $
*/
#ifndef __CONFIG_H
@ -32,34 +32,6 @@
#define MaxFileName 256
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4)
class cChannel : public cListObject {
private:
static char *buffer;
static const char *ToText(cChannel *Channel);
public:
enum { MaxChannelName = 32 }; // 31 chars + terminating 0!
char name[MaxChannelName];
int frequency; // MHz
char polarization;
int diseqc;
int srate;
int vpid;
int apid1, apid2;
int dpid1, dpid2;
int tpid;
int ca;
int pnr;
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);
};
enum eTimerActive { taInactive = 0,
taActive = 1,
taInstant = 2,
@ -193,7 +165,7 @@ public:
if (l->Parse(buffer))
Add(l);
else {
esyslog("error in %s, line %d\n", fileName, line);
esyslog("ERROR: error in %s, line %d\n", fileName, line);
delete l;
result = false;
break;
@ -229,23 +201,6 @@ public:
}
};
class cChannels : public cConfig<cChannel> {
protected:
int maxNumber;
public:
cChannels(void) { maxNumber = 0; }
virtual bool Load(const char *FileName, bool AllowComments = false);
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);
cChannel *GetByServiceID(unsigned short ServiceId);
const char *GetChannelNameByNumber(int Number);
bool SwitchTo(int Number);
int MaxNumber(void) { return maxNumber; }
};
class cTimers : public cConfig<cTimer> {
public:
cTimer *GetTimer(cTimer *Timer);
@ -265,7 +220,6 @@ public:
const cCaDefinition *Get(int Number);
};
extern cChannels Channels;
extern cTimers Timers;
extern cCommands Commands;
extern cSVDRPhosts SVDRPhosts;

View File

@ -4,13 +4,14 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.c 1.22 2002/09/28 12:20:22 kls Exp $
* $Id: device.c 1.23 2002/10/05 15:18:39 kls Exp $
*/
#include "device.h"
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "channels.h"
#include "eit.h"
#include "i18n.h"
#include "player.h"
@ -143,7 +144,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDe
|| !d->Receiving() // ...the one we have is not receiving...
&& (device[i]->Priority() < d->Priority() // ...this one has an even lower Priority, or...
|| device[i]->Priority() == d->Priority() // ...same Priority...
&& device[i]->ProvidesCa(Channel->ca) < d->ProvidesCa(Channel->ca) // ...but this one provides fewer Ca values
&& device[i]->ProvidesCa(Channel->Ca()) < d->ProvidesCa(Channel->Ca()) // ...but this one provides fewer Ca values
)
)
) {
@ -275,6 +276,11 @@ bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
return false;
}
bool cDevice::ProvidesSource(int Source) const
{
return false;
}
bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
{
return false;
@ -283,7 +289,7 @@ bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Needs
bool cDevice::SwitchChannel(const cChannel *Channel, bool LiveView)
{
if (LiveView)
isyslog("switching to channel %d", Channel->number);
isyslog("switching to channel %d", Channel->Number());
for (int i = 3; i--;) {
switch (SetChannel(Channel, LiveView)) {
case scrOk: return true;
@ -344,7 +350,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (CaDevice) {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
if (CaDevice->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
cControl::Launch(new cTransferControl(CaDevice, Channel->vpid, Channel->apid1, 0, 0, 0));//XXX+
cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apid1(), 0, 0, 0));//XXX+
else
Result = scrNoTransfer;
}
@ -359,10 +365,10 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (Result == scrOk) {
if (LiveView && IsPrimaryDevice()) {
cSIProcessor::SetCurrentServiceID(Channel->pnr);
currentChannel = Channel->number;
cSIProcessor::SetCurrentServiceID(Channel->Sid());
currentChannel = Channel->Number();
}
cStatus::MsgChannelSwitch(this, Channel->number); // only report status if channel switch successfull
cStatus::MsgChannelSwitch(this, Channel->Number()); // only report status if channel switch successfull
}
return Result;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: device.h 1.20 2002/09/28 12:20:34 kls Exp $
* $Id: device.h 1.21 2002/10/05 15:18:13 kls Exp $
*/
#ifndef __DEVICE_H
@ -139,6 +139,8 @@ public:
protected:
static int currentChannel;
public:
virtual bool ProvidesSource(int Source) const;
// Returns true if this device can provide the given source.
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
// Returns true if this device can provide the given channel.
// In case the device has cReceivers attached to it or it is the primary

136
diseqc.c Normal file
View File

@ -0,0 +1,136 @@
/*
* diseqc.c: DiSEqC handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: diseqc.c 1.1 2002/10/05 13:54:32 kls Exp $
*/
#include "diseqc.h"
#include <ctype.h>
#include "sources.h"
// -- cDiseqc ----------------------------------------------------------------
cDiseqc::cDiseqc(void)
{
commands = NULL;
currentAction = NULL;;
parsing = false;
numCodes = 0;
}
cDiseqc::~cDiseqc()
{
free(commands);
}
bool cDiseqc::Parse(const char *s)
{
bool result = false;
char *sourcebuf = NULL;
int fields = sscanf(s, "%a[^ ] %d %c %d %a[^\n]", &sourcebuf, &slof, &polarization, &lof, &commands);
if (fields == 4)
commands = NULL; //XXX Apparently sscanf() doesn't work correctly if the last %a argument results in an empty string
if (4 <= fields && fields <= 5) {
source = cSource::FromString(sourcebuf);
if (Sources.Get(source)) {
polarization = toupper(polarization);
if (polarization == 'V' || polarization == 'H') {
parsing = true;
bool Start = true;
while (Execute(Start) != daNone)
Start = false;
parsing = false;
result = !commands || currentAction && !*currentAction;
}
else
esyslog("ERROR: unknown polarization '%c'", polarization);
}
else
esyslog("ERROR: unknown source '%s'", sourcebuf);
}
free(sourcebuf);
return result;
}
char *cDiseqc::Wait(char *s)
{
char *p = NULL;
errno = 0;
int n = strtol(s, &p, 10);
if (!errno && p != s && n >= 0) {
if (!parsing)
usleep(n * 1000);
return p;
}
esyslog("ERROR: illegal value for wait time in '%s'", s - 1);
return NULL;
}
char *cDiseqc::Codes(char *s)
{
char *e = strchr(s, ']');
if (e) {
numCodes = 0;
char *t = s;
char *p = s;
while (t < e) {
if (numCodes < MaxDiseqcCodes) {
errno = 0;
int n = strtol(t, &p, 16);
if (!errno && p != t && 0 <= n && n <= 255) {
codes[numCodes++] = n;
t = skipspace(p);
}
else {
esyslog("ERROR: illegal code at '%s'", t);
return NULL;
}
}
else {
esyslog("ERROR: too many codes in code sequence '%s'", s - 1);
return NULL;
}
}
return e + 1;
}
else
esyslog("ERROR: missing closing ']' in code sequence '%s'", s - 1);
return NULL;
}
cDiseqc::eDiseqcActions cDiseqc::Execute(bool Start)
{
if (Start)
currentAction = commands;
while (currentAction && *currentAction) {
switch (*currentAction++) {
case ' ': break;
case 't': return daToneOff;
case 'T': return daToneOn;
case 'v': return daVoltage13;
case 'V': return daVoltage18;
case 'A': return daMiniA;
case 'B': return daMiniB;
case 'W': currentAction = Wait(currentAction); break;
case '[': currentAction = Codes(currentAction); return currentAction ? daCodes : daNone;
default: return daNone;
}
}
return daNone;
}
// -- cDiseqcs ---------------------------------------------------------------
cDiseqcs Diseqcs;
cDiseqc *cDiseqcs::Get(int Source, int Frequency, char Polarization)
{
for (cDiseqc *p = First(); p; p = Next(p)) {
if (p->Source() == Source && p->Slof() > Frequency && p->Polarization() == toupper(Polarization))
return p;
}
return NULL;
}

30
diseqc.conf Normal file
View File

@ -0,0 +1,30 @@
# DiSEqC configuration for VDR
#
# Format:
#
# satellite slof polarization lof command...
#
# satellite: one of the 'S' codes defined in sources.conf
# slof: switch frequency of LNB; the first entry with
# an slof greater than the actual transponder
# frequency will be used
# polarization: V = vertical, H = horizontal
# lof: the local oscillator frequency to subtract from
# the actual transponder frequency
# command:
# t tone off
# T tone on
# v voltage low (13V)
# V voltage high (18V)
# A mini A
# B mini B
# Wnn wait nn milliseconds (nn may be any positive integer number)
# [xx ...] hex code sequence (max. 6)
#
# The 'command...' part is optional.
S19.2E 11700 V 9750 t v W15 [E0 10 38 F0] W15 A W15 t
S19.2E 99999 V 10600 t v W15 [E0 10 38 F1] W15 A W15 T
S19.2E 11700 H 9750 t V W15 [E0 10 38 F2] W15 A W15 t
S19.2E 99999 H 10600 t V W15 [E0 10 38 F3] W15 A W15 T

60
diseqc.h Normal file
View File

@ -0,0 +1,60 @@
/*
* diseqc.h: DiSEqC handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: diseqc.h 1.1 2002/10/05 13:02:52 kls Exp $
*/
#ifndef __DISEQC_H
#define __DISEQC_H
#include "config.h"
class cDiseqc : public cListObject {
public:
enum eDiseqcActions {
daNone,
daToneOff,
daToneOn,
daVoltage13,
daVoltage18,
daMiniA,
daMiniB,
daCodes,
};
enum { MaxDiseqcCodes = 6 };
private:
int source;
int slof;
char polarization;
int lof;
char *commands;
char *currentAction;
bool parsing;
uchar codes[MaxDiseqcCodes];
int numCodes;
char *Wait(char *s);
char *Codes(char *s);
public:
cDiseqc(void);
~cDiseqc();
bool Parse(const char *s);
eDiseqcActions Execute(bool Start = false);
int Source(void) const { return source; }
int Slof(void) const { return slof; }
char Polarization(void) const { return polarization; }
int Lof(void) const { return lof; }
const char *Commands(void) const { return commands; }
uchar *Codes(int &NumCodes) { NumCodes = numCodes; return numCodes ? codes : NULL; }
};
class cDiseqcs : public cConfig<cDiseqc> {
public:
cDiseqc *Get(int Source, int Frequency, char Polarization);
};
extern cDiseqcs Diseqcs;
#endif //__DISEQC_H

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.c 1.21 2002/09/29 13:53:26 kls Exp $
* $Id: dvbdevice.c 1.22 2002/10/06 09:07:45 kls Exp $
*/
#include "dvbdevice.h"
@ -31,6 +31,8 @@ extern "C" {
#endif
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "channels.h"
#include "diseqc.h"
#include "dvbosd.h"
#include "player.h"
#include "receiver.h"
@ -124,7 +126,9 @@ cDvbDevice::cDvbDevice(int n)
else
esyslog("ERROR: can't open DVB device %d", n);
frequency = 0;
source = -1;
frequency = -1;
diseqcCommands = NULL;
}
cDvbDevice::~cDvbDevice()
@ -344,18 +348,33 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
return true;
}
bool cDvbDevice::IsTunedTo(const cChannel *Channel) const
{
return source == Channel->Source() && frequency == Channel->Frequency();
}
bool cDvbDevice::ProvidesSource(int Source) const
{
int type = Source & cSource::st_Mask;
return type == cSource::stNone
|| type == cSource::stCable && frontendType == FE_QAM
|| type == cSource::stSat && frontendType == FE_QPSK
|| type == cSource::stTerr && frontendType == FE_OFDM;
return true;
}
bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
{
bool result = false;
bool hasPriority = Priority < 0 || Priority > this->Priority();
bool needsDetachReceivers = true;
if (ProvidesCa(Channel->ca)) {
if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel->Ca())) {
if (Receiving()) {
if (frequency == Channel->frequency) {
if (IsTunedTo(Channel)) {
needsDetachReceivers = false;
if (!HasPid(Channel->vpid)) {
if (Channel->ca > CACONFBASE) {
if (!HasPid(Channel->Vpid())) {
if (Channel->Ca() > CACONFBASE) {
needsDetachReceivers = true;
result = hasPriority;
}
@ -394,24 +413,24 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
LiveView = true;
#endif
bool DoTune = frequency != Channel->frequency; // TODO will be changed when DiSEqC handling is revised
bool DoTune = !IsTunedTo(Channel);
bool TurnOffLivePIDs = HasDecoder()
&& (DoTune
|| Channel->ca > CACONFBASE && pidHandles[ptVideo].pid != Channel->vpid // CA channels can only be decrypted in "live" mode
|| Channel->Ca() > CACONFBASE && pidHandles[ptVideo].pid != Channel->Vpid() // CA channels can only be decrypted in "live" mode
|| IsPrimaryDevice()
&& (LiveView // for a new live view the old PIDs need to be turned off
|| pidHandles[ptVideo].pid == Channel->vpid // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
|| pidHandles[ptVideo].pid == Channel->Vpid() // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
)
);
bool StartTransferMode = IsPrimaryDevice() && !DoTune
&& (LiveView && HasPid(Channel->vpid) && pidHandles[ptVideo].pid != Channel->vpid // the PID is already set as DMX_PES_OTHER
|| !LiveView && pidHandles[ptVideo].pid == Channel->vpid // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
&& (LiveView && HasPid(Channel->Vpid()) && pidHandles[ptVideo].pid != Channel->Vpid() // the PID is already set as DMX_PES_OTHER
|| !LiveView && pidHandles[ptVideo].pid == Channel->Vpid() // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
);
bool TurnOnLivePIDs = HasDecoder() && !StartTransferMode
&& (Channel->ca > CACONFBASE // CA channels can only be decrypted in "live" mode
&& (Channel->Ca() > CACONFBASE // CA channels can only be decrypted in "live" mode
|| LiveView
);
@ -452,67 +471,127 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
switch (frontendType) {
case FE_QPSK: { // DVB-S
// Frequency offsets:
unsigned int frequency = Channel->Frequency();
unsigned int freq = Channel->frequency;
int tone = SEC_TONE_OFF;
if (Setup.DiSEqC) {
cDiseqc *diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
if (diseqc) {
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
#ifndef NEWSTRUCT
int SecTone = SEC_TONE_OFF;
int SecVolt = SEC_VOLTAGE_13;
#endif
cDiseqc::eDiseqcActions da;
for (bool Start = true; (da = diseqc->Execute(Start)) != cDiseqc::daNone; Start = false) {
switch (da) {
#ifdef NEWSTRUCT
case cDiseqc::daNone: break;
case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break;
case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break;
case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break;
case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break;
case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break;
case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break;
case cDiseqc::daCodes: {
int n = 0;
uchar *codes = diseqc->Codes(n);
if (codes) {
struct dvb_diseqc_master_cmd cmd;
memcpy(cmd.msg, codes, min(n, int(sizeof(cmd.msg))));
cmd.msg_len = n;
CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
}
}
break;
#else
// This may not work very good with the old driver.
// Let's try to emulate the NEWSTRUCT driver's behaviour as good as possible...
case cDiseqc::daNone: break;
case cDiseqc::daToneOff: CHECK(ioctl(fd_sec, SEC_SET_TONE, SecTone = SEC_TONE_OFF)); break;
case cDiseqc::daToneOn: CHECK(ioctl(fd_sec, SEC_SET_TONE, SecTone = SEC_TONE_ON)); break;
case cDiseqc::daVoltage13: CHECK(ioctl(fd_sec, SEC_SET_VOLTAGE, SecVolt = SEC_VOLTAGE_13)); break;
case cDiseqc::daVoltage18: CHECK(ioctl(fd_sec, SEC_SET_VOLTAGE, SecVolt = SEC_VOLTAGE_18)); break;
case cDiseqc::daMiniA:
case cDiseqc::daMiniB: {
secCmdSequence scmds;
memset(&scmds, 0, sizeof(scmds));
scmds.voltage = SecVolt;
scmds.miniCommand = (da == cDiseqc::daMiniA) ? SEC_MINI_A : SEC_MINI_B;
scmds.continuousTone = SecTone;
CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds));
}
break;
case cDiseqc::daCodes: {
int n = 0;
uchar *codes = diseqc->Codes(n);
if (codes && n >= 3 && codes[0] == 0xE0) {
secCommand scmd;
memset(&scmd, 0, sizeof(scmd));
scmd.type = SEC_CMDTYPE_DISEQC;
scmd.u.diseqc.addr = codes[1];
scmd.u.diseqc.cmd = codes[2];
scmd.u.diseqc.numParams = n - 3;
memcpy(scmd.u.diseqc.params, &codes[3], min(n - 3, int(sizeof(scmd.u.diseqc.params))));
secCmdSequence scmds;
memset(&scmds, 0, sizeof(scmds));
scmds.voltage = SecVolt;
scmds.miniCommand = SEC_MINI_NONE;
scmds.continuousTone = SecTone;
scmds.numCommands = 1;
scmds.commands = &scmd;
if (freq < (unsigned int)Setup.LnbSLOF) {
freq -= Setup.LnbFrequLo;
tone = SEC_TONE_OFF;
CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds));
}
}
break;
#endif
}
}
diseqcCommands = diseqc->Commands();
}
frequency -= diseqc->Lof();
}
else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", Channel->Number());
return false;
}
}
else {
freq -= Setup.LnbFrequHi;
tone = SEC_TONE_ON;
}
int tone = SEC_TONE_OFF;
if (frequency < (unsigned int)Setup.LnbSLOF) {
frequency -= Setup.LnbFrequLo;
tone = SEC_TONE_OFF;
}
else {
frequency -= Setup.LnbFrequHi;
tone = SEC_TONE_ON;
}
int volt = (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
#ifdef NEWSTRUCT
Frontend.frequency = freq * 1000UL;
Frontend.inversion = INVERSION_AUTO;
Frontend.u.qpsk.symbol_rate = Channel->srate * 1000UL;
Frontend.u.qpsk.fec_inner = FEC_AUTO;
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
#else
Frontend.Frequency = freq * 1000UL;
Frontend.Inversion = INVERSION_AUTO;
Frontend.u.qpsk.SymbolRate = Channel->srate * 1000UL;
Frontend.u.qpsk.FEC_inner = FEC_AUTO;
secCmdSequence scmds;
memset(&scmds, 0, sizeof(scmds));
scmds.voltage = volt;
scmds.miniCommand = SEC_MINI_NONE;
scmds.continuousTone = tone;
CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds));
#endif
int volt = (Channel->polarization == 'v' || Channel->polarization == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18;
// DiSEqC:
}
#ifdef NEWSTRUCT
struct dvb_diseqc_master_cmd cmd = { {0xE0, 0x10, 0x38, 0xF0, 0x00, 0x00}, 4};
cmd.msg[3] = 0xF0 | (((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0));
if (Setup.DiSEqC)
CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF));
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
if (Setup.DiSEqC) {
usleep(15 * 1000);
CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
usleep(15 * 1000);
CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, (Channel->diseqc / 4) % 2 ? SEC_MINI_B : SEC_MINI_A));
usleep(15 * 1000);
}
CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
Frontend.frequency = frequency * 1000UL;
Frontend.inversion = SpectralInversion(Channel->Inversion());
Frontend.u.qpsk.symbol_rate = Channel->Srate() * 1000UL;
Frontend.u.qpsk.fec_inner = CodeRate(Channel->CoderateH());
#else
secCommand scmd;
scmd.type = 0;
scmd.u.diseqc.addr = 0x10;
scmd.u.diseqc.cmd = 0x38;
scmd.u.diseqc.numParams = 1;
scmd.u.diseqc.params[0] = 0xF0 | ((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0);
secCmdSequence scmds;
scmds.voltage = volt;
scmds.miniCommand = SEC_MINI_NONE;
scmds.continuousTone = tone;
scmds.numCommands = Setup.DiSEqC ? 1 : 0;
scmds.commands = &scmd;
CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds));
Frontend.Frequency = frequency * 1000UL;
Frontend.Inversion = SpectralInversion(Channel->Inversion());
Frontend.u.qpsk.SymbolRate = Channel->Srate() * 1000UL;
Frontend.u.qpsk.FEC_inner = CodeRate(Channel->CoderateH());
#endif
}
break;
@ -521,17 +600,17 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
// Frequency and symbol rate:
#ifdef NEWSTRUCT
Frontend.frequency = Channel->frequency * 1000000UL;
Frontend.inversion = INVERSION_AUTO;
Frontend.u.qam.symbol_rate = Channel->srate * 1000UL;
Frontend.u.qam.fec_inner = FEC_AUTO;
Frontend.u.qam.modulation = QAM_64;
Frontend.frequency = Channel->Frequency() * 1000000UL;
Frontend.inversion = SpectralInversion(Channel->Inversion());
Frontend.u.qam.symbol_rate = Channel->Srate() * 1000UL;
Frontend.u.qam.fec_inner = CodeRate(Channel->CoderateH());
Frontend.u.qam.modulation = Modulation(Channel->Modulation());
#else
Frontend.Frequency = Channel->frequency * 1000000UL;
Frontend.Inversion = INVERSION_AUTO;
Frontend.u.qam.SymbolRate = Channel->srate * 1000UL;
Frontend.u.qam.FEC_inner = FEC_AUTO;
Frontend.u.qam.QAM = QAM_64;
Frontend.Frequency = Channel->Frequency() * 1000000UL;
Frontend.Inversion = SpectralInversion(Channel->Inversion());
Frontend.u.qam.SymbolRate = Channel->Srate() * 1000UL;
Frontend.u.qam.FEC_inner = CodeRate(Channel->CoderateH());
Frontend.u.qam.QAM = Modulation(Channel->Modulation());
#endif
}
break;
@ -540,25 +619,25 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
// Frequency and OFDM paramaters:
#ifdef NEWSTRUCT
Frontend.frequency = Channel->frequency * 1000UL;
Frontend.inversion = INVERSION_AUTO;
Frontend.u.ofdm.bandwidth=BANDWIDTH_8_MHZ;
Frontend.u.ofdm.code_rate_HP = FEC_2_3;
Frontend.u.ofdm.code_rate_LP = FEC_1_2;
Frontend.u.ofdm.constellation = QAM_64;
Frontend.u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
Frontend.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
Frontend.u.ofdm.hierarchy_information = HIERARCHY_NONE;
Frontend.frequency = Channel->Frequency() * 1000UL;
Frontend.inversion = SpectralInversion(Channel->Inversion());
Frontend.u.ofdm.bandwidth = BandWidth(Channel->Bandwidth());
Frontend.u.ofdm.code_rate_HP = CodeRate(Channel->CoderateH());
Frontend.u.ofdm.code_rate_LP = CodeRate(Channel->CoderateL());
Frontend.u.ofdm.constellation = Modulation(Channel->Modulation());
Frontend.u.ofdm.transmission_mode = TransmitMode(Channel->Transmission());
Frontend.u.ofdm.guard_interval = GuardInterval(Channel->Guard());
Frontend.u.ofdm.hierarchy_information = Hierarchy(Channel->Hierarchy());
#else
Frontend.Frequency = Channel->frequency * 1000UL;
Frontend.Inversion = INVERSION_AUTO;
Frontend.u.ofdm.bandWidth=BANDWIDTH_8_MHZ;
Frontend.u.ofdm.HP_CodeRate=FEC_2_3;
Frontend.u.ofdm.LP_CodeRate=FEC_1_2;
Frontend.u.ofdm.Constellation=QAM_64;
Frontend.u.ofdm.TransmissionMode=TRANSMISSION_MODE_2K;
Frontend.u.ofdm.guardInterval=GUARD_INTERVAL_1_32;
Frontend.u.ofdm.HierarchyInformation=HIERARCHY_NONE;
Frontend.Frequency = Channel->Frequency() * 1000UL;
Frontend.Inversion = SpectralInversion(Channel->Inversion());
Frontend.u.ofdm.bandWidth = BandWidth(Channel->Bandwidth());
Frontend.u.ofdm.HP_CodeRate = CodeRate(Channel->CoderateH());
Frontend.u.ofdm.LP_CodeRate = CodeRate(Channel->CoderateL());
Frontend.u.ofdm.Constellation = Modulation(Channel->Modulation());
Frontend.u.ofdm.TransmissionMode = TransmitMode(Channel->Transmission());
Frontend.u.ofdm.guardInterval = GuardInterval(Channel->Guard());
Frontend.u.ofdm.HierarchyInformation = Hierarchy(Channel->Hierarchy());
#endif
}
break;
@ -592,7 +671,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
usleep(10 * 1000);
}
if (!(status & FE_HAS_LOCK)) {
esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->number, CardIndex() + 1);
esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->Number(), CardIndex() + 1);
if (LiveView && IsPrimaryDevice())
cThread::RaisePanic();
return false;
@ -602,43 +681,44 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
FrontendEvent event;
if (ioctl(fd_frontend, FE_GET_EVENT, &event) >= 0) {
if (event.type != FE_COMPLETION_EV) {
esyslog("ERROR: channel %d not sync'ed on DVB card %d!", Channel->number, CardIndex() + 1);
esyslog("ERROR: channel %d not sync'ed on DVB card %d!", Channel->Number(), CardIndex() + 1);
if (LiveView && IsPrimaryDevice())
cThread::RaisePanic();
return false;
}
}
else
esyslog("ERROR in frontend get event (channel %d, card %d): %m", Channel->number, CardIndex() + 1);
esyslog("ERROR in frontend get event (channel %d, card %d): %m", Channel->Number(), CardIndex() + 1);
}
else
esyslog("ERROR: timeout while tuning on DVB card %d", CardIndex() + 1);
#endif
frequency = Channel->frequency;
source = Channel->Source();
frequency = Channel->Frequency();
}
// PID settings:
if (TurnOnLivePIDs) {
if (!(AddPid(Channel->apid1, ptAudio) && AddPid(Channel->vpid, ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached)
esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->number, CardIndex() + 1);
if (!(AddPid(Channel->Apid1(), ptAudio) && AddPid(Channel->Vpid(), ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached)
esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
return false;
}
if (IsPrimaryDevice())
AddPid(Channel->tpid, ptTeletext);
AddPid(Channel->Tpid(), ptTeletext);
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false));
}
else if (StartTransferMode)
cControl::Launch(new cTransferControl(this, Channel->vpid, Channel->apid1, 0, 0, 0));
cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), 0, 0, 0));
// Start setting system time:
if (siProcessor)
siProcessor->SetCurrentTransponder(Channel->frequency);
siProcessor->SetCurrentTransponder(Channel->Frequency());
return true;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: dvbdevice.h 1.11 2002/09/28 12:21:36 kls Exp $
* $Id: dvbdevice.h 1.12 2002/10/06 08:57:24 kls Exp $
*/
#ifndef __DVBDEVICE_H
@ -61,8 +61,12 @@ public:
// Channel facilities
private:
int source;
int frequency;
const char *diseqcCommands;
bool IsTunedTo(const cChannel *Channel) const;
public:
virtual bool ProvidesSource(int Source) const;
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
protected:
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);

7
eit.c
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* $Id: eit.c 1.52 2002/09/20 16:24:17 kls Exp $
* $Id: eit.c 1.53 2002/10/05 13:44:23 kls Exp $
***************************************************************************/
#include "eit.h"
@ -40,6 +40,7 @@
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include "channels.h"
#include "config.h"
#include "libdtv/libdtv.h"
#include "videodir.h"
@ -456,7 +457,7 @@ static void ReportEpgBugFixStats(bool Reset = false)
for (int c = 0; c < p->n; c++) {
cChannel *channel = Channels.GetByServiceID(p->serviceIDs[c]);
if (channel) {
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s%s", delim, channel->name);
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s%s", delim, channel->Name());
delim = ", ";
}
}
@ -768,7 +769,7 @@ void cSchedule::Dump(FILE *f, const char *Prefix) const
cChannel *channel = Channels.GetByServiceID(uServiceID);
if (channel)
{
fprintf(f, "%sC %u %s\n", Prefix, uServiceID, channel->name);
fprintf(f, "%sC %u %s\n", Prefix, uServiceID, channel->Name());
for (cEventInfo *p = Events.First(); p; p = Events.Next(p))
p->Dump(f, Prefix);
fprintf(f, "%sc\n", Prefix);

View File

@ -4,11 +4,12 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: eitscan.c 1.7 2002/09/08 11:08:52 kls Exp $
* $Id: eitscan.c 1.8 2002/10/05 13:44:35 kls Exp $
*/
#include "eitscan.h"
#include <stdlib.h>
#include "channels.h"
#include "dvbdevice.h"
cEITScanner::cEITScanner(void)
@ -28,11 +29,11 @@ cEITScanner::~cEITScanner()
bool cEITScanner::TransponderScanned(cChannel *Channel)
{
for (int i = 0; i < numTransponders; i++) {
if (transponders[i] == Channel->frequency)
if (transponders[i] == Channel->Frequency())
return true;
}
transponders = (int *)realloc(transponders, ++numTransponders * sizeof(int));
transponders[numTransponders - 1] = Channel->frequency;
transponders[numTransponders - 1] = Channel->Frequency();
return false;
}
@ -66,7 +67,7 @@ void cEITScanner::Process(void)
if (Channel) {
if (!Device->ProvidesChannel(Channel))
break;
if (Channel->pnr && !TransponderScanned(Channel)) {
if (Channel->Sid() && !TransponderScanned(Channel)) {
if (Device == cDevice::PrimaryDevice() && !currentChannel)
currentChannel = Device->CurrentChannel();
Device->SwitchChannel(Channel, false);

238
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: i18n.c 1.93 2002/09/29 12:32:46 kls Exp $
* $Id: i18n.c 1.94 2002/10/06 09:55:08 kls Exp $
*
* Translations provided by:
*
@ -890,21 +890,21 @@ const tI18nPhrase Phrases[] = {
"Polarizare",
"Polarizáció",
},
{ "DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
"DiSEqC",
{ "Source",
"Quelle",
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
"",//TODO
},
{ "Srate",
"Srate",
@ -1034,21 +1034,149 @@ const tI18nPhrase Phrases[] = {
"Criptare",
"CA",
},
{ "Pnr",
"Pnr",
"Pnr",
"Pnr",
"Pnr",
"Núm. Progr.",
"Num. Progr.",
"Program Id",
"Ohjelmatunnus",
"Pnr",
"Pnr",
"Pnr",
"Pnr",
"Nr. Prog.",
"Pnr",
{ "Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
"Sid",
},
{ "Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
"Inversion",
},
{ "Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
"Bandwidth",
},
{ "CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
"CoderateH",
},
{ "CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
"CoderateL",
},
{ "Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
"Modulation",
},
{ "Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
"Transmission",
},
{ "Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
"Guard",
},
{ "Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
"Hierarchy",
},
// Timer parameters:
{ "Active",
@ -2723,6 +2851,54 @@ const tI18nPhrase Phrases[] = {
"nu",
"nem",
},
{ "off",
"aus",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "none",
"keine",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "auto",
"auto",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "top",
"oben",
"zgoraj",

271
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: menu.c 1.209 2002/09/29 12:50:47 kls Exp $
* $Id: menu.c 1.210 2002/10/06 09:52:52 kls Exp $
*/
#include "menu.h"
@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "channels.h"
#include "config.h"
#include "cutter.h"
#include "eit.h"
@ -21,6 +22,7 @@
#include "plugin.h"
#include "recording.h"
#include "remote.h"
#include "sources.h"
#include "status.h"
#include "videodir.h"
@ -53,7 +55,7 @@ void cMenuEditChanItem::Set(void)
char buf[255];
cChannel *channel = Channels.GetByNumber(*value);
if (channel)
snprintf(buf, sizeof(buf), "%d %s", *value, channel->name);
snprintf(buf, sizeof(buf), "%d %s", *value, channel->Name());
else
*buf = 0;
SetValue(buf);
@ -77,8 +79,8 @@ cMenuEditTranItem::cMenuEditTranItem(const char *Name, int *Value)
transponder = *Value;
cChannel *channel = Channels.First();
while (channel) {
if (!channel->groupSep && ISTRANSPONDER(channel->frequency, *Value)) {
number = channel->number;
if (!channel->GroupSep() && ISTRANSPONDER(channel->Frequency(), *Value)) {
number = channel->Number();
break;
}
channel = (cChannel *)channel->Next();
@ -95,7 +97,7 @@ eOSState cMenuEditTranItem::ProcessKey(eKeys Key)
number = *value;
cChannel *channel = Channels.GetByNumber(*value);
if (channel)
transponder = channel->frequency;
transponder = channel->Frequency();
*value = transponder;
return state;
}
@ -391,12 +393,137 @@ eOSState cMenuEditCaItem::ProcessKey(eKeys Key)
return state;
}
// --- cMenuEditSrcItem ------------------------------------------------------
class cMenuEditSrcItem : public cMenuEditIntItem {
private:
const cSource *source;
protected:
virtual void Set(void);
public:
cMenuEditSrcItem(const char *Name, int *Value);
eOSState ProcessKey(eKeys Key);
};
cMenuEditSrcItem::cMenuEditSrcItem(const char *Name, int *Value)
:cMenuEditIntItem(Name, Value, 0)
{
source = Sources.Get(*Value);
Set();
}
void cMenuEditSrcItem::Set(void)
{
if (source) {
char *buffer = NULL;
asprintf(&buffer, "%s - %s", cSource::ToString(source->Code()), source->Description());
SetValue(buffer);
free(buffer);
}
else
cMenuEditIntItem::Set();
}
eOSState cMenuEditSrcItem::ProcessKey(eKeys Key)
{
eOSState state = cMenuEditItem::ProcessKey(Key);
if (state == osUnknown) {
if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
if (source && source->Prev()) {
source = (cSource *)source->Prev();
*value = source->Code();
}
}
else if (NORMALKEY(Key) == kRight) {
if (source) {
if (source->Next())
source = (cSource *)source->Next();
}
else
source = Sources.First();
if (source)
*value = source->Code();
}
else
return state; // we don't call cMenuEditIntItem::ProcessKey(Key) here since we don't accept numerical input
Set();
state = osContinue;
}
return state;
}
// --- cMenuEditMapItem ------------------------------------------------------
class cMenuEditMapItem : public cMenuEditItem {
protected:
int *value;
const tChannelParameterMap *map;
const char *zeroString;
virtual void Set(void);
public:
cMenuEditMapItem(const char *Name, int *Value, const tChannelParameterMap *Map, const char *ZeroString = NULL);
virtual eOSState ProcessKey(eKeys Key);
};
cMenuEditMapItem::cMenuEditMapItem(const char *Name, int *Value, const tChannelParameterMap *Map, const char *ZeroString)
:cMenuEditItem(Name)
{
value = Value;
map = Map;
zeroString = ZeroString;
Set();
}
void cMenuEditMapItem::Set(void)
{
int n = MapToUser(*value, map);
if (n == 999)
SetValue(tr("auto"));
else if (n == 0 && zeroString)
SetValue(zeroString);
else if (n >= 0) {
char buf[16];
snprintf(buf, sizeof(buf), "%d", n);
SetValue(buf);
}
else
SetValue("???");
}
eOSState cMenuEditMapItem::ProcessKey(eKeys Key)
{
eOSState state = cMenuEditItem::ProcessKey(Key);
if (state == osUnknown) {
int newValue = *value;
int n = DriverIndex(*value, map);
if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
if (n-- > 0)
newValue = map[n].driverValue;
}
else if (NORMALKEY(Key) == kRight) {
if (map[++n].userValue >= 0)
newValue = map[n].driverValue;
}
else
return state;
if (newValue != *value) {
*value = newValue;
Set();
}
state = osContinue;
}
return state;
}
// --- cMenuEditChannel ------------------------------------------------------
class cMenuEditChannel : public cOsdMenu {
private:
cChannel *channel;
cChannel data;
void Setup(void);
public:
cMenuEditChannel(int Index);
virtual eOSState ProcessKey(eKeys Key);
@ -408,24 +535,49 @@ cMenuEditChannel::cMenuEditChannel(int Index)
channel = Channels.Get(Index);
if (channel) {
data = *channel;
Add(new cMenuEditStrItem( tr("Name"), data.name, sizeof(data.name), tr(FileNameChars)));
Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency));
Add(new cMenuEditChrItem( tr("Polarization"), &data.polarization, "hv"));
Add(new cMenuEditIntItem( tr("DiSEqC"), &data.diseqc, 0, 10)); //TODO exact limits???
Add(new cMenuEditIntItem( tr("Srate"), &data.srate));
Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Apid1"), &data.apid1, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Apid2"), &data.apid2, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpid1, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpid2, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 0x1FFF));
Add(new cMenuEditCaItem( tr("CA"), &data.ca, true));
Add(new cMenuEditIntItem( tr("Pnr"), &data.pnr, 0));
Setup();
}
}
void cMenuEditChannel::Setup(void)
{
int current = Current();
char type = *cSource::ToString(data.source);
#define ST(s) if (strchr(s, type))
Clear();
// Parameters for all types of sources:
Add(new cMenuEditStrItem( tr("Name"), data.name, sizeof(data.name), tr(FileNameChars)));
Add(new cMenuEditSrcItem( tr("Source"), &data.source));
Add(new cMenuEditIntItem( tr("Frequency"), &data.frequency));
Add(new cMenuEditIntItem( tr("Vpid"), &data.vpid, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Apid1"), &data.apid1, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Apid2"), &data.apid2, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpid1, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpid2, 0, 0x1FFF));
Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 0x1FFF));
Add(new cMenuEditCaItem( tr("CA"), &data.ca, true));
Add(new cMenuEditIntItem( tr("Sid"), &data.sid, 0));
// Parameters for specific types of sources:
ST(" S ") Add(new cMenuEditChrItem( tr("Polarization"), &data.polarization, "hv"));
ST("CS ") Add(new cMenuEditIntItem( tr("Srate"), &data.srate));
ST("CST") Add(new cMenuEditMapItem( tr("Inversion"), &data.inversion, InversionValues, tr("off")));
ST("CST") Add(new cMenuEditMapItem( tr("CoderateH"), &data.coderateH, CoderateValues, tr("none")));
ST(" T") Add(new cMenuEditMapItem( tr("CoderateL"), &data.coderateL, CoderateValues, tr("none")));
ST("C T") Add(new cMenuEditMapItem( tr("Modulation"), &data.modulation, ModulationValues, "QPSK"));
ST(" T") Add(new cMenuEditMapItem( tr("Bandwidth"), &data.bandwidth, BandwidthValues));
ST(" T") Add(new cMenuEditMapItem( tr("Transmission"), &data.transmission, TransmissionValues));
ST(" T") Add(new cMenuEditMapItem( tr("Guard"), &data.guard, GuardValues));
ST(" T") Add(new cMenuEditMapItem( tr("Hierarchy"), &data.hierarchy, HierarchyValues, tr("none")));
SetCurrent(Get(current));
Display();
}
eOSState cMenuEditChannel::ProcessKey(eKeys Key)
{
int oldSource = data.source;
eOSState state = cOsdMenu::ProcessKey(Key);
if (state == osUnknown) {
@ -436,6 +588,8 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
state = osBack;
}
}
if (Key != kNone && (data.source & cSource::st_Mask) != (oldSource & cSource::st_Mask))
Setup();
return state;
}
@ -455,7 +609,7 @@ cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
{
index = Index;
channel = Channel;
if (channel->groupSep)
if (channel->GroupSep())
SetColor(clrCyan, clrBackground);
Set();
}
@ -463,10 +617,10 @@ cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
void cMenuChannelItem::Set(void)
{
char *buffer = NULL;
if (!channel->groupSep)
asprintf(&buffer, "%d\t%s", channel->number, channel->name );
if (!channel->GroupSep())
asprintf(&buffer, "%d\t%s", channel->Number(), channel->Name());
else
asprintf(&buffer, "---\t%s ----------------------------------------------------------------", channel->name);
asprintf(&buffer, "---\t%s ----------------------------------------------------------------", channel->Name());
SetText(buffer, false);
}
@ -530,7 +684,7 @@ eOSState cMenuChannels::New(void)
Channels.ReNumber();
Add(new cMenuChannelItem(channel->Index()/*XXX*/, channel), true);
Channels.Save();
isyslog("channel %d added", channel->number);
isyslog("channel %d added", channel->Number());
return AddSubMenu(new cMenuEditChannel(Current()));
}
@ -539,7 +693,7 @@ eOSState cMenuChannels::Del(void)
if (Count() > 0) {
int Index = Current();
cChannel *channel = Channels.Get(Index);
int DeletedChannel = channel->number;
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 == DeletedChannel) {
@ -578,8 +732,8 @@ eOSState cMenuChannels::Del(void)
void cMenuChannels::Move(int From, int To)
{
int FromNumber = Channels.Get(From)->number;
int ToNumber = Channels.Get(To)->number;
int FromNumber = Channels.Get(From)->Number();
int ToNumber = Channels.Get(To)->Number();
// Move and renumber the channels:
Channels.Move(From, To);
Channels.ReNumber();
@ -933,7 +1087,7 @@ cMenuEvent::cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch)
cChannel *channel = Channels.GetByServiceID(eventInfo->GetServiceID());
if (channel) {
char *buffer;
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->name, 5, eventInfo->GetDate(), eventInfo->GetTimeString(), eventInfo->GetEndTimeString());
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->Name(), 5, eventInfo->GetDate(), eventInfo->GetTimeString(), eventInfo->GetEndTimeString());
SetTitle(buffer, false);
free(buffer);
int Line = 2;
@ -984,7 +1138,7 @@ cMenuWhatsOnItem::cMenuWhatsOnItem(const cEventInfo *EventInfo)
eventInfo = EventInfo;
char *buffer = NULL;
cChannel *channel = Channels.GetByNumber(eventInfo->GetChannelNumber());
asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", eventInfo->GetChannelNumber(), 6, channel ? channel->name : "???", 5, eventInfo->GetTimeString(), eventInfo->GetTitle());
asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", eventInfo->GetChannelNumber(), 6, channel ? channel->Name() : "???", 5, eventInfo->GetTimeString(), eventInfo->GetTitle());
SetText(buffer, false);
}
@ -1026,7 +1180,7 @@ cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentCha
if (pArray[num]) {
cChannel *channel = Channels.GetByServiceID(pArray[num]->GetServiceID());
if (channel) {
pArray[num]->SetChannelNumber(channel->number);
pArray[num]->SetChannelNumber(channel->Number());
num++;
}
}
@ -1149,7 +1303,7 @@ cMenuSchedule::cMenuSchedule(void)
otherChannel = 0;
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (channel) {
cMenuWhatsOn::SetCurrentChannel(channel->number);
cMenuWhatsOn::SetCurrentChannel(channel->Number());
schedules = cSIProcessor::Schedules(mutexLock);
PrepareSchedule(channel);
SetHelp(tr("Record"), tr("Now"), tr("Next"));
@ -1170,11 +1324,11 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel)
{
Clear();
char *buffer = NULL;
asprintf(&buffer, tr("Schedule - %s"), Channel->name);
asprintf(&buffer, tr("Schedule - %s"), Channel->Name());
SetTitle(buffer);
free(buffer);
if (schedules) {
const cSchedule *Schedule = Channel->pnr ? schedules->GetSchedule(Channel->pnr) : schedules->GetSchedule();
const cSchedule *Schedule = Channel->Sid() ? schedules->GetSchedule(Channel->Sid()) : schedules->GetSchedule();
int num = Schedule->NumEvents();
const cEventInfo **pArray = MALLOC(const cEventInfo *, num);
if (pArray) {
@ -1238,7 +1392,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
if (Count()) {
cChannel *channel = Channels.GetByServiceID(((cMenuScheduleItem *)Get(Current()))->eventInfo->GetServiceID());
if (channel)
ChannelNr = channel->number;
ChannelNr = channel->Number();
}
now = true;
return AddSubMenu(new cMenuWhatsOn(schedules, true, ChannelNr));
@ -1266,8 +1420,8 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
cChannel *channel = Channels.GetByServiceID(ei->GetServiceID());
if (channel) {
PrepareSchedule(channel);
if (channel->number != cDevice::CurrentChannel()) {
otherChannel = channel->number;
if (channel->Number() != cDevice::CurrentChannel()) {
otherChannel = channel->Number();
SetHelp(tr("Record"), tr("Now"), tr("Next"), tr("Switch"));
}
Display();
@ -1636,17 +1790,44 @@ eOSState cMenuSetupDVB::ProcessKey(eKeys Key)
// --- cMenuSetupLNB ---------------------------------------------------------
class cMenuSetupLNB : public cMenuSetupBase {
private:
void Setup(void);
public:
cMenuSetupLNB(void);
virtual eOSState ProcessKey(eKeys Key);
};
cMenuSetupLNB::cMenuSetupLNB(void)
{
SetSection(tr("LNB"));
Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"), &data.LnbSLOF));
Add(new cMenuEditIntItem( tr("Setup.LNB$Low LNB frequency (MHz)"), &data.LnbFrequLo));
Add(new cMenuEditIntItem( tr("Setup.LNB$High LNB frequency (MHz)"), &data.LnbFrequHi));
Setup();
}
void cMenuSetupLNB::Setup(void)
{
int current = Current();
Clear();
Add(new cMenuEditBoolItem(tr("Setup.LNB$Use DiSEqC"), &data.DiSEqC));
if (!data.DiSEqC) {
Add(new cMenuEditIntItem( tr("Setup.LNB$SLOF (MHz)"), &data.LnbSLOF));
Add(new cMenuEditIntItem( tr("Setup.LNB$Low LNB frequency (MHz)"), &data.LnbFrequLo));
Add(new cMenuEditIntItem( tr("Setup.LNB$High LNB frequency (MHz)"), &data.LnbFrequHi));
}
SetCurrent(Get(current));
Display();
}
eOSState cMenuSetupLNB::ProcessKey(eKeys Key)
{
int oldDiSEqC = data.DiSEqC;
eOSState state = cMenuSetupBase::ProcessKey(Key);
if (Key != kNone && data.DiSEqC != oldDiSEqC)
Setup();
return state;
}
// --- cMenuSetupCICAM -------------------------------------------------------
@ -2152,10 +2333,10 @@ void cDisplayChannel::DisplayChannel(const cChannel *Channel)
{
int BufSize = Width() + 1;
char buffer[BufSize];
if (Channel && Channel->number > 0)
snprintf(buffer, BufSize, "%d%s %s", Channel->number, number ? "-" : "", Channel->name);
if (Channel && Channel->Number() > 0)
snprintf(buffer, BufSize, "%d%s %s", Channel->Number(), number ? "-" : "", Channel->Name());
else
snprintf(buffer, BufSize, "%s", Channel ? Channel->name : tr("*** Invalid Channel ***"));
snprintf(buffer, BufSize, "%s", Channel ? Channel->Name() : tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, Setup.OSDwidth, 1, clrBackground);
Interface->Write(0, 0, buffer);
const char *date = DayDateTime();
@ -2266,7 +2447,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
if (channel) {
Interface->Clear();
DisplayChannel(channel);
if (!channel->groupSep)
if (!channel->GroupSep())
group = -1;
}
}
@ -2283,7 +2464,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
//XXX case kGreen: return osEventNow;
//XXX case kYellow: return osEventNext;
case kOk: if (group >= 0)
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->number);
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->Number());
return osEnd;
default: if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown || (Key & (k_Repeat | k_Release)) == 0) {
cRemote::Put(Key);
@ -2433,7 +2614,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
fileName = strdup(Recording.FileName());
cRecordingUserCommand::InvokeCommand(RUC_BEFORERECORDING, fileName);
cChannel *ch = Channels.GetByNumber(timer->channel);
recorder = new cRecorder(fileName, ch->ca, timer->priority, ch->vpid, ch->apid1, ch->apid2, ch->dpid1, ch->dpid2);
recorder = new cRecorder(fileName, ch->Ca(), timer->priority, ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2());
if (device->AttachReceiver(recorder)) {
Recording.WriteSummary();
cStatus::MsgRecording(device, Recording.Name());
@ -2460,7 +2641,7 @@ bool cRecordControl::GetEventInfo(void)
cMutexLock MutexLock;
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
if (Schedules) {
const cSchedule *Schedule = Schedules->GetSchedule(channel->pnr);
const cSchedule *Schedule = Schedules->GetSchedule(channel->Sid());
if (Schedule) {
eventInfo = Schedule->GetEventAround(Time);
if (eventInfo) {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: recording.c 1.67 2002/08/24 14:09:49 kls Exp $
* $Id: recording.c 1.68 2002/10/05 13:44:56 kls Exp $
*/
#include "recording.h"
@ -14,6 +14,7 @@
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "channels.h"
#include "i18n.h"
#include "interface.h"
#include "remux.h" //XXX+ I_FRAME

104
sources.c Normal file
View File

@ -0,0 +1,104 @@
/*
* sources.c: Source handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: sources.c 1.1 2002/10/06 09:27:10 kls Exp $
*/
#include "sources.h"
#include <ctype.h>
// -- cSource ----------------------------------------------------------------
cSource::cSource(void)
{
code = stNone;
description = NULL;
}
cSource::~cSource()
{
free(description);
}
bool cSource::Parse(const char *s)
{
char *codeBuf = NULL;
if (2 == sscanf(s, "%a[^ ] %a[^\n]", &codeBuf, &description))
code = FromString(codeBuf);
free(codeBuf);
return code != stNone && description && *description;
}
const char *cSource::ToString(int Code)
{
static char buffer[16];
char *q = buffer;
switch (Code & st_Mask) {
case stCable: *q++ = 'C'; break;
case stSat: *q++ = 'S';
{
int pos = Code & ~st_Mask;
q += snprintf(q, sizeof(buffer) - 2, "%u.%u", (pos & ~st_Neg) / 10, (pos & ~st_Neg) % 10); // can't simply use "%g" here since the silly 'locale' messes up the decimal point
*q++ = (Code & st_Neg) ? 'E' : 'W';
}
break;
case stTerr: *q++ = 'T'; break;
default: *q++ = Code + '0'; // backward compatibility
}
*q = 0;
return buffer;
}
int cSource::FromString(const char *s)
{
int type = stNone;
switch (toupper(*s)) {
case 'C': type = stCable; break;
case 'S': type = stSat; break;
case 'T': type = stTerr; break;
case '0' ... '9': type = *s - '0'; break; // backward compatibility
default: esyslog("ERROR: unknown source key '%c'", *s);
return stNone;
}
int code = type;
if (type == stSat) {
int pos = 0;
bool dot = false;
bool neg = false;
while (*++s) {
switch (toupper(*s)) {
case '0' ... '9': pos *= 10;
pos += *s - '0';
break;
case '.': dot = true;
break;
case 'E': neg = true; // fall through to 'W'
case 'W': if (!dot)
pos *= 10;
break;
default: esyslog("ERROR: unknown source character '%c'", *s);
return stNone;
}
}
if (neg)
pos |= st_Neg;
code |= pos;
}
return code;
}
// -- cSources ---------------------------------------------------------------
cSources Sources;
cSource *cSources::Get(int Code)
{
for (cSource *p = First(); p; p = Next(p)) {
if (p->Code() == Code)
return p;
}
return NULL;
}

50
sources.conf Normal file
View File

@ -0,0 +1,50 @@
# Sources configuration for VDR
#
# Format:
#
# code description
#
# Please contact kls@cadsoft.de before assigning a new code
# to a description, in order to keep them unique.
# Satellites
S5E Sirius 2/3
S7E Eutelsat W3
S10E Eutelsat W1R
S13E Hotbird 1-5
S16E Eutelsat W2
S19.2E Astra 1
S23.5E Astra 3
S26E Arabsat 2A/3A
S28.2E Astra 2
S28.5E Eurobird
S30.E Arabsat 30.5E
S31.3 Türksat 1B
S36E Eutelsat W4 / Sesat
S42E Turksat 1C / Eurasiasat
S1W Thor 2/3 / Intelsat 707
S4W Amos 1
S5W Telecom 2C
S7W Nilesat 101/102
S8W Atlantic bird 2 / Telecom 2D
S11W Express 3A
S14W Express 2
S15W Telstar 12
S18W Intelsat
S21W NSS 803
S27.W Intelsat 27.5W
S30W Hispasat 1
S31.5W Intelsat 31.5W
S34.5W Intelsat 34.5W
S37.5W Telstar 11
S43W PAS
# Cable
C Cable
# Terrestrial
T Terrestrial

45
sources.h Normal file
View File

@ -0,0 +1,45 @@
/*
* sources.h: Source handling
*
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: sources.h 1.1 2002/10/04 14:25:03 kls Exp $
*/
#ifndef __SOURCES_H
#define __SOURCES_H
#include "config.h"
class cSource : public cListObject {
public:
enum eSourceType {
stNone = 0x0000,
stCable = 0x4000,
stSat = 0x8000,
stTerr = 0xC000,
st_Mask = 0xC000,
st_Neg = 0x0800,
};
private:
int code;
char *description;
public:
cSource(void);
~cSource();
int Code(void) const { return code; }
const char *Description(void) const { return description; }
bool Parse(const char *s);
static const char *ToString(int Code);
static int FromString(const char *s);
};
class cSources : public cConfig<cSource> {
public:
cSource *Get(int Code);
};
extern cSources Sources;
#endif //__SOURCES_H

27
svdrp.c
View File

@ -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.43 2002/09/28 15:50:19 kls Exp $
* $Id: svdrp.c 1.44 2002/10/05 13:45:05 kls Exp $
*/
#include "svdrp.h"
@ -26,6 +26,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include "channels.h"
#include "config.h"
#include "device.h"
#include "keys.h"
@ -412,7 +413,7 @@ void cSVDRP::CmdCHAN(const char *Option)
int i = 1;
cChannel *channel;
while ((channel = Channels.GetByNumber(i)) != NULL) {
if (strcasecmp(channel->name, Option) == 0) {
if (strcasecmp(channel->Name(), Option) == 0) {
n = i;
break;
}
@ -427,7 +428,7 @@ void cSVDRP::CmdCHAN(const char *Option)
cChannel *channel = Channels.GetByNumber(n);
if (channel) {
if (!cDevice::PrimaryDevice()->SwitchChannel(channel, true)) {
Reply(554, "Error switching to channel \"%d\"", channel->number);
Reply(554, "Error switching to channel \"%d\"", channel->Number());
return;
}
}
@ -441,7 +442,7 @@ void cSVDRP::CmdCHAN(const char *Option)
}
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (channel)
Reply(250, "%d %s", channel->number, channel->name);
Reply(250, "%d %s", channel->Number(), channel->Name());
else
Reply(550, "Unable to find channel \"%d\"", cDevice::CurrentChannel());
}
@ -630,7 +631,7 @@ void cSVDRP::CmdLSTC(const char *Option)
if (isnumber(Option)) {
cChannel *channel = Channels.GetByNumber(strtol(Option, NULL, 10));
if (channel)
Reply(250, "%d %s", channel->number, channel->ToText());
Reply(250, "%d %s", channel->Number(), channel->ToText());
else
Reply(501, "Channel \"%s\" not defined", Option);
}
@ -640,9 +641,9 @@ void cSVDRP::CmdLSTC(const char *Option)
while (i <= Channels.MaxNumber()) {
cChannel *channel = Channels.GetByNumber(i);
if (channel) {
if (strcasestr(channel->name, Option)) {
if (strcasestr(channel->Name(), Option)) {
if (next)
Reply(-250, "%d %s", next->number, next->ToText());
Reply(-250, "%d %s", next->Number(), next->ToText());
next = channel;
}
}
@ -653,7 +654,7 @@ void cSVDRP::CmdLSTC(const char *Option)
i++;
}
if (next)
Reply(250, "%d %s", next->number, next->ToText());
Reply(250, "%d %s", next->Number(), next->ToText());
else
Reply(501, "Channel \"%s\" not defined", Option);
}
@ -662,7 +663,7 @@ void cSVDRP::CmdLSTC(const char *Option)
for (int i = 1; i <= Channels.MaxNumber(); i++) {
cChannel *channel = Channels.GetByNumber(i);
if (channel)
Reply(i < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->number, channel->ToText());
Reply(i < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->Number(), channel->ToText());
else
Reply(501, "Channel \"%d\" not found", i);
}
@ -778,8 +779,8 @@ void cSVDRP::CmdMODC(const char *Option)
}
*channel = c;
Channels.Save();
isyslog("channel %d modified", channel->number);
Reply(250, "%d %s", channel->number, channel->ToText());
isyslog("channel %d modified", channel->Number());
Reply(250, "%d %s", channel->Number(), channel->ToText());
}
else
Reply(501, "Channel \"%d\" not defined", n);
@ -844,8 +845,8 @@ void cSVDRP::CmdNEWC(const char *Option)
Channels.Add(channel);
Channels.ReNumber();
Channels.Save();
isyslog("channel %d added", channel->number);
Reply(250, "%d %s", channel->number, channel->ToText());
isyslog("channel %d added", channel->Number());
Reply(250, "%d %s", channel->Number(), channel->ToText());
}
else
Reply(501, "Error in channel settings");

115
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
.\" $Id: vdr.5 1.5 2002/09/29 13:06:40 kls Exp $
.\" $Id: vdr.5 1.6 2002/10/06 08:56:01 kls Exp $
.\"
.TH vdr 5 "7 Sep 2002" "1.2.0" "Video Disk Recorder Files"
.SH NAME
@ -29,7 +29,7 @@ character, followed by arbitrary text. Example:
A \fBchannel definition\fR is a line with channel data, where the fields
are separated by ':' characters. Example:
\fBRTL:12188:h:1:27500:163:104:105:0:12003\fR
\fBRTL:12188:h:S19.2E:27500:163:104:105:0:12003\fR
The line number of a channel definition (not counting group separators!)
defines the channel's number in OSD menus and the \fItimers.conf\fR file.
@ -44,16 +44,44 @@ it has to be replaced by '|').
.B Frequency
The transponder frequency in MHz for DVB-S and DVB-C, kHz for DVB-T (as an integer).
.TP
.B Polarization
The polarization of the satellite signal. 'h' or 'H' for horizontal, 'v' or 'V'
for vertical (DVB-S only).
.B Parameters
Various parameters, depending on whether this is a DVB-S, DVB-C or DVB-T channel.
Each parameter consist of a key character, followed by an integer number that
represents the actual setting of that parameter. The valid key characters, their
meaning (and allowed values) are
.TS
tab (@);
l l.
\fBB\fR@Bandwidth (6, 7, 8)
\fBC\fR@Code rate high priority (0, 12, 23, 34, 45, 56, 67, 78, 89)
\fBD\fR@Code rate low priority (0, 12, 23, 34, 45, 56, 67, 78, 89)
\fBG\fR@Guard interval (4, 8, 16, 32)
\fBH\fR@Horizontal polarization
\fBI\fR@Inversion (0, 1)
\fBM\fR@Modulation (0, 16, 32, 64, 128, 256)
\fBT\fR@Transmission mode (2, 8)
\fBV\fR@Vertical polarization
\fBY\fR@Hierarchy (0, 1, 2, 4)
.TE
The polarization parameters have no integer numbers following them. This is for
compatibility with files from older versions and also to keep the DVB-S entries
as simple as possible.
The special value \fB999\fR is used for "automatic", which means the driver
will automatically determine the proper value (if possible).
An example of a parameter field for a DVB-T channel might look like this:
\fBB8C23D12M64T2G32Y0\fR
.TP
.B
DiSEqC
The DiSEqC code to use for this channel (integer, DVB-S only).
.B Source
The signal source of this channel, as defined in the file \fIsources.conf\fR.
For compatibility with files from older versions numeric values will be accepted
and also written back correctly, but they will have no meaning for the \fBDiSEqC\fR
settings. You should replace the numerical values with the proper source identifiers
defined in \fIsources.conf\fR.
.TP
.B
Srate
.B Srate
The symbol rate of this channel (DVB-S and DVB-C only).
.TP
.B VPID
@ -78,8 +106,8 @@ l l.
\fB>=100\fR@requires a specific decryption method defined in \fIca.conf\fR
.TE
.TP
.B PNR
The program number (aka service ID) of this channel.
.B SID
The service ID of this channel.
.SS TIMERS
The file \fItimers.conf\fR contains the timer setup.
Each line contains one timer definition, with individual fields
@ -191,6 +219,69 @@ Arbitrary text that describes the recording made by this timer.
Any newline characters in the summary have to be replaced by '|', and
the summary may contain ':' characters. If this field is not empty, its
contents will be written into the \fIsummary.vdr\fR file of the recording.
.SS SOURCES
The file \fIsources.conf\fR defines the codes to be used in the \fBSource\fR field
of channels in \fIchannels.conf\fR and assigns descriptive texts to them.
Example:
\fBS19.2E Astra 1\fR
Anything after (and including) a '#' character is comment.
The first character of the \fBcode\fR must be one of
.TS
tab (@);
l l.
\fBS\fR@Satellite
\fBC\fR@Cable
\fBT\fR@Terrestrial
.TE
and is followed by further data pertaining to that particular source. In case of
\fBS\fRatellite this is the orbital position in degrees, followed by \fBE\fR for
east or \fBW\fR for west.
.SS DISEQC
The file \fIdiseqc.conf\fR defines the \fBDiSEqC\fR control sequences to be sent
to the DVB-S card in order to access a given satellite position and/or band.
Example:
\fBS19.2E 11700 V 9750 t v W15 [E0 10 38 F0] W15 A W15 t\fR
Anything after (and including) a '#' character is comment.
The first word in a parameter line must be one of the codes defined in the
file \fIsources.conf\fR and tells which satellite this line applies to.
Following is the "switch frequency" of the LNB (slof), which is the transponder
frequency up to which this entry shall be used; the first entry with an slof greater
than the actual transponder frequency will be used. Typically there is only one slof
per LNB, but the syntax allows any number of frequency ranges to be defined.
Note that there should be a last entry with the value \fB99999\fR for each satellite,
which covers the upper frequency range.
The third parameter defines the polarization to which this entry applies. It can
be either \fBH\fR for horizontal or \fBV\fR for vertical.
The fourth parameter specifies the "local oscillator frequency" (lof) of the LNB
to use for the given frequency range. This number will be subtracted from the
actual transponder frequency when tuning to the channel.
The rest of the line holds the actual sequence of DiSEqC actions to be taken.
The code letters used here are
.TS
tab (@);
l l.
\fBt\fR@22kHz tone off
\fBT\fR@22kHz tone on
\fBv\fR@voltage low (13V)
\fBV\fR@voltage high (18V)
\fBA\fR@mini A
\fBB\fR@mini B
\fBWnn\fR@wait nn milliseconds (nn may be any positive integer number)
\fB[xx ...]\fR@hex code sequence (max. 6)
.TE
There can be any number of actions in a line, including none at all - in which case
the entry would be used only to set the LOF to use for the given frequency range
and polarization.
.SS CONDITIONAL ACCESS
The file \fIca.conf\fR defines the numbers to be used in the \fBConditional access\fR
field of channels in \fIchannels.conf\fR and assigns descriptive texts to them.

9
vdr.c
View File

@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.124 2002/09/29 12:55:03 kls Exp $
* $Id: vdr.c 1.125 2002/10/06 10:25:04 kls Exp $
*/
#include <getopt.h>
@ -30,9 +30,11 @@
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include "channels.h"
#include "config.h"
#include "cutter.h"
#include "device.h"
#include "diseqc.h"
#include "dvbdevice.h"
#include "eitscan.h"
#include "i18n.h"
@ -44,6 +46,7 @@
#include "plugin.h"
#include "rcu.h"
#include "recording.h"
#include "sources.h"
#include "tools.h"
#include "videodir.h"
@ -311,9 +314,11 @@ int main(int argc, char *argv[])
cPlugin::SetConfigDirectory(ConfigDirectory);
Setup.Load(AddDirectory(ConfigDirectory, "setup.conf"));
Sources.Load(AddDirectory(ConfigDirectory, "sources.conf"), true);
Diseqcs.Load(AddDirectory(ConfigDirectory, "diseqc.conf"), true);
Channels.Load(AddDirectory(ConfigDirectory, "channels.conf"));
Timers.Load(AddDirectory(ConfigDirectory, "timers.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"));
Commands.Load(AddDirectory(ConfigDirectory, "commands.conf"), true);
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true);
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));