diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-12-08 18:00:00 +0100 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-12-08 18:00:00 +0100 |
commit | 2b15337b71d71c5e486efe738a507b550bb28843 (patch) | |
tree | dcd6fe2d5a57366e0c39ab1fd400ec20a4226ed6 | |
parent | 96ebdbf4b1e495d44f8f837068af7c2d925bab62 (diff) | |
download | vdr-patch-lnbsharing-2b15337b71d71c5e486efe738a507b550bb28843.tar.gz vdr-patch-lnbsharing-2b15337b71d71c5e486efe738a507b550bb28843.tar.bz2 |
Version 1.1.19vdr-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.
-rw-r--r-- | CONTRIBUTORS | 18 | ||||
-rw-r--r-- | HISTORY | 26 | ||||
-rw-r--r-- | INSTALL | 10 | ||||
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | PLUGINS/src/sky/README | 5 | ||||
-rw-r--r-- | channels.conf.cable | 10 | ||||
-rw-r--r-- | config.h | 4 | ||||
-rw-r--r-- | diseqc.c | 25 | ||||
-rw-r--r-- | diseqc.h | 12 | ||||
-rw-r--r-- | dvbdevice.c | 355 | ||||
-rw-r--r-- | dvbdevice.h | 11 | ||||
-rw-r--r-- | interface.c | 4 | ||||
-rw-r--r-- | osd.c | 14 | ||||
-rw-r--r-- | osd.h | 4 | ||||
-rw-r--r-- | params.txt | 4 | ||||
-rw-r--r-- | rcu.c | 16 | ||||
-rw-r--r-- | rcu.h | 3 | ||||
-rw-r--r-- | remote.c | 67 | ||||
-rw-r--r-- | remote.h | 9 | ||||
-rw-r--r-- | vdr.5 | 6 | ||||
-rw-r--r-- | vdr.c | 19 |
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 @@ -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. @@ -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 @@ -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 @@ -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 @@ -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; } } @@ -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; @@ -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,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 - @@ -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) @@ -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); @@ -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 @@ -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 @@ -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 @@ -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; |