summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS18
-rw-r--r--HISTORY26
-rw-r--r--INSTALL10
-rw-r--r--Makefile10
-rw-r--r--PLUGINS/src/sky/README5
-rw-r--r--channels.conf.cable10
-rw-r--r--config.h4
-rw-r--r--diseqc.c25
-rw-r--r--diseqc.h12
-rw-r--r--dvbdevice.c355
-rw-r--r--dvbdevice.h11
-rw-r--r--interface.c4
-rw-r--r--osd.c14
-rw-r--r--osd.h4
-rw-r--r--params.txt4
-rw-r--r--rcu.c16
-rw-r--r--rcu.h3
-rw-r--r--remote.c67
-rw-r--r--remote.h9
-rw-r--r--vdr.56
-rw-r--r--vdr.c19
21 files changed, 383 insertions, 249 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index ef28cad..9709026 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -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
diff --git a/HISTORY b/HISTORY
index 6f9a025..d189379 100644
--- a/HISTORY
+++ b/HISTORY
@@ -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.
diff --git a/INSTALL b/INSTALL
index 841575d..8e61605 100644
--- a/INSTALL
+++ b/INSTALL
@@ -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
diff --git a/Makefile b/Makefile
index 1494cd6..7d169ce 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/PLUGINS/src/sky/README b/PLUGINS/src/sky/README
index e383279..bd089cc 100644
--- a/PLUGINS/src/sky/README
+++ b/PLUGINS/src/sky/README
@@ -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.
diff --git a/channels.conf.cable b/channels.conf.cable
index 1be4c53..58dc20d 100644
--- a/channels.conf.cable
+++ b/channels.conf.cable
@@ -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
diff --git a/config.h b/config.h
index 43fbfba..50e3156 100644
--- a/config.h
+++ b/config.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.h 1.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
diff --git a/diseqc.c b/diseqc.c
index 92b92cb..0766db8 100644
--- a/diseqc.c
+++ b/diseqc.c
@@ -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;
}
}
diff --git a/diseqc.h b/diseqc.h
index f2b0e99..602bdec 100644
--- a/diseqc.h
+++ b/diseqc.h
@@ -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; }
diff --git a/dvbdevice.c b/dvbdevice.c
index 3aa9f93..a2b4ce9 100644
--- a/dvbdevice.c
+++ b/dvbdevice.c
@@ -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:
diff --git a/dvbdevice.h b/dvbdevice.h
index 709790c..d135a29 100644
--- a/dvbdevice.h
+++ b/dvbdevice.h
@@ -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;
diff --git a/interface.c b/interface.c
index 804747a..7466a9a 100644
--- a/interface.c
+++ b/interface.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: interface.c 1.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;
diff --git a/osd.c b/osd.c
index eb0d2dc..7622955 100644
--- a/osd.c
+++ b/osd.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: osd.c 1.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
diff --git a/osd.h b/osd.h
index 2cd2f4b..5f1ec96 100644
--- a/osd.h
+++ b/osd.h
@@ -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"
diff --git a/params.txt b/params.txt
deleted file mode 100644
index 480a1a6..0000000
--- a/params.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Are the parameter names well chosen?
-
- "Coderate" <--> FEC
-
diff --git a/rcu.c b/rcu.c
index 6345bea..4157c0d 100644
--- a/rcu.c
+++ b/rcu.c
@@ -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)
diff --git a/rcu.h b/rcu.h
index 1c54999..d314275 100644
--- a/rcu.h
+++ b/rcu.h
@@ -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);
diff --git a/remote.c b/remote.c
index 7157a5f..d4f1702 100644
--- a/remote.c
+++ b/remote.c
@@ -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
diff --git a/remote.h b/remote.h
index 2aeec78..1c087d0 100644
--- a/remote.h
+++ b/remote.h
@@ -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
diff --git a/vdr.5 b/vdr.5
index 8a76fdd..8b833a2 100644
--- a/vdr.5
+++ b/vdr.5
@@ -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
diff --git a/vdr.c b/vdr.c
index 438f98f..8f22f11 100644
--- a/vdr.c
+++ b/vdr.c
@@ -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;