Version 1.1.19

- The character '|' in description texts of EPG records is now interpreted as a
  newline character (suggested by Gerhard Steiner).
- Updated 'channels.conf.cable' (thanks to Andreas Kool).
- Improved handling of repeated remote keys.
- The RCU now only sets the channel number display when there are no incoming remote
  control keys, which improves reaction on repeated keys.
- The actual tuning is now done in a separate thread, which makes zapping through the
  channels a lot faster and no longer gets stuck on channels that don't broadcast.
  This also makes "Motor-DiSEqC" work (thanks to Reinhard Walter Buchner for his help
  in testing this). Since switching channels now no longer explicitly waits for a
  channel lock in the foreground thread, the "panic level" mechanism is no longer
  used (maybe we don't need it any more, anyway).
- The keyboard is now by default always active to control VDR. The 'make' option
  REMOTE=KBD is therefore obsolete. When compiling VDR with REMOTE=RCU or REMOTE=LIRC,
  the keyboard can thus now be active together with the remote control. If you want
  to build VDR _without_ keyboard support you can set NO_KBD=1 in the 'make' call.
  Since the keyboard codes are now different from the ones used previously (which
  were mapped by the 'ncurses' library) you will need to go through the "Learning
  keys" procedure again. To do so, either delete the file /video/remote.conf or
  remove the KBD.* entries from it before starting this version of VDR.
  (Thanks to Thomas Sailer for pointing out how to set the terminal parameters to
  read from the keyboard).
- The 'ncurses' library is now only necessary when compiling VDR with DEBUG_OSD=1.
This commit is contained in:
Klaus Schmidinger 2002-12-08 18:00:00 +01:00
parent 96ebdbf4b1
commit 2b15337b71
21 changed files with 383 additions and 249 deletions

View File

@ -322,8 +322,8 @@ Ruben Nunez Francisco <ruben.nunez@tang-it.com>
for translating OSD texts to the Spanish language
Mirko Dölle <mdoelle@linux-user.de>
for reporting a bug when a timer records over midnight of a day that had a
change in Daylight Saving Time
for reporting a bug when a timer records over midnight of a day that had a
change in Daylight Saving Time
Michael Rakowski <mrak@gmx.de>
for translating OSD texts to the Polish language
@ -441,6 +441,7 @@ Oliver Endriss <o.endriss@gmx.de>
Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf'
for his help in testing tuning with "Motor-DiSEqC"
Lauri Tischler <lauri.tischler@efore.fi>
for helping to test and debug the new channel source and DiSEqC handling
@ -458,6 +459,8 @@ Gerhard Steiner <steiner@mail.austria.com>
the 'epg.data' file
for suggesting the new configuration file 'reccmds.conf' to define commands that
shall be executed from the "Recordings" menu
for suggesting to interpret the character '|' in the description texts of EPG
records as a newline character
Jaakko Hyvätti <jaakko@hyvatti.iki.fi>
for translating OSD texts to the Finnish language
@ -476,14 +479,14 @@ Stefan Schluenss <dxr3_osd@schluenss.de>
for reporting a bug where PID handles were not closed correctly
Régis Bossut <rbossut@auchan.com>
for pointing out that with some providers the channels can only be distinguished
through the RID
for pointing out that with some providers the channels can only be distinguished
through the RID
Andreas Kool <akool@akool.de>
for pointing out problems with non-unique definitions in 'channels.conf.cable'
for his help in keeping 'channels.conf.cable' up to date
Guy Roussin <guy.roussin@teledetection.fr>
for suggesting not to display channel group delimiters without text
for suggesting not to display channel group delimiters without text
Georg Hitsch <georg@hitsch.at>
for his help in keeping 'channels.conf' up to date
@ -498,3 +501,6 @@ Emil Naepflein <Emil.Naepflein@philosys.de>
Gerald Berwolf <genka@genka.de>
for suggesting to deactivate some templates in tools.h in case some plugin needs to
use the STL
Thomas Sailer <sailer@scs.ch>
for pointing out how to set the terminal parameters to read from the keyboard

26
HISTORY
View File

@ -1836,3 +1836,29 @@ Video Disk Recorder Revision History
function of a given plugin (see man vdr(5) for details).
- The new plugin 'sky' can be used to integrate a Sky Digibox into the VDR system,
using a Kfir MPEG2 encoder card (see PLUGINS/src/sky/README for details).
2002-12-08: Version 1.1.19
- The character '|' in description texts of EPG records is now interpreted as a
newline character (suggested by Gerhard Steiner).
- Updated 'channels.conf.cable' (thanks to Andreas Kool).
- Improved handling of repeated remote keys.
- The RCU now only sets the channel number display when there are no incoming remote
control keys, which improves reaction on repeated keys.
- The actual tuning is now done in a separate thread, which makes zapping through the
channels a lot faster and no longer gets stuck on channels that don't broadcast.
This also makes "Motor-DiSEqC" work (thanks to Reinhard Walter Buchner for his help
in testing this). Since switching channels now no longer explicitly waits for a
channel lock in the foreground thread, the "panic level" mechanism is no longer
used (maybe we don't need it nay more, anyway).
- The keyboard is now by default always active to control VDR. The 'make' option
REMOTE=KBD is therefore obsolete. When compiling VDR with REMOTE=RCU or REMOTE=LIRC,
the keyboard can thus now be active together with the remote control. If you want
to build VDR _without_ keyboard support you can set NO_KBD=1 in the 'make' call.
Since the keyboard codes are now different from the ones used previously (which
were mapped by the 'ncurses' library) you will need to go through the "Learning
keys" procedure again. To do so, either delete the file /video/remote.conf or
remove the KBD.* entries from it before starting this version of VDR.
(Thanks to Thomas Sailer for pointing out how to set the terminal parameters to
read from the keyboard).
- The 'ncurses' library is now only necessary when compiling VDR with DEBUG_OSD=1.

10
INSTALL
View File

@ -26,17 +26,17 @@ installed.
IMPORTANT: See "Configuration files" below for information on how
========= to set up the configuration files at the proper location!
The 'vdr' program can be controlled via the PC keyboard or
an infrared remote control unit. Define the REMOTE macro to one of the
following values 'make' call to activate the respective control mode:
By default the 'vdr' program can be controlled via the PC keyboard. If you have
an infrared remote control unit you can define the REMOTE macro to one of the
following values in the 'make' call to activate the respective control mode:
REMOTE=KBD control via the PC keyboard (default)
REMOTE=RCU control via the "Remote Control Unit" receiver
(see http://www.cadsoft.de/vdr/remote.htm)
REMOTE=LIRC control via the "Linux Infrared Remote Control"
(see http://www.lirc.org)
REMOTE=NONE no remote control (in case only SVDRP shall be used)
If you want to disable control via the PC keyboard, you can add NO_KBD=1
to the 'make' call.
Adding "DEBUG_OSD=1" will use the PC screen (or current window)
to display texts instead of the DVB card's on-screen display
interface. These modes are useful when testing new menus if you

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.52 2002/11/29 15:23:02 kls Exp $
# $Id: Makefile 1.53 2002/12/08 12:20:37 kls Exp $
.DELETE_ON_ERROR:
@ -38,12 +38,8 @@ OBJS = audio.o channels.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
ifndef REMOTE
REMOTE = KBD
endif
ifeq ($(REMOTE), KBD)
NCURSESLIB = -lncurses
ifndef NO_KBD
DEFINES += -DREMOTE_KBD
endif
DEFINES += -DREMOTE_$(REMOTE)

View File

@ -19,6 +19,9 @@ illegal, like decrypting the Sky programme without a subscription. You
will need a Sky Digibox and a valid subscription in order to use this
plugin.
The 'kfir' module must be loaded with the option 'streamtype=4' to make it
produce a Transport Stream.
The Digibox is remotely controlled through VDR via LIRC (see lirc.org).
The file lircd.conf.sky contains the remote control codes necessary to
control the Digibox.
@ -43,3 +46,5 @@ uses to generate the EPG pages are stored as the 'sid' parameter in
the channels.conf definitions of the Sky channels. You can keep your
EPG data up-to-date by entering a call to getskyepg.pl into your
/etc/crontab. Call 'getskyepg.pl -h' for a list of options.
The getskyepg.pl script requires the programs /usr/bin/wget and /usr/bin/logger
to be installed on your system.

View File

@ -37,9 +37,9 @@ Premiere 7:370:M64:C:6900:1023:1024:0:101:20:0:0:0
Premiere SERIE:378:M64:C:6900:1023:1024:0:101:16:0:0:0
Premiere Nostalgie:378:M64:C:6900:2559:2560:0:101:516:0:0:0
13 TH STREET:354:M64:C:6900:2303:2304:0:101:42:0:0:0
Studio Universal:402:M64:C:6900:1050:1054:0:101:36:0:0:0
Studio Universal:354:M64:C:6900:2047:2048:0:101:36:0:0:0
Krimi & Co:378:M64:C:6900:1535:1536:0:101:23:0:0:0
Disney Channel:402:M64:C:6900:1030:1034:0:101:34:0:0:0
Disney Channel:354:M64:C:6900:2559:2560:0:101:34:0:0:0
Discovery Channel:378:M64:C:6900:1791:1792:0:101:14:0:0:0
PLANET:354:M64:C:6900:1791:1792:0:101:13:0:0:0
Fox Kids:354:M64:C:6900:1279:1280:0:101:28:0:0:0
@ -48,12 +48,6 @@ K-TOON:354:M64:C:6900:511:512:0:101:12:0:0:0
HEIMATKANAL:354:M64:C:6900:1535:1536:0:101:22:0:0:0
GOLDSTAR TV:354:M64:C:6900:3839:3840:0:101:518:0:0:0
CLASSICA:354:M64:C:6900:767:768:0:101:15:0:0:0
:Mediavision
Bloomberg:346:M64:C:6900:811:812:0:101:50701:0:0:0
Fashion TV:346:M64:C:6900:821:822:0:101:50702:0:0:0
Einstein:346:M64:C:6900:623:624:0:101:50719:0:0:0
Extreme Sport:346:M64:C:6900:801:802:0:101:50700:0:0:0
LANDSCAPE:346:M64:C:6900:831:832:0:101:50703:0:0:0
:DIGIKABEL D
Avante:113:M64:C:6900:741:742,743:0:101:53404:0:0:0
BBC Prime:113:M64:C:6900:761:762:763:101:53406:0:0:0

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.142 2002/11/24 20:09:56 kls Exp $
* $Id: config.h 1.143 2002/12/06 14:17:55 kls Exp $
*/
#ifndef __CONFIG_H
@ -19,7 +19,7 @@
#include "device.h"
#include "tools.h"
#define VDRVERSION "1.1.18"
#define VDRVERSION "1.1.19"
#define MAXPRIORITY 99
#define MAXLIFETIME 99

View File

@ -4,7 +4,7 @@
* 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 $
* $Id: diseqc.c 1.2 2002/12/07 13:44:56 kls Exp $
*/
#include "diseqc.h"
@ -16,7 +16,6 @@
cDiseqc::cDiseqc(void)
{
commands = NULL;
currentAction = NULL;;
parsing = false;
numCodes = 0;
}
@ -39,11 +38,11 @@ bool cDiseqc::Parse(const char *s)
polarization = toupper(polarization);
if (polarization == 'V' || polarization == 'H') {
parsing = true;
bool Start = true;
while (Execute(Start) != daNone)
Start = false;
char *CurrentAction = NULL;
while (Execute(&CurrentAction) != daNone)
;
parsing = false;
result = !commands || currentAction && !*currentAction;
result = !commands || !*CurrentAction;
}
else
esyslog("ERROR: unknown polarization '%c'", polarization);
@ -101,12 +100,12 @@ char *cDiseqc::Codes(char *s)
return NULL;
}
cDiseqc::eDiseqcActions cDiseqc::Execute(bool Start)
cDiseqc::eDiseqcActions cDiseqc::Execute(char **CurrentAction)
{
if (Start)
currentAction = commands;
while (currentAction && *currentAction) {
switch (*currentAction++) {
if (!*CurrentAction)
*CurrentAction = commands;
while (*CurrentAction && **CurrentAction) {
switch (*(*CurrentAction)++) {
case ' ': break;
case 't': return daToneOff;
case 'T': return daToneOn;
@ -114,8 +113,8 @@ cDiseqc::eDiseqcActions cDiseqc::Execute(bool Start)
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;
case 'W': *CurrentAction = Wait(*CurrentAction); break;
case '[': *CurrentAction = Codes(*CurrentAction); return *CurrentAction ? daCodes : daNone;
default: return daNone;
}
}

View File

@ -4,7 +4,7 @@
* 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 $
* $Id: diseqc.h 1.2 2002/12/07 13:54:02 kls Exp $
*/
#ifndef __DISEQC_H
@ -31,7 +31,6 @@ private:
char polarization;
int lof;
char *commands;
char *currentAction;
bool parsing;
uchar codes[MaxDiseqcCodes];
int numCodes;
@ -41,7 +40,14 @@ public:
cDiseqc(void);
~cDiseqc();
bool Parse(const char *s);
eDiseqcActions Execute(bool Start = false);
eDiseqcActions Execute(char **CurrentAction);
// Parses the DiSEqC commands and returns the appropriate action code
// with every call. CurrentAction must be the address of a character pointer,
// which is initialized to NULL. This pointer is used internally while parsing
// the commands and shall not be modified once Execute() has been called with
// it. Call Execute() repeatedly (always providing the same CurrentAction pointer)
// until it returns daNone. After a successful execution of all commands
// *CurrentAction points to the value 0x00.
int Source(void) const { return source; }
int Slof(void) const { return slof; }
char Polarization(void) const { return polarization; }

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.37 2002/11/15 15:17:30 kls Exp $
* $Id: dvbdevice.c 1.38 2002/12/07 14:50:46 kls Exp $
*/
#include "dvbdevice.h"
@ -60,8 +60,207 @@ static int DvbOpen(const char *Name, int n, int Mode, bool ReportError = false)
return fd;
}
// --- cDvbTuner -------------------------------------------------------------
class cDvbTuner : public cThread {
private:
enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked };
int fd_frontend;
int cardIndex;
fe_type_t frontendType;
cChannel channel;
const char *diseqcCommands;
bool active;
eTunerStatus tunerStatus;
cMutex mutex;
cCondVar newSet;
bool SetFrontend(void);
virtual void Action(void);
public:
cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType);
virtual ~cDvbTuner();
bool IsTunedTo(const cChannel *Channel) const;
void Set(const cChannel *Channel);
bool Locked(void) { return tunerStatus == tsLocked; }
};
cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType)
{
fd_frontend = Fd_Frontend;
cardIndex = CardIndex;
frontendType = FrontendType;
diseqcCommands = NULL;
active = false;
tunerStatus = tsIdle;
Start();
}
cDvbTuner::~cDvbTuner()
{
active = false;
tunerStatus = tsIdle;
newSet.Broadcast();
Cancel(3);
}
bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
{
return tunerStatus != tsIdle && channel.Source() == Channel->Source() && channel.Frequency() == Channel->Frequency();
}
void cDvbTuner::Set(const cChannel *Channel)
{
cMutexLock MutexLock(&mutex);
channel = *Channel;
tunerStatus = tsSet;
newSet.Broadcast();
}
static unsigned int FrequencyToHz(unsigned int f)
{
while (f && f < 1000000)
f *= 1000;
return f;
}
bool cDvbTuner::SetFrontend(void)
{
dvb_frontend_parameters Frontend;
memset(&Frontend, 0, sizeof(Frontend));
switch (frontendType) {
case FE_QPSK: { // DVB-S
unsigned int frequency = channel.Frequency();
if (Setup.DiSEqC) {
cDiseqc *diseqc = Diseqcs.Get(channel.Source(), channel.Frequency(), channel.Polarization());
if (diseqc) {
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
cDiseqc::eDiseqcActions da;
for (char *CurrentAction = NULL; (da = diseqc->Execute(&CurrentAction)) != cDiseqc::daNone; ) {
switch (da) {
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;
}
}
diseqcCommands = diseqc->Commands();
}
frequency -= diseqc->Lof();
}
else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", channel.Number());
return false;
}
}
else {
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;
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
}
Frontend.frequency = frequency * 1000UL;
Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
Frontend.u.qpsk.symbol_rate = channel.Srate() * 1000UL;
Frontend.u.qpsk.fec_inner = fe_code_rate_t(channel.CoderateH());
}
break;
case FE_QAM: { // DVB-C
// Frequency and symbol rate:
Frontend.frequency = FrequencyToHz(channel.Frequency());
Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
Frontend.u.qam.symbol_rate = channel.Srate() * 1000UL;
Frontend.u.qam.fec_inner = fe_code_rate_t(channel.CoderateH());
Frontend.u.qam.modulation = fe_modulation_t(channel.Modulation());
}
break;
case FE_OFDM: { // DVB-T
// Frequency and OFDM paramaters:
Frontend.frequency = FrequencyToHz(channel.Frequency());
Frontend.inversion = fe_spectral_inversion_t(channel.Inversion());
Frontend.u.ofdm.bandwidth = fe_bandwidth_t(channel.Bandwidth());
Frontend.u.ofdm.code_rate_HP = fe_code_rate_t(channel.CoderateH());
Frontend.u.ofdm.code_rate_LP = fe_code_rate_t(channel.CoderateL());
Frontend.u.ofdm.constellation = fe_modulation_t(channel.Modulation());
Frontend.u.ofdm.transmission_mode = fe_transmit_mode_t(channel.Transmission());
Frontend.u.ofdm.guard_interval = fe_guard_interval_t(channel.Guard());
Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(channel.Hierarchy());
}
break;
default:
esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
return false;
}
if (ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend) < 0) {
esyslog("ERROR: frontend %d: %m", cardIndex);
return false;
}
return true;
}
void cDvbTuner::Action(void)
{
dsyslog("tuner thread started on device %d (pid=%d)", cardIndex + 1, getpid());
active = true;
while (active) {
cMutexLock MutexLock(&mutex);
if (tunerStatus == tsSet)
tunerStatus = SetFrontend() ? tsTuned : tsIdle;
if (tunerStatus == tsTuned) {
fe_status_t status = fe_status_t(0);
CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status));
if (status & FE_HAS_LOCK)
tunerStatus = tsLocked;
}
dvb_frontend_event event;
if (ioctl(fd_frontend, FE_GET_EVENT, &event) == 0) {
if (tunerStatus != tsIdle && event.status & FE_REINIT) {
tunerStatus = tsSet;
esyslog("ERROR: frontend %d was reinitialized - re-tuning", cardIndex);
continue;
}
}
newSet.TimedWait(mutex, 1000);
}
dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
}
// --- cDvbDevice ------------------------------------------------------------
cDvbDevice::cDvbDevice(int n)
{
dvbTuner = NULL;
frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
siProcessor = NULL;
spuDecoder = NULL;
@ -69,7 +268,7 @@ cDvbDevice::cDvbDevice(int n)
// Devices that are present on all card types:
fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
// Devices that are only present on cards with decoders:
@ -90,8 +289,10 @@ cDvbDevice::cDvbDevice(int n)
if (fd_frontend >= 0) {
dvb_frontend_info feinfo;
siProcessor = new cSIProcessor(DvbName(DEV_DVB_DEMUX, n));
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0)
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
frontendType = feinfo.type;
dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType);
}
else
LOG_ERROR;
}
@ -99,16 +300,13 @@ cDvbDevice::cDvbDevice(int n)
esyslog("ERROR: can't open DVB device %d", n);
aPid1 = aPid2 = 0;
source = -1;
frequency = -1;
diseqcCommands = NULL;
}
cDvbDevice::~cDvbDevice()
{
delete spuDecoder;
delete siProcessor;
delete dvbTuner;
// We're not explicitly closing any device files here, since this sometimes
// caused segfaults. Besides, the program is about to terminate anyway...
}
@ -322,11 +520,6 @@ 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;
@ -346,7 +539,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel->Ca())) {
#ifdef DO_MULTIPLE_RECORDINGS
if (Receiving()) {
if (IsTunedTo(Channel)) {
if (dvbTuner->IsTunedTo(Channel)) {
needsDetachReceivers = false;
if (!HasPid(Channel->Vpid())) {
if (Channel->Ca() > CACONFBASE) {
@ -375,18 +568,11 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
return result;
}
static unsigned int FrequencyToHz(unsigned int f)
{
while (f && f < 1000000)
f *= 1000;
return f;
}
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
{
bool IsEncrypted = Channel->Ca() > CACONFBASE;
bool DoTune = !IsTunedTo(Channel);
bool DoTune = !dvbTuner->IsTunedTo(Channel);
bool TurnOffLivePIDs = HasDecoder()
&& (DoTune
@ -436,136 +622,15 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
}
if (DoTune) {
dvb_frontend_parameters Frontend;
memset(&Frontend, 0, sizeof(Frontend));
switch (frontendType) {
case FE_QPSK: { // DVB-S
unsigned int frequency = Channel->Frequency();
if (Setup.DiSEqC) {
cDiseqc *diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization());
if (diseqc) {
if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) {
cDiseqc::eDiseqcActions da;
for (bool Start = true; (da = diseqc->Execute(Start)) != cDiseqc::daNone; Start = false) {
switch (da) {
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;
}
}
diseqcCommands = diseqc->Commands();
}
frequency -= diseqc->Lof();
}
else {
esyslog("ERROR: no DiSEqC parameters found for channel %d", Channel->Number());
return false;
}
}
else {
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;
CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt));
CHECK(ioctl(fd_frontend, FE_SET_TONE, tone));
}
Frontend.frequency = frequency * 1000UL;
Frontend.inversion = fe_spectral_inversion_t(Channel->Inversion());
Frontend.u.qpsk.symbol_rate = Channel->Srate() * 1000UL;
Frontend.u.qpsk.fec_inner = fe_code_rate_t(Channel->CoderateH());
}
break;
case FE_QAM: { // DVB-C
// Frequency and symbol rate:
Frontend.frequency = FrequencyToHz(Channel->Frequency());
Frontend.inversion = fe_spectral_inversion_t(Channel->Inversion());
Frontend.u.qam.symbol_rate = Channel->Srate() * 1000UL;
Frontend.u.qam.fec_inner = fe_code_rate_t(Channel->CoderateH());
Frontend.u.qam.modulation = fe_modulation_t(Channel->Modulation());
}
break;
case FE_OFDM: { // DVB-T
// Frequency and OFDM paramaters:
Frontend.frequency = FrequencyToHz(Channel->Frequency());
Frontend.inversion = fe_spectral_inversion_t(Channel->Inversion());
Frontend.u.ofdm.bandwidth = fe_bandwidth_t(Channel->Bandwidth());
Frontend.u.ofdm.code_rate_HP = fe_code_rate_t(Channel->CoderateH());
Frontend.u.ofdm.code_rate_LP = fe_code_rate_t(Channel->CoderateL());
Frontend.u.ofdm.constellation = fe_modulation_t(Channel->Modulation());
Frontend.u.ofdm.transmission_mode = fe_transmit_mode_t(Channel->Transmission());
Frontend.u.ofdm.guard_interval = fe_guard_interval_t(Channel->Guard());
Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(Channel->Hierarchy());
}
break;
default:
esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
return false;
}
// Discard stale events:
for (;;) {
dvb_frontend_event event;
if (ioctl(fd_frontend, FE_GET_EVENT, &event) < 0)
break;
}
// Tuning:
CHECK(ioctl(fd_frontend, FE_SET_FRONTEND, &Frontend));
// Wait for channel lock:
fe_status_t status = fe_status_t(0);
for (int i = 0; i < 100; i++) {
CHECK(ioctl(fd_frontend, FE_READ_STATUS, &status));
if (status & FE_HAS_LOCK)
break;
usleep(10 * 1000);
}
dvbTuner->Set(Channel);
/*XXX do we still need this???
if (!(status & FE_HAS_LOCK)) {
esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->Number(), CardIndex() + 1);
if (LiveView && IsPrimaryDevice())
cThread::RaisePanic();
return false;
}
source = Channel->Source();
frequency = Channel->Frequency();
XXX*/
}
// PID settings:

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.18 2002/11/03 12:31:15 kls Exp $
* $Id: dvbdevice.h 1.19 2002/12/07 14:44:29 kls Exp $
*/
#ifndef __DVBDEVICE_H
@ -22,6 +22,8 @@
#define MAXDVBDEVICES 4
class cDvbTuner;
class cDvbDevice : public cDevice {
friend class cDvbOsd;
private:
@ -33,7 +35,7 @@ public:
// Must be called before accessing any DVB functions.
private:
fe_type_t frontendType;
int fd_osd, fd_frontend, fd_audio, fd_video, fd_dvr;
int fd_osd, fd_audio, fd_video, fd_dvr;
int OsdDeviceHandle(void) const { return fd_osd; }
protected:
virtual void MakePrimaryDevice(bool On);
@ -53,10 +55,7 @@ public:
// Channel facilities
private:
int source;
int frequency;
const char *diseqcCommands;
bool IsTunedTo(const cChannel *Channel) const;
cDvbTuner *dvbTuner;
public:
virtual bool ProvidesSource(int Source) const;
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: interface.c 1.60 2002/11/01 10:50:38 kls Exp $
* $Id: interface.c 1.61 2002/12/06 14:13:16 kls Exp $
*/
#include "interface.h"
@ -157,6 +157,8 @@ char *cInterface::WrapText(const char *Text, int Width, int *Height)
t[strlen(t) - 1] = 0; // skips trailing newlines
for (char *p = t; *p; ) {
if (*p == '|')
*p = '\n';
if (*p == '\n') {
Lines++;
w = 0;

14
osd.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.c 1.38 2002/11/16 14:20:26 kls Exp $
* $Id: osd.c 1.39 2002/12/08 13:17:13 kls Exp $
*/
#include "osd.h"
@ -26,15 +26,8 @@
void cOsd::Initialize(void)
{
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
initscr();
keypad(stdscr, true);
nonl();
cbreak();
noecho();
timeout(10);
#endif
#if defined(DEBUG_OSD)
initscr();
start_color();
leaveok(stdscr, true);
#endif
@ -43,7 +36,7 @@ void cOsd::Initialize(void)
void cOsd::Shutdown(void)
{
Close();
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#if defined(DEBUG_OSD)
endwin();
#endif
}
@ -150,6 +143,7 @@ void cOsd::Clear(void)
#ifdef DEBUG_OSD
SetColor(clrBackground, clrBackground);
Fill(0, 0, cols, rows, clrBackground);
refresh();
#else
osd->Clear();
#endif

4
osd.h
View File

@ -4,13 +4,13 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: osd.h 1.37 2002/11/24 10:32:29 kls Exp $
* $Id: osd.h 1.38 2002/12/08 12:21:26 kls Exp $
*/
#ifndef __OSD_H
#define __OSD_H
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
#if defined(DEBUG_OSD)
#include <ncurses.h>
#endif
#include "config.h"

View File

@ -1,4 +0,0 @@
Are the parameter names well chosen?
"Coderate" <--> FEC

16
rcu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: rcu.c 1.2 2002/10/06 15:49:03 kls Exp $
* $Id: rcu.c 1.3 2002/12/07 12:22:40 kls Exp $
*/
#include "rcu.h"
@ -22,6 +22,7 @@ cRcuRemote::cRcuRemote(char *DeviceName)
dp = 0;
mode = modeB;
code = 0;
numberToSend = -1;
lastNumber = 0;
receivedCommand = false;
if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
@ -136,8 +137,13 @@ void cRcuRemote::Action(void)
repeat = false;
LastCommand = 0;
}
else
else {
LastCommand = 0;
if (numberToSend >= 0) {
Number(numberToSend);
numberToSend = -1;
}
}
if (code && time(NULL) - LastCodeRefresh > 60) {
SendCommand(code); // in case the PIC listens to the wrong code
LastCodeRefresh = time(NULL);
@ -302,8 +308,10 @@ bool cRcuRemote::DetectCode(unsigned char *Code)
void cRcuRemote::ChannelSwitch(const cDevice *Device, int ChannelNumber)
{
if (ChannelNumber && Device->IsPrimaryDevice())
Number(ChannelNumber);
if (ChannelNumber && Device->IsPrimaryDevice()) {
LOCK_THREAD;
numberToSend = ChannelNumber;
}
}
void cRcuRemote::Recording(const cDevice *Device, const char *Name)

3
rcu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: rcu.h 1.1 2002/09/29 08:56:15 kls Exp $
* $Id: rcu.h 1.2 2002/12/07 12:21:25 kls Exp $
*/
#ifndef __RCU_H
@ -19,6 +19,7 @@ private:
enum { modeH = 'h', modeB = 'b', modeS = 's' };
int f;
unsigned char dp, code, mode;
int numberToSend;
int lastNumber;
bool receivedCommand;
bool SendCommand(unsigned char Cmd);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remote.c 1.32 2002/12/01 10:40:04 kls Exp $
* $Id: remote.c 1.34 2002/12/08 13:37:13 kls Exp $
*/
#include "remote.h"
@ -13,13 +13,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <termios.h>
#include <unistd.h>
#if defined REMOTE_KBD
#include <ncurses.h>
#endif
#include "tools.h"
// --- cRemote ---------------------------------------------------------------
@ -68,7 +62,7 @@ bool cRemote::Put(eKeys Key)
{
if (Key != kNone) {
cMutexLock MutexLock(&mutex);
if ((Key & k_Release) != 0)
if (in != out && (keys[out] & k_Repeat) && (Key & k_Release))
Clear();
int d = out - in;
if (d <= 0)
@ -155,30 +149,65 @@ cRemotes Remotes;
// --- cKbdRemote ------------------------------------------------------------
#if defined REMOTE_KBD
cKbdRemote::cKbdRemote(void)
:cRemote("KBD")
{
active = false;
tcgetattr(STDIN_FILENO, &savedTm);
struct termios tm;
if (tcgetattr(STDIN_FILENO, &tm) == 0) {
tm.c_iflag = 0;
tm.c_lflag &= ~(ICANON | ECHO);
tm.c_cc[VMIN] = 0;
tm.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO, TCSANOW, &tm);
}
Start();
}
cKbdRemote::~cKbdRemote()
{
Cancel();
active = false;
Cancel(3);
tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
}
void cKbdRemote::Action(void)
{
dsyslog("KBD remote control thread started (pid=%d)", getpid());
cPoller Poller(STDIN_FILENO);
for (;;) {//XXX
int Command = getch();
if (Command != EOF)
Put(Command);
Poller.Poll(100);
}
active = true;
while (active) {
if (Poller.Poll(100)) {
uint64 Command = 0;
uint i = 0;
int t0 = time_ms();
while (active && i < sizeof(Command)) {
uchar ch;
int r = read(STDIN_FILENO, &ch, 1);
if (r == 1) {
Command <<= 8;
Command |= ch;
i++;
}
else if (r == 0) {
// don't know why, but sometimes special keys that start with
// 0x1B ('ESC') cause a short gap between the 0x1B and the rest
// of their codes, so we'll need to wait some 100ms to see if
// there is more coming up - or whether this really is the 'ESC'
// key (if somebody knows how to clean this up, please let me know):
if (Command == 0x1B && time_ms() - t0 < 100)
continue;
if (Command)
Put(Command);
break;
}
else {
LOG_ERROR;
break;
}
}
}
}
dsyslog("KBD remote control thread ended (pid=%d)", getpid());
}
#endif

View File

@ -4,13 +4,14 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: remote.h 1.21 2002/12/01 10:39:10 kls Exp $
* $Id: remote.h 1.22 2002/12/08 13:37:02 kls Exp $
*/
#ifndef __REMOTE_H
#define __REMOTE_H
#include <stdio.h>
#include <termios.h>
#include <time.h>
#include "keys.h"
#include "thread.h"
@ -50,16 +51,14 @@ class cRemotes : public cList<cRemote> {};
extern cRemotes Remotes;
#if defined REMOTE_KBD
class cKbdRemote : public cRemote, private cThread {
private:
bool active;
struct termios savedTm;
virtual void Action(void);
public:
cKbdRemote(void);
virtual ~cKbdRemote();
};
#endif
#endif //__REMOTE_H

6
vdr.5
View File

@ -8,9 +8,9 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
.\" $Id: vdr.5 1.16 2002/12/01 10:34:40 kls Exp $
.\" $Id: vdr.5 1.17 2002/12/08 14:35:12 kls Exp $
.\"
.TH vdr 5 "24 Nov 2002" "1.2.0" "Video Disk Recorder Files"
.TH vdr 5 "6 Dec 2002" "1.2.0" "Video Disk Recorder Files"
.SH NAME
vdr file formats - the Video Disk Recorder Files
.SH DESCRIPTION
@ -549,7 +549,7 @@ in (if this is left empty or 0 this event will not be overwritten\
or modified by data that comes from the DVB stream)
<title> @is the title of the event
<subtitle> @is the subtitle (typically the name of the episode etc.)
<description> @is the description of the event
<description> @is the description of the event (any '|' characters will be interpreted as newlines)
.TE
This file will be read at program startup in order to restore the results of

19
vdr.c
View File

@ -22,13 +22,14 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
* $Id: vdr.c 1.136 2002/12/01 10:44:48 kls Exp $
* $Id: vdr.c 1.137 2002/12/08 13:34:39 kls Exp $
*/
#include <getopt.h>
#include <locale.h>
#include <signal.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include "audio.h"
#include "channels.h"
@ -77,6 +78,11 @@ static void Watchdog(int signum)
int main(int argc, char *argv[])
{
// Save terminal settings:
struct termios savedTm;
tcgetattr(STDIN_FILENO, &savedTm);
// Initiate locale:
setlocale(LC_ALL, "");
@ -294,7 +300,7 @@ int main(int argc, char *argv[])
// Daemon mode:
if (DaemonMode) {
#if !defined(DEBUG_OSD) && !defined(REMOTE_KBD)
#if !defined(DEBUG_OSD)
pid_t pid = fork();
if (pid < 0) {
fprintf(stderr, "%m\n");
@ -307,7 +313,7 @@ int main(int argc, char *argv[])
fclose(stdout);
fclose(stderr);
#else
fprintf(stderr, "vdr: can't run in daemon mode with DEBUG_OSD or REMOTE_KBD on!\n");
fprintf(stderr, "vdr: can't run in daemon mode with DEBUG_OSD on!\n");
return 2;
#endif
}
@ -378,8 +384,10 @@ int main(int argc, char *argv[])
new cRcuRemote("/dev/ttyS1");
#elif defined(REMOTE_LIRC)
new cLircRemote("/dev/lircd");
#elif defined(REMOTE_KBD)
new cKbdRemote;
#endif
#if defined(REMOTE_KBD)
if (!DaemonMode)
new cKbdRemote;
#endif
Interface->LearnKeys();
@ -716,6 +724,7 @@ int main(int argc, char *argv[])
isyslog("exiting");
if (SysLogLevel > 0)
closelog();
tcsetattr(STDIN_FILENO, TCSANOW, &savedTm);
if (cThread::EmergencyExit()) {
esyslog("emergency exit!");
return 1;