summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-10-08 18:00:00 +0200
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2000-10-08 18:00:00 +0200
commita379eb714f7f5ef9a12efbe7588bb3509faba056 (patch)
treeea9a0720f305e8ee76ea7c60c996fd3a8bad0ce5
parentef8fe3f04c30caedeb17b11ac275581539f039c7 (diff)
downloadvdr-patch-lnbsharing-a379eb714f7f5ef9a12efbe7588bb3509faba056.tar.gz
vdr-patch-lnbsharing-a379eb714f7f5ef9a12efbe7588bb3509faba056.tar.bz2
Version 0.66vdr-0.66
- Remote control data is now received in a separate thread, which makes things a lot smoother. - Repeat and release of remote control keys is now explicitly distinguished. - In replay mode the search forward/back and skip functions now have two modes: Pressing the key shortly and releasing it starts the function, and pressing it again stops it. Pressing and holding down the key starts the function and releasing the key stops it. - The '@' character that marks an "instant recording" can now be turned off in the "Setup" menu (thanks to Matthias Schniedermeyer). - Pressing the "Back" button while replaying now stops replaying and brings up the "Recordings" menu (suggested by Carsten Koch). This can be used to easily delete a recording after watching it, or to switch to a different recording. - The "Recordings" menu now places the cursor on the last replayed recording, if that file still exists. - The "Blue" button in the "Main" menu can now be used to "Resume" a previously stopped replay session (suggested by Martin Hammerschmid). - The low and high LNB frequencies can now be changed in the "Setup" menu.
-rw-r--r--CONTRIBUTORS5
-rw-r--r--FORMATS8
-rw-r--r--HISTORY22
-rw-r--r--MANUAL29
-rw-r--r--Makefile11
-rw-r--r--config.c17
-rw-r--r--config.h17
-rw-r--r--dvbapi.c8
-rw-r--r--dvbosd.c8
-rw-r--r--interface.c82
-rw-r--r--interface.h15
-rw-r--r--menu.c105
-rw-r--r--menu.h16
-rw-r--r--osd.c26
-rw-r--r--recording.c4
-rw-r--r--remote.c309
-rw-r--r--remote.h44
-rw-r--r--setup.conf3
-rw-r--r--svdrp.c6
-rw-r--r--thread.c105
-rw-r--r--thread.h57
-rw-r--r--timers.conf10
-rw-r--r--tools.c18
-rw-r--r--tools.h3
-rw-r--r--vdr.c36
25 files changed, 682 insertions, 282 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 2eefd64..91c9540 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -7,6 +7,7 @@ Carsten Koch <Carsten.Koch@icem.de>
for adding the 'epg2timers' tool (see Tools/epg2timers)
for his idea of using multiple disks (and for testing this feature)
for implementing the 'new recording' indicator
+ for suggesting that the "Back" button in replay mode should bring up the "Recordings" menu
Plamen Ganev <pganev@com-it.net>
for fixing the frequency offset for Hotbird channels
@@ -31,6 +32,10 @@ Niels de Carpentier <niels@casema.net>
Martin Hammerschmid <martin@hammerschmid.com>
for suggesting to display the direct channel select input on the OSD
+ for suggesting to use the "Blue" button in the main menu to resume replay
Bastian Guse <bastian@nocopy.de>
for writing the FORMATS entry for timers.conf
+
+Matthias Schniedermeyer <ms@citd.de>
+ for implementing the 'MarkInstantRecord' setup option.
diff --git a/FORMATS b/FORMATS
index eb9de0f..331fe3d 100644
--- a/FORMATS
+++ b/FORMATS
@@ -55,3 +55,11 @@ Video Disk Recorder File Formats
- Name of timer (will be used to name the recording)
- Summary
+* setup.conf
+
+ This file contains the basic configuration options for VDR.
+
+ Each line contains one option in the format "Name = Value".
+
+ See the MANUAL file for a description of the available options.
+
diff --git a/HISTORY b/HISTORY
index 481e83e..717102a 100644
--- a/HISTORY
+++ b/HISTORY
@@ -212,7 +212,7 @@ Video Disk Recorder Revision History
against the version 0.71 DVB driver file 'dvb.c').
- When switching channels the channel is now immediately displayed, and the
current/next information is shown as soon as it becomes available.
-- No longer displaying the year in the 'Recordings' menu to saves space for the
+- No longer displaying the year in the 'Recordings' menu to save space for the
title.
- The 'Recordings' menu now displays a '*' to indicate new recordings.
- Added the description of the timers.conf file to the FORMATS file (thanks to
@@ -221,3 +221,23 @@ Video Disk Recorder Revision History
that would display only partially).
- In normal viewing mode the '0' key now toggles between the current and the
previous channel.
+
+2000-10-08: Version 0.66
+
+- Remote control data is now received in a separate thread, which makes things
+ a lot smoother.
+- Repeat and release of remote control keys is now explicitly distinguished.
+- In replay mode the search forward/back and skip functions now have two modes:
+ Pressing the key shortly and releasing it starts the function, and pressing it
+ again stops it. Pressing and holding down the key starts the function and
+ releasing the key stops it.
+- The '@' character that marks an "instant recording" can now be turned off
+ in the "Setup" menu (thanks to Matthias Schniedermeyer).
+- Pressing the "Back" button while replaying now stops replaying and brings up
+ the "Recordings" menu (suggested by Carsten Koch). This can be used to easily
+ delete a recording after watching it, or to switch to a different recording.
+- The "Recordings" menu now places the cursor on the last replayed recording, if
+ that file still exists.
+- The "Blue" button in the "Main" menu can now be used to "Resume" a previously
+ stopped replay session (suggested by Martin Hammerschmid).
+- The low and high LNB frequencies can now be changed in the "Setup" menu.
diff --git a/MANUAL b/MANUAL
index 24ee3ff..9b864e3 100644
--- a/MANUAL
+++ b/MANUAL
@@ -16,11 +16,11 @@ Video Disk Recorder User's Manual
Right Next group - - Enable Increment - Search forward
Ok Ch display Select Switch Edit Accept Play Progress disp.
Menu Menu on Menu off Menu off Menu off Menu off Menu off Menu on
- Back - Menu off Main menu Main menu Discard Main menu -
+ Back - Menu off Main menu Main menu Discard Main menu Recordings menu
Red - Record Edit Edit - Play -
Green - - New New - - Skip -60s
Yellow - - Delete Delete - Delete Skip +60s
- Blue - - Mark Mark - - Stop
+ Blue - Resume Mark Mark - - Stop
0..9 Ch select - - - Numeric inp. - -
* Navigating through the On Screen Menus
@@ -90,7 +90,7 @@ Video Disk Recorder User's Manual
* Instant Recording
You can start recording the current channel by pressing the "Red" button
- in the Main menu. This will create a timer event named "@channelname" that
+ in the "Main" menu. This will create a timer event named "@channelname" that
starts at the current time and records for two hours.
If you want to modify the recording time you need to edit the timer.
Stop instant recording by pressing the "Menu" button and selecting
@@ -101,8 +101,10 @@ Video Disk Recorder User's Manual
All recordings are listed in the "Recordings" menu. Browse through the
list with the "Up" and "Down" button and press "Ok" (or the "Red" button)
to start playback. New recordings are marked with an '*'.
- Playback can be stopped via the Main menu by selecting "Stop replaying",
+ Playback can be stopped via the "Main" menu by selecting "Stop replaying",
or by pressing the "Blue" button outside the menu.
+ A previously stopped playback session can be resumed by pressing the "Blue"
+ button in the "Main" menu.
* Replay Control
@@ -118,12 +120,19 @@ Video Disk Recorder User's Manual
Right Runs playback forward or backward at a higher speed; press
again to resume normal speed. If in Pause mode, runs forward or
backward at a slower speed; press again to return to pause mode.
+ Pressing and holding down the button performs the function until
+ the button is released again.
- Green
Yellow Skips about 60 seconds back or forward.
+ Pressing and holding down the button performs the function until
+ the button is released again.
- Ok Brings up the replay progress display, which shows the date,
time and title of the recording, a progress bar and the
current and total time of the recording.
Press "Ok" again to turn off the progress display.
+ - Back Stops replaying and brings up the "Recordings" menu. This can be
+ used to easily delete a recording after watching it, or to switch
+ to a different recording.
* Programming the Timer
@@ -171,7 +180,7 @@ Video Disk Recorder User's Manual
* Parameters in the "Setup" menu
- Select "Setup" from the main menu to enter the setup menu. From there you can
+ Select "Setup" from the "Main" menu to enter the setup menu. From there you can
modify the following system parameters (note that "boolean" values will be
displayed as "no" and "yes" in the "Setup" menu, while in the setup file they
are stored as '0' and '1', respectively):
@@ -197,3 +206,13 @@ Video Disk Recorder User's Manual
1 = dto., but the cursor remains at the bottom (top) of
the page (this mode allows for faster scrolling
through long lists).
+
+ MarkInstantRecord = 1 Defines whether an "instant recording" (started by
+ pressing the "Red" button in the "Main" menu) will be
+ marked with a '@' character to make it distinguishable
+ from timer recordings in the "Recordings" menu.
+ 0 = instant recordings will not be marked
+ 1 = instant recordings will be marked.
+
+ LnbFrequLo = 9750 The low and high LNB frequencies (in MHz)
+ LnbFrequHi = 10600
diff --git a/Makefile b/Makefile
index 1575774..8b32be2 100644
--- a/Makefile
+++ b/Makefile
@@ -4,13 +4,13 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: Makefile 1.12 2000/10/01 14:27:12 kls Exp $
+# $Id: Makefile 1.13 2000/10/07 16:24:08 kls Exp $
DVBDIR = ../DVB
INCLUDES = -I$(DVBDIR)/driver
OBJS = config.o dvbapi.o dvbosd.o eit.o font.o interface.o menu.o osd.o\
- recording.o remote.o svdrp.o tools.o vdr.o videodir.o
+ recording.o remote.o svdrp.o thread.o tools.o vdr.o videodir.o
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
@@ -40,12 +40,13 @@ dvbapi.o : dvbapi.c config.h dvbapi.h dvbosd.h font.h interface.h svdrp.h tool
dvbosd.o : dvbosd.c dvbosd.h font.h tools.h
eit.o : eit.c eit.h tools.h
font.o : font.c font.h fontosd.c tools.h
-interface.o: interface.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h tools.h
+interface.o: interface.c config.h dvbapi.h dvbosd.h eit.h font.h interface.h remote.h svdrp.h thread.h tools.h
menu.o : menu.c config.h dvbapi.h dvbosd.h font.h interface.h menu.h osd.h recording.h svdrp.h tools.h
osd.o : osd.c config.h dvbapi.h dvbosd.h font.h interface.h osd.h svdrp.h tools.h
recording.o: recording.c config.h dvbapi.h dvbosd.h font.h interface.h recording.h svdrp.h tools.h videodir.h
-remote.o : remote.c config.h dvbapi.h dvbosd.h font.h remote.h tools.h
+remote.o : remote.c config.h dvbapi.h dvbosd.h font.h remote.h thread.h tools.h
svdrp.o : svdrp.c config.h dvbapi.h dvbosd.h font.h interface.h svdrp.h tools.h
+thread.o : thread.c thread.h
tools.o : tools.c tools.h
vdr.o : vdr.c config.h dvbapi.h dvbosd.h font.h interface.h menu.h osd.h recording.h svdrp.h tools.h videodir.h
videodir.o : videodir.c tools.h videodir.h
@@ -53,7 +54,7 @@ videodir.o : videodir.c tools.h videodir.h
# The main program:
vdr: $(OBJS)
- g++ -g -O2 $(OBJS) -lncurses -ljpeg -o vdr
+ g++ -g -O2 $(OBJS) -lncurses -ljpeg -lpthread -o vdr
# The font file:
diff --git a/config.c b/config.c
index e161efd..1714651 100644
--- a/config.c
+++ b/config.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.c 1.23 2000/09/17 09:11:59 kls Exp $
+ * $Id: config.c 1.26 2000/10/08 16:10:40 kls Exp $
*/
#include "config.h"
@@ -275,7 +275,7 @@ bool cChannel::Switch(cDvbApi *DvbApi)
}
return false;
}
- Interface.Info(DvbApi->Recording() ? "Channel locked (recording)!" : name);
+ Interface->Info(DvbApi->Recording() ? "Channel locked (recording)!" : name);
return false;
}
@@ -303,7 +303,7 @@ cTimer::cTimer(bool Instant)
*file = 0;
summary = NULL;
if (Instant && ch)
- snprintf(file, sizeof(file), "@%s", ch->name);
+ snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", ch->name);
}
cTimer::~cTimer()
@@ -566,7 +566,7 @@ eKeys cChannels::ShowChannel(int Number, bool Switched, bool Group)
{
cChannel *channel = Group ? Get(Number) : GetByNumber(Number);
if (channel)
- return Interface.DisplayChannel(channel->number, channel->name, !Switched || Setup.ShowInfoOnChSwitch);
+ return Interface->DisplayChannel(channel->number, channel->name, !Switched || Setup.ShowInfoOnChSwitch);
return kNone;
}
@@ -596,6 +596,9 @@ cSetup::cSetup(void)
PrimaryDVB = 1;
ShowInfoOnChSwitch = 1;
MenuScrollPage = 1;
+ MarkInstantRecord = 1;
+ LnbFrequLo = 9750;
+ LnbFrequHi = 10600;
}
bool cSetup::Parse(char *s)
@@ -607,6 +610,9 @@ bool cSetup::Parse(char *s)
if (!strcasecmp(Name, "PrimaryDVB")) PrimaryDVB = atoi(Value);
else if (!strcasecmp(Name, "ShowInfoOnChSwitch")) ShowInfoOnChSwitch = atoi(Value);
else if (!strcasecmp(Name, "MenuScrollPage")) MenuScrollPage = atoi(Value);
+ else if (!strcasecmp(Name, "MarkInstantRecord")) MarkInstantRecord = atoi(Value);
+ else if (!strcasecmp(Name, "LnbFrequLo")) LnbFrequLo = atoi(Value);
+ else if (!strcasecmp(Name, "LnbFrequHi")) LnbFrequHi = atoi(Value);
else
return false;
return true;
@@ -651,6 +657,9 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
fprintf(f, "ShowInfoOnChSwitch = %d\n", ShowInfoOnChSwitch);
fprintf(f, "MenuScrollPage = %d\n", MenuScrollPage);
+ fprintf(f, "MarkInstantRecord = %d\n", MarkInstantRecord);
+ fprintf(f, "LnbFrequLo = %d\n", LnbFrequLo);
+ fprintf(f, "LnbFrequHi = %d\n", LnbFrequHi);
fclose(f);
isyslog(LOG_INFO, "saved setup to %s", FileName);
return true;
diff --git a/config.h b/config.h
index 224a7b3..56f3618 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.22 2000/10/01 14:14:18 kls Exp $
+ * $Id: config.h 1.27 2000/10/08 16:33:48 kls Exp $
*/
#ifndef __CONFIG_H
@@ -17,7 +17,7 @@
#include "dvbapi.h"
#include "tools.h"
-#define VDRVERSION "0.65"
+#define VDRVERSION "0.66"
#define MaxBuffer 10000
@@ -34,9 +34,17 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
kYellow,
kBlue,
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
- kNone
+ kNone,
+ // The following flags are OR'd with the above codes:
+ k_Repeat = 0x8000,
+ k_Release = 0x4000,
+ k_Flags = k_Repeat | k_Release,
};
+#define RAWKEY(k) ((k) & ~k_Flags)
+#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
+#define NORMALKEY(k) ((k) & ~k_Repeat)
+
struct tKey {
eKeys type;
char *name;
@@ -223,6 +231,9 @@ public:
int PrimaryDVB;
int ShowInfoOnChSwitch;
int MenuScrollPage;
+ int MarkInstantRecord;
+ int LnbFrequLo;
+ int LnbFrequHi;
cSetup(void);
bool Load(const char *FileName);
bool Save(const char *FileName = NULL);
diff --git a/dvbapi.c b/dvbapi.c
index 04873fc..e5c692c 100644
--- a/dvbapi.c
+++ b/dvbapi.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbapi.c 1.30 2000/10/03 13:26:16 kls Exp $
+ * $Id: dvbapi.c 1.31 2000/10/08 16:14:45 kls Exp $
*/
#include "dvbapi.h"
@@ -19,7 +19,7 @@ extern "C" {
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
-#include "dvbapi.h"
+#include "config.h"
#include "interface.h"
#include "tools.h"
#include "videodir.h"
@@ -1657,9 +1657,9 @@ bool cDvbApi::SetChannel(int FrequencyMHz, char Polarization, int Diseqc, int Sr
unsigned int freq = FrequencyMHz;
front.ttk = (freq < 11700UL) ? 0 : 1;
if (freq < 11700UL)
- freq -= 9750UL;
+ freq -= Setup.LnbFrequLo;
else
- freq -= 10600UL;
+ freq -= Setup.LnbFrequHi;
front.channel_flags = Ca ? DVB_CHANNEL_CA : DVB_CHANNEL_FTA;
front.pnr = Pnr;
front.freq = freq * 1000000UL;
diff --git a/dvbosd.c b/dvbosd.c
index 1e2c354..97c7932 100644
--- a/dvbosd.c
+++ b/dvbosd.c
@@ -4,10 +4,11 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbosd.c 1.2 2000/10/03 13:34:13 kls Exp $
+ * $Id: dvbosd.c 1.3 2000/10/07 14:42:48 kls Exp $
*/
#include "dvbosd.h"
+#include <signal.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/unistd.h>
@@ -138,11 +139,16 @@ void cDvbOsd::Cmd(OSD_Command cmd, int color, int x0, int y0, int x1, int y1, co
dc.x1 = x1;
dc.y1 = y1;
dc.data = (void *)data;
+ // must block all signals, otherwise the command might not be fully executed
+ sigset_t set, oldset;
+ sigfillset(&set);
+ sigprocmask(SIG_BLOCK, &set, &oldset);
ioctl(videoDev, VIDIOCSOSDCOMMAND, &dc);
usleep(10); // XXX Workaround for a driver bug (cInterface::DisplayChannel() displayed texts at wrong places
// XXX and sometimes the OSD was no longer displayed).
// XXX Increase the value if the problem still persists on your particular system.
// TODO Check if this is still necessary with driver versions after 0.7.
+ sigprocmask(SIG_SETMASK, &oldset, NULL);
}
}
diff --git a/interface.c b/interface.c
index a0fca0e..5940195 100644
--- a/interface.c
+++ b/interface.c
@@ -4,43 +4,39 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: interface.c 1.21 2000/10/03 13:28:02 kls Exp $
+ * $Id: interface.c 1.25 2000/10/08 16:34:17 kls Exp $
*/
#include "interface.h"
#include <unistd.h>
#include "eit.h"
-#include "remote.h"
cEIT EIT;
-#if defined(REMOTE_RCU)
-cRcIoRCU RcIo("/dev/ttyS1");
-#elif defined(REMOTE_LIRC)
-cRcIoLIRC RcIo("/dev/lircd");
-#else
-cRcIoKBD RcIo;
-#endif
-
-cInterface Interface;
+cInterface *Interface = NULL;
-cInterface::cInterface(void)
+cInterface::cInterface(int SVDRPport)
{
open = 0;
cols[0] = 0;
keyFromWait = kNone;
+ rcIo = NULL;
SVDRP = NULL;
-}
-
-void cInterface::Init(int SVDRPport)
-{
- RcIo.SetCode(Keys.code, Keys.address);
+#if defined(REMOTE_RCU)
+ rcIo = new cRcIoRCU("/dev/ttyS1");
+#elif defined(REMOTE_LIRC)
+ rcIo = new cRcIoLIRC("/dev/lircd");
+#else
+ rcIo = new cRcIoKBD;
+#endif
+ rcIo->SetCode(Keys.code, Keys.address);
if (SVDRPport)
SVDRP = new cSVDRP(SVDRPport);
}
-void cInterface::Cleanup(void)
+cInterface::~cInterface()
{
+ delete rcIo;
delete SVDRP;
}
@@ -58,22 +54,29 @@ void cInterface::Close(void)
cDvbApi::PrimaryDvbApi->Close();
}
-unsigned int cInterface::GetCh(bool Wait)
+unsigned int cInterface::GetCh(bool Wait, bool *Repeat, bool *Release)
{
- if (RcIo.InputAvailable(Wait)) {
- unsigned int Command;
- return RcIo.GetCommand(&Command, NULL) ? Command : 0;
- }
- return 0;
+ if (open)
+ cDvbApi::PrimaryDvbApi->Flush();
+ if (!rcIo->InputAvailable())
+ cFile::AnyFileReady(-1, Wait ? 1000 : 0);
+ unsigned int Command;
+ return rcIo->GetCommand(&Command, Repeat, Release) ? Command : 0;
}
eKeys cInterface::GetKey(bool Wait)
{
- if (open)
- cDvbApi::PrimaryDvbApi->Flush();
if (SVDRP)
SVDRP->Process();
- eKeys Key = keyFromWait != kNone ? keyFromWait : Keys.Get(GetCh(Wait));
+ eKeys Key = keyFromWait;
+ if (Key == kNone) {
+ bool Repeat = false, Release = false;
+ Key = Keys.Get(GetCh(Wait, &Repeat, &Release));
+ if (Repeat)
+ Key = eKeys(Key | k_Repeat);
+ if (Release)
+ Key = eKeys(Key | k_Release);
+ }
keyFromWait = kNone;
return Key;
}
@@ -85,13 +88,16 @@ void cInterface::PutKey(eKeys Key)
eKeys cInterface::Wait(int Seconds, bool KeepChar)
{
- eKeys Key = kNone;
if (open)
cDvbApi::PrimaryDvbApi->Flush();
- RcIo.Flush(500);
- if (cFile::AnyFileReady(-1, Seconds * 1000))
- Key = GetKey();
- if (KeepChar)
+ eKeys Key = kNone;
+ time_t timeout = time(NULL) + Seconds;
+ for (;;) {
+ Key = GetKey();
+ if ((Key != kNone && (RAWKEY(Key) != kOk || RAWKEY(Key) == Key)) || time(NULL) > timeout)
+ break;
+ }
+ if (KeepChar && ISRAWKEY(Key))
keyFromWait = Key;
return Key;
}
@@ -220,9 +226,11 @@ void cInterface::Help(const char *Red, const char *Green, const char *Yellow, co
void cInterface::QueryKeys(void)
{
Keys.Clear();
+ Clear();
WriteText(1, 1, "Learning Remote Control Keys");
WriteText(1, 3, "Phase 1: Detecting RC code type");
WriteText(1, 5, "Press any key on the RC unit");
+ cDvbApi::PrimaryDvbApi->Flush();
#ifndef REMOTE_KBD
unsigned char Code = 0;
unsigned short Address;
@@ -233,14 +241,16 @@ void cInterface::QueryKeys(void)
break;
#else
//TODO on screen display...
- if (RcIo.DetectCode(&Code, &Address)) {
+ if (rcIo->DetectCode(&Code, &Address)) {
Keys.code = Code;
Keys.address = Address;
WriteText(1, 5, "RC code detected!");
WriteText(1, 6, "Do not press any key...");
- RcIo.Flush(3000);
+ cDvbApi::PrimaryDvbApi->Flush();
+ rcIo->Flush(3000);
ClearEol(0, 5);
ClearEol(0, 6);
+ cDvbApi::PrimaryDvbApi->Flush();
break;
}
#endif
@@ -328,7 +338,7 @@ eKeys cInterface::DisplayChannel(int Number, const char *Name, bool WithInfo)
{
// Number = 0 is used for channel group display and no EIT
if (Number)
- RcIo.Number(Number);
+ rcIo->Number(Number);
if (Name && !Recording()) {
Open(MenuColumns, 5);
cDvbApi::PrimaryDvbApi->Fill(0, 0, MenuColumns, 1, clrBackground);
@@ -387,7 +397,7 @@ eKeys cInterface::DisplayChannel(int Number, const char *Name, bool WithInfo)
void cInterface::DisplayRecording(int Index, bool On)
{
- RcIo.SetPoints(1 << Index, On);
+ rcIo->SetPoints(1 << Index, On);
}
bool cInterface::Recording(void)
diff --git a/interface.h b/interface.h
index 8f7f1b8..8d0f8f6 100644
--- a/interface.h
+++ b/interface.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: interface.h 1.13 2000/09/18 22:29:31 kls Exp $
+ * $Id: interface.h 1.16 2000/10/08 12:15:49 kls Exp $
*/
#ifndef __INTERFACE_H
@@ -12,6 +12,7 @@
#include "config.h"
#include "dvbapi.h"
+#include "remote.h"
#include "svdrp.h"
class cInterface {
@@ -22,14 +23,14 @@ private:
int cols[MaxCols];
eKeys keyFromWait;
cSVDRP *SVDRP;
- unsigned int GetCh(bool Wait = true);
+ cRcIoBase *rcIo;
+ unsigned int GetCh(bool Wait = true, bool *Repeat = NULL, bool *Release = NULL);
void QueryKeys(void);
void HelpButton(int Index, const char *Text, eDvbColor FgColor, eDvbColor BgColor);
eKeys Wait(int Seconds = 1, bool KeepChar = false);
public:
- cInterface(void);
- void Init(int SVDRPport = 0);
- void Cleanup(void);
+ cInterface(int SVDRPport = 0);
+ ~cInterface();
void Open(int NumCols = MenuColumns, int NumLines = MenuLines);
void Close(void);
eKeys GetKey(bool Wait = true);
@@ -38,7 +39,7 @@ public:
void ClearEol(int x, int y, eDvbColor Color = clrBackground);
void SetCols(int *c);
void Write(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
- void WriteText(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBlack);
+ void WriteText(int x, int y, const char *s, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
void Title(const char *s);
void Status(const char *s, eDvbColor FgColor = clrBlack, eDvbColor BgColor = clrCyan);
void Info(const char *s);
@@ -51,6 +52,6 @@ public:
bool Recording(void);
};
-extern cInterface Interface;
+extern cInterface *Interface;
#endif //__INTERFACE_H
diff --git a/menu.c b/menu.c
index 1f5fd88..39689c9 100644
--- a/menu.c
+++ b/menu.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.c 1.30 2000/10/03 14:06:44 kls Exp $
+ * $Id: menu.c 1.36 2000/10/08 16:11:22 kls Exp $
*/
#include "menu.h"
@@ -13,7 +13,6 @@
#include <stdio.h>
#include <string.h>
#include "config.h"
-#include "recording.h"
#define MENUTIMEOUT 120 // seconds
@@ -94,11 +93,11 @@ eOSState cMenuEditIntItem::ProcessKey(eKeys Key)
}
newValue = *value * 10 + (Key - k0);
}
- else if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly?
+ else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
newValue = *value - 1;
fresh = true;
}
- else if (Key == kRight) {
+ else if (NORMALKEY(Key) == kRight) {
newValue = *value + 1;
fresh = true;
}
@@ -211,6 +210,7 @@ void cMenuEditDayItem::Set(void)
eOSState cMenuEditDayItem::ProcessKey(eKeys Key)
{
switch (Key) {
+ case kLeft|k_Repeat:
case kLeft: if (d > 0)
*value = days[--d];
else if (d == 0) {
@@ -225,6 +225,7 @@ eOSState cMenuEditDayItem::ProcessKey(eKeys Key)
return cMenuEditIntItem::ProcessKey(Key);
Set();
break;
+ case kRight|k_Repeat:
case kRight: if (d >= 0) {
*value = days[++d];
if (*value == 0) {
@@ -310,7 +311,7 @@ eOSState cMenuEditTimeItem::ProcessKey(eKeys Key)
break;
}
}
- else if (Key == kLeft) { // TODO might want to increase the delta if repeated quickly?
+ else if (NORMALKEY(Key) == kLeft) { // TODO might want to increase the delta if repeated quickly?
if (--mm < 0) {
mm = 59;
if (--hh < 0)
@@ -318,7 +319,7 @@ eOSState cMenuEditTimeItem::ProcessKey(eKeys Key)
}
fresh = true;
}
- else if (Key == kRight) {
+ else if (NORMALKEY(Key) == kRight) {
if (++mm > 59) {
mm = 0;
if (++hh > 23)
@@ -377,11 +378,11 @@ eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
eOSState state = cMenuEditItem::ProcessKey(Key);
if (state == osUnknown) {
- if (Key == kLeft) {
+ if (NORMALKEY(Key) == kLeft) {
if (current > allowed)
current--;
}
- else if (Key == kRight) {
+ else if (NORMALKEY(Key) == kRight) {
if (*(current + 1))
current++;
}
@@ -455,12 +456,14 @@ char cMenuEditStrItem::Inc(char c, bool Up)
eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
{
switch (Key) {
+ case kLeft|k_Repeat:
case kLeft: if (pos > 0) {
if (value[pos] == '^')
value[pos] = 0;
pos--;
}
break;
+ case kRight|k_Repeat:
case kRight: if (pos < length && value[pos] != '^' && (pos < int(strlen(value) - 1) || value[pos] != ' ')) {
if (++pos >= int(strlen(value))) {
value[pos] = ' ';
@@ -468,9 +471,11 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
}
}
break;
+ case kUp|k_Repeat:
case kUp:
+ case kDown|k_Repeat:
case kDown: if (pos >= 0)
- value[pos] = Inc(value[pos], Key == kUp);
+ value[pos] = Inc(value[pos], NORMALKEY(Key) == kUp);
else
return cMenuEditItem::ProcessKey(Key);
break;
@@ -635,11 +640,11 @@ eOSState cMenuChannels::Del(void)
// Check if there is a timer using this channel:
for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
if (ti->channel == DeletedChannel) {
- Interface.Error("Channel is being used by a timer!");
+ Interface->Error("Channel is being used by a timer!");
return osContinue;
}
}
- if (Interface.Confirm("Delete Channel?")) {
+ if (Interface->Confirm("Delete Channel?")) {
// Move and renumber the channels:
Channels.Del(channel);
Channels.ReNumber();
@@ -916,7 +921,7 @@ eOSState cMenuTimers::Del(void)
cTimer *ti = Timers.Get(Index);
if (ti) {
if (!ti->recording) {
- if (Interface.Confirm("Delete Timer?")) {
+ if (Interface->Confirm("Delete Timer?")) {
Timers.Del(Timers.Get(Index));
cOsdMenu::Del(Index);
Timers.Save();
@@ -925,7 +930,7 @@ eOSState cMenuTimers::Del(void)
}
}
else
- Interface.Error("Timer is recording!");
+ Interface->Error("Timer is recording!");
}
return osContinue;
}
@@ -990,28 +995,19 @@ void cMenuRecordingItem::Set(void)
// --- cMenuRecordings -------------------------------------------------------
-class cMenuRecordings : public cOsdMenu {
-private:
- cRecordings Recordings;
- eOSState Play(void);
- eOSState Del(void);
- eOSState Summary(void);
-public:
- cMenuRecordings(void);
- virtual eOSState ProcessKey(eKeys Key);
- };
-
cMenuRecordings::cMenuRecordings(void)
:cOsdMenu("Recordings", 6, 6)
{
if (Recordings.Load()) {
+ const char *lastReplayed = cReplayControl::LastReplayed();
cRecording *recording = Recordings.First();
while (recording) {
- Add(new cMenuRecordingItem(recording));
+ Add(new cMenuRecordingItem(recording), lastReplayed && strcmp(lastReplayed, recording->FileName()) == 0);
recording = Recordings.Next(recording);
}
}
- SetHelp("Play", NULL/*XXX"Resume"*/, "Delete", "Summary");
+ SetHelp("Play", NULL, "Delete", "Summary");
+ Display();
}
eOSState cMenuRecordings::Play(void)
@@ -1030,17 +1026,18 @@ eOSState cMenuRecordings::Del(void)
if (ri) {
//XXX what if this recording's file is currently in use???
//XXX if (!ti->recording) {
- if (Interface.Confirm("Delete Recording?")) {
+ if (Interface->Confirm("Delete Recording?")) {
if (ri->recording->Delete()) {
+ cReplayControl::ClearLastReplayed(ri->recording->FileName());
cOsdMenu::Del(Current());
Display();
}
else
- Interface.Error("Error while deleting recording!");
+ Interface->Error("Error while deleting recording!");
}
//XXX }
//XXX else
-//XXX Interface.Error("Timer is recording!");
+//XXX Interface->Error("Timer is recording!");
}
return osContinue;
}
@@ -1065,6 +1062,7 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
case kRed: return Play();
case kYellow: return Del();
case kBlue: return Summary();
+ case kMenu: return osEnd;
default: break;
}
}
@@ -1088,6 +1086,9 @@ cMenuSetup::cMenuSetup(void)
Add(new cMenuEditIntItem( "PrimaryDVB", &data.PrimaryDVB, 1, cDvbApi::NumDvbApis));
Add(new cMenuEditBoolItem("ShowInfoOnChSwitch", &data.ShowInfoOnChSwitch));
Add(new cMenuEditBoolItem("MenuScrollPage", &data.MenuScrollPage));
+ Add(new cMenuEditBoolItem("MarkInstantRecord", &data.MarkInstantRecord));
+ Add(new cMenuEditIntItem( "LnbFrequLo", &data.LnbFrequLo));
+ Add(new cMenuEditIntItem( "LnbFrequHi", &data.LnbFrequHi));
}
eOSState cMenuSetup::ProcessKey(eKeys Key)
@@ -1126,7 +1127,7 @@ cMenuMain::cMenuMain(bool Replaying)
Add(new cOsdItem(buffer, osStopRecord));
delete buffer;
}
- SetHelp("Record");
+ SetHelp("Record", NULL, NULL, cReplayControl::LastReplayed() ? "Resume" : NULL);
Display();
lastActivity = time(NULL);
}
@@ -1140,7 +1141,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
case osTimer: return AddSubMenu(new cMenuTimers);
case osRecordings: return AddSubMenu(new cMenuRecordings);
case osSetup: return AddSubMenu(new cMenuSetup);
- case osStopRecord: if (Interface.Confirm("Stop Recording?")) {
+ case osStopRecord: if (Interface->Confirm("Stop Recording?")) {
cOsdItem *item = Get(Current());
if (item) {
cRecordControls::Stop(item->Text() + strlen(STOP_RECORDING));
@@ -1152,6 +1153,9 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
case kRed: if (!HasSubMenu())
state = osRecord;
break;
+ case kBlue: if (!HasSubMenu())
+ state = osReplay;
+ break;
default: break;
}
}
@@ -1172,15 +1176,15 @@ cDirectChannelSelect::cDirectChannelSelect(eKeys FirstKey)
oldNumber = CurrentChannel;
number = 0;
lastTime = time_ms();
- Interface.Open(MenuColumns, 1);
+ Interface->Open(MenuColumns, 1);
ProcessKey(FirstKey);
}
cDirectChannelSelect::~cDirectChannelSelect()
{
if (number < 0)
- Interface.DisplayChannel(oldNumber);
- Interface.Close();
+ Interface->DisplayChannel(oldNumber);
+ Interface->Close();
}
eOSState cDirectChannelSelect::ProcessKey(eKeys Key)
@@ -1194,9 +1198,9 @@ eOSState cDirectChannelSelect::ProcessKey(eKeys Key)
int BufSize = MenuColumns + 1;
char buffer[BufSize];
snprintf(buffer, BufSize, "%d %s", number, Name);
- Interface.DisplayChannel(number);
- Interface.Clear();
- Interface.Write(0, 0, buffer);
+ Interface->DisplayChannel(number);
+ Interface->Clear();
+ Interface->Write(0, 0, buffer);
lastTime = time_ms();
if (!channel) {
number = -1;
@@ -1235,14 +1239,14 @@ cRecordControl::cRecordControl(cDvbApi *DvbApi, cTimer *Timer)
cRecording Recording(timer);
if (dvbApi->StartRecord(Recording.FileName()))
Recording.WriteSummary();
- Interface.DisplayRecording(dvbApi->Index(), true);
+ Interface->DisplayRecording(dvbApi->Index(), true);
}
cRecordControl::~cRecordControl()
{
Stop(true);
delete instantId;
- Interface.DisplayRecording(dvbApi->Index(), false);
+ Interface->DisplayRecording(dvbApi->Index(), false);
}
void cRecordControl::Stop(bool KeepInstant)
@@ -1357,10 +1361,23 @@ void cReplayControl::SetRecording(const char *FileName, const char *Title)
title = Title ? strdup(Title) : NULL;
}
+const char *cReplayControl::LastReplayed(void)
+{
+ return fileName;
+}
+
+void cReplayControl::ClearLastReplayed(const char *FileName)
+{
+ if (fileName && FileName && strcmp(fileName, FileName) == 0) {
+ delete fileName;
+ fileName = NULL;
+ }
+}
+
void cReplayControl::Show(void)
{
if (!visible) {
- Interface.Open(MenuColumns, -3);
+ Interface->Open(MenuColumns, -3);
needsFastResponse = visible = true;
shown = dvbApi->ShowProgress(true);
}
@@ -1369,7 +1386,7 @@ void cReplayControl::Show(void)
void cReplayControl::Hide(void)
{
if (visible) {
- Interface.Close();
+ Interface->Close();
needsFastResponse = visible = false;
}
}
@@ -1388,10 +1405,16 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
return osEnd;
case kLeft: dvbApi->Backward(); break;
case kRight: dvbApi->Forward(); break;
+ case kLeft|k_Release:
+ case kRight|k_Release:
+ dvbApi->Play(); break;
+ case kGreen|k_Repeat:
case kGreen: dvbApi->Skip(-60); break;
+ case kYellow|k_Repeat:
case kYellow: dvbApi->Skip(60); break;
case kMenu: Hide(); return osMenu; // allow direct switching to menu
case kOk: visible ? Hide() : Show(); break;
+ case kBack: return osRecordings;
default: return osUnknown;
}
return osContinue;
diff --git a/menu.h b/menu.h
index 8b4f82e..c36427f 100644
--- a/menu.h
+++ b/menu.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: menu.h 1.10 2000/09/10 14:42:20 kls Exp $
+ * $Id: menu.h 1.12 2000/10/08 15:21:52 kls Exp $
*/
#ifndef _MENU_H
@@ -14,6 +14,7 @@
#include "dvbapi.h"
#include "osd.h"
+#include "recording.h"
class cMenuMain : public cOsdMenu {
private:
@@ -34,6 +35,17 @@ public:
virtual eOSState ProcessKey(eKeys Key);
};
+class cMenuRecordings : public cOsdMenu {
+private:
+ cRecordings Recordings;
+ eOSState Play(void);
+ eOSState Del(void);
+ eOSState Summary(void);
+public:
+ cMenuRecordings(void);
+ virtual eOSState ProcessKey(eKeys Key);
+ };
+
class cRecordControl {
private:
cDvbApi *dvbApi;
@@ -72,6 +84,8 @@ public:
virtual eOSState ProcessKey(eKeys Key);
bool Visible(void) { return visible; }
static void SetRecording(const char *FileName, const char *Title);
+ static const char *LastReplayed(void);
+ static void ClearLastReplayed(const char *FileName);
};
#endif //_MENU_H
diff --git a/osd.c b/osd.c
index e1c99b4..75d9ead 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.7 2000/09/10 08:24:50 kls Exp $
+ * $Id: osd.c 1.9 2000/10/08 12:20:34 kls Exp $
*/
#include "osd.h"
@@ -64,7 +64,7 @@ void cOsdItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor)
if (Offset >= 0)
offset = Offset;
if (offset >= 0)
- Interface.WriteText(0, offset + 2, text, userColor ? fgColor : FgColor, userColor ? bgColor : BgColor);
+ Interface->WriteText(0, offset + 2, text, userColor ? fgColor : FgColor, userColor ? bgColor : BgColor);
}
eOSState cOsdItem::ProcessKey(eKeys Key)
@@ -88,7 +88,7 @@ cOsdMenu::cOsdMenu(char *Title, int c0, int c1, int c2, int c3, int c4)
subMenu = NULL;
helpRed = helpGreen = helpYellow = helpBlue = NULL;
status = NULL;
- Interface.Open();
+ Interface->Open();
}
cOsdMenu::~cOsdMenu()
@@ -96,8 +96,8 @@ cOsdMenu::~cOsdMenu()
delete title;
delete subMenu;
delete status;
- Interface.Clear();
- Interface.Close();
+ Interface->Clear();
+ Interface->Close();
}
void cOsdMenu::SetStatus(const char *s)
@@ -105,7 +105,7 @@ void cOsdMenu::SetStatus(const char *s)
delete status;
status = s ? strdup(s) : NULL;
if (visible)
- Interface.Status(status);
+ Interface->Status(status);
}
void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, const char *Blue)
@@ -117,7 +117,7 @@ void cOsdMenu::SetHelp(const char *Red, const char *Green, const char *Yellow, c
helpBlue = Blue;
if (visible)
Display();
- //XXX Interface.Help(helpRed, helpGreen, helpYellow, helpBlue);
+ //XXX Interface->Help(helpRed, helpGreen, helpYellow, helpBlue);
//XXX must clear unused button areas!
}
@@ -140,10 +140,10 @@ void cOsdMenu::Add(cOsdItem *Item, bool Current)
void cOsdMenu::Display(void)
{
visible = true;
- Interface.Clear();
- Interface.SetCols(cols);
- Interface.Title(title);
- Interface.Help(helpRed, helpGreen, helpYellow, helpBlue);
+ Interface->Clear();
+ Interface->SetCols(cols);
+ Interface->Title(title);
+ Interface->Help(helpRed, helpGreen, helpYellow, helpBlue);
int count = Count();
if (count > 0) {
if (current < 0)
@@ -164,7 +164,7 @@ void cOsdMenu::Display(void)
break;
}
}
- Interface.Status(status);
+ Interface->Status(status);
}
void cOsdMenu::RefreshCurrent(void)
@@ -274,7 +274,9 @@ eOSState cOsdMenu::ProcessKey(eKeys Key)
return state;
}
switch (Key) {
+ case kUp|k_Repeat:
case kUp: CursorUp(); break;
+ case kDown|k_Repeat:
case kDown: CursorDown(); break;
case kBack: return osBack;
case kOk: if (marked >= 0) {
diff --git a/recording.c b/recording.c
index 60ea4a1..f9ab016 100644
--- a/recording.c
+++ b/recording.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.c 1.18 2000/10/03 12:39:28 kls Exp $
+ * $Id: recording.c 1.19 2000/10/08 12:20:53 kls Exp $
*/
#define _GNU_SOURCE
@@ -254,7 +254,7 @@ bool cRecordings::Load(bool Deleted)
result = Count() > 0;
}
else
- Interface.Error("Error while opening pipe!");
+ Interface->Error("Error while opening pipe!");
delete cmd;
return result;
}
diff --git a/remote.c b/remote.c
index 1bf8108..f60d768 100644
--- a/remote.c
+++ b/remote.c
@@ -6,7 +6,7 @@
*
* Ported to LIRC by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
*
- * $Id: remote.c 1.15 2000/10/03 10:49:58 kls Exp $
+ * $Id: remote.c 1.18 2000/10/08 16:49:41 kls Exp $
*/
#include "remote.h"
@@ -27,16 +27,11 @@
#include "config.h"
#include "tools.h"
-#define REPEATLIMIT 100 // ms
-#define REPEATDELAY 250 // ms
-
// --- cRcIoBase -------------------------------------------------------------
cRcIoBase::cRcIoBase(void)
{
t = 0;
- firstTime = lastTime = 0;
- lastCommand = 0;
}
cRcIoBase::~cRcIoBase()
@@ -69,12 +64,12 @@ void cRcIoKBD::Flush(int WaitMs)
}
}
-bool cRcIoKBD::InputAvailable(bool Wait)
+bool cRcIoKBD::InputAvailable(void)
{
- return f.Ready(Wait);
+ return f.Ready(false);
}
-bool cRcIoKBD::GetCommand(unsigned int *Command, unsigned short *)
+bool cRcIoKBD::GetCommand(unsigned int *Command, bool *Repeat, bool *Release)
{
if (Command) {
*Command = getch();
@@ -87,36 +82,122 @@ bool cRcIoKBD::GetCommand(unsigned int *Command, unsigned short *)
#elif defined REMOTE_RCU
+#define REPEATLIMIT 20 // ms
+#define REPEATDELAY 350 // ms
+
cRcIoRCU::cRcIoRCU(char *DeviceName)
{
dp = 0;
mode = modeB;
code = 0;
address = 0xFFFF;
+ receivedAddress = 0;
+ receivedCommand = 0;
+ receivedData = receivedRepeat = receivedRelease = false;
lastNumber = 0;
- if (f.Open(DeviceName, O_RDWR | O_NONBLOCK)) {
+ if ((f = open(DeviceName, O_RDWR | O_NONBLOCK)) >= 0) {
struct termios t;
if (tcgetattr(f, &t) == 0) {
cfsetspeed(&t, B9600);
cfmakeraw(&t);
- if (tcsetattr(f, TCSAFLUSH, &t) == 0)
+ if (tcsetattr(f, TCSAFLUSH, &t) == 0) {
+ Start();
return;
+ }
}
LOG_ERROR_STR(DeviceName);
- f.Close();
+ close(f);
}
else
LOG_ERROR_STR(DeviceName);
+ f = -1;
}
cRcIoRCU::~cRcIoRCU()
{
+ Stop();
}
-int cRcIoRCU::ReceiveByte(bool Wait)
+void cRcIoRCU::Action(void)
+{
+#pragma pack(1)
+ union {
+ struct {
+ unsigned short address;
+ unsigned int command;
+ } data;
+ unsigned char raw[6];
+ } buffer;
+#pragma pack()
+
+ dsyslog(LOG_INFO, "RCU remote control thread started (pid=%d)", getpid());
+
+ int FirstTime = 0;
+ unsigned int LastCommand = 0;
+
+ for (; f >= 0;) {
+
+ LOCK_THREAD;
+
+ if (ReceiveByte(REPEATLIMIT) == 'X') {
+ for (int i = 0; i < 6; i++) {
+ int b = ReceiveByte();
+ if (b >= 0) {
+ buffer.raw[i] = b;
+ if (i == 5) {
+ unsigned short Address = ntohs(buffer.data.address); // the PIC sends bytes in "network order"
+ unsigned int Command = ntohl(buffer.data.command);
+ if (code == 'B' && address == 0x0000 && Command == 0x00004000)
+ // Well, well, if it isn't the "d-box"...
+ // This remote control sends the above command before and after
+ // each keypress - let's just drop this:
+ break;
+ if (!receivedData) { // only accept new data the previous data has been fetched
+ int Now = time_ms();
+ if (Command != LastCommand) {
+ receivedAddress = Address;
+ receivedCommand = Command;
+ receivedData = true;
+ receivedRepeat = receivedRelease = false;
+ FirstTime = Now;
+ }
+ else {
+ if (Now - FirstTime < REPEATDELAY)
+ break; // repeat function kicks in after a short delay
+ receivedData = receivedRepeat = true;
+ }
+ LastCommand = Command;
+ WakeUp();
+ }
+ }
+ }
+ else
+ break;
+ }
+ }
+ else if (receivedData) { // the last data before releasing the key hasn't been fetched yet
+ if (receivedRepeat) { // it was a repeat, so let's make it a release
+ receivedRepeat = false;
+ receivedRelease = true;
+ LastCommand = 0;
+ WakeUp();
+ }
+ }
+ else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release
+ receivedData = receivedRelease = true;
+ receivedRepeat = false;
+ LastCommand = 0;
+ WakeUp();
+ }
+ else
+ LastCommand = 0;
+ }
+}
+
+int cRcIoRCU::ReceiveByte(int TimeoutMs)
{
// Returns the byte if one was received within a timeout, -1 otherwise
- if (InputAvailable(Wait)) {
+ if (cFile::FileReady(f, TimeoutMs)) {
unsigned char b;
if (read(f, &b, 1) == 1)
return b;
@@ -128,16 +209,16 @@ int cRcIoRCU::ReceiveByte(bool Wait)
bool cRcIoRCU::SendByteHandshake(unsigned char c)
{
- if (f.IsOpen()) {
+ if (f >= 0) {
int w = write(f, &c, 1);
if (w == 1) {
- for (int reply = ReceiveByte(); reply >= 0;) {
+ for (int reply = ReceiveByte(REPEATLIMIT); reply >= 0;) {
if (reply == c)
return true;
else if (reply == 'X') {
// skip any incoming RC code - it will come again
for (int i = 6; i--;) {
- if (ReceiveByte(false) < 0)
+ if (ReceiveByte() < 0)
return false;
}
}
@@ -152,6 +233,8 @@ bool cRcIoRCU::SendByteHandshake(unsigned char c)
bool cRcIoRCU::SendByte(unsigned char c)
{
+ LOCK_THREAD;
+
for (int retry = 5; retry--;) {
if (SendByteHandshake(c))
return true;
@@ -174,66 +257,34 @@ bool cRcIoRCU::SetMode(unsigned char Mode)
void cRcIoRCU::Flush(int WaitMs)
{
- int t0 = time_ms();
+ LOCK_THREAD;
+ int t0 = time_ms();
for (;;) {
- while (ReceiveByte(false) >= 0)
+ while (ReceiveByte() >= 0)
t0 = time_ms();
if (time_ms() - t0 >= WaitMs)
break;
}
+ receivedData = receivedRepeat = false;
}
-bool cRcIoRCU::InputAvailable(bool Wait)
+bool cRcIoRCU::GetCommand(unsigned int *Command, bool *Repeat, bool *Release)
{
- return f.Ready(Wait);
-}
-
-bool cRcIoRCU::GetCommand(unsigned int *Command, unsigned short *Address)
-{
-#pragma pack(1)
- union {
- struct {
- unsigned short address;
- unsigned int command;
- } data;
- unsigned char raw[6];
- } buffer;
-#pragma pack()
-
- Flush();
- if (Command && ReceiveByte() == 'X') {
- for (int i = 0; i < 6; i++) {
- int b = ReceiveByte(false);
- if (b >= 0)
- buffer.raw[i] = b;
- else
- return false;
- }
- if (Address)
- *Address = ntohs(buffer.data.address); // the PIC sends bytes in "network order"
- else if (address != ntohs(buffer.data.address))
- return false;
- *Command = ntohl(buffer.data.command);
- if (code == 'B' && address == 0x0000 && *Command == 0x00004000)
- // Well, well, if it isn't the "d-box"...
- // This remote control sends the above command before and after
- // each keypress - let's just drop this:
- return false;
- if (*Command == lastCommand) {
- // let's have a timeout to avoid getting overrun by commands
- int now = time_ms();
- int delta = now - lastTime;
- lastTime = now;
- if (delta < REPEATLIMIT) { // if commands come in rapidly...
- if (now - firstTime < REPEATDELAY)
- return false; // ...repeat function kicks in after a short delay
- return true;
- }
+ if (receivedData) { // first we check the boolean flag without a lock, to avoid delays
+
+ LOCK_THREAD;
+
+ if (receivedData) { // need to check again, since the status might have changed while waiting for the lock
+ if (Command)
+ *Command = receivedCommand;
+ if (Repeat)
+ *Repeat = receivedRepeat;
+ if (Release)
+ *Release = receivedRelease;
+ receivedData = false;
+ return true;
}
- lastTime = firstTime = time_ms();
- lastCommand = *Command;
- return true;
}
if (time(NULL) - t > 60) {
SendCommand(code); // in case the PIC listens to the wrong code
@@ -254,6 +305,8 @@ bool cRcIoRCU::Digit(int n, int v)
bool cRcIoRCU::Number(int n, bool Hex)
{
+ LOCK_THREAD;
+
if (!Hex) {
char buf[8];
sprintf(buf, "%4d", n & 0xFFFF);
@@ -275,6 +328,8 @@ bool cRcIoRCU::Number(int n, bool Hex)
bool cRcIoRCU::String(char *s)
{
+ LOCK_THREAD;
+
const char *chars = mode == modeH ? "0123456789ABCDEF" : "0123456789-EHLP ";
int n = 0;
@@ -318,8 +373,11 @@ bool cRcIoRCU::DetectCode(unsigned char *Code, unsigned short *Address)
sprintf(buf, "C0D%c", *Code);
String(buf);
SetCode(*Code, 0);
- unsigned int Command;
- if (GetCommand(&Command, Address)) {
+ delay_ms(REPEATDELAY);
+ receivedData = receivedRepeat = 0;
+ delay_ms(REPEATDELAY);
+ if (GetCommand()) {
+ *Address = receivedAddress;
SetMode(modeB);
String("----");
return true;
@@ -337,77 +395,94 @@ bool cRcIoRCU::DetectCode(unsigned char *Code, unsigned short *Address)
#elif defined REMOTE_LIRC
+#define REPEATLIMIT 20 // ms
+#define REPEATDELAY 350 // ms
+
cRcIoLIRC::cRcIoLIRC(char *DeviceName)
{
- repeat = 1;
+ *keyName = 0;
+ receivedData = receivedRepeat = false;
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, DeviceName);
- int sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock >= 0) {
- if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
- f.Open(sock);
+ if ((f = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
+ if (connect(f, (struct sockaddr *)&addr, sizeof(addr)) >= 0) {
+ Start();
return;
}
LOG_ERROR_STR(DeviceName);
- close(sock);
+ close(f);
}
else
LOG_ERROR_STR(DeviceName);
+ f = -1;
}
cRcIoLIRC::~cRcIoLIRC()
{
+ Stop();
}
-const char *cRcIoLIRC::ReceiveString(void)
+void cRcIoLIRC::Action(void)
{
- int oldrepeat = 1;
-
- if (repeat != 0) {
- Flush();
- if (repeat != 0) {
- oldrepeat = repeat;
- Flush(REPEATLIMIT);
- }
- }
-
- if (repeat == 0) {
- firstTime = time_ms();
- repeat = 1;
- return keyName;
- }
-
- if ((repeat > 1) && (repeat != oldrepeat) && (time_ms() > firstTime + REPEATDELAY)) {
- repeat = 1;
- return keyName;
- }
+ dsyslog(LOG_INFO, "LIRC remote control thread started (pid=%d)", getpid());
- return NULL;
-}
-
-void cRcIoLIRC::Flush(int WaitMs)
-{
+ int FirstTime = 0;
char buf[LIRC_BUFFER_SIZE];
- int t0 = time_ms();
-
- do {
- if (InputAvailable(false) && (read(f, buf, sizeof(buf)) > 21))
- sscanf(buf, "%*x %x %7s", &repeat, keyName); // '7' in '%7s' is LIRC_KEY_BUF-1!
- } while ((repeat != 0) && (time_ms() < t0 + WaitMs));
-}
-
-bool cRcIoLIRC::InputAvailable(bool Wait)
-{
- return f.Ready(Wait);
+ char LastKeyName[LIRC_KEY_BUF];
+
+ for (; f >= 0;) {
+
+ LOCK_THREAD;
+
+ if (cFile::FileReady(f, REPEATLIMIT) && read(f, buf, sizeof(buf)) > 21) {
+ if (!receivedData) { // only accept new data the previous data has been fetched
+ int count;
+ sscanf(buf, "%*x %x %7s", &count, LastKeyName); // '7' in '%7s' is LIRC_KEY_BUF-1!
+ int Now = time_ms();
+ if (count == 0) {
+ strcpy(keyName, LastKeyName);
+ receivedData = true;
+ receivedRepeat = receivedRelease = false;
+ FirstTime = Now;
+ }
+ else {
+ if (Now - FirstTime < REPEATDELAY)
+ continue; // repeat function kicks in after a short delay
+ receivedData = receivedRepeat = true;
+ }
+ WakeUp();
+ }
+ }
+ else if (receivedData) { // the last data before releasing the key hasn't been fetched yet
+ if (receivedRepeat) { // it was a repeat, so let's make it a release
+ receivedRepeat = false;
+ receivedRelease = true;
+ WakeUp();
+ }
+ }
+ else if (receivedRepeat) { // all data has already been fetched, but the last one was a repeat, so let's generate a release
+ receivedData = receivedRelease = true;
+ receivedRepeat = false;
+ WakeUp();
+ }
+ }
}
-bool cRcIoLIRC::GetCommand(unsigned int *Command, unsigned short *)
+bool cRcIoLIRC::GetCommand(unsigned int *Command, bool *Repeat, bool *Release)
{
- if (Command) {
- const char *cmd = ReceiveString();
- if (cmd) {
- *Command = Keys.Encode(cmd);
+ if (receivedData) { // first we check the boolean flag without a lock, to avoid delays
+
+ LOCK_THREAD;
+
+ if (receivedData) { // need to check again, since the status might have changed while waiting for the lock
+ if (Command)
+ *Command = Keys.Encode(keyName);
+ if (Repeat)
+ *Repeat = receivedRepeat;
+ if (Release)
+ *Release = receivedRelease;
+ receivedData = false;
return true;
}
}
diff --git a/remote.h b/remote.h
index 75dc4ac..0ea4442 100644
--- a/remote.h
+++ b/remote.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remote.h 1.10 2000/10/03 10:45:35 kls Exp $
+ * $Id: remote.h 1.13 2000/10/08 12:11:34 kls Exp $
*/
#ifndef __REMOTE_H
@@ -12,26 +12,25 @@
#include <stdio.h>
#include <time.h>
+#include "thread.h"
#include "tools.h"
class cRcIoBase {
protected:
time_t t;
- int firstTime, lastTime;
- unsigned int lastCommand;
cRcIoBase(void);
- virtual ~cRcIoBase();
public:
enum { modeH = 'h', modeB = 'b', modeS = 's' };
+ virtual ~cRcIoBase();
virtual bool SetCode(unsigned char Code, unsigned short Address) { return true; }
virtual bool SetMode(unsigned char Mode) { return true; }
virtual bool Number(int n, bool Hex = false) { return true; }
virtual void SetPoints(unsigned char Dp, bool On) {}
virtual bool String(char *s) { return true; }
virtual bool DetectCode(unsigned char *Code, unsigned short *Address) { return true; }
- virtual void Flush(int WaitMs = 0) = 0;
- virtual bool InputAvailable(bool Wait = false) = 0;
- virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL) = 0;
+ virtual void Flush(int WaitMs = 0) {}
+ virtual bool InputAvailable(void) = 0;
+ virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL) = 0;
};
#if defined REMOTE_KBD
@@ -43,23 +42,27 @@ public:
cRcIoKBD(void);
virtual ~cRcIoKBD();
virtual void Flush(int WaitMs = 0);
- virtual bool InputAvailable(bool Wait = false);
- virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
+ virtual bool InputAvailable(void);
+ virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL);
};
#elif defined REMOTE_RCU
-class cRcIoRCU : public cRcIoBase {
+class cRcIoRCU : public cRcIoBase, private cThread {
private:
- cFile f;
+ int f;
unsigned char dp, code, mode;
unsigned short address;
+ unsigned short receivedAddress;
+ unsigned int receivedCommand;
+ bool receivedData, receivedRepeat, receivedRelease;
int lastNumber;
bool SendCommand(unsigned char Cmd);
- int ReceiveByte(bool Wait = true);
+ int ReceiveByte(int TimeoutMs = 0);
bool SendByteHandshake(unsigned char c);
bool SendByte(unsigned char c);
bool Digit(int n, int v);
+ virtual void Action(void);
public:
cRcIoRCU(char *DeviceName);
virtual ~cRcIoRCU();
@@ -70,25 +73,24 @@ public:
virtual bool String(char *s);
virtual bool DetectCode(unsigned char *Code, unsigned short *Address);
virtual void Flush(int WaitMs = 0);
- virtual bool InputAvailable(bool Wait = false);
- virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
+ virtual bool InputAvailable(void) { return receivedData; }
+ virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL);
};
#elif defined REMOTE_LIRC
-class cRcIoLIRC : public cRcIoBase {
+class cRcIoLIRC : public cRcIoBase, private cThread {
private:
enum { LIRC_KEY_BUF = 8, LIRC_BUFFER_SIZE = 128 };
- cFile f;
+ int f;
char keyName[LIRC_KEY_BUF];
- int repeat;
- const char *ReceiveString(void);
+ bool receivedData, receivedRepeat, receivedRelease;
+ virtual void Action(void);
public:
cRcIoLIRC(char *DeviceName);
virtual ~cRcIoLIRC();
- virtual void Flush(int WaitMs = 0);
- virtual bool InputAvailable(bool Wait = false);
- virtual bool GetCommand(unsigned int *Command, unsigned short *Address = NULL);
+ virtual bool InputAvailable(void) { return receivedData; }
+ virtual bool GetCommand(unsigned int *Command = NULL, bool *Repeat = NULL, bool *Release = NULL);
};
#else
diff --git a/setup.conf b/setup.conf
index e80c2e0..e7ec267 100644
--- a/setup.conf
+++ b/setup.conf
@@ -2,3 +2,6 @@
PrimaryDVB = 1
ShowInfoOnChSwitch = 1
MenuScrollPage = 1
+MarkInstantRecord = 1
+LnbFrequLo = 9750
+LnbFrequHi = 10600
diff --git a/svdrp.c b/svdrp.c
index c9ea7c3..cf91caf 100644
--- a/svdrp.c
+++ b/svdrp.c
@@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection.
*
- * $Id: svdrp.c 1.10 2000/09/17 13:39:37 kls Exp $
+ * $Id: svdrp.c 1.11 2000/10/08 12:21:14 kls Exp $
*/
#define _GNU_SOURCE
@@ -326,7 +326,7 @@ void cSVDRP::CmdCHAN(const char *Option)
Reply(501, "Undefined channel \"%s\"", Option);
return;
}
- if (Interface.Recording()) {
+ if (Interface->Recording()) {
Reply(550, "Can't switch channel, interface is recording");
return;
}
@@ -474,7 +474,7 @@ void cSVDRP::CmdHITK(const char *Option)
if (*Option) {
eKeys k = Keys.Translate(Option);
if (k != kNone) {
- Interface.PutKey(k);
+ Interface->PutKey(k);
Reply(250, "Key \"%s\" accepted", Option);
}
else
diff --git a/thread.c b/thread.c
new file mode 100644
index 0000000..7304e68
--- /dev/null
+++ b/thread.c
@@ -0,0 +1,105 @@
+/*
+ * thread.c: A simple thread base class
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: thread.c 1.2 2000/10/08 16:45:50 kls Exp $
+ */
+
+#include "thread.h"
+#include <signal.h>
+#include <unistd.h>
+
+// --- cThread ---------------------------------------------------------------
+
+// The signal handler is necessary to be able to use SIGIO to wake up any
+// pending 'select()' call.
+
+bool cThread::signalHandlerInstalled = false;
+
+cThread::cThread(void)
+{
+ if (!signalHandlerInstalled) {
+ signal(SIGIO, SignalHandler);
+ signalHandlerInstalled = true;
+ }
+ pthread_mutex_init(&mutex, NULL);
+ running = false;
+ parentPid = lockingPid = 0;
+ locked = 0;
+}
+
+cThread::~cThread()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void cThread::SignalHandler(int signum)
+{
+ signal(signum, SignalHandler);
+}
+
+void *cThread::StartThread(cThread *Thread)
+{
+ Thread->Action();
+ return NULL;
+}
+
+bool cThread::Start(void)
+{
+ if (!running) {
+ running = true;
+ parentPid = getpid();
+ pthread_create(&thread, NULL, &StartThread, (void *)this);
+ }
+ return true; //XXX return value of pthread_create()???
+}
+
+void cThread::Stop(void)
+{
+ pthread_cancel(thread);
+}
+
+bool cThread::Lock(void)
+{
+ if (!lockingPid || lockingPid != getpid()) {
+ pthread_mutex_lock(&mutex);
+ lockingPid = getpid();
+ }
+ locked++;
+ return true;
+}
+
+void cThread::Unlock(void)
+{
+ if (!--locked) {
+ lockingPid = 0;
+ pthread_mutex_unlock(&mutex);
+ }
+}
+
+void cThread::WakeUp(void)
+{
+ kill(parentPid, SIGIO); // makes any waiting 'select()' call return immediately
+}
+
+// --- cThreadLock -----------------------------------------------------------
+
+cThreadLock::cThreadLock(cThread *Thread)
+{
+ thread = Thread;
+ locked = Thread->Lock();
+}
+
+cThreadLock::~cThreadLock()
+{
+ if (locked)
+ thread->Unlock();
+}
+
+bool cThreadLock::Locked(void)
+{
+ return locked;
+}
+
diff --git a/thread.h b/thread.h
new file mode 100644
index 0000000..86b9e92
--- /dev/null
+++ b/thread.h
@@ -0,0 +1,57 @@
+/*
+ * thread.h: A simple thread base class
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: thread.h 1.1 2000/10/08 08:36:21 kls Exp $
+ */
+
+#ifndef __THREAD_H
+#define __THREAD_H
+
+#include <pthread.h>
+#include <sys/types.h>
+
+class cThread {
+ friend class cThreadLock;
+private:
+ pthread_t thread;
+ pthread_mutex_t mutex;
+ pid_t parentPid, lockingPid;
+ int locked;
+ bool running;
+ static bool signalHandlerInstalled;
+ static void SignalHandler(int signum);
+ static void *StartThread(cThread *Thread);
+ bool Lock(void);
+ void Unlock(void);
+protected:
+ void WakeUp(void);
+ virtual void Action(void) = 0;
+ void Stop(void);
+public:
+ cThread(void);
+ virtual ~cThread();
+ bool Start(void);
+ };
+
+// cThreadLock can be used to easily set a lock in a thread and make absolutely
+// sure that it will be unlocked when the block will be left. Several locks can
+// be stacked, so a function that makes many calls to another function which uses
+// cThreadLock may itself use a cThreadLock to make one longer lock instead of many
+// short ones.
+
+class cThreadLock {
+private:
+ cThread *thread;
+ bool locked;
+public:
+ cThreadLock(cThread *Thread);
+ ~cThreadLock();
+ bool Locked(void);
+ };
+
+#define LOCK_THREAD cThreadLock ThreadLock(this)
+
+#endif //__THREAD_H
diff --git a/timers.conf b/timers.conf
index 2a58454..fc0e12a 100644
--- a/timers.conf
+++ b/timers.conf
@@ -1,16 +1,16 @@
1:15:M------:2128:2205:99:7:Neues:
1:3:-T-----:2013:2125:99:99:SevenDays:
1:10:-T-----:2058:2202:99:10:Quarks:
-1:26:-T-----:2235:2345:99:99:UFO:
+1:26:-T-----:2320:0040:99:99:UFO:
+1:14:--W----:1920:2020:99:99:Rettungsflieger:
1:2:--W----:2110:2325:99:99:BulleVonToelz:
1:3:---T---:2210:2315:99:10:IngoAppelt:
-1:2:----F--:2140:2225:10:10:WWW:
+0:2:----F--:2140:2225:10:10:WWW:
1:1:----F--:2212:2325:99:99:7Tage7Koepfe:
1:11:-----S-:2058:2135:99:99:Computer:
1:2:-----S-:2211:2340:99:30:Wochenshow:
1:11:------S:2013:2035:99:10:Centauri:
1:14:------S:2158:2235:99:14:MaxUndLisa:
-0:15:MTWTF--:1828:1901:10:5:nano:
+1:15:MTWTF--:1828:1901:10:5:nano:
1:1:-TWTF--:0955:1040:99:99:Ellen:
-0:1:MTWTF--:1553:1710:99:99:Hammerman:
-1:1:4:0755:0910:99:99:Hammerman:
+1:1:MTWTF--:1553:1710:99:99:Hammerman:
diff --git a/tools.c b/tools.c
index 5bb56e6..fc15a98 100644
--- a/tools.c
+++ b/tools.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.c 1.20 2000/09/29 16:19:28 kls Exp $
+ * $Id: tools.c 1.21 2000/10/07 18:02:24 kls Exp $
*/
#define _GNU_SOURCE
@@ -393,6 +393,22 @@ bool cFile::AnyFileReady(int FileDes, int TimeoutMs)
return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && (FileDes < 0 || FD_ISSET(FileDes, &set));
}
+bool cFile::FileReady(int FileDes, int TimeoutMs)
+{
+#ifdef DEBUG_OSD
+ refresh();
+#endif
+ fd_set set;
+ struct timeval timeout;
+ FD_ZERO(&set);
+ FD_SET(FileDes, &set);
+ if (TimeoutMs < 100)
+ TimeoutMs = 100;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = TimeoutMs * 1000;
+ return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && FD_ISSET(FileDes, &set);
+}
+
// --- cListObject -----------------------------------------------------------
cListObject::cListObject(void)
diff --git a/tools.h b/tools.h
index 441f571..17b643f 100644
--- a/tools.h
+++ b/tools.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: tools.h 1.16 2000/09/29 16:19:31 kls Exp $
+ * $Id: tools.h 1.17 2000/10/07 18:00:21 kls Exp $
*/
#ifndef __TOOLS_H
@@ -68,6 +68,7 @@ public:
int ReadString(char *Buffer, int Size);
bool Ready(bool Wait = true);
static bool AnyFileReady(int FileDes = -1, int TimeoutMs = 1000);
+ static bool FileReady(int FileDes, int TimeoutMs = 1000);
};
class cListObject {
diff --git a/vdr.c b/vdr.c
index 042b03c..c8cabb0 100644
--- a/vdr.c
+++ b/vdr.c
@@ -22,7 +22,7 @@
*
* The project's page is at http://www.cadsoft.de/people/kls/vdr
*
- * $Id: vdr.c 1.36 2000/10/03 13:52:26 kls Exp $
+ * $Id: vdr.c 1.39 2000/10/08 14:49:25 kls Exp $
*/
#include <getopt.h>
@@ -161,6 +161,10 @@ int main(int argc, char *argv[])
if (!cDvbApi::Init())
abort();
+ // User interface:
+
+ Interface = new cInterface(SVDRPport);
+
// Configuration data:
if (!ConfigDirectory)
@@ -173,9 +177,8 @@ int main(int argc, char *argv[])
Keys.SetDummyValues();
#else
if (!Keys.Load(AddDirectory(ConfigDirectory, KEYS_CONF)))
- Interface.LearnKeys();
+ Interface->LearnKeys();
#endif
- Interface.Init(SVDRPport);
cDvbApi::SetPrimaryDvbApi(Setup.PrimaryDVB);
@@ -215,7 +218,7 @@ int main(int argc, char *argv[])
}
// User Input:
cOsdBase **Interact = Menu ? &Menu : (cOsdBase **)&ReplayControl;
- eKeys key = Interface.GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
+ eKeys key = Interface->GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
if (*Interact) {
switch ((*Interact)->ProcessKey(key)) {
case osMenu: DELETENULL(Menu);
@@ -223,7 +226,12 @@ int main(int argc, char *argv[])
break;
case osRecord: DELETENULL(Menu);
if (!cRecordControls::Start())
- Interface.Error("No free DVB device to record!");
+ Interface->Error("No free DVB device to record!");
+ break;
+ case osRecordings:
+ DELETENULL(Menu);
+ DELETENULL(ReplayControl);
+ Menu = new cMenuRecordings;
break;
case osReplay: DELETENULL(Menu);
DELETENULL(ReplayControl);
@@ -235,7 +243,7 @@ int main(int argc, char *argv[])
break;
case osSwitchDvb:
DELETENULL(*Interact);
- Interface.Info("Switching primary DVB...");
+ Interface->Info("Switching primary DVB...");
cDvbApi::SetPrimaryDvbApi(Setup.PrimaryDVB);
break;
case osBack:
@@ -253,14 +261,16 @@ int main(int argc, char *argv[])
break;
// Direct Channel Select:
case k1 ... k9:
- if (!Interface.Recording())
+ if (!Interface->Recording())
Menu = new cDirectChannelSelect(key);
break;
// Left/Right rotates trough channel groups:
+ case kLeft|k_Repeat:
case kLeft:
- case kRight: if (!Interface.Recording()) {
+ case kRight|k_Repeat:
+ case kRight: if (!Interface->Recording()) {
int SaveGroup = CurrentGroup;
- if (key == kRight)
+ if (NORMALKEY(key) == kRight)
CurrentGroup = Channels.GetNextGroup(CurrentGroup) ;
else
CurrentGroup = Channels.GetPrevGroup(CurrentGroup < 1 ? 1 : CurrentGroup);
@@ -271,9 +281,11 @@ int main(int argc, char *argv[])
}
break;
// Up/Down Channel Select:
+ case kUp|k_Repeat:
case kUp:
- case kDown: if (!Interface.Recording()) {
- int n = CurrentChannel + (key == kUp ? 1 : -1);
+ case kDown|k_Repeat:
+ case kDown: if (!Interface->Recording()) {
+ int n = CurrentChannel + (NORMALKEY(key) == kUp ? 1 : -1);
cChannel *channel = Channels.GetByNumber(n);
if (channel)
channel->Switch();
@@ -290,7 +302,7 @@ int main(int argc, char *argv[])
isyslog(LOG_INFO, "caught signal %d", Interrupted);
delete Menu;
delete ReplayControl;
- Interface.Cleanup();
+ delete Interface;
cDvbApi::Cleanup();
isyslog(LOG_INFO, "exiting");
if (SysLogLevel > 0)