summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <kls (at) cadsoft (dot) de>2002-10-27 17:00:00 +0100
committerKlaus Schmidinger <kls (at) cadsoft (dot) de>2002-10-27 17:00:00 +0100
commit57bd7eeed1c1aa84316f8299e1528b3bc63d7623 (patch)
tree6c523eb1727d488fabbf860db21dbcd39a7f9d97
parentcd7ccd64fd51b77b8b75b6e85ef6891b1917aa59 (diff)
downloadvdr-patch-lnbsharing-57bd7eeed1c1aa84316f8299e1528b3bc63d7623.tar.gz
vdr-patch-lnbsharing-57bd7eeed1c1aa84316f8299e1528b3bc63d7623.tar.bz2
Version 1.1.14vdr-1.1.14
- Fixed some faulty default parameter initializations (thanks to Robert Schiele). - Added further satellites to 'sources.conf' (thanks to Reinhard Walter Buchner and Oliver Endriss). - Updated Finnish OSD texts (thanks to Jaakko Hyvätti). - Fixed a small glitch when switching channels (thanks to Dennis Noordsij for reporting this one). - Fixed handling multiple 'CaCaps' entries in 'setup.conf'. - Group separators in 'channels.conf' may now be given like ':@201 My Channels', where '@201' indicates the number to be given to the next channel. This can be used to create 'gaps' in the channel numbering (see 'man 5 vdr'). BE CAREFUL TO UPDATE YOUR 'timers.conf' ACCORDINGLY IF INSERTING THIS NEW FEATURE INTO YOUR 'channels.conf' FILE! - Timers now internally have a pointer to their channel (this is necessary to handle gaps in channel numbers, and in preparation for unique channel ids). - Fixed slow reaction on SVDRP input (thanks to Guido Fiala for reporting this one). - Added KI.KA to channels.conf.cable (thanks to Robert Schiele). - Frequency values for cable and terrestrial channels in 'channels.conf' can now be given either in MHz, kHz or Hz. The actual value given will be multiplied by 1000 until it is larger than 1000000. - Fixed skipping unavailable channels when zapping downwards. - Fixed checking the Ca() status of a cDevice (thanks to Stefan Huelswitt). - Fixed switching audio tracks in 'Transfer Mode' on the primary DVB device (thanks to Steffen Barszus and Stefan Huelswitt for reporting this one and helping to fix it). - Fixed channel switching in case of an active 'Transfer Mode' on the primary device ('Transfer Mode' is now launched with priority '-1'). - Fixed a ternary expression in dvbspu.c. - Fixed handling 'Transfer Mode' on single device systems when recording an encrypted channel (thanks to Stefan Huelswitt). - Fixed blocking replaying in case an encrypted channel is being recorded on the primary device. - Now the name of the remote control is displayed when learning the keys. - Fixed learning remote control keys in case there is more than one remote control (thanks to Oliver Endriss for reporting this one). - Implemented additional dedicated keys for "Play", "Pause", "Stop", "Record", "FastFwd", "FastRew", "Channel+" and "Channel-". If your remote control supports any of these keys you can delete your 'remote.conf' file and restart VDR to go through the key learning procedure again in order to assign these new keys. See MANUAL for more information. Authors of player plugins should update their ProcessKey() functions so that the new player keys have the same functionality as the "Up", "Down", "Left", "Right" and "Blue" keys, respectively. Note that the existing functionality of these keys should by all means be retained, since VDR (and any plugins) shall be fully usable with just the basic set of keys. These new keys are only for additional comfort in case the remote control in use supports them. - Implemented new keys to directly access the VDR main menu functions "Schedule", "Channels", "Timers", "Recordings", "Setup" and "Commands". If your remote control provides keys you want to assign these functions to, you can delete your 'remote.cof' file and restart VDR to go through the key learning procedure again in order to assign these new keys. See MANUAL for more information. - The new configuration file 'keymacros.conf' can be used to assign macros to the color buttons in normal viewing mode, as well as to up to 9 user defined keys. See MANUAL and man vdr(5) for more information. The default 'keymacros.conf' implements the functionality of the "color button patch". - Fixed a crash when learning the keys of several remote controls and pressing buttons of those that have already been learned (thanks to Oliver Endriss for reporting this one).
-rw-r--r--CONTRIBUTORS20
-rw-r--r--HISTORY60
-rw-r--r--MANUAL32
-rw-r--r--Makefile4
-rw-r--r--PLUGINS.html32
-rw-r--r--PLUGINS/SRC/hello/HISTORY4
-rw-r--r--PLUGINS/SRC/hello/hello.c6
-rw-r--r--PLUGINS/SRC/status/HISTORY4
-rw-r--r--PLUGINS/SRC/status/status.c6
-rw-r--r--channels.c79
-rw-r--r--channels.conf9
-rw-r--r--channels.conf.cable1
-rw-r--r--channels.h5
-rw-r--r--config.c386
-rw-r--r--config.h65
-rw-r--r--device.c29
-rw-r--r--device.h9
-rw-r--r--dvbdevice.c41
-rw-r--r--dvbdevice.h3
-rw-r--r--dvbplayer.c4
-rw-r--r--dvbspu.c4
-rw-r--r--eitscan.c6
-rw-r--r--i18n.c190
-rw-r--r--interface.c64
-rw-r--r--keymacros.conf11
-rw-r--r--keys.c127
-rw-r--r--keys.h42
-rw-r--r--menu.c283
-rw-r--r--menu.h3
-rwxr-xr-xnewplugin4
-rw-r--r--recording.c20
-rw-r--r--recording.h3
-rw-r--r--remote.c18
-rw-r--r--remote.h5
-rw-r--r--sources.conf78
-rw-r--r--svdrp.c39
-rw-r--r--svdrp.h4
-rw-r--r--timers.c408
-rw-r--r--timers.h91
-rw-r--r--tools.c9
-rw-r--r--tools.h3
-rw-r--r--transfer.c6
-rw-r--r--vdr.534
-rw-r--r--vdr.c194
44 files changed, 1536 insertions, 909 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index 33d89d7..7b75ac8 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -31,6 +31,7 @@ Guido Fiala <gfiala@s.netic.de>
(overlay capabilities have been removed again in VDR 0.98, since kvdr version 0.4
now does these things itself)
for making the replay progress display avoid unnecessary code execution
+ for reporting a problem with slow reaction on SVDRP input
Robert Schneider <Robert.Schneider@de.ibm.com>
for implementing EIT support for displaying the current/next info
@@ -153,6 +154,10 @@ Stefan Huelswitt <huels@iname.com>
be switched or has actually been switched successfully
for adding a missing StripAudioPackets() to cDvbPlayer::Action()
for improving skipping channels that are (currently) not available
+ for fixing checking the Ca() status of a cDevice
+ for helping to fix switching audio tracks in 'Transfer Mode' on the primary DVB device
+ for fixing handling 'Transfer Mode' on single device systems when recording an
+ encrypted channel
Ulrich Röder <roeder@efr-net.de>
for pointing out that there are channels that have a symbol rate higher than
@@ -416,6 +421,11 @@ Oliver Endriss <o.endriss@gmx.de>
for reporting a bug when pressing the "Blue" button in the main menu without
having displayed it
for helping to debug a crash when closing down with remote control plugins
+ for adding some satellites to 'sources.conf'
+ for reporting a bug in learning remote control keys in case there is more than
+ one remote control
+ for reporting a crash when learning the keys of several remote controls and
+ pressing buttons of those that have already been learned
Reinhard Walter Buchner <rw.buchner@freenet.de>
for adding some satellites to 'sources.conf'
@@ -428,9 +438,19 @@ Andy Carter <fruit@ukgateway.net>
Robert Schiele <rschiele@uni-mannheim.de>
for his help in keeping 'channels.conf.cable' up to date
+ for reporting some faulty default parameter initializations
Gerhard Steiner <steiner@mail.austria.com>
for suggesting that the SVDRP command PUTE shall trigger an immediate write of
the 'epg.data' file
for suggesting the new configuration file 'reccmds.conf' to define commands that
shall be executed from the "Recordings" menu
+
+Jaakko Hyvätti <jaakko@hyvatti.iki.fi>
+ for translating OSD texts to the Finnish language
+
+Dennis Noordsij <dennis.noordsij@wiral.com>
+ for reporting a small glitch when switching channels
+
+Steffen Barszus <st_barszus@gmx.de>
+ for reporting a bug in switching audio tracks in 'Transfer Mode' on the primary DVB device
diff --git a/HISTORY b/HISTORY
index 37afb35..536ea28 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1610,3 +1610,63 @@ Video Disk Recorder Revision History
- The new configuration file 'reccmds.conf' can be used to define commands that
shall be executed from the "Recordings" menu; see MANUAL and 'man vdr(5)' for
details (suggested by Gerhard Steiner).
+
+2002-10-27: Version 1.1.14
+
+- Fixed some faulty default parameter initializations (thanks to Robert Schiele).
+- Added further satellites to 'sources.conf' (thanks to Reinhard Walter Buchner
+ and Oliver Endriss).
+- Updated Finnish OSD texts (thanks to Jaakko Hyvätti).
+- Fixed a small glitch when switching channels (thanks to Dennis Noordsij for
+ reporting this one).
+- Fixed handling multiple 'CaCaps' entries in 'setup.conf'.
+- Group separators in 'channels.conf' may now be given like ':@201 My Channels',
+ where '@201' indicates the number to be given to the next channel. This can be
+ used to create 'gaps' in the channel numbering (see 'man 5 vdr'). BE CAREFUL
+ TO UPDATE YOUR 'timers.conf' ACCORDINGLY IF INSERTING THIS NEW FEATURE INTO YOUR
+ 'channels.conf' FILE!
+- Timers now internally have a pointer to their channel (this is necessary to
+ handle gaps in channel numbers, and in preparation for unique channel ids).
+- Fixed slow reaction on SVDRP input (thanks to Guido Fiala for reporting this one).
+- Added KI.KA to channels.conf.cable (thanks to Robert Schiele).
+- Frequency values for cable and terrestrial channels in 'channels.conf' can
+ now be given either in MHz, kHz or Hz. The actual value given will be multiplied
+ by 1000 until it is larger than 1000000.
+- Fixed skipping unavailable channels when zapping downwards.
+- Fixed checking the Ca() status of a cDevice (thanks to Stefan Huelswitt).
+- Fixed switching audio tracks in 'Transfer Mode' on the primary DVB device
+ (thanks to Steffen Barszus and Stefan Huelswitt for reporting this one and
+ helping to fix it).
+- Fixed channel switching in case of an active 'Transfer Mode' on the primary
+ device ('Transfer Mode' is now launched with priority '-1').
+- Fixed a ternary expression in dvbspu.c.
+- Fixed handling 'Transfer Mode' on single device systems when recording an
+ encrypted channel (thanks to Stefan Huelswitt).
+- Fixed blocking replaying in case an encrypted channel is being recorded on
+ the primary device.
+- Now the name of the remote control is displayed when learning the keys.
+- Fixed learning remote control keys in case there is more than one remote
+ control (thanks to Oliver Endriss for reporting this one).
+- Implemented additional dedicated keys for "Play", "Pause", "Stop", "Record",
+ "FastFwd", "FastRew", "Channel+" and "Channel-". If your remote control supports
+ any of these keys you can delete your 'remote.conf' file and restart VDR to
+ go through the key learning procedure again in order to assign these new keys.
+ See MANUAL for more information.
+ Authors of player plugins should update their ProcessKey() functions so that
+ the new player keys have the same functionality as the "Up", "Down", "Left",
+ "Right" and "Blue" keys, respectively. Note that the existing functionality
+ of these keys should by all means be retained, since VDR (and any plugins)
+ shall be fully usable with just the basic set of keys. These new keys are only
+ for additional comfort in case the remote control in use supports them.
+- Implemented new keys to directly access the VDR main menu functions "Schedule",
+ "Channels", "Timers", "Recordings", "Setup" and "Commands". If your remote
+ control provides keys you want to assign these functions to, you can delete
+ your 'remote.cof' file and restart VDR to go through the key learning procedure
+ again in order to assign these new keys. See MANUAL for more information.
+- The new configuration file 'keymacros.conf' can be used to assign macros to
+ the color buttons in normal viewing mode, as well as to up to 9 user defined
+ keys. See MANUAL and man vdr(5) for more information. The default 'keymacros.conf'
+ implements the functionality of the "color button patch".
+- Fixed a crash when learning the keys of several remote controls and pressing
+ buttons of those that have already been learned (thanks to Oliver Endriss for
+ reporting this one).
diff --git a/MANUAL b/MANUAL
index 79e80d0..3c0504e 100644
--- a/MANUAL
+++ b/MANUAL
@@ -23,10 +23,34 @@ Video Disk Recorder User's Manual
Blue - Stop/Resume Mark On/Off(1) - Summary Stop
0..9 Ch select - - - Numeric inp. Exec cmd(2) Editing
- Power Shutdown
- Volume+ Volume up
- Volume- Volume down
- Mute Mute
+ If your remote control provides additional keys, they can be used for the
+ following functions:
+
+ Play resume normal replay
+ Pause pause replay
+ Stop stop replay
+ Record instant recording
+ FastFwd fast forward
+ FastRew fast rewind
+
+ Channel+ channel up
+ Channel- channel down
+
+ Power shutdown
+
+ Volume+ volume up
+ Volume- volume down
+ Mute mute
+
+ Schedule \
+ Channels |
+ Timers | directly access the VDR
+ Recordings | main menu functions
+ Setup |
+ Commands /
+
+ User1...9 additional user defined keys for macro functions
+ (defined in 'keymacros.conf')
(1) The "On/Off" button in the "Timers" menu only works if sorting the timers
has been enabled in the "Setup" menu. Otherwise the Blue button is used
diff --git a/Makefile b/Makefile
index cfb6f3a..6b88356 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: Makefile 1.48 2002/10/04 14:29:14 kls Exp $
+# $Id: Makefile 1.49 2002/10/19 15:46:08 kls Exp $
.DELETE_ON_ERROR:
@@ -36,7 +36,7 @@ OBJS = audio.o channels.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd
dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o interface.o keys.o\
lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o\
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sources.o\
- spu.o status.o svdrp.o thread.o tools.o transfer.o vdr.o videodir.o
+ spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
diff --git a/PLUGINS.html b/PLUGINS.html
index 5cec857..3a26783 100644
--- a/PLUGINS.html
+++ b/PLUGINS.html
@@ -21,18 +21,18 @@ VDR program and present itself to the user.
The <i>inside</i> interface provides the plugin code access to VDR's internal data
structures and allows it to hook itself into specific areas to perform special actions.
<p>
-<!--X1.1.9--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
-Important modifications introduced in version 1.1.9 are marked like this.
-<!--X1.1.9--></td></tr></table>
-<!--X1.1.11--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
+<!--X1.1.11--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.11 are marked like this.
<!--X1.1.11--></td></tr></table>
-<!--X1.1.12--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
+<!--X1.1.12--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.12 are marked like this.
<!--X1.1.12--></td></tr></table>
-<!--X1.1.13--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<!--X1.1.13--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.1.13 are marked like this.
<!--X1.1.13--></td></tr></table>
+<!--X1.1.14--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+Important modifications introduced in version 1.1.14 are marked like this.
+<!--X1.1.14--></td></tr></table>
<a name="Part I - The Outside Interface"><hr><center><h1>Part I - The Outside Interface</h1></center>
@@ -964,7 +964,7 @@ bool DevicePoll(cPoller &amp;Poller, int TimeoutMs = 0);
</pre></td></tr></table><p>
to determine whether the device is ready for further data.
-<!--X1.1.13--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<!--X1.1.13--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<p>
If the player can provide more than a single audio track, it can implement the
following functions to make them available:
@@ -1064,11 +1064,12 @@ consider here are
<i>Play</i>, <i>Pause</i>, <i>Fast Rewind</i> and <i>Fast Forward</i>, respectively
(provided that this particular player can implement these functions) if the player
is not currently showing any menu. If there is a menu, they shall allow the user
- to navigate in the menu.
+ to navigate in the menu. The dedicated <i>Play</i>, <i>Pause</i>, <i>FastRew</i>
+ and <i>FastFwd</i> keys shall always result in their specific functionality.
<li>The <i>Green</i> and <i>Yellow</i> buttons shall skip back- and forward by an
amount of time suitable for this player (provided that this particular player can
implement these functions).
-<li>The <i>Blue</i> button shall immediately stop the replay session.
+<li>The <i>Blue</i> and <i>Stop</i> button shall immediately stop the replay session.
</ul>
Of course, these are only suggestions which should make it easier for VDR users to
enjoy additional players, since they will be able to control them with actions
@@ -1194,9 +1195,8 @@ the <tt>cDvbDevice</tt>, which is used to access the DVB PCI cards.
If the new device can receive, it most likely needs to provide a way of
selecting which channel it shall tune to:
-<!--X1.1.9--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
-<!--X1.1.12--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
+<!--X1.1.12--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
virtual bool ProvidesSource(int Source) const;
<!--X1.1.12--></td></tr></table>
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
@@ -1206,8 +1206,7 @@ virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
These functions will be called with the desired source or channel and shall return whether
this device can provide the requested source or channel and whether tuning to it was successful,
repectively.
-<!--X1.1.9--></td></tr></table>
-<!--X1.1.13--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+<!--X1.1.13--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<p>
<b>Audio selection</b>
<p>
@@ -1230,9 +1229,7 @@ A device that can be used for recording must implement the functions
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
virtual bool OpenDvr(void);
virtual void CloseDvr(void);
-<!--X1.1.9--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
virtual bool GetTSPacket(uchar *&amp;Data);
-<!--X1.1.9--></td></tr></table>
</pre></td></tr></table><p>
which allow VDR to set the PIDs that shall be recorded, set up the device for
@@ -1256,6 +1253,9 @@ The functions to implement replaying capabilites are
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
virtual bool HasDecoder(void) const;
+<!--X1.1.14--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
+virtual bool CanReplay(void) const;
+<!--X1.1.14--></td></tr></table>
virtual bool SetPlayMode(ePlayMode PlayMode);
virtual void TrickSpeed(int Speed);
virtual void Clear(void);
@@ -1315,7 +1315,7 @@ shut down (delete) all devices when the program terminates. It is therefore
important that the devices are created on the heap, using the <tt>new</tt>
operator!
-<!--X1.1.11--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
+<!--X1.1.11--><table width=100%><tr><td bgcolor=#0000AA>&nbsp;</td><td width=100%>
<hr><h2>Remote Control</h2>
<center><i><b>The joy of zapping!</b></i></center><p>
diff --git a/PLUGINS/SRC/hello/HISTORY b/PLUGINS/SRC/hello/HISTORY
index 3507baf..10d905e 100644
--- a/PLUGINS/SRC/hello/HISTORY
+++ b/PLUGINS/SRC/hello/HISTORY
@@ -26,3 +26,7 @@ VDR Plugin 'hello' Revision History
2002-09-21: Version 0.0.6
- Fixed Makefile for NEWSTRUCT driver.
+
+2002-10-26: Version 0.0.7
+
+- Fixed a typo.
diff --git a/PLUGINS/SRC/hello/hello.c b/PLUGINS/SRC/hello/hello.c
index 3d1b22f..5073e30 100644
--- a/PLUGINS/SRC/hello/hello.c
+++ b/PLUGINS/SRC/hello/hello.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: hello.c 1.7 2002/09/21 08:44:56 kls Exp $
+ * $Id: hello.c 1.8 2002/10/26 14:34:48 kls Exp $
*/
#include <getopt.h>
@@ -12,7 +12,7 @@
#include <vdr/plugin.h>
#include "i18n.h"
-static const char *VERSION = "0.0.6";
+static const char *VERSION = "0.0.7";
static const char *DESCRIPTION = "A friendly greeting";
static const char *MAINMENUENTRY = "Hello";
@@ -71,7 +71,7 @@ void cMenuSetupHello::Store(void)
cPluginHello::cPluginHello(void)
{
- // Initialize any member varaiables here.
+ // Initialize any member variables here.
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
option_a = NULL;
diff --git a/PLUGINS/SRC/status/HISTORY b/PLUGINS/SRC/status/HISTORY
index f8e5297..b66f654 100644
--- a/PLUGINS/SRC/status/HISTORY
+++ b/PLUGINS/SRC/status/HISTORY
@@ -12,3 +12,7 @@ VDR Plugin 'status' Revision History
2002-09-21: Version 0.0.3
- Fixed Makefile for NEWSTRUCT driver.
+
+2002-10-26: Version 0.0.4
+
+- Fixed a typo.
diff --git a/PLUGINS/SRC/status/status.c b/PLUGINS/SRC/status/status.c
index 5624936..15a3ee9 100644
--- a/PLUGINS/SRC/status/status.c
+++ b/PLUGINS/SRC/status/status.c
@@ -3,13 +3,13 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: status.c 1.3 2002/09/21 08:46:01 kls Exp $
+ * $Id: status.c 1.4 2002/10/26 14:34:53 kls Exp $
*/
#include <vdr/plugin.h>
#include <vdr/status.h>
-static const char *VERSION = "0.0.3";
+static const char *VERSION = "0.0.4";
static const char *DESCRIPTION = "Status monitor test";
static const char *MAINMENUENTRY = NULL;
@@ -122,7 +122,7 @@ public:
cPluginStatus::cPluginStatus(void)
{
- // Initialize any member varaiables here.
+ // Initialize any member variables here.
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
statusTest = NULL;
diff --git a/channels.c b/channels.c
index f86f8ef..e142a28 100644
--- a/channels.c
+++ b/channels.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.c 1.3 2002/10/06 12:41:49 kls Exp $
+ * $Id: channels.c 1.5 2002/10/20 11:50:47 kls Exp $
*/
#include "channels.h"
@@ -158,6 +158,7 @@ cChannel::cChannel(void)
tpid = 0;
ca = 0;
sid = 0;
+ number = 0;
groupSep = false;
//XXX
polarization = 'v';
@@ -282,8 +283,12 @@ const char *cChannel::ToText(cChannel *Channel)
strreplace(s, ':', '|');
}
free(buffer);
- if (Channel->groupSep)
- asprintf(&buffer, ":%s\n", s);
+ if (Channel->groupSep) {
+ if (Channel->number)
+ asprintf(&buffer, ":@%d %s\n", Channel->number, s);
+ else
+ asprintf(&buffer, ":%s\n", s);
+ }
else {
char apidbuf[32];
char *q = apidbuf;
@@ -308,13 +313,17 @@ const char *cChannel::ToText(void)
bool cChannel::Parse(const char *s)
{
if (*s == ':') {
- if (*++s) {
- strn0cpy(name, s, MaxChannelName);
- groupSep = true;
- number = 0;
+ groupSep = true;
+ if (*++s == '@' && *++s) {
+ char *p = NULL;
+ errno = 0;
+ int n = strtol(s, &p, 10);
+ if (!errno && p != s && n > 0) {
+ number = n;
+ s = p;
+ }
}
- else
- return false;
+ strn0cpy(name, skipspace(s), MaxChannelName);
}
else {
groupSep = false;
@@ -400,35 +409,39 @@ int cChannels::GetNextNormal(int Idx)
void cChannels::ReNumber( void )
{
- int Number = 0;
- cChannel *ch = (cChannel *)First();
- while (ch) {
- if (!ch->GroupSep())
- ch->SetNumber(++Number);
- ch = (cChannel *)ch->Next();
- }
- maxNumber = Number;
+ int Number = 1;
+ for (cChannel *channel = First(); channel; channel = Next(channel)) {
+ if (channel->GroupSep()) {
+ if (channel->Number() > Number)
+ Number = channel->Number();
+ }
+ else
+ channel->SetNumber(Number++);
+ }
+ maxNumber = Number - 1;
}
-cChannel *cChannels::GetByNumber(int Number)
+cChannel *cChannels::GetByNumber(int Number, int SkipGap)
{
- cChannel *channel = (cChannel *)First();
- while (channel) {
- if (!channel->GroupSep() && channel->Number() == Number)
- return channel;
- channel = (cChannel *)channel->Next();
- }
+ cChannel *previous = NULL;
+ for (cChannel *channel = First(); channel; channel = Next(channel)) {
+ if (!channel->GroupSep()) {
+ if (channel->Number() == Number)
+ return channel;
+ else if (SkipGap && channel->Number() > Number)
+ return SkipGap > 0 ? channel : previous;
+ previous = channel;
+ }
+ }
return NULL;
}
cChannel *cChannels::GetByServiceID(unsigned short ServiceId)
{
- cChannel *channel = (cChannel *)First();
- while (channel) {
- if (!channel->GroupSep() && channel->Sid() == ServiceId)
- return channel;
- channel = (cChannel *)channel->Next();
- }
+ for (cChannel *channel = First(); channel; channel = Next(channel)) {
+ if (!channel->GroupSep() && channel->Sid() == ServiceId)
+ return channel;
+ }
return NULL;
}
@@ -437,9 +450,3 @@ bool cChannels::SwitchTo(int Number)
cChannel *channel = GetByNumber(Number);
return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
}
-
-const char *cChannels::GetChannelNameByNumber(int Number)
-{
- cChannel *channel = GetByNumber(Number);
- return channel ? channel->Name() : NULL;
-}
diff --git a/channels.conf b/channels.conf
index 9288c40..da014a8 100644
--- a/channels.conf
+++ b/channels.conf
@@ -181,11 +181,6 @@ ORF/ZDF:12699:h:S19.2E:22000:506:507:0:0:13012
VIVA:12670:v:S19.2E:22000:309:310:0:0:12732
VIVA2:12552:v:S19.2E:22000:171:172:0:0:12120
MTV German:12699:v:S19.2E:22000:3031:3032:0:0:28643
-IFA-TV:10832:h:S19.2E:22000:132:133:32:0:7251
+:#IFA-TV:10832:h:S19.2E:22000:132:133:32:0:7251
QVC Germany:12552:v:S19.2E:22000:165:166:0:0:12100
-TANGOTV:10832:h:S19.2E:22000:61:62:0:0:61920
-:Sky
-Sky One:0:h:S28.2E:0:160:80:0:5:106
-itv2:0:h:S28.2E:0:160:80:0:5:226
-sci-fi:0:h:S28.2E:0:160:80:0:5:130
-Paramount Comedy:0:h:S28.2E:0:160:80:0:5:127
+:#TANGOTV:10832:h:S19.2E:22000:61:62:0:0:61920
diff --git a/channels.conf.cable b/channels.conf.cable
index 65321fc..14d9200 100644
--- a/channels.conf.cable
+++ b/channels.conf.cable
@@ -9,6 +9,7 @@ EinsExtra:426:M64:C:6900:101:102:0:0:28201
EinsFestival:426:M64:C:6900:201:202:0:0:28202
EinsMuXx:426:M64:C:6900:301:302:0:0:28203
Phoenix:410:M64:C:6900:901:902:904:0:28114
+KI.KA:394:M64:C:6900:310:320:330:0:28008
EuroNews:394:M64:C:6900:2221:2233:768:0:28015
CNBC:394:M64:C:6900:510:520:530:0:28010
Eurosport:394:M64:C:6900:410:420:430:0:28009
diff --git a/channels.h b/channels.h
index 8a784f7..7eb818c 100644
--- a/channels.h
+++ b/channels.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: channels.h 1.1 2002/10/05 13:53:15 kls Exp $
+ * $Id: channels.h 1.3 2002/10/20 11:50:36 kls Exp $
*/
#ifndef __CHANNELS_H
@@ -112,9 +112,8 @@ public:
int GetPrevGroup(int Idx); // Get previous channel group
int GetNextNormal(int Idx); // Get next normal channel (not group)
void ReNumber(void); // Recalculate 'number' based on channel type
- cChannel *GetByNumber(int Number);
+ cChannel *GetByNumber(int Number, int SkipGap = 0);
cChannel *GetByServiceID(unsigned short ServiceId);
- const char *GetChannelNameByNumber(int Number);
bool SwitchTo(int Number);
int MaxNumber(void) { return maxNumber; }
};
diff --git a/config.c b/config.c
index d9cdb43..7cea98e 100644
--- a/config.c
+++ b/config.c
@@ -4,13 +4,12 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: config.c 1.109 2002/10/13 10:03:49 kls Exp $
+ * $Id: config.c 1.111 2002/10/19 15:49:51 kls Exp $
*/
#include "config.h"
#include <ctype.h>
#include <stdlib.h>
-#include "channels.h" //XXX timers!
#include "i18n.h"
#include "interface.h"
#include "plugin.h"
@@ -20,339 +19,6 @@
// format characters in order to allow any number of blanks after a numeric
// value!
-// -- cTimer -----------------------------------------------------------------
-
-char *cTimer::buffer = NULL;
-
-cTimer::cTimer(bool Instant)
-{
- startTime = stopTime = 0;
- recording = pending = false;
- active = Instant ? taActInst : taInactive;
- cChannel *ch = Channels.GetByNumber(cDevice::CurrentChannel());
- channel = ch ? ch->Number() : 0;
- time_t t = time(NULL);
- struct tm tm_r;
- struct tm *now = localtime_r(&t, &tm_r);
- day = now->tm_mday;
- start = now->tm_hour * 100 + now->tm_min;
- stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
- stop = (stop / 60) * 100 + (stop % 60);
- if (stop >= 2400)
- stop -= 2400;
-//TODO VPS???
- priority = Setup.DefaultPriority;
- lifetime = Setup.DefaultLifetime;
- *file = 0;
- firstday = 0;
- summary = NULL;
- if (Instant && ch)
- snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : ch->Name());
-}
-
-cTimer::cTimer(const cEventInfo *EventInfo)
-{
- startTime = stopTime = 0;
- recording = pending = false;
- active = true;
- cChannel *ch = Channels.GetByServiceID(EventInfo->GetServiceID());
- channel = ch ? ch->Number() : 0;
- time_t tstart = EventInfo->GetTime();
- time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
- tstart -= Setup.MarginStart * 60;
- struct tm tm_r;
- struct tm *time = localtime_r(&tstart, &tm_r);
- day = time->tm_mday;
- start = time->tm_hour * 100 + time->tm_min;
- time = localtime_r(&tstop, &tm_r);
- stop = time->tm_hour * 100 + time->tm_min;
- if (stop >= 2400)
- stop -= 2400;
- priority = Setup.DefaultPriority;
- lifetime = Setup.DefaultLifetime;
- *file = 0;
- const char *Title = EventInfo->GetTitle();
- if (!isempty(Title))
- strn0cpy(file, EventInfo->GetTitle(), sizeof(file));
- firstday = 0;
- summary = NULL;
-}
-
-cTimer::~cTimer()
-{
- free(summary);
-}
-
-cTimer& cTimer::operator= (const cTimer &Timer)
-{
- memcpy(this, &Timer, sizeof(*this));
- if (summary)
- summary = strdup(summary);
- return *this;
-}
-
-bool cTimer::operator< (const cListObject &ListObject)
-{
- cTimer *ti = (cTimer *)&ListObject;
- time_t t1 = StartTime();
- time_t t2 = ti->StartTime();
- return t1 < t2 || (t1 == t2 && priority > ti->priority);
-}
-
-const char *cTimer::ToText(cTimer *Timer)
-{
- free(buffer);
- strreplace(Timer->file, ':', '|');
- strreplace(Timer->summary, '\n', '|');
- asprintf(&buffer, "%d:%d:%s:%04d:%04d:%d:%d:%s:%s\n", Timer->active, Timer->channel, PrintDay(Timer->day, Timer->firstday), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file, Timer->summary ? Timer->summary : "");
- strreplace(Timer->summary, '|', '\n');
- strreplace(Timer->file, '|', ':');
- return buffer;
-}
-
-const char *cTimer::ToText(void)
-{
- return ToText(this);
-}
-
-int cTimer::TimeToInt(int t)
-{
- return (t / 100 * 60 + t % 100) * 60;
-}
-
-int cTimer::ParseDay(const char *s, time_t *FirstDay)
-{
- char *tail;
- int d = strtol(s, &tail, 10);
- if (FirstDay)
- *FirstDay = 0;
- if (tail && *tail) {
- d = 0;
- if (tail == s) {
- const char *first = strchr(s, '@');
- int l = first ? first - s : strlen(s);
- if (l == 7) {
- for (const char *p = s + 6; p >= s; p--) {
- d <<= 1;
- d |= (*p != '-');
- }
- d |= 0x80000000;
- }
- if (FirstDay && first) {
- ++first;
- if (strlen(first) == 10) {
- struct tm tm_r;
- if (3 == sscanf(first, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
- tm_r.tm_year -= 1900;
- tm_r.tm_mon--;
- tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
- tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
- *FirstDay = mktime(&tm_r);
- }
- }
- else
- d = 0;
- }
- }
- }
- else if (d < 1 || d > 31)
- d = 0;
- return d;
-}
-
-const char *cTimer::PrintDay(int d, time_t FirstDay)
-{
-#define DAYBUFFERSIZE 32
- static char buffer[DAYBUFFERSIZE];
- if ((d & 0x80000000) != 0) {
- char *b = buffer;
- const char *w = tr("MTWTFSS");
- while (*w) {
- *b++ = (d & 1) ? *w : '-';
- d >>= 1;
- w++;
- }
- if (FirstDay) {
- struct tm tm_r;
- localtime_r(&FirstDay, &tm_r);
- b += strftime(b, DAYBUFFERSIZE - (b - buffer), "@%Y-%m-%d", &tm_r);
- }
- *b = 0;
- }
- else
- sprintf(buffer, "%d", d);
- return buffer;
-}
-
-const char *cTimer::PrintFirstDay(void)
-{
- if (firstday) {
- const char *s = PrintDay(day, firstday);
- if (strlen(s) == 18)
- return s + 8;
- }
- return ""; // not NULL, so the caller can always use the result
-}
-
-bool cTimer::Parse(const char *s)
-{
- char *buffer1 = NULL;
- char *buffer2 = NULL;
- free(summary);
- summary = NULL;
- //XXX Apparently sscanf() doesn't work correctly if the last %a argument
- //XXX results in an empty string (this first occured when the EIT gathering
- //XXX was put into a separate thread - don't know why this happens...
- //XXX As a cure we copy the original string and add a blank.
- //XXX If anybody can shed some light on why sscanf() failes here, I'd love
- //XXX to hear about that!
- char *s2 = NULL;
- int l2 = strlen(s);
- while (l2 > 0 && isspace(s[l2 - 1]))
- l2--;
- if (s[l2 - 1] == ':') {
- s2 = MALLOC(char, l2 + 3);
- strcat(strn0cpy(s2, s, l2 + 1), " \n");
- s = s2;
- }
- if (8 <= sscanf(s, "%d :%d :%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &active, &channel, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
- if (summary && !*skipspace(summary)) {
- free(summary);
- summary = NULL;
- }
- //TODO add more plausibility checks
- day = ParseDay(buffer1, &firstday);
- strn0cpy(file, buffer2, MaxFileName);
- strreplace(file, '|', ':');
- strreplace(summary, '|', '\n');
- free(buffer1);
- free(buffer2);
- free(s2);
- return day != 0;
- }
- free(s2);
- return false;
-}
-
-bool cTimer::Save(FILE *f)
-{
- return fprintf(f, ToText()) > 0;
-}
-
-bool cTimer::IsSingleEvent(void)
-{
- return (day & 0x80000000) == 0;
-}
-
-int cTimer::GetMDay(time_t t)
-{
- struct tm tm_r;
- return localtime_r(&t, &tm_r)->tm_mday;
-}
-
-int cTimer::GetWDay(time_t t)
-{
- struct tm tm_r;
- int weekday = localtime_r(&t, &tm_r)->tm_wday;
- return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
-}
-
-bool cTimer::DayMatches(time_t t)
-{
- return IsSingleEvent() ? GetMDay(t) == day : (day & (1 << GetWDay(t))) != 0;
-}
-
-time_t cTimer::IncDay(time_t t, int Days)
-{
- struct tm tm_r;
- tm tm = *localtime_r(&t, &tm_r);
- tm.tm_mday += Days; // now tm_mday may be out of its valid range
- int h = tm.tm_hour; // save original hour to compensate for DST change
- tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
- t = mktime(&tm); // normalize all values
- tm.tm_hour = h; // compensate for DST change
- return mktime(&tm); // calculate final result
-}
-
-time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
-{
- struct tm tm_r;
- tm tm = *localtime_r(&t, &tm_r);
- tm.tm_hour = SecondsFromMidnight / 3600;
- tm.tm_min = (SecondsFromMidnight % 3600) / 60;
- tm.tm_sec = SecondsFromMidnight % 60;
- tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
- return mktime(&tm);
-}
-
-char *cTimer::SetFile(const char *File)
-{
- if (!isempty(File))
- strn0cpy(file, File, sizeof(file));
- return file;
-}
-
-bool cTimer::Matches(time_t t)
-{
- startTime = stopTime = 0;
- if (t == 0)
- t = time(NULL);
-
- int begin = TimeToInt(start); // seconds from midnight
- int length = TimeToInt(stop) - begin;
- if (length < 0)
- length += SECSINDAY;
-
- int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31
- for (int i = -1; i <= DaysToCheck; i++) {
- time_t t0 = IncDay(t, i);
- if (DayMatches(t0)) {
- time_t a = SetTime(t0, begin);
- time_t b = a + length;
- if ((!firstday || a >= firstday) && t <= b) {
- startTime = a;
- stopTime = b;
- break;
- }
- }
- }
- if (!startTime)
- startTime = firstday; // just to have something that's more than a week in the future
- else if (t > startTime || t > firstday + SECSINDAY + 3600) // +3600 in case of DST change
- firstday = 0;
- return active && startTime <= t && t < stopTime; // must stop *before* stopTime to allow adjacent timers
-}
-
-time_t cTimer::StartTime(void)
-{
- if (!startTime)
- Matches();
- return startTime;
-}
-
-time_t cTimer::StopTime(void)
-{
- if (!stopTime)
- Matches();
- return stopTime;
-}
-
-void cTimer::SetRecording(bool Recording)
-{
- recording = Recording;
- isyslog("timer %d %s", Index() + 1, recording ? "start" : "stop");
-}
-
-void cTimer::SetPending(bool Pending)
-{
- pending = Pending;
-}
-
-void cTimer::Skip(void)
-{
- firstday = IncDay(SetTime(StartTime(), 0), 1);
-}
-
// --- cCommand -------------------------------------------------------------
char *cCommand::result = NULL;
@@ -476,47 +142,6 @@ bool cCaDefinition::Parse(const char *s)
cCommands Commands;
cCommands RecordingCommands;
-// -- cTimers ----------------------------------------------------------------
-
-cTimers Timers;
-
-cTimer *cTimers::GetTimer(cTimer *Timer)
-{
- cTimer *ti = (cTimer *)First();
- while (ti) {
- if (ti->channel == Timer->channel && ti->day == Timer->day && ti->start == Timer->start && ti->stop == Timer->stop)
- return ti;
- ti = (cTimer *)ti->Next();
- }
- return NULL;
-}
-
-cTimer *cTimers::GetMatch(time_t t)
-{
- cTimer *t0 = NULL;
- cTimer *ti = First();
- while (ti) {
- if (!ti->recording && ti->Matches(t)) {
- if (!t0 || ti->priority > t0->priority)
- t0 = ti;
- }
- ti = (cTimer *)ti->Next();
- }
- return t0;
-}
-
-cTimer *cTimers::GetNextActiveTimer(void)
-{
- cTimer *t0 = NULL;
- cTimer *ti = First();
- while (ti) {
- if (ti->active && (!t0 || *ti < *t0))
- t0 = ti;
- ti = (cTimer *)ti->Next();
- }
- return t0;
-}
-
// -- cSVDRPhosts ------------------------------------------------------------
cSVDRPhosts SVDRPhosts;
@@ -680,11 +305,11 @@ cSetupLine *cSetup::Get(const char *Name, const char *Plugin)
return NULL;
}
-void cSetup::Store(const char *Name, const char *Value, const char *Plugin)
+void cSetup::Store(const char *Name, const char *Value, const char *Plugin, bool AllowMultiple)
{
if (Name && *Name) {
cSetupLine *l = Get(Name, Plugin);
- if (l)
+ if (l && !AllowMultiple)
Del(l);
if (Value)
Add(new cSetupLine(Name, Value, Plugin));
@@ -726,6 +351,9 @@ bool cSetup::Load(const char *FileName)
void cSetup::StoreCaCaps(const char *Name)
{
+ cSetupLine *l;
+ while ((l = Get(Name)) != NULL)
+ Del(l);
for (int d = 0; d < MAXDEVICES; d++) {
char buffer[MAXPARSEBUFFER];
char *q = buffer;
@@ -738,7 +366,7 @@ void cSetup::StoreCaCaps(const char *Name)
}
}
if (*buffer)
- Store(Name, buffer);
+ Store(Name, buffer, NULL, true);
}
}
diff --git a/config.h b/config.h
index 1f043c4..0cac7b9 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.134 2002/10/13 10:03:09 kls Exp $
+ * $Id: config.h 1.137 2002/10/19 15:43:31 kls Exp $
*/
#ifndef __CONFIG_H
@@ -20,7 +20,7 @@
#include "eit.h"
#include "tools.h"
-#define VDRVERSION "1.1.13"
+#define VDRVERSION "1.1.14"
#define MAXPRIORITY 99
#define MAXLIFETIME 99
@@ -32,57 +32,6 @@
#define MaxFileName 256
-enum eTimerActive { taInactive = 0,
- taActive = 1,
- taInstant = 2,
- taActInst = (taActive | taInstant)
- };
-
-class cTimer : public cListObject {
-private:
- time_t startTime, stopTime;
- static char *buffer;
- static const char *ToText(cTimer *Timer);
-public:
- bool recording, pending;
- int active;
- int channel;
- int day;
- int start;
- int stop;
-//TODO VPS???
- int priority;
- int lifetime;
- char file[MaxFileName];
- time_t firstday;
- char *summary;
- cTimer(bool Instant = false);
- cTimer(const cEventInfo *EventInfo);
- virtual ~cTimer();
- cTimer& operator= (const cTimer &Timer);
- virtual bool operator< (const cListObject &ListObject);
- const char *ToText(void);
- bool Parse(const char *s);
- bool Save(FILE *f);
- bool IsSingleEvent(void);
- int GetMDay(time_t t);
- int GetWDay(time_t t);
- bool DayMatches(time_t t);
- static time_t IncDay(time_t t, int Days);
- static time_t SetTime(time_t t, int SecondsFromMidnight);
- char *SetFile(const char *File);
- bool Matches(time_t t = 0);
- time_t StartTime(void);
- time_t StopTime(void);
- void SetRecording(bool Recording);
- void SetPending(bool Pending);
- void Skip(void);
- const char *PrintFirstDay(void);
- static int TimeToInt(int t);
- static int ParseDay(const char *s, time_t *FirstDay = NULL);
- static const char *PrintDay(int d, time_t FirstDay = 0);
- };
-
class cCommand : public cListObject {
private:
char *title;
@@ -203,13 +152,6 @@ public:
}
};
-class cTimers : public cConfig<cTimer> {
-public:
- cTimer *GetTimer(cTimer *Timer);
- cTimer *GetMatch(time_t t);
- cTimer *GetNextActiveTimer(void);
- };
-
class cCommands : public cConfig<cCommand> {};
class cSVDRPhosts : public cConfig<cSVDRPhost> {
@@ -222,7 +164,6 @@ public:
const cCaDefinition *Get(int Number);
};
-extern cTimers Timers;
extern cCommands Commands;
extern cCommands RecordingCommands;
extern cSVDRPhosts SVDRPhosts;
@@ -252,7 +193,7 @@ private:
bool ParseCaCaps(const char *Value);
bool Parse(const char *Name, const char *Value);
cSetupLine *Get(const char *Name, const char *Plugin = NULL);
- void Store(const char *Name, const char *Value, const char *Plugin = NULL);
+ void Store(const char *Name, const char *Value, const char *Plugin = NULL, bool AllowMultiple = false);
void Store(const char *Name, int Value, const char *Plugin = NULL);
public:
// Also adjust cMenuSetup (menu.c) when adding parameters here!
diff --git a/device.c b/device.c
index 637632b..2d3d1d9 100644
--- a/device.c
+++ b/device.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: device.c 1.27 2002/10/12 13:24:37 kls Exp $
+ * $Id: device.c 1.32 2002/10/26 11:43:52 kls Exp $
*/
#include "device.h"
@@ -52,7 +52,6 @@ cDevice::cDevice(void)
for (int i = 0; i < MAXRECEIVERS; i++)
receiver[i] = NULL;
- ca = -1;
if (numDevices < MAXDEVICES) {
device[numDevices++] = this;
@@ -322,13 +321,12 @@ bool cDevice::SwitchChannel(int Direction)
if (Direction) {
int n = CurrentChannel() + Direction;
int first = n;
- PrimaryDevice()->StopReplay(); // otherwise a running Transfer Mode would block channels
cChannel *channel;
- while ((channel = Channels.GetByNumber(n)) != NULL) {
+ while ((channel = Channels.GetByNumber(n, Direction)) != NULL) {
// try only channels which are currently available
- if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || GetDevice(channel, 0))
+ if (PrimaryDevice()->ProvidesChannel(channel, Setup.PrimaryLimit) || PrimaryDevice()->CanReplay() && GetDevice(channel, 0))
break;
- n += Direction;
+ n = channel->Number() + Direction;
}
if (channel) {
int d = n - first;
@@ -362,7 +360,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
if (NeedsTransferMode) {
cDevice *CaDevice = GetDevice(Channel, 0);
- if (CaDevice) {
+ if (CaDevice && CanReplay()) {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
if (CaDevice->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()!
cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2()));//XXX+
@@ -448,6 +446,11 @@ void cDevice::SetAudioTrack(int Index)
SetAudioTrackDevice(Index);
}
+bool cDevice::CanReplay(void) const
+{
+ return HasDecoder();
+}
+
bool cDevice::SetPlayMode(ePlayMode PlayMode)
{
return false;
@@ -484,7 +487,7 @@ bool cDevice::Replaying(void) const
bool cDevice::AttachPlayer(cPlayer *Player)
{
- if (HasDecoder()) {
+ if (CanReplay()) {
if (player)
Detach(player);
player = Player;
@@ -531,6 +534,16 @@ int cDevice::PlayAudio(const uchar *Data, int Length)
return -1;
}
+int cDevice::Ca(void) const
+{
+ int ca = 0;
+ for (int i = 0; i < MAXRECEIVERS; i++) {
+ if (receiver[i] && (ca = receiver[i]->ca) != 0)
+ break; // all receivers have the same ca
+ }
+ return ca;
+}
+
int cDevice::Priority(void) const
{
int priority = IsPrimaryDevice() ? Setup.PrimaryLimit - 1 : DEFAULTPRIORITY;
diff --git a/device.h b/device.h
index 54dc41e..1070c52 100644
--- a/device.h
+++ b/device.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: device.h 1.23 2002/10/12 11:15:13 kls Exp $
+ * $Id: device.h 1.25 2002/10/26 11:33:42 kls Exp $
*/
#ifndef __DEVICE_H
@@ -278,6 +278,8 @@ private:
cPlayer *player;
bool playerDetached;
protected:
+ virtual bool CanReplay(void) const;
+ // Returns true if this device can currently start a replay session.
virtual bool SetPlayMode(ePlayMode PlayMode);
// Sets the device into the given play mode.
// Returns true if the operation was successful.
@@ -324,7 +326,6 @@ public:
private:
cReceiver *receiver[MAXRECEIVERS];
- int ca;
int CanShift(int Ca, int Priority, int UsedCards = 0) const;
protected:
int Priority(void) const;
@@ -344,8 +345,8 @@ protected:
// false in case of a non recoverable error, otherwise it returns true,
// even if Data is NULL.
public:
- int Ca(void) const { return ca; }
- // Returns the ca of the current receiving session.
+ int Ca(void) const;
+ // Returns the ca of the current receiving session(s).
bool Receiving(void) const;
// Returns true if we are currently receiving.
bool AttachReceiver(cReceiver *Receiver);
diff --git a/dvbdevice.c b/dvbdevice.c
index a4a4308..a1a8913 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.24 2002/10/12 11:15:45 kls Exp $
+ * $Id: dvbdevice.c 1.30 2002/10/26 11:37:03 kls Exp $
*/
#include "dvbdevice.h"
@@ -428,6 +428,13 @@ 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)
{
#if (DVB_DRIVER_VERSION < MIN_DVB_DRIVER_VERSION_FOR_TIMESHIFT)
@@ -435,24 +442,26 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
LiveView = true;
#endif
+ bool IsEncrypted = Channel->Ca() > CACONFBASE;
+
bool DoTune = !IsTunedTo(Channel);
bool TurnOffLivePIDs = HasDecoder()
&& (DoTune
- || Channel->Ca() > CACONFBASE && pidHandles[ptVideo].pid != Channel->Vpid() // CA channels can only be decrypted in "live" mode
+ || IsEncrypted && pidHandles[ptVideo].pid != Channel->Vpid() // CA channels can only be decrypted in "live" mode
|| IsPrimaryDevice()
&& (LiveView // for a new live view the old PIDs need to be turned off
|| pidHandles[ptVideo].pid == Channel->Vpid() // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
)
);
- bool StartTransferMode = IsPrimaryDevice() && !DoTune
+ bool StartTransferMode = IsPrimaryDevice() && !IsEncrypted && !DoTune
&& (LiveView && HasPid(Channel->Vpid()) && pidHandles[ptVideo].pid != Channel->Vpid() // the PID is already set as DMX_PES_OTHER
|| !LiveView && pidHandles[ptVideo].pid == Channel->Vpid() // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
);
bool TurnOnLivePIDs = HasDecoder() && !StartTransferMode
- && (Channel->Ca() > CACONFBASE // CA channels can only be decrypted in "live" mode
+ && (IsEncrypted // CA channels can only be decrypted in "live" mode
|| LiveView
);
@@ -622,13 +631,13 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
// Frequency and symbol rate:
#ifdef NEWSTRUCT
- Frontend.frequency = Channel->Frequency() * 1000000UL;
+ 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());
#else
- Frontend.Frequency = Channel->Frequency() * 1000000UL;
+ Frontend.Frequency = FrequencyToHz(Channel->Frequency());
Frontend.Inversion = SpectralInversion(Channel->Inversion());
Frontend.u.qam.SymbolRate = Channel->Srate() * 1000UL;
Frontend.u.qam.FEC_inner = CodeRate(Channel->CoderateH());
@@ -641,7 +650,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
// Frequency and OFDM paramaters:
#ifdef NEWSTRUCT
- Frontend.frequency = Channel->Frequency() * 1000UL;
+ 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());
@@ -651,7 +660,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
Frontend.u.ofdm.guard_interval = fe_guard_interval_t(Channel->Guard());
Frontend.u.ofdm.hierarchy_information = fe_hierarchy_t(Channel->Hierarchy());
#else
- Frontend.Frequency = Channel->Frequency() * 1000UL;
+ Frontend.Frequency = FrequencyToHz(Channel->Frequency());
Frontend.Inversion = SpectralInversion(Channel->Inversion());
Frontend.u.ofdm.bandWidth = BandWidth(Channel->Bandwidth());
Frontend.u.ofdm.HP_CodeRate = CodeRate(Channel->CoderateH());
@@ -733,11 +742,9 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
if (IsPrimaryDevice())
AddPid(Channel->Tpid(), ptTeletext);
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
- CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
- CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false));
}
else if (StartTransferMode)
- cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), 0, 0, 0));
+ cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2()));
// Start setting system time:
@@ -765,13 +772,15 @@ int cDvbDevice::NumAudioTracksDevice(void) const
int n = 0;
if (aPid1)
n++;
- if (aPid2 && aPid1 != aPid2)
+ if (!Ca() && aPid2 && aPid1 != aPid2) // a Ca recording session blocks switching live audio tracks
n++;
return n;
}
const char **cDvbDevice::GetAudioTracksDevice(int *CurrentTrack) const
{
+ if (Ca())
+ return NULL; // a Ca recording session blocks switching live audio tracks
if (NumAudioTracks()) {
if (CurrentTrack)
*CurrentTrack = (pidHandles[ptAudio].pid == aPid1) ? 0 : 1;
@@ -785,11 +794,19 @@ const char **cDvbDevice::GetAudioTracksDevice(int *CurrentTrack) const
void cDvbDevice::SetAudioTrackDevice(int Index)
{
if (0 <= Index && Index < NumAudioTracks()) {
+ int vpid = pidHandles[ptVideo].pid; // need to turn video PID off/on to restart demux
+ DelPid(vpid);
DelPid(pidHandles[ptAudio].pid);
AddPid(Index ? aPid2 : aPid1, ptAudio);
+ AddPid(vpid, ptVideo);
}
}
+bool cDvbDevice::CanReplay(void) const
+{
+ return cDevice::CanReplay() && !Ca(); // we can only replay if there is no Ca recording going on
+}
+
bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
{
if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) {
diff --git a/dvbdevice.h b/dvbdevice.h
index b5484dc..8784c74 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.14 2002/10/12 11:15:39 kls Exp $
+ * $Id: dvbdevice.h 1.15 2002/10/26 11:35:04 kls Exp $
*/
#ifndef __DVBDEVICE_H
@@ -101,6 +101,7 @@ private:
protected:
ePlayMode playMode;
+ virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode PlayMode);
public:
virtual void TrickSpeed(int Speed);
diff --git a/dvbplayer.c b/dvbplayer.c
index 927fde4..0bc75c0 100644
--- a/dvbplayer.c
+++ b/dvbplayer.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbplayer.c 1.14 2002/10/12 12:29:31 kls Exp $
+ * $Id: dvbplayer.c 1.15 2002/10/13 16:08:40 kls Exp $
*/
#include "dvbplayer.h"
@@ -635,7 +635,7 @@ int cDvbPlayer::NumAudioTracks(void) const
return canToggleAudioTrack ? 2 : 1;
}
-const char **cDvbPlayer::GetAudioTracks(int *CurrentTrack = NULL) const
+const char **cDvbPlayer::GetAudioTracks(int *CurrentTrack) const
{
if (NumAudioTracks()) {
if (CurrentTrack)
diff --git a/dvbspu.c b/dvbspu.c
index 95edb1b..4b31401 100644
--- a/dvbspu.c
+++ b/dvbspu.c
@@ -8,7 +8,7 @@
*
* parts of this file are derived from the OMS program.
*
- * $Id: dvbspu.c 1.2 2002/09/29 13:48:39 kls Exp $
+ * $Id: dvbspu.c 1.3 2002/10/26 10:46:49 kls Exp $
*/
#include <assert.h>
@@ -192,7 +192,7 @@ void cDvbSpuBitmap::putFieldData(int field, uint8_t * data, uint8_t * endp)
int len = vlc >> 2;
// if len == 0 -> end sequence - fill to end of line
- len = len ? : bmpsize.x2 - xp + 1;
+ len = len ? len : bmpsize.x2 - xp + 1;
putPixel(xp, yp, len, color);
xp += len;
diff --git a/eitscan.c b/eitscan.c
index c29b6b5..2a89cec 100644
--- a/eitscan.c
+++ b/eitscan.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: eitscan.c 1.8 2002/10/05 13:44:35 kls Exp $
+ * $Id: eitscan.c 1.9 2002/10/19 11:48:02 kls Exp $
*/
#include "eitscan.h"
@@ -63,7 +63,7 @@ void cEITScanner::Process(void)
ch = 1;
numTransponders = 0;
}
- cChannel *Channel = Channels.GetByNumber(ch);
+ cChannel *Channel = Channels.GetByNumber(ch, 1);
if (Channel) {
if (!Device->ProvidesChannel(Channel))
break;
@@ -75,7 +75,7 @@ void cEITScanner::Process(void)
break;
}
}
- ch++;
+ ch = Channel->Number() + 1;
}
}
}
diff --git a/i18n.c b/i18n.c
index 311378c..08b2765 100644
--- a/i18n.c
+++ b/i18n.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: i18n.c 1.96 2002/10/13 11:03:39 kls Exp $
+ * $Id: i18n.c 1.99 2002/10/27 14:24:00 kls Exp $
*
* Translations provided by:
*
@@ -14,7 +14,7 @@
* Portuguese Paulo Lopes <pmml@netvita.pt>
* French Jean-Claude Repetto <jc@repetto.org>
* Norwegian Jørgen Tvedt <pjtvedt@online.no> and Truls Slevigen <truls@slevigen.no>
- * Finnish Hannu Savolainen <hannu@opensound.com>
+ * Finnish Hannu Savolainen <hannu@opensound.com> and Jaakko Hyvätti <jaakko@hyvatti.iki.fi>
* Polish Michael Rakowski <mrak@gmx.de>
* Spanish Ruben Nunez Francisco <ruben.nunez@tang-it.com>
* Greek Dimitrios Dimitrakos <mail@dimitrios.de>
@@ -207,7 +207,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Nauhoituskomennot",
"",// TODO
"",// TODO
"",// TODO
@@ -640,7 +640,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Lisää",
"",// TODO
"",// TODO
"Isodos",
@@ -656,7 +656,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Korvaa",
"",// TODO
"",// TODO
"Epanagrafi",
@@ -914,7 +914,7 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
+ "Lähde",
"",//TODO
"",//TODO
"",//TODO
@@ -1074,7 +1074,7 @@ const tI18nPhrase Phrases[] = {
"Inversion",
"Inversion",
"Inversion",
- "Inversion",
+ "Inversio",
"Inversion",
"Inversion",
"Inversion",
@@ -1138,7 +1138,7 @@ const tI18nPhrase Phrases[] = {
"Modulation",
"Modulation",
"Modulation",
- "Modulation",
+ "Modulaatio",
"Modulation",
"Modulation",
"Modulation",
@@ -1460,7 +1460,7 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
+ "Kanavaa ei voi katsoa nyt!",
"",//TODO
"",//TODO
"",//TODO
@@ -1701,7 +1701,7 @@ const tI18nPhrase Phrases[] = {
"Plugins",
"Plugins",
"Plugins",
- "Plugins",
+ "Laajennokset",
"Plugins",
"Plugins",
"Plugins",
@@ -1717,7 +1717,7 @@ const tI18nPhrase Phrases[] = {
"Plugin",
"Plugin",
"Plugin",
- "Plugin",
+ "Laajennos",
"Plugin",
"Plugin",
"Plugin",
@@ -2198,7 +2198,7 @@ const tI18nPhrase Phrases[] = {
"",//TODO
"",//TODO
"",//TODO
- "",//TODO
+ "Pikanauhoituksen pituus (min)",
"",//TODO
"",//TODO
"",//TODO
@@ -2359,7 +2359,7 @@ const tI18nPhrase Phrases[] = {
"SegTerQuaQuiSexSabDom",
"LunMarMerJeuVenSamDim",
"ManTirOnsTorFreLørSøn",
- "MaaTiiKesTorPerLauSun",
+ "Ma Ti Ke To Pe La Su ",
"PonWtoSroCzwPiaSobNie",
"LunMarMieJueVieSabDom",
"DevTriTetPemParSavKir",
@@ -2376,7 +2376,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ " abcdefghijklmnopqrstuvxyzåäö0123456789-.#~",
"",// TODO
" aábcdeéfghiíjklmnñoópqrstuúvwxyz0123456789-.#~",
"",// TODO
@@ -2385,21 +2385,21 @@ const tI18nPhrase Phrases[] = {
" aábcdeéfghijklmnoóöpqrstuúüvwxyz0123456789-.,#~",
},
// Learning keys:
- { "Learning Remote Control Keys",
- "Fernbedienungs-Codes lernen",
- "Ucim se kod upravljalca",
- "Apprendimento tasti unita` remota",
- "Leren toetsen afstandsbediening",
- "Aprender as teclas do telecomando",
- "Apprentissage des codes de télécommande",
- "Lære fjernkontrolltaster",
- "Kaukosäätimen näppäinten opettelu",
- "Nauka kodu pilota",
- "Aprendiendo teclas del telemando",
- "Ekmathisi Remote Control",
- "Inlärning av fjärrkontrollsknappar",
- "Invatare taste telecomanda",
- "Távirányító betanítása",
+ { "Learning Remote Control Keys (%s)",
+ "Fernbedienungs-Codes lernen (%s)",
+ "Ucim se kod upravljalca (%s)",
+ "Apprendimento tasti unita` remota (%s)",
+ "Leren toetsen afstandsbediening (%s)",
+ "Aprender as teclas do telecomando (%s)",
+ "Apprentissage des codes de télécommande (%s)",
+ "Lære fjernkontrolltaster (%s)",
+ "Kaukosäätimen näppäinten opettelu (%s)",
+ "Nauka kodu pilota (%s)",
+ "Aprendiendo teclas del telemando (%s)",
+ "Ekmathisi Remote Control (%s)",
+ "Inlärning av fjärrkontrollsknappar (%s)",
+ "Invatare taste telecomanda (%s)",
+ "Távirányító betanítása (%s)",
},
{ "Phase 1: Detecting RC code type",
"Phase 1: FB Code feststellen",
@@ -2569,7 +2569,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "(Paina 'Valikko' jos näppäintä ei ole)",
"",// TODO
"",// TODO
"",// TODO
@@ -2786,6 +2786,102 @@ const tI18nPhrase Phrases[] = {
"Albastru",
"Kék",
},
+ { "Play",
+ "Wiedergabe",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "Pause",
+ "Pause",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "Stop",
+ "Stop",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "Record",
+ "Aufnehmen",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "FastFwd",
+ "Vorlauf",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "FastRew",
+ "Rücklauf",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
{ "Power",
"Ausschalten",
"Izklop",
@@ -2802,6 +2898,38 @@ const tI18nPhrase Phrases[] = {
"Pornit",
"Kikapcsolni",
},
+ { "Channel+",
+ "Kanal+",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
+ { "Channel-",
+ "Kanal-",
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ "",// TODO
+ },
{ "Volume+",
"Lautstärke+",
"Glasnost+",
@@ -3179,7 +3307,7 @@ const tI18nPhrase Phrases[] = {
"",// TODO
"",// TODO
"",// TODO
- "",// TODO
+ "Tällä laajennoksella ei ole asetuksia!",
"",// TODO
"",// TODO
"",// TODO
diff --git a/interface.c b/interface.c
index 64c7489..a9f0d9a 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.56 2002/09/30 15:32:10 kls Exp $
+ * $Id: interface.c 1.59 2002/10/27 15:54:05 kls Exp $
*/
#include "interface.h"
@@ -58,7 +58,8 @@ eKeys cInterface::GetKey(bool Wait)
{
Flush();
if (SVDRP) {
- SVDRP->Process();
+ if (SVDRP->Process())
+ Wait = false;
if (!open) {
char *message = SVDRP->GetMessage();
if (message) {
@@ -327,9 +328,6 @@ void cInterface::Help(const char *Red, const char *Green, const char *Yellow, co
void cInterface::QueryKeys(cRemote *Remote)
{
- cRemote::Clear();
- Clear();
- WriteText(1, 1, tr("Learning Remote Control Keys"));//XXX Remote->name()!!!
WriteText(1, 3, tr("Phase 1: Detecting RC code type"));
WriteText(1, 5, tr("Press any key on the RC unit"));
Flush();
@@ -354,12 +352,12 @@ void cInterface::QueryKeys(cRemote *Remote)
char *NewCode = NULL;
eKeys Key = cRemote::Get(100, &NewCode);
switch (Key) {
- case kUp: {
- NewKey = eKeys(NewKey - 1);
- cKey *last = Keys.Last();
- if (last && last->Key() == NewKey)
- Keys.Del(last);
- }
+ case kUp: if (NewKey > kUp) {
+ NewKey = eKeys(NewKey - 1);
+ cKey *last = Keys.Last();
+ if (last && last->Key() == NewKey)
+ Keys.Del(last);
+ }
break;
case kDown: WriteText(1, 5, tr("Press 'Up' to confirm"));
WriteText(1, 6, tr("Press 'Down' to continue"));
@@ -415,28 +413,30 @@ void cInterface::LearnKeys(void)
dsyslog("remote control %s - %s", Remote->Name(), known ? "keys known" : "learning keys");
if (!known) {
Open();
+ char Headline[Width()];
+ snprintf(Headline, sizeof(Headline), tr("Learning Remote Control Keys (%s)"), Remote->Name());
+ Clear();
+ cRemote::Clear();
+ WriteText(1, 1, Headline);
+ cRemote::SetLearning(true);
+ QueryKeys(Remote);
+ cRemote::SetLearning(false);
+ Clear();
+ WriteText(1, 1, Headline);
+ WriteText(1, 3, tr("Phase 3: Saving key codes"));
+ WriteText(1, 5, tr("Press 'Up' to save, 'Down' to cancel"));
for (;;) {
- Clear();
- cRemote::SetLearning(true);
- QueryKeys(Remote);
- cRemote::SetLearning(false);
- Clear();
- WriteText(1, 1, tr("Learning Remote Control Keys"));//XXX Remote->name()!!!
- WriteText(1, 3, tr("Phase 3: Saving key codes"));
- WriteText(1, 5, tr("Press 'Up' to save, 'Down' to cancel"));
- for (;;) {
- eKeys key = GetKey();
- if (key == kUp) {
- Keys.Save();
- Close();
- return;
- }
- else if (key == kDown) {
- Keys.Load();
- Close();
- return;
- }
- }
+ eKeys key = GetKey();
+ if (key == kUp) {
+ Keys.Save();
+ Close();
+ break;
+ }
+ else if (key == kDown) {
+ Keys.Load();
+ Close();
+ break;
+ }
}
}
}
diff --git a/keymacros.conf b/keymacros.conf
new file mode 100644
index 0000000..767d49d
--- /dev/null
+++ b/keymacros.conf
@@ -0,0 +1,11 @@
+# Remote control key macros for VDR
+#
+# Format:
+#
+# macrokey key1 key2 key3...
+#
+# See man vdr(5)
+
+Red Recordings
+Green Schedule
+Blue Timers
diff --git a/keys.c b/keys.c
index 0d91d67..4647f3a 100644
--- a/keys.c
+++ b/keys.c
@@ -4,40 +4,63 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: keys.c 1.1 2002/09/29 09:56:51 kls Exp $
+ * $Id: keys.c 1.3 2002/10/27 15:19:40 kls Exp $
*/
#include "keys.h"
static tKey keyTable[] = { // "Up" and "Down" must be the first two keys!
- { kUp, "Up" },
- { kDown, "Down" },
- { kMenu, "Menu" },
- { kOk, "Ok" },
- { kBack, "Back" },
- { kLeft, "Left" },
- { kRight, "Right" },
- { kRed, "Red" },
- { kGreen, "Green" },
- { kYellow, "Yellow" },
- { kBlue, "Blue" },
- { k0, "0" },
- { k1, "1" },
- { k2, "2" },
- { k3, "3" },
- { k4, "4" },
- { k5, "5" },
- { k6, "6" },
- { k7, "7" },
- { k8, "8" },
- { k9, "9" },
- { kPower, "Power" },
- { kVolUp, "Volume+" },
- { kVolDn, "Volume-" },
- { kMute, "Mute" },
- { kNone, "" },
- { k_Setup, "_Setup" },
- { kNone, NULL },
+ { kUp, "Up" },
+ { kDown, "Down" },
+ { kMenu, "Menu" },
+ { kOk, "Ok" },
+ { kBack, "Back" },
+ { kLeft, "Left" },
+ { kRight, "Right" },
+ { kRed, "Red" },
+ { kGreen, "Green" },
+ { kYellow, "Yellow" },
+ { kBlue, "Blue" },
+ { k0, "0" },
+ { k1, "1" },
+ { k2, "2" },
+ { k3, "3" },
+ { k4, "4" },
+ { k5, "5" },
+ { k6, "6" },
+ { k7, "7" },
+ { k8, "8" },
+ { k9, "9" },
+ { kPlay, "Play" },
+ { kPause, "Pause" },
+ { kStop, "Stop" },
+ { kRecord, "Record" },
+ { kFastFwd, "FastFwd" },
+ { kFastRew, "FastRew" },
+ { kPower, "Power" },
+ { kChanUp, "Channel+" },
+ { kChanDn, "Channel-" },
+ { kVolUp, "Volume+" },
+ { kVolDn, "Volume-" },
+ { kMute, "Mute" },
+ { kSchedule, "Schedule" },
+ { kChannels, "Channels" },
+ { kTimers, "Timers" },
+ { kRecordings, "Recordings" },
+ { kSetup, "Setup" },
+ { kCommands, "Commands" },
+ { kUser1, "User1" },
+ { kUser2, "User2" },
+ { kUser3, "User3" },
+ { kUser4, "User4" },
+ { kUser5, "User5" },
+ { kUser6, "User6" },
+ { kUser7, "User7" },
+ { kUser8, "User8" },
+ { kUser9, "User9" },
+ { kNone, "" },
+ { k_Setup, "_Setup" },
+ { kNone, NULL },
};
// -- cKey -------------------------------------------------------------------
@@ -152,3 +175,49 @@ void cKeys::PutSetup(const char *Remote, const char *Setup)
else
esyslog("ERROR: called PutSetup() for %s, but setup has already been defined!", Remote);
}
+
+// -- cKeyMacro --------------------------------------------------------------
+
+cKeyMacro::cKeyMacro(void)
+{
+ for (int i = 0; i < MAXKEYSINMACRO; i++)
+ macro[i] = kNone;
+}
+
+bool cKeyMacro::Parse(char *s)
+{
+ int n = 0;
+ char *p;
+ while ((p = strtok(s, " \t")) != NULL) {
+ if (n < MAXKEYSINMACRO) {
+ macro[n] = cKey::FromString(p);
+ if (macro[n] == kNone) {
+ esyslog("ERROR: unknown key '%s'", p);
+ return false;
+ }
+ n++;
+ s = NULL;
+ }
+ else {
+ esyslog("ERROR: key macro too long");
+ return false;
+ }
+ }
+ if (n < 2) {
+ esyslog("ERROR: empty key macro");
+ }
+ return true;
+}
+
+// -- cKeyMacros -------------------------------------------------------------
+
+cKeyMacros KeyMacros;
+
+const cKeyMacro *cKeyMacros::Get(eKeys Key)
+{
+ for (cKeyMacro *k = First(); k; k = Next(k)) {
+ if (*k->Macro() == Key)
+ return k;
+ }
+ return NULL;
+}
diff --git a/keys.h b/keys.h
index d5ecbbc..ceb2d1c 100644
--- a/keys.h
+++ b/keys.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: keys.h 1.1 2002/09/29 09:55:52 kls Exp $
+ * $Id: keys.h 1.3 2002/10/27 15:18:21 kls Exp $
*/
#ifndef __KEYS_H
@@ -26,10 +26,25 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
kYellow,
kBlue,
k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
+ kPlay,
+ kPause,
+ kStop,
+ kRecord,
+ kFastFwd,
+ kFastRew,
kPower,
+ kChanUp,
+ kChanDn,
kVolUp,
kVolDn,
kMute,
+ kSchedule,
+ kChannels,
+ kTimers,
+ kRecordings,
+ kSetup,
+ kCommands,
+ kUser1, kUser2, kUser3, kUser4, kUser5, kUser6, kUser7, kUser8, kUser9,
kNone,
k_Setup,
// The following flags are OR'd with the above codes:
@@ -47,9 +62,10 @@ enum eKeys { // "Up" and "Down" must be the first two keys!
#define kEditCut k2
#define kEditTest k8
-#define RAWKEY(k) (eKeys((k) & ~k_Flags))
-#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
-#define NORMALKEY(k) (eKeys((k) & ~k_Repeat))
+#define RAWKEY(k) (eKeys((k) & ~k_Flags))
+#define ISRAWKEY(k) ((k) != kNone && ((k) & k_Flags) == 0)
+#define NORMALKEY(k) (eKeys((k) & ~k_Repeat))
+#define ISMODELESSKEY(k) (RAWKEY(k) > k9)
struct tKey {
eKeys type;
@@ -84,4 +100,22 @@ public:
extern cKeys Keys;
+#define MAXKEYSINMACRO 16
+
+class cKeyMacro : public cListObject {
+private:
+ eKeys macro[MAXKEYSINMACRO];
+public:
+ cKeyMacro(void);
+ bool Parse(char *s);
+ const eKeys *Macro(void) const { return macro; }
+ };
+
+class cKeyMacros : public cConfig<cKeyMacro> {
+public:
+ const cKeyMacro *Get(eKeys Key);
+ };
+
+extern cKeyMacros KeyMacros;
+
#endif //__KEYS_H
diff --git a/menu.c b/menu.c
index 077922a..0bd24be 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.217 2002/10/13 12:10:54 kls Exp $
+ * $Id: menu.c 1.221 2002/10/27 14:06:02 kls Exp $
*/
#include "menu.h"
@@ -24,6 +24,7 @@
#include "remote.h"
#include "sources.h"
#include "status.h"
+#include "timers.h"
#include "videodir.h"
#define MENUTIMEOUT 120 // seconds
@@ -33,7 +34,7 @@
#define MAXRECORDCONTROLS (MAXDEVICES * MAXRECEIVERS)
#define MAXINSTANTRECTIME (24 * 60 - 1) // 23:59 hours
-#define CHNUMWIDTH (Channels.Count() > 999 ? 5 : 4) // there are people with more than 999 channels...
+#define CHNUMWIDTH (numdigits(Channels.MaxNumber()) + 1)
// --- cMenuEditChanItem -----------------------------------------------------
@@ -42,6 +43,7 @@ protected:
virtual void Set(void);
public:
cMenuEditChanItem(const char *Name, int *Value);
+ virtual eOSState ProcessKey(eKeys Key);
};
cMenuEditChanItem::cMenuEditChanItem(const char *Name, int *Value)
@@ -54,13 +56,32 @@ void cMenuEditChanItem::Set(void)
{
char buf[255];
cChannel *channel = Channels.GetByNumber(*value);
- if (channel)
- snprintf(buf, sizeof(buf), "%d %s", *value, channel->Name());
- else
- *buf = 0;
+ snprintf(buf, sizeof(buf), "%d %s", *value, channel ? channel->Name() : "");
SetValue(buf);
}
+eOSState cMenuEditChanItem::ProcessKey(eKeys Key)
+{
+ int delta = 1;
+
+ switch (Key) {
+ case kLeft|k_Repeat:
+ case kLeft: delta = -1;
+ case kRight|k_Repeat:
+ case kRight:
+ {
+ cChannel *channel = Channels.GetByNumber(*value + delta, delta);
+ if (channel) {
+ *value = channel->Number();
+ Set();
+ }
+ }
+ break;
+ default : return cMenuEditIntItem::ProcessKey(Key);
+ }
+ return osContinue;
+}
+
// --- cMenuEditTranItem -----------------------------------------------------
class cMenuEditTranItem : public cMenuEditChanItem {
@@ -597,17 +618,14 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
class cMenuChannelItem : public cOsdItem {
private:
- int index;
cChannel *channel;
public:
- cMenuChannelItem(int Index, cChannel *Channel);
+ cMenuChannelItem(cChannel *Channel);
virtual void Set(void);
- void SetIndex(int Index);
};
-cMenuChannelItem::cMenuChannelItem(int Index, cChannel *Channel)
+cMenuChannelItem::cMenuChannelItem(cChannel *Channel)
{
- index = Index;
channel = Channel;
if (channel->GroupSep())
SetColor(clrCyan, clrBackground);
@@ -624,15 +642,11 @@ void cMenuChannelItem::Set(void)
SetText(buffer, false);
}
-void cMenuChannelItem::SetIndex(int Index)
-{
- index = Index;
- Set();
-}
-
// --- cMenuChannels ---------------------------------------------------------
class cMenuChannels : public cOsdMenu {
+private:
+ void Propagate(void);
protected:
eOSState Switch(void);
eOSState Edit(void);
@@ -653,12 +667,22 @@ cMenuChannels::cMenuChannels(void)
int curr = ((channel = Channels.GetByNumber(cDevice::CurrentChannel())) != NULL) ? channel->Index() : -1;
while ((channel = Channels.Get(i)) != NULL) {
- Add(new cMenuChannelItem(i, channel), i == curr);
+ Add(new cMenuChannelItem(channel), i == curr);
i++;
}
SetHelp(tr("Edit"), tr("New"), tr("Delete"), tr("Mark"));
}
+void cMenuChannels::Propagate(void)
+{
+ Channels.ReNumber();
+ Channels.Save();
+ for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
+ ci->Set();
+ Timers.Save(); // channel numbering has changed!
+ Display();
+}
+
eOSState cMenuChannels::Switch(void)
{
cChannel *ch = Channels.Get(Current());
@@ -671,8 +695,12 @@ eOSState cMenuChannels::Edit(void)
{
if (HasSubMenu() || Count() == 0)
return osContinue;
- isyslog("editing channel %d", Current() + 1);
- return AddSubMenu(new cMenuEditChannel(Current()));
+ cChannel *ch = Channels.Get(Current());
+ if (ch) {
+ isyslog("editing channel %d", ch->Number());
+ return AddSubMenu(new cMenuEditChannel(Current()));
+ }
+ return osContinue;
}
eOSState cMenuChannels::New(void)
@@ -682,7 +710,7 @@ eOSState cMenuChannels::New(void)
cChannel *channel = new cChannel(Channels.Get(Current()));
Channels.Add(channel);
Channels.ReNumber();
- Add(new cMenuChannelItem(channel->Index()/*XXX*/, channel), true);
+ Add(new cMenuChannelItem(channel), true);
Channels.Save();
isyslog("channel %d added", channel->Number());
return AddSubMenu(new cMenuEditChannel(Current()));
@@ -695,36 +723,17 @@ eOSState cMenuChannels::Del(void)
cChannel *channel = Channels.Get(Index);
int DeletedChannel = channel->Number();
// Check if there is a timer using this channel:
- for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
- if (ti->channel == DeletedChannel) {
+ for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) {
+ if (ti->Channel() == channel) {
Interface->Error(tr("Channel is being used by a timer!"));
return osContinue;
}
}
if (Interface->Confirm(tr("Delete channel?"))) {
- // Move and renumber the channels:
Channels.Del(channel);
- Channels.ReNumber();
cOsdMenu::Del(Index);
- int i = 0;
- for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
- ci->SetIndex(i++);
- Channels.Save();
+ Propagate();
isyslog("channel %d deleted", DeletedChannel);
- // Fix the timers:
- bool TimersModified = false;
- for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
- int OldChannel = ti->channel;
- if (ti->channel > DeletedChannel)
- ti->channel--;
- if (ti->channel != OldChannel) {
- TimersModified = true;
- isyslog("timer %d: channel changed from %d to %d", ti->Index() + 1, OldChannel, ti->channel);
- }
- }
- if (TimersModified)
- Timers.Save();
- Display();
}
}
return osContinue;
@@ -734,35 +743,10 @@ void cMenuChannels::Move(int From, int To)
{
int FromNumber = Channels.Get(From)->Number();
int ToNumber = Channels.Get(To)->Number();
- // Move and renumber the channels:
Channels.Move(From, To);
- Channels.ReNumber();
cOsdMenu::Move(From, To);
- int i = 0;
- for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
- ci->SetIndex(i++);
- Channels.Save();
+ Propagate();
isyslog("channel %d moved to %d", FromNumber, ToNumber);
- // Fix the timers:
- bool TimersModified = false;
- From++; // user visible channel numbers start with '1'
- To++;
- for (cTimer *ti = Timers.First(); ti; ti = (cTimer *)ti->Next()) {
- int OldChannel = ti->channel;
- if (ti->channel == FromNumber)
- ti->channel = ToNumber;
- else if (ti->channel > FromNumber && ti->channel <= ToNumber)
- ti->channel--;
- else if (ti->channel < FromNumber && ti->channel >= ToNumber)
- ti->channel++;
- if (ti->channel != OldChannel) {
- TimersModified = true;
- isyslog("timer %d: channel changed from %d to %d", ti->Index() + 1, OldChannel, ti->channel);
- }
- }
- if (TimersModified)
- Timers.Save();
- Display();
}
eOSState cMenuChannels::ProcessKey(eKeys Key)
@@ -815,6 +799,7 @@ class cMenuEditTimer : public cOsdMenu {
private:
cTimer *timer;
cTimer data;
+ int channel;
cMenuEditDateItem *firstday;
void SetFirstDayItem(void);
public:
@@ -831,12 +816,12 @@ cMenuEditTimer::cMenuEditTimer(int Index, bool New)
data = *timer;
if (New)
data.active = 1;
+ channel = data.Channel()->Number();
Add(new cMenuEditBoolItem(tr("Active"), &data.active));
- Add(new cMenuEditChanItem(tr("Channel"), &data.channel));
+ Add(new cMenuEditChanItem(tr("Channel"), &channel));
Add(new cMenuEditDayItem( tr("Day"), &data.day));
Add(new cMenuEditTimeItem(tr("Start"), &data.start));
Add(new cMenuEditTimeItem(tr("Stop"), &data.stop));
-//TODO VPS???
Add(new cMenuEditIntItem( tr("Priority"), &data.priority, 0, MAXPRIORITY));
Add(new cMenuEditIntItem( tr("Lifetime"), &data.lifetime, 0, MAXLIFETIME));
Add(new cMenuEditStrItem( tr("File"), data.file, sizeof(data.file), tr(FileNameChars)));
@@ -864,15 +849,24 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
if (state == osUnknown) {
switch (Key) {
- case kOk: if (!*data.file)
- strcpy(data.file, Channels.GetChannelNameByNumber(data.channel));
- if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
- *timer = data;
- if (timer->active)
- timer->active = 1; // allows external programs to mark active timers with values > 1 and recognize if the user has modified them
- Timers.Save();
- isyslog("timer %d modified (%s)", timer->Index() + 1, timer->active ? "active" : "inactive");
- }
+ case kOk: {
+ cChannel *ch = Channels.GetByNumber(channel);
+ if (ch)
+ data.channel = ch;
+ else {
+ Interface->Error(tr("*** Invalid Channel ***"));
+ break;
+ }
+ if (!*data.file)
+ strcpy(data.file, data.Channel()->Name());
+ if (timer && memcmp(timer, &data, sizeof(data)) != 0) {
+ *timer = data;
+ if (timer->active)
+ timer->active = 1; // allows external programs to mark active timers with values > 1 and recognize if the user has modified them
+ Timers.Save();
+ isyslog("timer %d modified (%s)", timer->Index() + 1, timer->active ? "active" : "inactive");
+ }
+ }
return osBack;
case kRed:
case kGreen:
@@ -913,14 +907,14 @@ void cMenuTimerItem::Set(void)
{
char *buffer = NULL;
asprintf(&buffer, "%c\t%d\t%s\t%02d:%02d\t%02d:%02d\t%s",
- !timer->active ? ' ' : timer->firstday ? '!' : timer->recording ? '#' : '>',
- timer->channel,
- timer->PrintDay(timer->day),
- timer->start / 100,
- timer->start % 100,
- timer->stop / 100,
- timer->stop % 100,
- timer->file);
+ !timer->Active() ? ' ' : timer->FirstDay() ? '!' : timer->Recording() ? '#' : '>',
+ timer->Channel()->Number(),
+ timer->PrintDay(timer->Day()),
+ timer->Start() / 100,
+ timer->Start() % 100,
+ timer->Stop() / 100,
+ timer->Stop() % 100,
+ timer->File());
SetText(buffer, false);
}
@@ -965,23 +959,13 @@ eOSState cMenuTimers::OnOff(void)
{
cTimer *timer = CurrentTimer();
if (timer) {
- if (timer->IsSingleEvent())
- timer->active = !timer->active;
- else if (timer->firstday) {
- timer->firstday = 0;
- timer->active = false;
- }
- else if (timer->active)
- timer->Skip();
- else
- timer->active = true;
- timer->Matches(); // refresh start and end time
+ timer->OnOff();
RefreshCurrent();
DisplayCurrent(true);
- if (timer->firstday)
+ if (timer->FirstDay())
isyslog("timer %d first day set to %s", timer->Index() + 1, timer->PrintFirstDay());
else
- isyslog("timer %d %sactivated", timer->Index() + 1, timer->active ? "" : "de");
+ isyslog("timer %d %sactivated", timer->Index() + 1, timer->Active() ? "" : "de");
Timers.Save();
}
return osContinue;
@@ -1012,7 +996,7 @@ eOSState cMenuTimers::Del(void)
// Check if this timer is active:
cTimer *ti = CurrentTimer();
if (ti) {
- if (!ti->recording) {
+ if (!ti->Recording()) {
if (Interface->Confirm(tr("Delete timer?"))) {
int Index = ti->Index();
Timers.Del(ti);
@@ -1042,8 +1026,8 @@ eOSState cMenuTimers::Summary(void)
if (HasSubMenu() || Count() == 0)
return osContinue;
cTimer *ti = CurrentTimer();
- if (ti && ti->summary && *ti->summary)
- return AddSubMenu(new cMenuText(tr("Summary"), ti->summary));
+ if (ti && !isempty(ti->Summary()))
+ return AddSubMenu(new cMenuText(tr("Summary"), ti->Summary()));
return Edit(); // convenience for people not using the Summary feature ;-)
}
@@ -1242,6 +1226,7 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key)
if (state == osUnknown) {
switch (Key) {
+ case kRecord:
case kRed: return Record();
case kYellow: state = osBack;
// continue with kGreen
@@ -1385,6 +1370,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
if (state == osUnknown) {
switch (Key) {
+ case kRecord:
case kRed: return Record();
case kGreen: if (schedules) {
if (!now && !next) {
@@ -2178,7 +2164,12 @@ cMenuMain::cMenuMain(bool Replaying, eOSState State)
// Initial submenus:
switch (State) {
+ case osSchedule: AddSubMenu(new cMenuSchedule); break;
+ case osChannels: AddSubMenu(new cMenuChannels); break;
+ case osTimers: AddSubMenu(new cMenuTimers); break;
case osRecordings: AddSubMenu(new cMenuRecordings(NULL, 0, true)); break;
+ case osSetup: AddSubMenu(new cMenuSetup); break;
+ case osCommands: AddSubMenu(new cMenuCommands(tr("Commands"), &Commands)); break;
default: break;
}
}
@@ -2305,6 +2296,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
}
break;
default: switch (Key) {
+ case kRecord:
case kRed: if (!HasSubMenu())
state = osRecord;
break;
@@ -2367,6 +2359,7 @@ cDisplayChannel::cDisplayChannel(eKeys FirstKey)
:cOsdObject(true)
{
group = -1;
+ lines = 0;
number = 0;
lastTime = time_ms();
int EpgLines = Setup.ShowInfoOnChSwitch ? 5 : 1;
@@ -2383,10 +2376,17 @@ void cDisplayChannel::DisplayChannel(const cChannel *Channel)
{
int BufSize = Width() + 1;
char buffer[BufSize];
- if (Channel && Channel->Number() > 0)
- snprintf(buffer, BufSize, "%d%s %s", Channel->Number(), number ? "-" : "", Channel->Name());
+ *buffer = 0;
+ if (Channel) {
+ if (Channel->Number() > 0)
+ snprintf(buffer, BufSize, "%d%s %s", Channel->Number(), number ? "-" : "", Channel->Name());
+ else if (Channel->Name())
+ snprintf(buffer, BufSize, "%s", Channel->Name());
+ }
+ else if (number)
+ snprintf(buffer, BufSize, "%d-", number);
else
- snprintf(buffer, BufSize, "%s", Channel ? Channel->Name() : tr("*** Invalid Channel ***"));
+ snprintf(buffer, BufSize, "%s", tr("*** Invalid Channel ***"));
Interface->Fill(0, 0, Setup.OSDwidth, 1, clrBackground);
Interface->Write(0, 0, buffer);
const char *date = DayDateTime();
@@ -2452,6 +2452,14 @@ void cDisplayChannel::DisplayInfo(void)
}
}
+void cDisplayChannel::Refresh(void)
+{
+ Interface->Clear();
+ DisplayChannel(Channels.GetByNumber(cDevice::CurrentChannel()));
+ lastTime = time_ms();
+ lines = 0;
+}
+
eOSState cDisplayChannel::ProcessKey(eKeys Key)
{
switch (Key) {
@@ -2468,10 +2476,6 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
cChannel *channel = Channels.GetByNumber(number);
DisplayChannel(channel);
lastTime = time_ms();
- if (!channel) {
- number = -1;
- lastTime += 1000;
- }
}
}
break;
@@ -2503,10 +2507,28 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
}
lastTime = time_ms();
break;
+ case kUp|k_Repeat:
+ case kUp:
+ case kDown|k_Repeat:
+ case kDown:
+ cDevice::SwitchChannel(NORMALKEY(Key) == kUp ? 1 : -1);
+ // no break here
+ case kChanUp|k_Repeat:
+ case kChanUp:
+ case kChanDn|k_Repeat:
+ case kChanDn:
+ Refresh();
+ break;
case kNone:
if (number && time_ms() - lastTime > DIRECTCHANNELTIMEOUT) {
- if (number > 0 && !Channels.SwitchTo(number))
- number = -1;
+ if (Channels.GetByNumber(number))
+ Channels.SwitchTo(number);
+ else {
+ number = 0;
+ DisplayChannel(NULL);
+ lastTime = time_ms();
+ return osContinue;
+ }
return osEnd;
}
break;
@@ -2516,7 +2538,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
case kOk: if (group >= 0)
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->Number());
return osEnd;
- default: if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown || (Key & (k_Repeat | k_Release)) == 0) {
+ default: if ((Key & (k_Repeat | k_Release)) == 0) {
cRemote::Put(Key);
return osEnd;
}
@@ -2646,7 +2668,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
timer = new cTimer(true);
Timers.Add(timer);
Timers.Save();
- asprintf(&instantId, cDevice::NumDevices() > 1 ? "%s - %d" : "%s", Channels.GetChannelNameByNumber(timer->channel), device->CardIndex() + 1);
+ asprintf(&instantId, cDevice::NumDevices() > 1 ? "%s - %d" : "%s", timer->Channel()->Name(), device->CardIndex() + 1);
}
timer->SetPending(true);
timer->SetRecording(true);
@@ -2663,8 +2685,8 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
cRecording Recording(timer, Title, Subtitle, Summary);
fileName = strdup(Recording.FileName());
cRecordingUserCommand::InvokeCommand(RUC_BEFORERECORDING, fileName);
- cChannel *ch = Channels.GetByNumber(timer->channel);
- recorder = new cRecorder(fileName, ch->Ca(), timer->priority, ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2());
+ const cChannel *ch = timer->Channel();
+ recorder = new cRecorder(fileName, ch->Ca(), timer->Priority(), ch->Vpid(), ch->Apid1(), ch->Apid2(), ch->Dpid1(), ch->Dpid2());
if (device->AttachReceiver(recorder)) {
Recording.WriteSummary();
cStatus::MsgRecording(device, Recording.Name());
@@ -2684,8 +2706,8 @@ cRecordControl::~cRecordControl()
bool cRecordControl::GetEventInfo(void)
{
- cChannel *channel = Channels.GetByNumber(timer->channel);
- time_t Time = timer->active == taActInst ? timer->StartTime() + INSTANT_REC_EPG_LOOKAHEAD : timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2;
+ const cChannel *channel = timer->Channel();
+ time_t Time = timer->Active() == taActInst ? timer->StartTime() + INSTANT_REC_EPG_LOOKAHEAD : timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2;
for (int seconds = 0; seconds <= MAXWAIT4EPGINFO; seconds++) {
{
cMutexLock MutexLock;
@@ -2730,7 +2752,7 @@ bool cRecordControl::Process(time_t t)
{
if (!recorder || !timer || !timer->Matches(t))
return false;
- AssertFreeDiskSpace(timer->priority);
+ AssertFreeDiskSpace(timer->Priority());
return true;
}
@@ -2740,12 +2762,12 @@ cRecordControl *cRecordControls::RecordControls[MAXRECORDCONTROLS] = { NULL };
bool cRecordControls::Start(cTimer *Timer)
{
- int ch = Timer ? Timer->channel : cDevice::CurrentChannel();
+ int ch = Timer ? Timer->Channel()->Number() : cDevice::CurrentChannel();
cChannel *channel = Channels.GetByNumber(ch);
if (channel) {
bool NeedsDetachReceivers = false;
- cDevice *device = cDevice::GetDevice(channel, Timer ? Timer->priority : Setup.DefaultPriority, &NeedsDetachReceivers);
+ cDevice *device = cDevice::GetDevice(channel, Timer ? Timer->Priority() : Setup.DefaultPriority, &NeedsDetachReceivers);
if (device) {
if (NeedsDetachReceivers)
Stop(device);
@@ -2760,7 +2782,7 @@ bool cRecordControls::Start(cTimer *Timer)
}
}
}
- else if (!Timer || (Timer->priority >= Setup.PrimaryLimit && !Timer->pending))
+ else if (!Timer || (Timer->Priority() >= Setup.PrimaryLimit && !Timer->Pending()))
isyslog("no free DVB device to record channel %d!", ch);
}
else
@@ -3087,19 +3109,23 @@ void cReplayControl::TimeSearchProcess(eKeys Key)
TimeSearchDisplay();
}
break;
+ case kFastRew:
case kLeft:
+ case kFastFwd:
case kRight: {
- int dir = (Key == kRight ? 1 : -1);
+ int dir = ((Key == kRight || Key == kFastFwd) ? 1 : -1);
if (dir > 0)
Seconds = min(Total - Current - STAY_SECONDS_OFF_END, Seconds);
SkipSeconds(Seconds * dir);
timeSearchActive = false;
}
break;
+ case kPlay:
case kUp:
+ case kPause:
case kDown:
Seconds = min(Total - STAY_SECONDS_OFF_END, Seconds);
- Goto(Seconds * FRAMESPERSEC, Key == kDown);
+ Goto(Seconds * FRAMESPERSEC, Key == kDown || Key == kPause);
timeSearchActive = false;
break;
default:
@@ -3244,19 +3270,26 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
bool DoShowMode = true;
switch (Key) {
// Positioning:
+ case kPlay:
case kUp: Play(); break;
+ case kPause:
case kDown: Pause(); break;
+ case kFastRew|k_Release:
case kLeft|k_Release:
if (Setup.MultiSpeedMode) break;
+ case kFastRew:
case kLeft: Backward(); break;
+ case kFastFwd|k_Release:
case kRight|k_Release:
if (Setup.MultiSpeedMode) break;
+ case kFastFwd:
case kRight: Forward(); break;
case kRed: TimeSearch(); break;
case kGreen|k_Repeat:
case kGreen: SkipSeconds(-60); break;
case kYellow|k_Repeat:
case kYellow: SkipSeconds( 60); break;
+ case kStop:
case kBlue: Hide();
Stop();
return osEnd;
diff --git a/menu.h b/menu.h
index ba3c3d5..be70e53 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.48 2002/10/13 10:34:09 kls Exp $
+ * $Id: menu.h 1.49 2002/10/27 12:04:49 kls Exp $
*/
#ifndef __MENU_H
@@ -35,6 +35,7 @@ private:
int number;
void DisplayChannel(const cChannel *Channel);
void DisplayInfo(void);
+ void Refresh(void);
public:
cDisplayChannel(int Number, bool Switched);
cDisplayChannel(eKeys FirstKey);
diff --git a/newplugin b/newplugin
index e9bfc85..3a4586c 100755
--- a/newplugin
+++ b/newplugin
@@ -12,7 +12,7 @@
# See the main source file 'vdr.c' for copyright information and
# how to reach the author.
#
-# $Id: newplugin 1.8 2002/09/17 15:24:23 kls Exp $
+# $Id: newplugin 1.9 2002/10/26 14:32:12 kls Exp $
$PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
@@ -174,7 +174,7 @@ public:
cPlugin${PLUGIN_CLASS}::cPlugin$PLUGIN_CLASS(void)
{
- // Initialize any member varaiables here.
+ // Initialize any member variables here.
// DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
// VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
}
diff --git a/recording.c b/recording.c
index 1be6623..ba85ded 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.69 2002/10/13 09:08:45 kls Exp $
+ * $Id: recording.c 1.70 2002/10/20 11:54:29 kls Exp $
*/
#include "recording.h"
@@ -307,13 +307,13 @@ cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, c
name = NULL;
// set up the actual name:
if (isempty(Title))
- Title = Channels.GetChannelNameByNumber(Timer->channel);
+ Title = Timer->Channel()->Name();
if (isempty(Subtitle))
Subtitle = " ";
- char *macroTITLE = strstr(Timer->file, TIMERMACRO_TITLE);
- char *macroEPISODE = strstr(Timer->file, TIMERMACRO_EPISODE);
+ char *macroTITLE = strstr(Timer->File(), TIMERMACRO_TITLE);
+ char *macroEPISODE = strstr(Timer->File(), TIMERMACRO_EPISODE);
if (macroTITLE || macroEPISODE) {
- name = strdup(Timer->file);
+ name = strdup(Timer->File());
name = strreplace(name, TIMERMACRO_TITLE, Title);
name = strreplace(name, TIMERMACRO_EPISODE, Subtitle);
if (Timer->IsSingleEvent()) {
@@ -322,16 +322,16 @@ cRecording::cRecording(cTimer *Timer, const char *Title, const char *Subtitle, c
}
}
else if (Timer->IsSingleEvent() || !Setup.UseSubtitle)
- name = strdup(Timer->file);
+ name = strdup(Timer->File());
else
- asprintf(&name, "%s~%s", Timer->file, Subtitle);
+ asprintf(&name, "%s~%s", Timer->File(), Subtitle);
// substitute characters that would cause problems in file names:
strreplace(name, '\n', ' ');
start = Timer->StartTime();
- priority = Timer->priority;
- lifetime = Timer->lifetime;
+ priority = Timer->Priority();
+ lifetime = Timer->Lifetime();
// handle summary:
- summary = !isempty(Timer->summary) ? strdup(Timer->summary) : NULL;
+ summary = !isempty(Timer->Summary()) ? strdup(Timer->Summary()) : NULL;
if (!summary) {
if (isempty(Subtitle))
Subtitle = "";
diff --git a/recording.h b/recording.h
index 2fae49e..82f2fcc 100644
--- a/recording.h
+++ b/recording.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: recording.h 1.24 2002/06/22 10:09:27 kls Exp $
+ * $Id: recording.h 1.25 2002/10/19 15:48:52 kls Exp $
*/
#ifndef __RECORDING_H
@@ -12,6 +12,7 @@
#include <time.h>
#include "config.h"
+#include "timers.h"
#include "tools.h"
void RemoveDeletedRecordings(void);
diff --git a/remote.c b/remote.c
index 05ce606..6078c26 100644
--- a/remote.c
+++ b/remote.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: remote.c 1.29 2002/10/12 15:22:08 kls Exp $
+ * $Id: remote.c 1.30 2002/10/27 15:15:58 kls Exp $
*/
#include "remote.h"
@@ -84,6 +84,22 @@ bool cRemote::Put(eKeys Key)
return true; // only a real key shall report an overflow!
}
+bool cRemote::PutMacro(eKeys Key)
+{
+ const cKeyMacro *km = KeyMacros.Get(Key);
+ if (km) {
+ for (int i = 1; i < MAXKEYSINMACRO; i++) {
+ if (km->Macro()[i] != kNone) {
+ if (!Put(km->Macro()[i]))
+ return false;
+ }
+ else
+ break;
+ }
+ }
+ return true;
+}
+
bool cRemote::Put(uint64 Code, bool Repeat, bool Release)
{
char buffer[32];
diff --git a/remote.h b/remote.h
index f715ade..2bb9ea5 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.17 2002/09/29 11:26:45 kls Exp $
+ * $Id: remote.h 1.18 2002/10/27 15:16:50 kls Exp $
*/
#ifndef __REMOTE_H
@@ -20,7 +20,7 @@ typedef unsigned long long int uint64;
class cRemote : public cListObject {
private:
- enum { MaxKeys = 16 };
+ enum { MaxKeys = MAXKEYSINMACRO };
static eKeys keys[MaxKeys];
static int in;
static int out;
@@ -42,6 +42,7 @@ public:
static void SetLearning(bool On) { learning = On; }
static void Clear(void);
static bool Put(eKeys Key);
+ static bool PutMacro(eKeys Key);
static eKeys Get(int WaitMs = 1000, char **UnknownCode = NULL);
};
diff --git a/sources.conf b/sources.conf
index f30e52f..90a7573 100644
--- a/sources.conf
+++ b/sources.conf
@@ -4,6 +4,14 @@
#
# code description
#
+# S (satellite) xy.z (orbital position in degrees) E or W (east or west)
+# Note: only the first part is actually used by VDR. The description part
+# is for the "human" interface for clarity.
+#
+# '&' means same orbital position but different host company.
+# '/' means same (or very little deviation) orbital position & host.
+# A value in () means this satellite is still in it's test phase.
+#
# Please contact kls@cadsoft.de before assigning a new code
# to a description, in order to keep them unique.
@@ -12,34 +20,66 @@
S5E Sirius 2/3
S7E Eutelsat W3
S10E Eutelsat W1R
-S13E Hotbird 1-5
+S13E Hotbird 1-(5)-6
S16E Eutelsat W2
-S19.2E Astra 1
-S23.5E Astra 3
+S19.2E Astra 1B/C/E/F/G/H/2C
+S21.5E Eutelsat II F3
+S23.5E Astra 3A
+S24.2E Astra 1D
S26E Arabsat 2A/3A
-S28.2E Astra 2
+S28.2E Astra 2D/A/B
S28.5E Eurobird
-S30.E Arabsat 30.5E
-S31.3 Türksat 1B
-S36E Eutelsat W4 / Sesat
-S42E Turksat 1C / Eurasiasat
+S30.5E Arabsat 2B
+S31.3E Türksat 1B
+S36E Eutelsat W4 & Sesat
+S39E Hellas Sat
+S40E Express A1R
+S42E Turksat 1C & EurAsiaSat 1 & NewSat 1
+S45E Europe*Star 1
+S47E Telecom 2B
+S48E Eutelsat II F1
+S50E Anatolia 1
+S53E Gorizont 32
+S55.1E Insat 2DT
+S56E Most 1
+S57E NSS 703
+S60E Intelsat 904
+S62E Intelsat 902
+S64E Intelsat 906
+S66E Intelsat 704
+S68.5E PAS 7/10
+S72E PAS 4
+S74E Insat 3C
+S75E LMI 1
+S76.5E Apstar
+S78.5E Thaicom 2/3
+S80E Express 6A
+S83E Insat 2E/3B
-S1W Thor 2/3 / Intelsat 707
+S1W Thor 2/3 & Intelsat 707
S4W Amos 1
-S5W Telecom 2C
-S7W Nilesat 101/102
-S8W Atlantic bird 2 / Telecom 2D
+S5W Telecom 2C & Atlantic Bird 3
+S7W Nilesat 101 & 102
+S8W Telecom 2A/2D & Atlantic Bird 2
S11W Express 3A
-S14W Express 2
+S12.5W Eutelsat II F2
+S14W Gorizont 26
S15W Telstar 12
-S18W Intelsat
-S21W NSS 803
-S27.W Intelsat 27.5W
+S18W Intelsat 901
+S21.5W NSS 7
+S27.5W Intelsat 605
S30W Hispasat 1
-S31.5W Intelsat 31.5W
-S34.5W Intelsat 34.5W
+S31.5W Intelsat 801
+S34.5W Intelsat 903
S37.5W Telstar 11
-S43W PAS
+S40.5W NSS 806
+S43W PAS 3R/6/6B
+S45W PAS 1/5R
+S47W TDRS 6
+S53W Intelsat 706
+S55.5W Intelsat 805
+S58W PAS 9
+S61.5W Echostar 3
# Cable
diff --git a/svdrp.c b/svdrp.c
index 4117149..2859fb9 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.45 2002/10/13 09:31:31 kls Exp $
+ * $Id: svdrp.c 1.48 2002/10/20 12:45:03 kls Exp $
*/
#include "svdrp.h"
@@ -31,6 +31,7 @@
#include "device.h"
#include "keys.h"
#include "remote.h"
+#include "timers.h"
#include "tools.h"
// --- cSocket ---------------------------------------------------------------
@@ -413,12 +414,12 @@ void cSVDRP::CmdCHAN(const char *Option)
else {
int i = 1;
cChannel *channel;
- while ((channel = Channels.GetByNumber(i)) != NULL) {
+ while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
if (strcasecmp(channel->Name(), Option) == 0) {
n = i;
break;
}
- i++;
+ i = channel->Number() + 1;
}
}
if (n < 0) {
@@ -487,7 +488,7 @@ void cSVDRP::CmdDELT(const char *Option)
if (isnumber(Option)) {
cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1);
if (timer) {
- if (!timer->recording) {
+ if (!timer->Recording()) {
Timers.Del(timer);
Timers.Save();
isyslog("timer %s deleted", Option);
@@ -640,7 +641,7 @@ void cSVDRP::CmdLSTC(const char *Option)
int i = 1;
cChannel *next = NULL;
while (i <= Channels.MaxNumber()) {
- cChannel *channel = Channels.GetByNumber(i);
+ cChannel *channel = Channels.GetByNumber(i, 1);
if (channel) {
if (strcasestr(channel->Name(), Option)) {
if (next)
@@ -652,7 +653,7 @@ void cSVDRP::CmdLSTC(const char *Option)
Reply(501, "Channel \"%d\" not found", i);
return;
}
- i++;
+ i = channel->Number() + 1;
}
if (next)
Reply(250, "%d %s", next->Number(), next->ToText());
@@ -661,13 +662,15 @@ void cSVDRP::CmdLSTC(const char *Option)
}
}
else if (Channels.MaxNumber() >= 1) {
- for (int i = 1; i <= Channels.MaxNumber(); i++) {
- cChannel *channel = Channels.GetByNumber(i);
- if (channel)
- Reply(i < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->Number(), channel->ToText());
- else
- Reply(501, "Channel \"%d\" not found", i);
- }
+ int i = 1;
+ while (i <= Channels.MaxNumber()) {
+ cChannel *channel = Channels.GetByNumber(i, 1);
+ if (channel)
+ Reply(channel->Number() < Channels.MaxNumber() ? -250 : 250, "%d %s", channel->Number(), channel->ToText());
+ else
+ Reply(501, "Channel \"%d\" not found", i);
+ i = channel->Number() + 1;
+ }
}
else
Reply(550, "No channels defined");
@@ -804,16 +807,16 @@ void cSVDRP::CmdMODT(const char *Option)
if (timer) {
cTimer t = *timer;
if (strcasecmp(tail, "ON") == 0)
- t.active = 1;
+ t.SetActive(taActive);
else if (strcasecmp(tail, "OFF") == 0)
- t.active = 0;
+ t.SetActive(taInactive);
else if (!t.Parse(tail)) {
Reply(501, "Error in timer settings");
return;
}
*timer = t;
Timers.Save();
- isyslog("timer %d modified (%s)", timer->Index() + 1, timer->active ? "active" : "inactive");
+ isyslog("timer %d modified (%s)", timer->Index() + 1, timer->Active() ? "active" : "inactive");
Reply(250, "%d %s", timer->Index() + 1, timer->ToText());
}
else
@@ -1009,7 +1012,7 @@ void cSVDRP::Execute(char *Cmd)
else Reply(500, "Command unrecognized: \"%s\"", Cmd);
}
-void cSVDRP::Process(void)
+bool cSVDRP::Process(void)
{
bool NewConnection = !file.IsOpen();
bool SendGreeting = NewConnection;
@@ -1070,7 +1073,9 @@ void cSVDRP::Process(void)
isyslog("timeout on SVDRP connection");
Close(true);
}
+ return true;
}
+ return false;
}
char *cSVDRP::GetMessage(void)
diff --git a/svdrp.h b/svdrp.h
index 879fb64..8b673df 100644
--- a/svdrp.h
+++ b/svdrp.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: svdrp.h 1.16 2002/08/25 10:35:25 kls Exp $
+ * $Id: svdrp.h 1.17 2002/10/20 12:44:42 kls Exp $
*/
#ifndef __SVDRP_H
@@ -79,7 +79,7 @@ private:
public:
cSVDRP(int Port);
~cSVDRP();
- void Process(void);
+ bool Process(void);
char *GetMessage(void);
};
diff --git a/timers.c b/timers.c
new file mode 100644
index 0000000..76f86a5
--- /dev/null
+++ b/timers.c
@@ -0,0 +1,408 @@
+/*
+ * timers.c: Timer handling
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: timers.c 1.1 2002/10/20 12:28:55 kls Exp $
+ */
+
+#include "timers.h"
+#include <ctype.h>
+#include "channels.h"
+#include "i18n.h"
+
+// IMPORTANT NOTE: in the 'sscanf()' calls there is a blank after the '%d'
+// format characters in order to allow any number of blanks after a numeric
+// value!
+
+// -- cTimer -----------------------------------------------------------------
+
+char *cTimer::buffer = NULL;
+
+cTimer::cTimer(bool Instant)
+{
+ startTime = stopTime = 0;
+ recording = pending = false;
+ active = Instant ? taActInst : taInactive;
+ channel = Channels.GetByNumber(cDevice::CurrentChannel());
+ time_t t = time(NULL);
+ struct tm tm_r;
+ struct tm *now = localtime_r(&t, &tm_r);
+ day = now->tm_mday;
+ start = now->tm_hour * 100 + now->tm_min;
+ stop = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
+ stop = (stop / 60) * 100 + (stop % 60);
+ if (stop >= 2400)
+ stop -= 2400;
+ priority = Setup.DefaultPriority;
+ lifetime = Setup.DefaultLifetime;
+ *file = 0;
+ firstday = 0;
+ summary = NULL;
+ if (Instant && channel)
+ snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name());
+}
+
+cTimer::cTimer(const cEventInfo *EventInfo)
+{
+ startTime = stopTime = 0;
+ recording = pending = false;
+ active = true;
+ channel = Channels.GetByServiceID(EventInfo->GetServiceID());
+ time_t tstart = EventInfo->GetTime();
+ time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
+ tstart -= Setup.MarginStart * 60;
+ struct tm tm_r;
+ struct tm *time = localtime_r(&tstart, &tm_r);
+ day = time->tm_mday;
+ start = time->tm_hour * 100 + time->tm_min;
+ time = localtime_r(&tstop, &tm_r);
+ stop = time->tm_hour * 100 + time->tm_min;
+ if (stop >= 2400)
+ stop -= 2400;
+ priority = Setup.DefaultPriority;
+ lifetime = Setup.DefaultLifetime;
+ *file = 0;
+ const char *Title = EventInfo->GetTitle();
+ if (!isempty(Title))
+ strn0cpy(file, EventInfo->GetTitle(), sizeof(file));
+ firstday = 0;
+ summary = NULL;
+}
+
+cTimer::~cTimer()
+{
+ free(summary);
+}
+
+cTimer& cTimer::operator= (const cTimer &Timer)
+{
+ memcpy(this, &Timer, sizeof(*this));
+ if (summary)
+ summary = strdup(summary);
+ return *this;
+}
+
+bool cTimer::operator< (const cListObject &ListObject)
+{
+ cTimer *ti = (cTimer *)&ListObject;
+ time_t t1 = StartTime();
+ time_t t2 = ti->StartTime();
+ return t1 < t2 || (t1 == t2 && priority > ti->priority);
+}
+
+const char *cTimer::ToText(cTimer *Timer)
+{
+ free(buffer);
+ strreplace(Timer->file, ':', '|');
+ strreplace(Timer->summary, '\n', '|');
+ asprintf(&buffer, "%d:%d:%s:%04d:%04d:%d:%d:%s:%s\n", Timer->active, Timer->Channel()->Number(), PrintDay(Timer->day, Timer->firstday), Timer->start, Timer->stop, Timer->priority, Timer->lifetime, Timer->file, Timer->summary ? Timer->summary : "");
+ strreplace(Timer->summary, '|', '\n');
+ strreplace(Timer->file, '|', ':');
+ return buffer;
+}
+
+const char *cTimer::ToText(void)
+{
+ return ToText(this);
+}
+
+int cTimer::TimeToInt(int t)
+{
+ return (t / 100 * 60 + t % 100) * 60;
+}
+
+int cTimer::ParseDay(const char *s, time_t *FirstDay)
+{
+ char *tail;
+ int d = strtol(s, &tail, 10);
+ if (FirstDay)
+ *FirstDay = 0;
+ if (tail && *tail) {
+ d = 0;
+ if (tail == s) {
+ const char *first = strchr(s, '@');
+ int l = first ? first - s : strlen(s);
+ if (l == 7) {
+ for (const char *p = s + 6; p >= s; p--) {
+ d <<= 1;
+ d |= (*p != '-');
+ }
+ d |= 0x80000000;
+ }
+ if (FirstDay && first) {
+ ++first;
+ if (strlen(first) == 10) {
+ struct tm tm_r;
+ if (3 == sscanf(first, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
+ tm_r.tm_year -= 1900;
+ tm_r.tm_mon--;
+ tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
+ tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+ *FirstDay = mktime(&tm_r);
+ }
+ }
+ else
+ d = 0;
+ }
+ }
+ }
+ else if (d < 1 || d > 31)
+ d = 0;
+ return d;
+}
+
+const char *cTimer::PrintDay(int d, time_t FirstDay)
+{
+#define DAYBUFFERSIZE 32
+ static char buffer[DAYBUFFERSIZE];
+ if ((d & 0x80000000) != 0) {
+ char *b = buffer;
+ const char *w = tr("MTWTFSS");
+ while (*w) {
+ *b++ = (d & 1) ? *w : '-';
+ d >>= 1;
+ w++;
+ }
+ if (FirstDay) {
+ struct tm tm_r;
+ localtime_r(&FirstDay, &tm_r);
+ b += strftime(b, DAYBUFFERSIZE - (b - buffer), "@%Y-%m-%d", &tm_r);
+ }
+ *b = 0;
+ }
+ else
+ sprintf(buffer, "%d", d);
+ return buffer;
+}
+
+const char *cTimer::PrintFirstDay(void)
+{
+ if (firstday) {
+ const char *s = PrintDay(day, firstday);
+ if (strlen(s) == 18)
+ return s + 8;
+ }
+ return ""; // not NULL, so the caller can always use the result
+}
+
+bool cTimer::Parse(const char *s)
+{
+ char *buffer1 = NULL;
+ char *buffer2 = NULL;
+ free(summary);
+ summary = NULL;
+ //XXX Apparently sscanf() doesn't work correctly if the last %a argument
+ //XXX results in an empty string (this first occured when the EIT gathering
+ //XXX was put into a separate thread - don't know why this happens...
+ //XXX As a cure we copy the original string and add a blank.
+ //XXX If anybody can shed some light on why sscanf() failes here, I'd love
+ //XXX to hear about that!
+ char *s2 = NULL;
+ int l2 = strlen(s);
+ while (l2 > 0 && isspace(s[l2 - 1]))
+ l2--;
+ if (s[l2 - 1] == ':') {
+ s2 = MALLOC(char, l2 + 3);
+ strcat(strn0cpy(s2, s, l2 + 1), " \n");
+ s = s2;
+ }
+ int ch = 0;
+ if (8 <= sscanf(s, "%d :%d :%a[^:]:%d :%d :%d :%d :%a[^:\n]:%a[^\n]", &active, &ch, &buffer1, &start, &stop, &priority, &lifetime, &buffer2, &summary)) {
+ if (summary && !*skipspace(summary)) {
+ free(summary);
+ summary = NULL;
+ }
+ //TODO add more plausibility checks
+ day = ParseDay(buffer1, &firstday);
+ strn0cpy(file, buffer2, MaxFileName);
+ strreplace(file, '|', ':');
+ strreplace(summary, '|', '\n');
+ free(buffer1);
+ free(buffer2);
+ free(s2);
+ channel = Channels.GetByNumber(ch);
+ if (!channel) {
+ esyslog("ERROR: channel %d not defined", ch);
+ return false;
+ }
+ return day != 0;
+ }
+ free(s2);
+ return false;
+}
+
+bool cTimer::Save(FILE *f)
+{
+ return fprintf(f, ToText()) > 0;
+}
+
+bool cTimer::IsSingleEvent(void)
+{
+ return (day & 0x80000000) == 0;
+}
+
+int cTimer::GetMDay(time_t t)
+{
+ struct tm tm_r;
+ return localtime_r(&t, &tm_r)->tm_mday;
+}
+
+int cTimer::GetWDay(time_t t)
+{
+ struct tm tm_r;
+ int weekday = localtime_r(&t, &tm_r)->tm_wday;
+ return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
+}
+
+bool cTimer::DayMatches(time_t t)
+{
+ return IsSingleEvent() ? GetMDay(t) == day : (day & (1 << GetWDay(t))) != 0;
+}
+
+time_t cTimer::IncDay(time_t t, int Days)
+{
+ struct tm tm_r;
+ tm tm = *localtime_r(&t, &tm_r);
+ tm.tm_mday += Days; // now tm_mday may be out of its valid range
+ int h = tm.tm_hour; // save original hour to compensate for DST change
+ tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+ t = mktime(&tm); // normalize all values
+ tm.tm_hour = h; // compensate for DST change
+ return mktime(&tm); // calculate final result
+}
+
+time_t cTimer::SetTime(time_t t, int SecondsFromMidnight)
+{
+ struct tm tm_r;
+ tm tm = *localtime_r(&t, &tm_r);
+ tm.tm_hour = SecondsFromMidnight / 3600;
+ tm.tm_min = (SecondsFromMidnight % 3600) / 60;
+ tm.tm_sec = SecondsFromMidnight % 60;
+ tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+ return mktime(&tm);
+}
+
+char *cTimer::SetFile(const char *File)
+{
+ if (!isempty(File))
+ strn0cpy(file, File, sizeof(file));
+ return file;
+}
+
+bool cTimer::Matches(time_t t)
+{
+ startTime = stopTime = 0;
+ if (t == 0)
+ t = time(NULL);
+
+ int begin = TimeToInt(start); // seconds from midnight
+ int length = TimeToInt(stop) - begin;
+ if (length < 0)
+ length += SECSINDAY;
+
+ int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31
+ for (int i = -1; i <= DaysToCheck; i++) {
+ time_t t0 = IncDay(t, i);
+ if (DayMatches(t0)) {
+ time_t a = SetTime(t0, begin);
+ time_t b = a + length;
+ if ((!firstday || a >= firstday) && t <= b) {
+ startTime = a;
+ stopTime = b;
+ break;
+ }
+ }
+ }
+ if (!startTime)
+ startTime = firstday; // just to have something that's more than a week in the future
+ else if (t > startTime || t > firstday + SECSINDAY + 3600) // +3600 in case of DST change
+ firstday = 0;
+ return active && startTime <= t && t < stopTime; // must stop *before* stopTime to allow adjacent timers
+}
+
+time_t cTimer::StartTime(void)
+{
+ if (!startTime)
+ Matches();
+ return startTime;
+}
+
+time_t cTimer::StopTime(void)
+{
+ if (!stopTime)
+ Matches();
+ return stopTime;
+}
+
+void cTimer::SetRecording(bool Recording)
+{
+ recording = Recording;
+ isyslog("timer %d %s", Index() + 1, recording ? "start" : "stop");
+}
+
+void cTimer::SetPending(bool Pending)
+{
+ pending = Pending;
+}
+
+void cTimer::SetActive(int Active)
+{
+ active = Active;
+}
+
+void cTimer::Skip(void)
+{
+ firstday = IncDay(SetTime(StartTime(), 0), 1);
+}
+
+void cTimer::OnOff(void)
+{
+ if (IsSingleEvent())
+ active = !active;
+ else if (firstday) {
+ firstday = 0;
+ active = false;
+ }
+ else if (active)
+ Skip();
+ else
+ active = true;
+ Matches(); // refresh start and end time
+}
+
+// -- cTimers ----------------------------------------------------------------
+
+cTimers Timers;
+
+cTimer *cTimers::GetTimer(cTimer *Timer)
+{
+ for (cTimer *ti = First(); ti; ti = Next(ti)) {
+ if (ti->Channel() == Timer->Channel() && ti->Day() == Timer->Day() && ti->Start() == Timer->Start() && ti->Stop() == Timer->Stop())
+ return ti;
+ }
+ return NULL;
+}
+
+cTimer *cTimers::GetMatch(time_t t)
+{
+ cTimer *t0 = NULL;
+ for (cTimer *ti = First(); ti; ti = Next(ti)) {
+ if (!ti->Recording() && ti->Matches(t)) {
+ if (!t0 || ti->Priority() > t0->Priority())
+ t0 = ti;
+ }
+ }
+ return t0;
+}
+
+cTimer *cTimers::GetNextActiveTimer(void)
+{
+ cTimer *t0 = NULL;
+ for (cTimer *ti = First(); ti; ti = Next(ti)) {
+ if (ti->Active() && (!t0 || *ti < *t0))
+ t0 = ti;
+ }
+ return t0;
+}
diff --git a/timers.h b/timers.h
new file mode 100644
index 0000000..8dc762e
--- /dev/null
+++ b/timers.h
@@ -0,0 +1,91 @@
+/*
+ * timers.h: Timer handling
+ *
+ * See the main source file 'vdr.c' for copyright information and
+ * how to reach the author.
+ *
+ * $Id: timers.h 1.1 2002/10/20 11:52:23 kls Exp $
+ */
+
+#ifndef __TIMERS_H
+#define __TIMERS_H
+
+#include "channels.h"
+#include "config.h"
+#include "tools.h"
+
+enum eTimerActive { taInactive = 0,
+ taActive = 1,
+ taInstant = 2,
+ taActInst = (taActive | taInstant)
+ };
+
+class cTimer : public cListObject {
+ friend class cMenuEditTimer;
+private:
+ time_t startTime, stopTime;
+ static char *buffer;
+ bool recording, pending;
+ int active;
+ cChannel *channel;
+ int day;
+ int start;
+ int stop;
+ int priority;
+ int lifetime;
+ char file[MaxFileName];
+ time_t firstday;
+ char *summary;
+ static const char *ToText(cTimer *Timer);
+public:
+ cTimer(bool Instant = false);
+ cTimer(const cEventInfo *EventInfo);
+ virtual ~cTimer();
+ cTimer& operator= (const cTimer &Timer);
+ virtual bool operator< (const cListObject &ListObject);
+ bool Recording(void) { return recording; }
+ bool Pending(void) { return pending; }
+ int Active(void) { return active; }
+ const cChannel *Channel(void) { return channel; }
+ int Day(void) { return day; }
+ int Start(void) { return start; }
+ int Stop(void) { return stop; }
+ int Priority(void) { return priority; }
+ int Lifetime(void) { return lifetime; }
+ const char *File(void) { return file; }
+ time_t FirstDay(void) { return firstday; }
+ const char *Summary(void) { return summary; }
+ const char *ToText(void);
+ bool Parse(const char *s);
+ bool Save(FILE *f);
+ bool IsSingleEvent(void);
+ int GetMDay(time_t t);
+ int GetWDay(time_t t);
+ bool DayMatches(time_t t);
+ static time_t IncDay(time_t t, int Days);
+ static time_t SetTime(time_t t, int SecondsFromMidnight);
+ char *SetFile(const char *File);
+ bool Matches(time_t t = 0);
+ time_t StartTime(void);
+ time_t StopTime(void);
+ void SetRecording(bool Recording);
+ void SetPending(bool Pending);
+ void SetActive(int Active);
+ void Skip(void);
+ void OnOff(void);
+ const char *PrintFirstDay(void);
+ static int TimeToInt(int t);
+ static int ParseDay(const char *s, time_t *FirstDay = NULL);
+ static const char *PrintDay(int d, time_t FirstDay = 0);
+ };
+
+class cTimers : public cConfig<cTimer> {
+public:
+ cTimer *GetTimer(cTimer *Timer);
+ cTimer *GetMatch(time_t t);
+ cTimer *GetNextActiveTimer(void);
+ };
+
+extern cTimers Timers;
+
+#endif //__TIMERS_H
diff --git a/tools.c b/tools.c
index b3b64fc..df2d570 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.71 2002/09/09 21:35:49 kls Exp $
+ * $Id: tools.c 1.72 2002/10/19 12:32:53 kls Exp $
*/
#include "tools.h"
@@ -207,6 +207,13 @@ bool isempty(const char *s)
return !(s && *skipspace(s));
}
+int numdigits(int n)
+{
+ char buf[16];
+ snprintf(buf, sizeof(buf), "%d", n);
+ return strlen(buf);
+}
+
int time_ms(void)
{
static time_t t0 = 0;
diff --git a/tools.h b/tools.h
index f8bf43f..08f2429 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.50 2002/09/08 10:22:29 kls Exp $
+ * $Id: tools.h 1.51 2002/10/19 12:31:50 kls Exp $
*/
#ifndef __TOOLS_H
@@ -64,6 +64,7 @@ const char *strescape(const char *s, const char *chars); // returns a statically
bool startswith(const char *s, const char *p);
bool endswith(const char *s, const char *p);
bool isempty(const char *s);
+int numdigits(int n);
int time_ms(void);
void delay_ms(int ms);
bool isnumber(const char *s);
diff --git a/transfer.c b/transfer.c
index adb7260..ddfb28c 100644
--- a/transfer.c
+++ b/transfer.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: transfer.c 1.4 2002/10/12 13:32:48 kls Exp $
+ * $Id: transfer.c 1.6 2002/10/26 10:17:17 kls Exp $
*/
#include "transfer.h"
@@ -17,7 +17,7 @@
// --- cTransfer -------------------------------------------------------------
cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2)
-:cReceiver(0, 0, 5, VPid, APid1, APid2, DPid1, DPid2)
+:cReceiver(0, -1, 5, VPid, APid1, APid2, DPid1, DPid2)
{
ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, true);
remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2);
@@ -155,7 +155,7 @@ int cTransfer::NumAudioTracks(void) const
return canToggleAudioTrack ? 2 : 1;
}
-const char **cTransfer::GetAudioTracks(int *CurrentTrack = NULL) const
+const char **cTransfer::GetAudioTracks(int *CurrentTrack) const
{
if (NumAudioTracks()) {
if (CurrentTrack)
diff --git a/vdr.5 b/vdr.5
index ccb7b92..2db8a7b 100644
--- a/vdr.5
+++ b/vdr.5
@@ -8,9 +8,9 @@
.\" License as specified in the file COPYING that comes with the
.\" vdr distribution.
.\"
-.\" $Id: vdr.5 1.8 2002/10/13 12:14:49 kls Exp $
+.\" $Id: vdr.5 1.11 2002/10/27 15:36:44 kls Exp $
.\"
-.TH vdr 5 "7 Sep 2002" "1.2.0" "Video Disk Recorder Files"
+.TH vdr 5 "7 Oct 2002" "1.2.0" "Video Disk Recorder Files"
.SH NAME
vdr file formats - the Video Disk Recorder Files
.SH DESCRIPTION
@@ -26,12 +26,22 @@ character, followed by arbitrary text. Example:
\fB:First group\fR
+Group delimiters may also be used to specify the number of the next channel.
+To do this, the character '@' and a number must immediately follow the ':',
+as in
+
+\fB:@201 First group\fR
+
+The given number must be larger than the number of any previous channel
+(otherwise it is silently ignored).
+
A \fBchannel definition\fR is a line with channel data, where the fields
are separated by ':' characters. Example:
\fBRTL:12188:h:S19.2E:27500:163:104:105:0:12003\fR
-The line number of a channel definition (not counting group separators!)
+The line number of a channel definition (not counting group separators,
+and based on a possible previous '@...' parameter)
defines the channel's number in OSD menus and the \fItimers.conf\fR file.
The fields in a channel definition have the following meaning (from left
@@ -42,7 +52,9 @@ The channel's name (if the name originally contains a ':' character
it has to be replaced by '|').
.TP
.B Frequency
-The transponder frequency in MHz for DVB-S and DVB-C, kHz for DVB-T (as an integer).
+The transponder frequency (as an integer). For DVB-S this value is in MHz. For DVB-C
+and DVB-T it can be given either in MHz, kHz or Hz (the actual value given will be
+multiplied by 1000 until it is larger than 1000000).
.TP
.B Parameters
Various parameters, depending on whether this is a DVB-S, DVB-C or DVB-T channel.
@@ -311,6 +323,20 @@ PC keyboard, RCU for the home-built "Remote Control Unit", or LIRC for the
"Linux Infrared Remote Control"), \fBkey\fR is the name of the key that is
defined (like Up, Down, Menu etc.), and \fBcode\fR is a character string that
this remote control delivers when the given key is pressed.
+.SS KEY MACROS
+The file \fIkeymacros.conf\fR contains user defined macros that will be executed
+whenever the given key is pressed. The format is
+
+\fBmacrokey key1 key2 key3...\fR
+
+where \fBmacrokey\fR is the key that shall initiate execution of this macro
+and can be one of \fIRed\fR, \fIGreen\fR, \fIYellow\fR, \fIBlue\fR or
+\fIUser1\fR...\fIUser9\fR. The rest of the line consists of a set of
+keys, which will be executed just as if they had been pressed in the given
+sequence. Note that the color keys will only execute their macro function
+in "normal viewing" mode (i.e. when no other menu or player is active). The
+\fIUser1\fR...\fIUser9\fR keys will always execute their macro function.
+There may be up to 15 keys in such a key sequence.
.SS COMMANDS
The file \fIcommands.conf\fR contains the definitions of commands that can
be executed from the \fBvdr\fR main menu's "Commands" option.
diff --git a/vdr.c b/vdr.c
index beeee88..41d2047 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.127 2002/10/13 12:13:19 kls Exp $
+ * $Id: vdr.c 1.130 2002/10/27 15:20:56 kls Exp $
*/
#include <getopt.h>
@@ -47,6 +47,7 @@
#include "rcu.h"
#include "recording.h"
#include "sources.h"
+#include "timers.h"
#include "tools.h"
#include "videodir.h"
@@ -323,6 +324,7 @@ int main(int argc, char *argv[])
SVDRPhosts.Load(AddDirectory(ConfigDirectory, "svdrphosts.conf"), true);
CaDefinitions.Load(AddDirectory(ConfigDirectory, "ca.conf"), true);
Keys.Load(AddDirectory(ConfigDirectory, "remote.conf"));
+ KeyMacros.Load(AddDirectory(ConfigDirectory, "keymacros.conf"), true);
// DVB interfaces:
@@ -455,6 +457,26 @@ int main(int argc, char *argv[])
Menu = new cMenuMain(cControl::Control());
Temp = NULL;
break;
+ #define DirectMainFunction(function)\
+ DELETENULL(Menu);\
+ if (cControl::Control())\
+ cControl::Control()->Hide();\
+ Menu = new cMenuMain(cControl::Control(), function);\
+ Temp = NULL;
+ case kSchedule: DirectMainFunction(osSchedule); break;
+ case kChannels: DirectMainFunction(osChannels); break;
+ case kTimers: DirectMainFunction(osTimers); break;
+ case kRecordings: DirectMainFunction(osRecordings); break;
+ case kSetup: DirectMainFunction(osSetup); break;
+ case kCommands: DirectMainFunction(osCommands); break;
+ case kUser1 ... kUser9: cRemote::PutMacro(key); break;
+ // Channel up/down:
+ case kChanUp|k_Repeat:
+ case kChanUp:
+ case kChanDn|k_Repeat:
+ case kChanDn:
+ cDevice::SwitchChannel(NORMALKEY(key) == kChanUp ? 1 : -1);
+ break;
// Volume Control:
case kVolUp|k_Repeat:
case kVolUp:
@@ -486,81 +508,99 @@ int main(int argc, char *argv[])
}
LastActivity = 1; // not 0, see below!
break;
- default:
- if (Interact) {
- switch (Interact->ProcessKey(key)) {
- case osRecord: DELETENULL(Menu);
- Temp = NULL;
- if (!cRecordControls::Start())
- Interface->Error(tr("No free DVB device to record!"));
- break;
- case osRecordings:
- DELETENULL(Menu);
- cControl::Shutdown();
- Temp = NULL;
- Menu = new cMenuMain(false, osRecordings);
- break;
- case osReplay: DELETENULL(Menu);
- cControl::Shutdown();
- Temp = NULL;
- cControl::Launch(new cReplayControl);
- break;
- case osStopReplay:
- DELETENULL(Menu);
- cControl::Shutdown();
- Temp = NULL;
- break;
- case osSwitchDvb:
- DELETENULL(Menu);
- cControl::Shutdown();
- Temp = NULL;
- Interface->Info(tr("Switching primary DVB..."));
- cDevice::SetPrimaryDevice(Setup.PrimaryDVB);
- break;
- case osBack:
- case osEnd: if (Interact == Menu)
- DELETENULL(Menu);
- else
- cControl::Shutdown();
- Temp = NULL;
- break;
- default: ;
- }
- }
- else {
- // Key functions in "normal" viewing mode:
- switch (key) {
- // Toggle channels:
- case k0: {
- int CurrentChannel = cDevice::CurrentChannel();
- Channels.SwitchTo(PreviousChannel);
- PreviousChannel = CurrentChannel;
- break;
- }
- // Direct Channel Select:
- case k1 ... k9:
- Menu = new cDisplayChannel(key);
- break;
- // Left/Right rotates trough channel groups:
- case kLeft|k_Repeat:
- case kLeft:
- case kRight|k_Repeat:
- case kRight:
- Menu = new cDisplayChannel(NORMALKEY(key));
- break;
- // Up/Down Channel Select:
- case kUp|k_Repeat:
- case kUp:
- case kDown|k_Repeat:
- case kDown:
- cDevice::SwitchChannel(NORMALKEY(key) == kUp ? 1 : -1);
- break;
- // Viewing Control:
- case kOk: LastChannel = -1; break; // forces channel display
- default: break;
- }
- }
+ default: break;
}
+ Interact = Menu ? Menu : cControl::Control(); // might have been closed in the mean time
+ if (Interact) {
+ eOSState state = Interact->ProcessKey(key);
+ if (state == osUnknown && ISMODELESSKEY(key) && cControl::Control() && Interact != cControl::Control())
+ state = cControl::Control()->ProcessKey(key);
+ switch (state) {
+ case osRecord: DELETENULL(Menu);
+ Temp = NULL;
+ if (cRecordControls::Start())
+ Interface->Info(tr("Recording"));
+ else
+ Interface->Error(tr("No free DVB device to record!"));
+ break;
+ case osRecordings:
+ DELETENULL(Menu);
+ cControl::Shutdown();
+ Temp = NULL;
+ Menu = new cMenuMain(false, osRecordings);
+ break;
+ case osReplay: DELETENULL(Menu);
+ cControl::Shutdown();
+ Temp = NULL;
+ cControl::Launch(new cReplayControl);
+ break;
+ case osStopReplay:
+ DELETENULL(Menu);
+ cControl::Shutdown();
+ Temp = NULL;
+ break;
+ case osSwitchDvb:
+ DELETENULL(Menu);
+ cControl::Shutdown();
+ Temp = NULL;
+ Interface->Info(tr("Switching primary DVB..."));
+ cDevice::SetPrimaryDevice(Setup.PrimaryDVB);
+ break;
+ case osBack:
+ case osEnd: if (Interact == Menu)
+ DELETENULL(Menu);
+ else
+ cControl::Shutdown();
+ Temp = NULL;
+ break;
+ default: ;
+ }
+ }
+ else {
+ // Key functions in "normal" viewing mode:
+ switch (key) {
+ // Toggle channels:
+ case k0: {
+ int CurrentChannel = cDevice::CurrentChannel();
+ Channels.SwitchTo(PreviousChannel);
+ PreviousChannel = CurrentChannel;
+ break;
+ }
+ // Direct Channel Select:
+ case k1 ... k9:
+ Menu = new cDisplayChannel(key);
+ break;
+ // Left/Right rotates trough channel groups:
+ case kLeft|k_Repeat:
+ case kLeft:
+ case kRight|k_Repeat:
+ case kRight:
+ Menu = new cDisplayChannel(NORMALKEY(key));
+ break;
+ // Up/Down Channel Select:
+ case kUp|k_Repeat:
+ case kUp:
+ case kDown|k_Repeat:
+ case kDown:
+ cDevice::SwitchChannel(NORMALKEY(key) == kUp ? 1 : -1);
+ break;
+ // Viewing Control:
+ case kOk: LastChannel = -1; break; // forces channel display
+ // Instant recording:
+ case kRecord:
+ if (cRecordControls::Start())
+ Interface->Info(tr("Recording"));
+ else
+ Interface->Error(tr("No free DVB device to record!"));
+ break;
+ // Key macros:
+ case kRed:
+ case kGreen:
+ case kYellow:
+ case kBlue: cRemote::PutMacro(key); break;
+ default: break;
+ }
+ }
if (!Menu) {
EITScanner.Process();
if (!cCutter::Active() && cCutter::Ended()) {
@@ -603,8 +643,8 @@ int main(int argc, char *argv[])
if (WatchdogTimeout > 0)
signal(SIGALRM, SIG_IGN);
if (Interface->Confirm(tr("Press any key to cancel shutdown"), UserShutdown ? 5 : SHUTDOWNWAIT, true)) {
- int Channel = timer ? timer->channel : 0;
- const char *File = timer ? timer->file : "";
+ int Channel = timer ? timer->Channel()->Number() : 0;
+ const char *File = timer ? timer->File() : "";
char *cmd;
asprintf(&cmd, "%s %ld %ld %d \"%s\" %d", Shutdown, Next, Delta, Channel, strescape(File, "\"$"), UserShutdown);
isyslog("executing '%s'", cmd);