diff options
-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; |