mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Version 1.1.4
- Added Hungarian language texts (thanks to Istvan Koenigsberger and Guido Josten). - Activated cutting. - Activated 'Transfer Mode'. - Moved handling of the Menu key entirely into vdr.c. - Switched VDR's own player to the new cPlayer/cControl structures. - Switched handling 'Transfer Mode' to the new cPlayer/cControl structures. - The following limitations apply to this version: + The '-a' option (for Dolby Digital audio) doesn't work yet. + Switching between different language tracks doesn't work yet.
This commit is contained in:
parent
f06d2c27fc
commit
54d069c95c
@ -362,3 +362,6 @@ Matthias Fechner <matthiasfechner@web.de>
|
||||
|
||||
Paul Lacatus <paul@campina.iiruc.ro>
|
||||
for translating OSD texts to the Romanian language
|
||||
|
||||
Istvan Koenigsberger <istvnko@hotmail.com> and Guido Josten <guido.josten@t-online.de>
|
||||
for translating OSD texts to the Hungarian language
|
||||
|
18
HISTORY
18
HISTORY
@ -724,7 +724,7 @@ Video Disk Recorder Revision History
|
||||
"next timer event at..." messages in that case).
|
||||
- Reduced the default value for MinEventTimeout to 30 minutes.
|
||||
- Fixed detecting manual start in shutdown feature.
|
||||
- An error message is now displayed in case the Transfer Mode can't be
|
||||
- An error message is now displayed in case the 'Transfer Mode' can't be
|
||||
started because the necessary DVB card is currently recording (or there
|
||||
is no DVB card that can access this channel).
|
||||
- Fixed toggling channels with the '0' key in case the "Ok" button has been
|
||||
@ -1108,7 +1108,7 @@ Video Disk Recorder Revision History
|
||||
- The "Left" and "Right" keys are now used to page up and down in text displays
|
||||
(like the EPG descriptions or the results of commands executed from the
|
||||
"Commands" menu).
|
||||
- Fixed high CPU usage in transfer mode.
|
||||
- Fixed high CPU usage in 'Transfer Mode'.
|
||||
- Replaced 'killproc' with 'killall' in 'runvdr', since apparently 'killproc'
|
||||
is not available by default on some Linux distributions, whereas 'killall' is.
|
||||
Please check if your system provides 'killall' - if it doesn't, please change
|
||||
@ -1343,7 +1343,19 @@ Video Disk Recorder Revision History
|
||||
will use the same DVB card. During the time where both timers record the data
|
||||
is simply saved to both files.
|
||||
- The following limitations apply to this version:
|
||||
+ Transfer mode doesn't work yet.
|
||||
+ 'Transfer Mode' doesn't work yet.
|
||||
+ The '-a' option (for Dolby Digital audio) doesn't work yet.
|
||||
+ Switching between different language tracks doesn't work yet.
|
||||
+ Cutting doesn't work yet.
|
||||
|
||||
2002-06-23: Version 1.1.4
|
||||
|
||||
- Added Hungarian language texts (thanks to Istvan Koenigsberger and Guido Josten).
|
||||
- Activated cutting.
|
||||
- Activated 'Transfer Mode'.
|
||||
- Moved handling of the Menu key entirely into vdr.c.
|
||||
- Switched VDR's own player to the new cPlayer/cControl structures.
|
||||
- Switched handling 'Transfer Mode' to the new cPlayer/cControl structures.
|
||||
- The following limitations apply to this version:
|
||||
+ The '-a' option (for Dolby Digital audio) doesn't work yet.
|
||||
+ Switching between different language tracks doesn't work yet.
|
||||
|
6
Makefile
6
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 1.40 2002/06/10 16:31:34 kls Exp $
|
||||
# $Id: Makefile 1.42 2002/06/22 10:21:56 kls Exp $
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
@ -21,10 +21,10 @@ INCLUDES = -I$(DVBDIR)/ost/include
|
||||
|
||||
DTVLIB = $(DTVDIR)/libdtv.a
|
||||
|
||||
OBJS = audio.o config.o device.o dvbplayer.o dvbosd.o eit.o eitscan.o font.o i18n.o\
|
||||
OBJS = audio.o config.o cutter.o device.o dvbplayer.o dvbosd.o eit.o eitscan.o font.o i18n.o\
|
||||
interface.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o receiver.o\
|
||||
recorder.o recording.o remote.o remux.o ringbuffer.o status.o svdrp.o thread.o\
|
||||
tools.o vdr.o videodir.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
|
||||
|
188
PLUGINS.html
188
PLUGINS.html
@ -12,7 +12,7 @@ This interface allows programmers to develop additional functionality for VDR co
|
||||
separate from the core VDR source, without the need of patching the original
|
||||
VDR code (and all the problems of correlating various patches).
|
||||
<p>
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
This document is divided into two parts, the first one describing the
|
||||
<a href="#Part I - The Outside Interface"><i>outside</i> interface</a>
|
||||
of the plugin system, and the second one describing the
|
||||
@ -23,16 +23,18 @@ The <i>inside</i> interface provides the plugin code access to VDR's internal da
|
||||
structures and allows it to hook itself into specific areas to perform special actions.
|
||||
<!--X1.1.3--></td></tr></table>
|
||||
<p>
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=lime> </td><td width=100%>
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
Important modifications introduced in version 1.1.1 are marked like this.
|
||||
<!--X1.1.1--></td></tr></table>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
Important modifications introduced in version 1.1.2 are marked like this.
|
||||
<!--X1.1.2--></td></tr></table>
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
Important modifications introduced in version 1.1.3 are marked like this.
|
||||
<!--X1.1.3--></td></tr></table>
|
||||
<!--<p>TODO: Link to the document about VDR base classes to use when implementing actual functionality (yet to be written).-->
|
||||
<!--X1.1.4--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
Important modifications introduced in version 1.1.4 are marked like this.
|
||||
<!--X1.1.4--></td></tr></table>
|
||||
|
||||
<a name="Part I - The Outside Interface"><hr><center><h1>Part I - The Outside Interface</h1></center>
|
||||
|
||||
@ -129,7 +131,7 @@ from the web, it will typically have a name like
|
||||
<p>
|
||||
and will unpack into a directory named
|
||||
<p>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
<tt>hello-0.0.1</tt>
|
||||
<!--X1.1.2--></td></tr></table>
|
||||
<p>
|
||||
@ -137,7 +139,7 @@ To use the <tt>plugins</tt> and <tt>plugins-clean</tt> targets from the VDR <tt>
|
||||
you need to unpack such an archive into the <tt>VDR/PLUGINS/SRC</tt> directory and
|
||||
create a symbolic link with the basic plugin name, as in
|
||||
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
ln -s hello-0.0.1 hello
|
||||
</pre></td></tr></table><p>
|
||||
@ -203,7 +205,7 @@ its memory. You don't need to worry about the details behind all this.
|
||||
If your plugin requires additional source files, simply add them to your plugin's
|
||||
source directory and adjust the <tt>Makefile</tt> accordingly.
|
||||
<p>
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=lime> </td><td width=100%>
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
Header files usually contain preprocessor statements that prevent the same
|
||||
file (or rather its contents, to be precise) from being included more than once, like
|
||||
|
||||
@ -422,7 +424,7 @@ If a plugin implements a function that runs in the background (presumably in a
|
||||
thread of its own), or wants to make use of <a href="#Internationalization">internationalization</a>,
|
||||
it needs to implement the function
|
||||
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
virtual bool Start(void);
|
||||
</pre></td></tr></table><p>
|
||||
@ -434,7 +436,7 @@ its task. This may, for instance, be a thread that collects data from the DVB
|
||||
stream, which is later presented to the user via a function that is available
|
||||
from the main menu.
|
||||
<p>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
A return value of <i>false</i> indicates that something has gone wrong and the
|
||||
plugin will not be able to perform its task. In that case, the plugin should
|
||||
write a proper error message to the log file. The first plugin that returns
|
||||
@ -498,7 +500,7 @@ interaction is possible. If a specific action takes longer than a few seconds,
|
||||
the plugin should launch a separate thread to do this.
|
||||
</b>
|
||||
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
<hr><h2>Housekeeping</h2>
|
||||
|
||||
<center><i><b>Chores, chores...</b></i></center><p>
|
||||
@ -545,7 +547,7 @@ previously stored in the global setup data (see below). It shall return
|
||||
<i>true</i> if the parameter was parsed correctly, <i>false</i> in case of
|
||||
an error. If <i>false</i> is returned, an error message will be written to
|
||||
the log file (and program execution will continue).
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=lime> </td><td width=100%>
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
A possible implementation of <tt>SetupParse()</tt> could look like this:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
@ -600,7 +602,7 @@ needs setup parameters that are not directly user adjustable. It can use
|
||||
<tt>SetupStore()</tt> and <tt>SetupParse()</tt> without presenting these
|
||||
parameters to the user.
|
||||
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=lime> </td><td width=100%>
|
||||
<!--X1.1.1--><table width=100%><tr><td bgcolor=#0000AA> </td><td width=100%>
|
||||
<a name="The Setup menu"><hr><h2>The Setup menu</h2>
|
||||
|
||||
<center><i><b>Have it your way!</b></i></center><p>
|
||||
@ -660,7 +662,7 @@ your setup parameters and use that one to copy all parameters with one single st
|
||||
(like VDR does with its cSetup class).
|
||||
<!--X1.1.1--></td></tr></table>
|
||||
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=cyan> </td><td width=100%>
|
||||
<!--X1.1.2--><table width=100%><tr><td bgcolor=#00AA00> </td><td width=100%>
|
||||
<hr><h2>Configuration files</h2>
|
||||
|
||||
<center><i><b>I want my own stuff!</b></i></center><p>
|
||||
@ -746,6 +748,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
@ -827,7 +832,7 @@ and display their help and/or version information in addition to its own output.
|
||||
|
||||
If you want to make your plugin available to other VDR users, you'll need to
|
||||
make a package that can be easily distributed.
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
The <tt>Makefile</tt> that has been created by the call to
|
||||
<a href="#Initializing a new plugin directory"><tt>newplugin</tt></a>
|
||||
provides the target <tt>dist</tt>, which does this for you.
|
||||
@ -849,7 +854,7 @@ vdr-hello-0.0.1.tgz
|
||||
in your source directory, where <tt>hello</tt> will be replaced with your actual
|
||||
plugin's name, and <tt>0.0.1</tt> will be your plugin's current version number.
|
||||
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=red> </td><td width=100%>
|
||||
<!--X1.1.3--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
<a name="Part II - The Inside Interface"><hr><center><h1>Part II - The Inside Interface</h1></center>
|
||||
|
||||
<hr><h2>Status monitor</h2>
|
||||
@ -926,5 +931,156 @@ member functions are available in <tt>cStatus</tt>. You only need to implement
|
||||
the functions you actually want to use.
|
||||
<!--X1.1.3--></td></tr></table>
|
||||
|
||||
<!--X1.1.4--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<hr><h2>Players</h2>
|
||||
|
||||
<center><i><b>Play it again, Sam!</b></i></center><p>
|
||||
|
||||
Implementing a player is a two step process.
|
||||
First you need the actual player class, which is derived from the abstract <tt>cPlayer</tt>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
#include <vdr/player.h>
|
||||
|
||||
class cMyPlayer : public cPlayer {
|
||||
protected:
|
||||
virtual void Activate(bool On);
|
||||
public:
|
||||
cMyPlayer(void);
|
||||
virtual ~cMyPlayer();
|
||||
};
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
What exactly you do in this class is entirely up to you. If you want to run a separate
|
||||
thread which, e.g., reads data from a file, you can additionally derive your class from
|
||||
<tt>cThread</tt> and implement the necessary functionality:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
#include <vdr/player.h>
|
||||
|
||||
class cMyPlayer : public cPlayer, cThread {
|
||||
protected:
|
||||
virtual void Activate(bool On);
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cMyPlayer(void);
|
||||
virtual ~cMyPlayer();
|
||||
};
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Take a look at the files <tt>player.h</tt> and <tt>dvbplayer.c</tt> to see how VDR implements
|
||||
its own player for the VDR recordings.
|
||||
<p>
|
||||
To play the video data, the player needs to call its member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
int PlayVideo(const uchar *Data, int Length);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
where <tt>Data</tt> point to a block of <tt>Length</tt> bytes of a PES data
|
||||
stream. There are no prerequisites regarding the length or alignment of an
|
||||
individual block of data. The sum of all blocks must simply result in the
|
||||
desired video data stream, and it must be delivered fast enough so that the
|
||||
DVB device doesn't run out of data.
|
||||
<p>
|
||||
TODO: PlayAudio()???
|
||||
<p>
|
||||
The second part needed here is a control object that receives user input from the main
|
||||
program loop and reacts on this by telling the player what to do:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
#include <vdr/player.h>
|
||||
|
||||
class cMyControl : public cControl {
|
||||
private:
|
||||
cMyPlayer *player;
|
||||
public:
|
||||
cMyControl(void);
|
||||
virtual ~cMyControl();
|
||||
virtual void Hide(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
<tt>cMyControl</tt> shall create an object of type <tt>cMyPlayer</tt> and
|
||||
hand over a pointer to it to the <tt>cControl</tt> base class, so that it
|
||||
can be later attached to the primary DVB device:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
cMyControl::cMyControl(void)
|
||||
:cControl(player = new cMyPlayer)
|
||||
{
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
<tt>cMyControl</tt> will receive the user's key presses through the <tt>ProcessKey()</tt>
|
||||
function. It will get all button presses, except for the volume control buttons
|
||||
(<tt>kVolUp</tt>, <tt>kVolDn</tt>, <tt>kMute</tt>), the power button (<tt>kPower</tt>)
|
||||
and the menu button (<tt>kMenu</tt>). If the user has not pressed a button for a while
|
||||
(which is typically in the area of about one second), <tt>ProcessKey()</tt> will be called
|
||||
with <tt>kNone</tt>, so that the <tt>cMyControl</tt> gets a chance to check whether its
|
||||
player is still active. Once the player has become inactive (because the user has decided
|
||||
to stop it or the DVB device has detached it), <tt>ProcessKey()</tt> must return <tt>osEnd</tt>
|
||||
to make the main program loop shut down the player control.
|
||||
<p>
|
||||
A derived <tt>cControl</tt> <b>must</b> implement the <tt>Hide()</tt> function, in which
|
||||
it has to hide itself from the OSD, in case it uses it. <tt>Hide()</tt> may be called at
|
||||
any time, and it may be called even if the <tt>cControl</tt> is not visible at the moment.
|
||||
The reason for this is that the <tt>Menu</tt> button shall always bring up the main VDR
|
||||
menu, so any active <tt>cControl</tt> needs to be hidden when that button is pressed.
|
||||
<p>
|
||||
Finally, to get things going, a plugin that implements a player (and the surrounding
|
||||
infrastructure like displaying a list of playable stuff etc) simply has to call the
|
||||
static function <tt>cControl::Launch()</tt> with the player control object, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
cControl::Launch(new cMyControl);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Ownership of the <tt>MyControl</tt> object is handed over to the VDR core code,
|
||||
so the plugin should not keep a pointer to it, because VDR will destroy the object
|
||||
whenever it sees fit (for instance because a recording shall start that needs to
|
||||
use the primary DVB device, or the user decides to start a different replay).
|
||||
<p>
|
||||
The <tt>cPlayer</tt> class has a member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
void DeviceStillPicture(const uchar *Data, int Length);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which can be called to display a still picture. VDR uses this function when handling
|
||||
its editing marks. A special case of a "player" might use this function to implement
|
||||
a "picture viewer".
|
||||
<p>
|
||||
For detailed information on how to implement your own player, please take a look
|
||||
at VDR's <tt>cDvbPlayer</tt> and <tt>cDvbPlayerControl</tt> classes.
|
||||
<p>
|
||||
<b>User interface</b>
|
||||
<p>
|
||||
In order for a new player to nicely "blend in" to the overall VDR appearance it
|
||||
is recommended that it implements the same functionality with the same keys as the
|
||||
VDR player does (as far as this is possible and makes sense). The main points to
|
||||
consider here are
|
||||
<ul>
|
||||
<li>The <i>Ok</i> button shall bring up some display that indicates what is currently
|
||||
being played, and what the status of this replay session is. As an alternative (for
|
||||
instance with a DVD player) it may display a player specific menu, from which the
|
||||
user can select certain options.
|
||||
<li>The <i>Up</i>, <i>Down</i>, <i>Left</i> and <i>Right</i> buttons shall control
|
||||
<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.
|
||||
<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.
|
||||
</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
|
||||
that they already know. If you absolutely want to do things differently, just go
|
||||
ahead - it's your show...
|
||||
<!--X1.1.4--></td></tr></table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: i18n.c 1.2 2002/05/11 12:27:00 kls Exp $
|
||||
* $Id: i18n.c 1.3 2002/06/23 13:05:59 kls Exp $
|
||||
*/
|
||||
|
||||
#include "i18n.h"
|
||||
@ -21,6 +21,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Hello world!",
|
||||
"Hallo Welt!",
|
||||
@ -34,6 +37,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Howdy folks!",
|
||||
"Tach zusammen!",
|
||||
@ -47,6 +53,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "A friendly greeting",
|
||||
"Ein freundlicher Gruß",
|
||||
@ -60,6 +69,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Greeting time (s)",
|
||||
"Dauer des Grußes (s)",
|
||||
@ -73,6 +85,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ "Use alternate greeting",
|
||||
"Alternativen Gruß verwenden",
|
||||
@ -86,6 +101,9 @@ const tI18nPhrase Phrases[] = {
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
"",// TODO
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
4
config.h
4
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.118 2002/05/31 10:20:56 kls Exp $
|
||||
* $Id: config.h 1.119 2002/06/16 14:49:52 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -19,7 +19,7 @@
|
||||
#include "eit.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "1.1.3"
|
||||
#define VDRVERSION "1.1.4"
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
|
253
cutter.c
Normal file
253
cutter.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* cutter.c: The video cutting facilities
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.c 1.1 2002/06/22 10:09:34 kls Exp $
|
||||
*/
|
||||
|
||||
#include "cutter.h"
|
||||
#include "recording.h"
|
||||
#include "remux.h"
|
||||
#include "thread.h"
|
||||
#include "videodir.h"
|
||||
|
||||
// --- cCuttingThread --------------------------------------------------------
|
||||
|
||||
class cCuttingThread : public cThread {
|
||||
private:
|
||||
const char *error;
|
||||
bool active;
|
||||
int fromFile, toFile;
|
||||
cFileName *fromFileName, *toFileName;
|
||||
cIndexFile *fromIndex, *toIndex;
|
||||
cMarks fromMarks, toMarks;
|
||||
protected:
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cCuttingThread(const char *FromFileName, const char *ToFileName);
|
||||
virtual ~cCuttingThread();
|
||||
const char *Error(void) { return error; }
|
||||
};
|
||||
|
||||
cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
||||
{
|
||||
error = NULL;
|
||||
active = false;
|
||||
fromFile = toFile = -1;
|
||||
fromFileName = toFileName = NULL;
|
||||
fromIndex = toIndex = NULL;
|
||||
if (fromMarks.Load(FromFileName) && fromMarks.Count()) {
|
||||
fromFileName = new cFileName(FromFileName, false, true);
|
||||
toFileName = new cFileName(ToFileName, true, true);
|
||||
fromIndex = new cIndexFile(FromFileName, false);
|
||||
toIndex = new cIndexFile(ToFileName, true);
|
||||
toMarks.Load(ToFileName); // doesn't actually load marks, just sets the file name
|
||||
Start();
|
||||
}
|
||||
else
|
||||
esyslog("no editing marks found for %s", FromFileName);
|
||||
}
|
||||
|
||||
cCuttingThread::~cCuttingThread()
|
||||
{
|
||||
active = false;
|
||||
Cancel(3);
|
||||
delete fromFileName;
|
||||
delete toFileName;
|
||||
delete fromIndex;
|
||||
delete toIndex;
|
||||
}
|
||||
|
||||
void cCuttingThread::Action(void)
|
||||
{
|
||||
dsyslog("video cutting thread started (pid=%d)", getpid());
|
||||
|
||||
cMark *Mark = fromMarks.First();
|
||||
if (Mark) {
|
||||
fromFile = fromFileName->Open();
|
||||
toFile = toFileName->Open();
|
||||
active = fromFile >= 0 && toFile >= 0;
|
||||
int Index = Mark->position;
|
||||
Mark = fromMarks.Next(Mark);
|
||||
int FileSize = 0;
|
||||
int CurrentFileNumber = 0;
|
||||
int LastIFrame = 0;
|
||||
toMarks.Add(0);
|
||||
toMarks.Save();
|
||||
uchar buffer[MAXFRAMESIZE];
|
||||
while (active) {
|
||||
uchar FileNumber;
|
||||
int FileOffset, Length;
|
||||
uchar PictureType;
|
||||
|
||||
// Make sure there is enough disk space:
|
||||
|
||||
AssertFreeDiskSpace();
|
||||
|
||||
// Read one frame:
|
||||
|
||||
if (fromIndex->Get(Index++, &FileNumber, &FileOffset, &PictureType, &Length)) {
|
||||
if (FileNumber != CurrentFileNumber) {
|
||||
fromFile = fromFileName->SetOffset(FileNumber, FileOffset);
|
||||
CurrentFileNumber = FileNumber;
|
||||
}
|
||||
if (fromFile >= 0) {
|
||||
int len = ReadFrame(fromFile, buffer, Length, sizeof(buffer));
|
||||
if (len < 0) {
|
||||
error = "ReadFrame";
|
||||
break;
|
||||
}
|
||||
if (len != Length) {
|
||||
CurrentFileNumber = 0; // this re-syncs in case the frame was larger than the buffer
|
||||
Length = len;
|
||||
}
|
||||
}
|
||||
else {
|
||||
error = "fromFile";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
// Write one frame:
|
||||
|
||||
if (PictureType == I_FRAME) { // every file shall start with an I_FRAME
|
||||
if (!Mark) // edited version shall end before next I-frame
|
||||
break;
|
||||
if (FileSize > MEGABYTE(Setup.MaxVideoFileSize)) {
|
||||
toFile = toFileName->NextFile();
|
||||
if (toFile < 0) {
|
||||
error = "toFile 1";
|
||||
break;
|
||||
}
|
||||
FileSize = 0;
|
||||
}
|
||||
LastIFrame = 0;
|
||||
}
|
||||
if (safe_write(toFile, buffer, Length) < 0) {
|
||||
error = "safe_write";
|
||||
break;
|
||||
}
|
||||
if (!toIndex->Write(PictureType, toFileName->Number(), FileSize)) {
|
||||
error = "toIndex";
|
||||
break;
|
||||
}
|
||||
FileSize += Length;
|
||||
if (!LastIFrame)
|
||||
LastIFrame = toIndex->Last();
|
||||
|
||||
// Check editing marks:
|
||||
|
||||
if (Mark && Index >= Mark->position) {
|
||||
Mark = fromMarks.Next(Mark);
|
||||
toMarks.Add(LastIFrame);
|
||||
if (Mark)
|
||||
toMarks.Add(toIndex->Last() + 1);
|
||||
toMarks.Save();
|
||||
if (Mark) {
|
||||
Index = Mark->position;
|
||||
Mark = fromMarks.Next(Mark);
|
||||
CurrentFileNumber = 0; // triggers SetOffset before reading next frame
|
||||
if (Setup.SplitEditedFiles) {
|
||||
toFile = toFileName->NextFile();
|
||||
if (toFile < 0) {
|
||||
error = "toFile 2";
|
||||
break;
|
||||
}
|
||||
FileSize = 0;
|
||||
}
|
||||
}
|
||||
// the 'else' case (i.e. 'final end mark reached') is handled above
|
||||
// in 'Write one frame', so that the edited version will end right
|
||||
// before the next I-frame.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
esyslog("no editing marks found!");
|
||||
dsyslog("end video cutting thread");
|
||||
}
|
||||
|
||||
// --- cCutter ---------------------------------------------------------------
|
||||
|
||||
char *cCutter::editedVersionName = NULL;
|
||||
cCuttingThread *cCutter::cuttingThread = NULL;
|
||||
bool cCutter::error = false;
|
||||
bool cCutter::ended = false;
|
||||
|
||||
bool cCutter::Start(const char *FileName)
|
||||
{
|
||||
if (!cuttingThread) {
|
||||
error = false;
|
||||
ended = false;
|
||||
cRecording Recording(FileName);
|
||||
const char *evn = Recording.PrefixFileName('%');
|
||||
if (evn && RemoveVideoFile(evn) && MakeDirs(evn, true)) {
|
||||
// XXX this can be removed once RenameVideoFile() follows symlinks (see videodir.c)
|
||||
// remove a possible deleted recording with the same name to avoid symlink mixups:
|
||||
char *s = strdup(evn);
|
||||
char *e = strrchr(s, '.');
|
||||
if (e) {
|
||||
if (strcmp(e, ".rec") == 0) {
|
||||
strcpy(e, ".del");
|
||||
RemoveVideoFile(s);
|
||||
}
|
||||
}
|
||||
delete s;
|
||||
// XXX
|
||||
editedVersionName = strdup(evn);
|
||||
Recording.WriteSummary();
|
||||
cuttingThread = new cCuttingThread(FileName, editedVersionName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cCutter::Stop(void)
|
||||
{
|
||||
bool Interrupted = cuttingThread && cuttingThread->Active();
|
||||
const char *Error = cuttingThread ? cuttingThread->Error() : NULL;
|
||||
delete cuttingThread;
|
||||
cuttingThread = NULL;
|
||||
if ((Interrupted || Error) && editedVersionName) {
|
||||
if (Interrupted)
|
||||
isyslog("editing process has been interrupted");
|
||||
if (Error)
|
||||
esyslog("ERROR: '%s' during editing process", Error);
|
||||
RemoveVideoFile(editedVersionName); //XXX what if this file is currently being replayed?
|
||||
}
|
||||
}
|
||||
|
||||
bool cCutter::Active(void)
|
||||
{
|
||||
if (cuttingThread) {
|
||||
if (cuttingThread->Active())
|
||||
return true;
|
||||
error = cuttingThread->Error();
|
||||
Stop();
|
||||
if (!error)
|
||||
cRecordingUserCommand::InvokeCommand(RUC_EDITEDRECORDING, editedVersionName);
|
||||
delete editedVersionName;
|
||||
editedVersionName = NULL;
|
||||
ended = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cCutter::Error(void)
|
||||
{
|
||||
bool result = error;
|
||||
error = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool cCutter::Ended(void)
|
||||
{
|
||||
bool result = ended;
|
||||
ended = false;
|
||||
return result;
|
||||
}
|
29
cutter.h
Normal file
29
cutter.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* cutter.h: The video cutting facilities
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.h 1.1 2002/06/22 10:03:15 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CUTTER_H
|
||||
#define __CUTTER_H
|
||||
|
||||
class cCuttingThread;
|
||||
|
||||
class cCutter {
|
||||
private:
|
||||
static char *editedVersionName;
|
||||
static cCuttingThread *cuttingThread;
|
||||
static bool error;
|
||||
static bool ended;
|
||||
public:
|
||||
static bool Start(const char *FileName);
|
||||
static void Stop(void);
|
||||
static bool Active(void);
|
||||
static bool Error(void);
|
||||
static bool Ended(void);
|
||||
};
|
||||
|
||||
#endif //__CUTTER_H
|
23
device.c
23
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.2 2002/06/16 13:23:31 kls Exp $
|
||||
* $Id: device.c 1.5 2002/06/23 12:51:24 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -21,6 +21,7 @@ extern "C" {
|
||||
#include "player.h"
|
||||
#include "receiver.h"
|
||||
#include "status.h"
|
||||
#include "transfer.h"
|
||||
|
||||
#define DEV_VIDEO "/dev/video"
|
||||
#define DEV_OST_OSD "/dev/ost/osd"
|
||||
@ -456,8 +457,7 @@ bool cDevice::SetPid(int fd, dmxPesType_t PesType, int Pid, dmxOutput_t Output)
|
||||
|
||||
eSetChannelResult cDevice::SetChannel(int ChannelNumber, int Frequency, char Polarization, int Diseqc, int Srate, int Vpid, int Apid, int Tpid, int Ca, int Pnr)
|
||||
{
|
||||
//XXX+StopTransfer();
|
||||
//XXX+StopReplay();
|
||||
StopReplay();
|
||||
|
||||
cStatus::MsgChannelSwitch(this, 0);
|
||||
|
||||
@ -620,10 +620,8 @@ eSetChannelResult cDevice::SetChannel(int ChannelNumber, int Frequency, char Pol
|
||||
if (NeedsTransferMode) {
|
||||
cDevice *CaDevice = GetDevice(Ca, 0);
|
||||
if (CaDevice && !CaDevice->Receiving()) {
|
||||
if ((Result = CaDevice->SetChannel(ChannelNumber, Frequency, Polarization, Diseqc, Srate, Vpid, Apid, Tpid, Ca, Pnr)) == scrOk) {
|
||||
//XXX+SetModeReplay();
|
||||
//XXX+transferringFromDevice = CaDevice->StartTransfer(fd_video);
|
||||
}
|
||||
if ((Result = CaDevice->SetChannel(ChannelNumber, Frequency, Polarization, Diseqc, Srate, Vpid, Apid, Tpid, Ca, Pnr)) == scrOk)
|
||||
cControl::Launch(new cTransferControl(CaDevice, Vpid, Apid, 0, 0, 0));//XXX+
|
||||
}
|
||||
else
|
||||
Result = scrNoTransfer;
|
||||
@ -731,15 +729,10 @@ void cDevice::StillPicture(const uchar *Data, int Length)
|
||||
|
||||
bool cDevice::Replaying(void)
|
||||
{
|
||||
/*XXX+
|
||||
if (replayBuffer && !replayBuffer->Active())
|
||||
StopReplay();
|
||||
return replayBuffer != NULL;
|
||||
XXX*/
|
||||
return player != NULL;
|
||||
}
|
||||
|
||||
bool cDevice::Attach(cPlayer *Player)
|
||||
bool cDevice::AttachPlayer(cPlayer *Player)
|
||||
{
|
||||
if (Receiving()) {
|
||||
esyslog("ERROR: attempt to attach a cPlayer while receiving on device %d - ignored", CardIndex() + 1);
|
||||
@ -792,6 +785,8 @@ void cDevice::StopReplay(void)
|
||||
{
|
||||
if (player) {
|
||||
Detach(player);
|
||||
if (IsPrimaryDevice())
|
||||
cControl::Shutdown();
|
||||
/*XXX+
|
||||
if (IsPrimaryDevice()) {
|
||||
// let's explicitly switch the channel back in case it was in Transfer Mode:
|
||||
@ -958,7 +953,7 @@ void cDevice::Action(void)
|
||||
dsyslog("receiver thread ended on device %d (pid=%d)", CardIndex() + 1, getpid());
|
||||
}
|
||||
|
||||
bool cDevice::Attach(cReceiver *Receiver)
|
||||
bool cDevice::AttachReceiver(cReceiver *Receiver)
|
||||
{
|
||||
//XXX+ check for same transponder???
|
||||
if (!Receiver)
|
||||
|
6
device.h
6
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.1 2002/06/09 15:48:32 kls Exp $
|
||||
* $Id: device.h 1.3 2002/06/23 11:50:24 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -172,7 +172,7 @@ public:
|
||||
// Returns true if we are currently replaying.
|
||||
void StopReplay(void);
|
||||
// Stops the current replay session (if any).
|
||||
bool Attach(cPlayer *Player);
|
||||
bool AttachPlayer(cPlayer *Player);
|
||||
void Detach(cPlayer *Player);
|
||||
virtual int PlayVideo(const uchar *Data, int Length);
|
||||
virtual int PlayAudio(const uchar *Data, int Length);
|
||||
@ -192,7 +192,7 @@ public:
|
||||
// Returns the ca of the current receiving session.
|
||||
bool Receiving(void);
|
||||
// Returns true if we are currently receiving.
|
||||
bool Attach(cReceiver *Receiver);
|
||||
bool AttachReceiver(cReceiver *Receiver);
|
||||
void Detach(cReceiver *Receiver);
|
||||
};
|
||||
|
||||
|
@ -1,12 +0,0 @@
|
||||
--- dmxdev.c Mon Apr 1 10:59:46 2002
|
||||
+++ dmxdev.c Sun Jun 16 11:02:38 2002
|
||||
@@ -1048,6 +1048,9 @@
|
||||
if (dmxdev->dvr_buffer.pread!=dmxdev->dvr_buffer.pwrite)
|
||||
return (POLLIN | POLLRDNORM | POLLPRI);
|
||||
|
||||
+ if (dmxdev->dvr_buffer.error)
|
||||
+ return (POLLIN | POLLRDNORM | POLLPRI | POLLERR);
|
||||
+
|
||||
return 0;
|
||||
} else
|
||||
return (POLLOUT | POLLWRNORM | POLLPRI);
|
35
dvbplayer.c
35
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.1 2002/06/16 10:59:45 kls Exp $
|
||||
* $Id: dvbplayer.c 1.4 2002/06/23 10:52:51 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
@ -13,22 +13,6 @@
|
||||
#include "ringbuffer.h"
|
||||
#include "thread.h"
|
||||
|
||||
// --- ReadFrame -------------------------------------------------------------
|
||||
|
||||
int ReadFrame(int f, uchar *b, int Length, int Max)
|
||||
{
|
||||
if (Length == -1)
|
||||
Length = Max; // this means we read up to EOF (see cIndex)
|
||||
else if (Length > Max) {
|
||||
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, Max);
|
||||
Length = Max;
|
||||
}
|
||||
int r = safe_read(f, b, Length);
|
||||
if (r < 0)
|
||||
LOG_ERROR;
|
||||
return r;
|
||||
}
|
||||
|
||||
// --- cBackTrace ----------------------------------------------------------
|
||||
|
||||
#define AVG_FRAME_SIZE 15000 // an assumption about the average frame size
|
||||
@ -91,9 +75,6 @@ int cBackTrace::Get(bool Forward)
|
||||
// (must be larger than MINVIDEODATA - see remux.h)
|
||||
#define VIDEOBUFSIZE MEGABYTE(1)
|
||||
|
||||
// The maximum size of a single frame:
|
||||
#define MAXFRAMESIZE KILOBYTE(192)
|
||||
|
||||
// The number of frames to back up when resuming an interrupted replay session:
|
||||
#define RESUMEBACKUP (10 * FRAMESPERSEC)
|
||||
|
||||
@ -644,9 +625,9 @@ bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed)
|
||||
|
||||
// --- cDvbPlayerControl -----------------------------------------------------
|
||||
|
||||
cDvbPlayerControl::cDvbPlayerControl(void)
|
||||
cDvbPlayerControl::cDvbPlayerControl(const char *FileName)
|
||||
:cControl(player = new cDvbPlayer(FileName))
|
||||
{
|
||||
player = NULL;
|
||||
}
|
||||
|
||||
cDvbPlayerControl::~cDvbPlayerControl()
|
||||
@ -659,16 +640,6 @@ bool cDvbPlayerControl::Active(void)
|
||||
return player && player->Active();
|
||||
}
|
||||
|
||||
bool cDvbPlayerControl::Start(const char *FileName)
|
||||
{
|
||||
delete player;
|
||||
player = new cDvbPlayer(FileName);
|
||||
if (cDevice::PrimaryDevice()->Attach(player))
|
||||
return true;
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDvbPlayerControl::Stop(void)
|
||||
{
|
||||
delete player;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbplayer.h 1.1 2002/06/16 10:59:14 kls Exp $
|
||||
* $Id: dvbplayer.h 1.2 2002/06/23 10:13:51 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBPLAYER_H
|
||||
@ -19,11 +19,10 @@ class cDvbPlayerControl : public cControl {
|
||||
private:
|
||||
cDvbPlayer *player;
|
||||
public:
|
||||
cDvbPlayerControl(void);
|
||||
cDvbPlayerControl(const char *FileName);
|
||||
// Sets up a player for the given file.
|
||||
virtual ~cDvbPlayerControl();
|
||||
bool Active(void);
|
||||
bool Start(const char *FileName);
|
||||
// Starts replaying the given file.
|
||||
void Stop(void);
|
||||
// Stops the current replay session (if any).
|
||||
void Pause(void);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eitscan.c 1.2 2002/06/02 09:02:05 kls Exp $
|
||||
* $Id: eitscan.c 1.3 2002/06/22 13:02:40 kls Exp $
|
||||
*/
|
||||
|
||||
#include "eitscan.h"
|
||||
@ -52,7 +52,7 @@ void cEITScanner::Process(void)
|
||||
cDevice *Device = cDevice::GetDevice(i + 1, MAXPRIORITY + 1);
|
||||
if (Device) {
|
||||
if (Device != cDevice::PrimaryDevice() || (cDevice::NumDevices() == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) {
|
||||
if (!(Device->Receiving() || Device->Replaying()/*XXX+ || Device->Transferring()XXX*/)) {
|
||||
if (!(Device->Receiving() || Device->Replaying())) {
|
||||
int oldCh = lastChannel;
|
||||
int ch = oldCh + 1;
|
||||
while (ch != oldCh) {
|
||||
|
4
i18n.h
4
i18n.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.h 1.4 2002/06/10 16:14:02 kls Exp $
|
||||
* $Id: i18n.h 1.5 2002/06/22 09:12:21 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __I18N_H
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
const int I18nNumLanguages = 14;
|
||||
const int I18nNumLanguages = 15;
|
||||
|
||||
typedef const char *tI18nPhrase[I18nNumLanguages];
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: interface.h 1.26 2002/05/18 13:43:20 kls Exp $
|
||||
* $Id: interface.h 1.27 2002/06/22 14:39:48 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __INTERFACE_H
|
||||
@ -33,6 +33,7 @@ private:
|
||||
public:
|
||||
cInterface(int SVDRPport = 0);
|
||||
~cInterface();
|
||||
bool IsOpen(void) { return open > 0; }
|
||||
void Open(int NumCols = 0, int NumLines = 0);
|
||||
void Close(void);
|
||||
void Interrupt(void) { interrupted = true; }
|
||||
|
30
menu.c
30
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.197 2002/06/16 13:23:51 kls Exp $
|
||||
* $Id: menu.c 1.201 2002/06/23 11:07:19 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -14,6 +14,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "cutter.h"
|
||||
#include "eit.h"
|
||||
#include "i18n.h"
|
||||
#include "menuitems.h"
|
||||
@ -1512,7 +1513,6 @@ eOSState cMenuRecordings::ProcessKey(eKeys Key)
|
||||
case kGreen: return Rewind();
|
||||
case kYellow: return Del();
|
||||
case kBlue: return Summary();
|
||||
case kMenu: return osEnd;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -2026,10 +2026,8 @@ void cMenuMain::Set(void)
|
||||
|
||||
// Editing control:
|
||||
|
||||
/*XXX+
|
||||
if (cVideoCutter::Active())
|
||||
if (cCutter::Active())
|
||||
Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit));
|
||||
XXX*/
|
||||
|
||||
// Color buttons:
|
||||
|
||||
@ -2063,7 +2061,7 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
}
|
||||
break;
|
||||
case osCancelEdit: if (Interface->Confirm(tr("Cancel editing?"))) {
|
||||
//XXX+cVideoCutter::Stop();
|
||||
cCutter::Stop();
|
||||
return osEnd;
|
||||
}
|
||||
break;
|
||||
@ -2081,7 +2079,6 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
}
|
||||
break;
|
||||
default: switch (Key) {
|
||||
case kMenu: state = osEnd; break;
|
||||
case kRed: if (!HasSubMenu())
|
||||
state = osRecord;
|
||||
break;
|
||||
@ -2443,7 +2440,7 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer)
|
||||
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);
|
||||
if (device->Attach(recorder)) {
|
||||
if (device->AttachReceiver(recorder)) {
|
||||
Recording.WriteSummary();
|
||||
cStatus::MsgRecording(device, fileName);
|
||||
Interface->DisplayRecording(device->CardIndex(), true);
|
||||
@ -2684,18 +2681,14 @@ char *cReplayControl::fileName = NULL;
|
||||
char *cReplayControl::title = NULL;
|
||||
|
||||
cReplayControl::cReplayControl(void)
|
||||
:cDvbPlayerControl(fileName)
|
||||
{
|
||||
visible = modeOnly = shown = displayFrames = false;
|
||||
lastCurrent = lastTotal = -1;
|
||||
timeoutShow = 0;
|
||||
timeSearchActive = false;
|
||||
if (fileName) {
|
||||
marks.Load(fileName);
|
||||
if (!Start(fileName))
|
||||
Interface->Error(tr("Channel locked (recording)!"));//XXX+
|
||||
else
|
||||
cStatus::MsgReplaying(this, fileName);
|
||||
}
|
||||
marks.Load(fileName);
|
||||
cStatus::MsgReplaying(this, fileName);
|
||||
}
|
||||
|
||||
cReplayControl::~cReplayControl()
|
||||
@ -2973,11 +2966,10 @@ void cReplayControl::MarkMove(bool Forward)
|
||||
|
||||
void cReplayControl::EditCut(void)
|
||||
{
|
||||
/*XXX+
|
||||
if (fileName) {
|
||||
Hide();
|
||||
if (!cVideoCutter::Active()) {
|
||||
if (!cVideoCutter::Start(fileName))
|
||||
if (!cCutter::Active()) {
|
||||
if (!cCutter::Start(fileName))
|
||||
Interface->Error(tr("Can't start editing process!"));
|
||||
else
|
||||
Interface->Info(tr("Editing process started"));
|
||||
@ -2986,7 +2978,6 @@ void cReplayControl::EditCut(void)
|
||||
Interface->Error(tr("Editing process already active!"));
|
||||
ShowMode();
|
||||
}
|
||||
XXX*/
|
||||
}
|
||||
|
||||
void cReplayControl::EditTest(void)
|
||||
@ -3065,7 +3056,6 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
|
||||
displayFrames = DisplayedFrames;
|
||||
switch (Key) {
|
||||
// Menu control:
|
||||
case kMenu: Hide(); return osMenu; // allow direct switching to menu
|
||||
case kOk: if (visible && !modeOnly) {
|
||||
Hide();
|
||||
DoShowMode = true;
|
||||
|
4
menu.h
4
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.44 2002/06/14 12:33:35 kls Exp $
|
||||
* $Id: menu.h 1.45 2002/06/22 14:49:15 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENU_H
|
||||
@ -124,7 +124,6 @@ private:
|
||||
void TimeSearchProcess(eKeys Key);
|
||||
void TimeSearch(void);
|
||||
void Show(int Seconds = 0);
|
||||
void Hide(void);
|
||||
static char *fileName;
|
||||
static char *title;
|
||||
void DisplayAtBottom(const char *s = NULL);
|
||||
@ -139,6 +138,7 @@ public:
|
||||
cReplayControl(void);
|
||||
virtual ~cReplayControl();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
virtual void Hide(void);
|
||||
bool Visible(void) { return visible; }
|
||||
static void SetRecording(const char *FileName, const char *Title);
|
||||
static const char *LastReplayed(void);
|
||||
|
5
osd.h
5
osd.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osd.h 1.31 2002/05/18 14:00:15 kls Exp $
|
||||
* $Id: osd.h 1.32 2002/06/23 09:13:17 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSD_H
|
||||
@ -22,7 +22,6 @@
|
||||
#define MAXOSDITEMS (Setup.OSDheight - 4)
|
||||
|
||||
enum eOSState { osUnknown,
|
||||
osMenu,
|
||||
osContinue,
|
||||
osSchedule,
|
||||
osChannels,
|
||||
@ -115,7 +114,7 @@ public:
|
||||
int Width(void) { return Interface->Width(); }
|
||||
int Height(void) { return Interface->Height(); }
|
||||
bool NeedsFastResponse(void) { return needsFastResponse; }
|
||||
virtual eOSState ProcessKey(eKeys Key) = 0;
|
||||
virtual eOSState ProcessKey(eKeys Key) { return osUnknown; }
|
||||
};
|
||||
|
||||
class cOsdMenu : public cOsdObject, public cList<cOsdItem> {
|
||||
|
41
player.c
41
player.c
@ -4,10 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: player.c 1.1 2002/06/16 10:34:50 kls Exp $
|
||||
* $Id: player.c 1.3 2002/06/23 12:56:25 kls Exp $
|
||||
*/
|
||||
|
||||
#include "player.h"
|
||||
#include "i18n.h"
|
||||
|
||||
// --- cPlayer ---------------------------------------------------------------
|
||||
|
||||
@ -46,10 +47,46 @@ void cPlayer::Detach(void)
|
||||
|
||||
// --- cControl --------------------------------------------------------------
|
||||
|
||||
cControl::cControl(void)
|
||||
cControl *cControl::control = NULL;
|
||||
|
||||
cControl::cControl(cPlayer *Player, bool Hidden)
|
||||
{
|
||||
attached = false;
|
||||
hidden = Hidden;
|
||||
player = Player;
|
||||
}
|
||||
|
||||
cControl::~cControl()
|
||||
{
|
||||
if (this == control)
|
||||
control = NULL;
|
||||
}
|
||||
|
||||
cControl *cControl::Control(void)
|
||||
{
|
||||
return (control && !control->hidden) ? control : NULL;
|
||||
}
|
||||
|
||||
void cControl::Launch(cControl *Control)
|
||||
{
|
||||
delete control;
|
||||
control = Control;
|
||||
}
|
||||
|
||||
void cControl::Attach(void)
|
||||
{
|
||||
if (control && !control->attached && control->player && !control->player->IsAttached()) {
|
||||
if (cDevice::PrimaryDevice()->AttachPlayer(control->player))
|
||||
control->attached = true;
|
||||
else {
|
||||
Interface->Error(tr("Channel locked (recording)!"));
|
||||
Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cControl::Shutdown(void)
|
||||
{
|
||||
delete control;
|
||||
control = NULL;
|
||||
}
|
||||
|
16
player.h
16
player.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: player.h 1.1 2002/06/16 11:52:45 kls Exp $
|
||||
* $Id: player.h 1.4 2002/06/23 12:56:38 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PLAYER_H
|
||||
@ -40,12 +40,24 @@ protected:
|
||||
public:
|
||||
cPlayer(void);
|
||||
virtual ~cPlayer();
|
||||
bool IsAttached(void) { return device != NULL; }
|
||||
};
|
||||
|
||||
class cControl : public cOsdObject {
|
||||
private:
|
||||
static cControl *control;
|
||||
bool attached;
|
||||
bool hidden;
|
||||
protected:
|
||||
cPlayer *player;
|
||||
public:
|
||||
cControl(void);
|
||||
cControl(cPlayer *Player, bool Hidden = false);
|
||||
virtual ~cControl();
|
||||
virtual void Hide(void) = 0;
|
||||
static void Launch(cControl *Control);
|
||||
static void Attach(void);
|
||||
static void Shutdown(void);
|
||||
static cControl *Control(void);
|
||||
};
|
||||
|
||||
#endif //__PLAYER_H
|
||||
|
22
recording.c
22
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.63 2002/06/16 11:29:27 kls Exp $
|
||||
* $Id: recording.c 1.64 2002/06/22 10:11:49 kls Exp $
|
||||
*/
|
||||
|
||||
#include "recording.h"
|
||||
@ -1056,6 +1056,8 @@ int cFileName::NextFile(void)
|
||||
return SetOffset(fileNumber + 1);
|
||||
}
|
||||
|
||||
// --- Index stuff -----------------------------------------------------------
|
||||
|
||||
const char *IndexToHMSF(int Index, bool WithFrame)
|
||||
{
|
||||
static char buffer[16];
|
||||
@ -1080,3 +1082,21 @@ int SecondsToFrames(int Seconds)
|
||||
{
|
||||
return Seconds * FRAMESPERSEC;
|
||||
}
|
||||
|
||||
// --- ReadFrame -------------------------------------------------------------
|
||||
|
||||
int ReadFrame(int f, uchar *b, int Length, int Max)
|
||||
{
|
||||
if (Length == -1)
|
||||
Length = Max; // this means we read up to EOF (see cIndex)
|
||||
else if (Length > Max) {
|
||||
esyslog("ERROR: frame larger than buffer (%d > %d)", Length, Max);
|
||||
Length = Max;
|
||||
}
|
||||
int r = safe_read(f, b, Length);
|
||||
if (r < 0)
|
||||
LOG_ERROR;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recording.h 1.23 2002/06/16 11:29:47 kls Exp $
|
||||
* $Id: recording.h 1.24 2002/06/22 10:09:27 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RECORDING_H
|
||||
@ -107,6 +107,9 @@ public:
|
||||
//XXX+
|
||||
#define FRAMESPERSEC 25
|
||||
|
||||
// The maximum size of a single frame:
|
||||
#define MAXFRAMESIZE KILOBYTE(192)
|
||||
|
||||
// The maximum file size is limited by the range that can be covered
|
||||
// with 'int'. 4GB might be possible (if the range is considered
|
||||
// 'unsigned'), 2GB should be possible (even if the range is considered
|
||||
@ -163,4 +166,6 @@ int HMSFToIndex(const char *HMSF);
|
||||
int SecondsToFrames(int Seconds); //XXX+ ->player???
|
||||
// Returns the number of frames corresponding to the given number of seconds.
|
||||
|
||||
int ReadFrame(int f, uchar *b, int Length, int Max);
|
||||
|
||||
#endif //__RECORDING_H
|
||||
|
135
transfer.c
Normal file
135
transfer.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* transfer.c: Transfer mode
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: transfer.c 1.2 2002/06/23 12:56:49 kls Exp $
|
||||
*/
|
||||
|
||||
#include "transfer.h"
|
||||
|
||||
//XXX+ also used in recorder.c - find a better place???
|
||||
// The size of the array used to buffer video data:
|
||||
// (must be larger than MINVIDEODATA - see remux.h)
|
||||
#define VIDEOBUFSIZE MEGABYTE(1)
|
||||
|
||||
// --- cTransfer -------------------------------------------------------------
|
||||
|
||||
cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2)
|
||||
:cReceiver(0, 0, 5, VPid, APid1, APid2, DPid1, DPid2)
|
||||
{
|
||||
ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, true);
|
||||
remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2);
|
||||
gotBufferReserve = false;
|
||||
active = false;
|
||||
}
|
||||
|
||||
cTransfer::~cTransfer()
|
||||
{
|
||||
cReceiver::Detach();
|
||||
cPlayer::Detach();
|
||||
delete remux;
|
||||
delete ringBuffer;
|
||||
}
|
||||
|
||||
void cTransfer::Activate(bool On)
|
||||
{
|
||||
if (On) {
|
||||
if (!active)
|
||||
Start();
|
||||
}
|
||||
else if (active) {
|
||||
active = false;
|
||||
Cancel(3);
|
||||
}
|
||||
}
|
||||
|
||||
void cTransfer::Receive(uchar *Data, int Length)
|
||||
{
|
||||
int p = ringBuffer->Put(Data, Length);
|
||||
if (p != Length && active)
|
||||
esyslog("ERROR: ring buffer overflow (%d bytes dropped)", Length - p);
|
||||
}
|
||||
|
||||
void cTransfer::Action(void)
|
||||
{
|
||||
dsyslog("transfer thread started (pid=%d)", getpid());
|
||||
|
||||
uchar b[MINVIDEODATA];
|
||||
int r = 0;
|
||||
active = true;
|
||||
while (active) {
|
||||
|
||||
//XXX+ Maybe we need this to avoid "buffer empty" log messages from the driver.
|
||||
//XXX+ But then again, it appears to play just fine without this...
|
||||
/*
|
||||
if (!gotBufferReserve) {
|
||||
if (ringBuffer->Available() < 4 * MAXFRAMESIZE) {
|
||||
usleep(100000); // allow the buffer to collect some reserve
|
||||
continue;
|
||||
}
|
||||
else
|
||||
gotBufferReserve = true;
|
||||
}
|
||||
*/
|
||||
|
||||
// Get data from the buffer:
|
||||
|
||||
int g = ringBuffer->Get(b + r, sizeof(b) - r);
|
||||
if (g > 0)
|
||||
r += g;
|
||||
|
||||
// Play the data:
|
||||
|
||||
if (r > 0) {
|
||||
int Count = r, Result;
|
||||
const uchar *p = remux->Process(b, Count, Result);
|
||||
if (p) {
|
||||
//XXX+ StripAudio???
|
||||
while (Result > 0 && active) {
|
||||
int w = PlayVideo(p, Result);
|
||||
if (w > 0) {
|
||||
p += w;
|
||||
Result -= w;
|
||||
}
|
||||
else if (w < 0 && FATALERRNO) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Count > 0) {
|
||||
r -= Count;
|
||||
if (r > 0)
|
||||
memmove(b, b + Count, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dsyslog("transfer thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
void cTransfer::SetAudioPid(int APid)
|
||||
{
|
||||
/*XXX+
|
||||
Clear();
|
||||
//XXX we may need to have access to the audio device, too, in order to clear it
|
||||
CHECK(ioctl(toDevice, VIDEO_CLEAR_BUFFER));
|
||||
gotBufferReserve = false;
|
||||
remux.SetAudioPid(APid);
|
||||
XXX*/
|
||||
}
|
||||
|
||||
// --- cTransferControl ------------------------------------------------------
|
||||
|
||||
cTransferControl::cTransferControl(cDevice *ReceiverDevice, int VPid, int APid1, int APid2, int DPid1, int DPid2)
|
||||
:cControl(transfer = new cTransfer(VPid, APid1, APid2, DPid1, DPid2), true)
|
||||
{
|
||||
ReceiverDevice->AttachReceiver(transfer);
|
||||
}
|
||||
|
||||
cTransferControl::~cTransferControl()
|
||||
{
|
||||
delete transfer;
|
||||
}
|
44
transfer.h
Normal file
44
transfer.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* transfer.h: Transfer mode
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: transfer.h 1.2 2002/06/23 12:26:24 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TRANSFER_H
|
||||
#define __TRANSFER_H
|
||||
|
||||
#include "player.h"
|
||||
#include "receiver.h"
|
||||
#include "remux.h"
|
||||
#include "ringbuffer.h"
|
||||
#include "thread.h"
|
||||
|
||||
class cTransfer : public cReceiver, public cPlayer, public cThread {
|
||||
private:
|
||||
cRingBufferLinear *ringBuffer;
|
||||
cRemux *remux;
|
||||
bool gotBufferReserve;
|
||||
bool active;
|
||||
protected:
|
||||
virtual void Activate(bool On);
|
||||
virtual void Receive(uchar *Data, int Length);
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2);
|
||||
virtual ~cTransfer();
|
||||
void SetAudioPid(int APid);
|
||||
};
|
||||
|
||||
class cTransferControl : public cControl {
|
||||
private:
|
||||
cTransfer *transfer;
|
||||
public:
|
||||
cTransferControl(cDevice *ReceiverDevice, int VPid, int APid1, int APid2, int DPid1, int DPid2);
|
||||
~cTransferControl();
|
||||
virtual void Hide(void) {}
|
||||
};
|
||||
|
||||
#endif //__TRANSFER_H
|
80
vdr.c
80
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.114 2002/06/16 11:30:28 kls Exp $
|
||||
* $Id: vdr.c 1.117 2002/06/23 11:23:34 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -31,6 +31,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
#include "cutter.h"
|
||||
#include "device.h"
|
||||
#include "eitscan.h"
|
||||
#include "i18n.h"
|
||||
@ -371,7 +372,7 @@ int main(int argc, char *argv[])
|
||||
// Main program loop:
|
||||
|
||||
cOsdObject *Menu = NULL;
|
||||
cReplayControl *ReplayControl = NULL;
|
||||
cOsdObject *Temp = NULL;
|
||||
int LastChannel = -1;
|
||||
int PreviousChannel = cDevice::CurrentChannel();
|
||||
time_t LastActivity = 0;
|
||||
@ -389,6 +390,8 @@ int main(int argc, char *argv[])
|
||||
esyslog("emergency exit requested - shutting down");
|
||||
break;
|
||||
}
|
||||
// Attach launched player control:
|
||||
cControl::Attach();
|
||||
// Restart the Watchdog timer:
|
||||
if (WatchdogTimeout > 0) {
|
||||
int LatencyTime = WatchdogTimeout - alarm(WatchdogTimeout);
|
||||
@ -400,7 +403,7 @@ int main(int argc, char *argv[])
|
||||
// Channel display:
|
||||
if (!EITScanner.Active() && cDevice::CurrentChannel() != LastChannel) {
|
||||
if (!Menu)
|
||||
Menu = new cDisplayChannel(cDevice::CurrentChannel(), LastChannel > 0);
|
||||
Menu = Temp = new cDisplayChannel(cDevice::CurrentChannel(), LastChannel > 0);
|
||||
if (LastChannel > 0)
|
||||
PreviousChannel = LastChannel;
|
||||
LastChannel = cDevice::CurrentChannel();
|
||||
@ -416,14 +419,26 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
// User Input:
|
||||
cOsdObject **Interact = Menu ? &Menu : (cOsdObject **)&ReplayControl;
|
||||
eKeys key = Interface->GetKey(!*Interact || !(*Interact)->NeedsFastResponse());
|
||||
cOsdObject *Interact = Menu ? Menu : cControl::Control();
|
||||
eKeys key = Interface->GetKey(!Interact || !Interact->NeedsFastResponse());
|
||||
if (NORMALKEY(key) != kNone) {
|
||||
EITScanner.Activity();
|
||||
LastActivity = time(NULL);
|
||||
}
|
||||
// Keys that must work independent of any interactive mode:
|
||||
switch (key) {
|
||||
// Menu control:
|
||||
case kMenu:
|
||||
if (Menu) {
|
||||
DELETENULL(Menu);
|
||||
if (!Temp)
|
||||
break;
|
||||
}
|
||||
if (cControl::Control())
|
||||
cControl::Control()->Hide();
|
||||
Menu = new cMenuMain(cControl::Control());
|
||||
Temp = NULL;
|
||||
break;
|
||||
// Volume Control:
|
||||
case kVolUp|k_Repeat:
|
||||
case kVolUp:
|
||||
@ -436,13 +451,15 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
else
|
||||
cDevice::PrimaryDevice()->SetVolume(NORMALKEY(key) == kVolDn ? -VOLUMEDELTA : VOLUMEDELTA);
|
||||
if (!Menu && (!ReplayControl || !ReplayControl->Visible()))
|
||||
Menu = cDisplayVolume::Create();
|
||||
if (!Interface->IsOpen())
|
||||
Menu = Temp = cDisplayVolume::Create();
|
||||
cDisplayVolume::Process(key);
|
||||
break;
|
||||
// Power off:
|
||||
case kPower: isyslog("Power button pressed");
|
||||
DELETENULL(*Interact);
|
||||
DELETENULL(Menu);
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
if (!Shutdown) {
|
||||
Interface->Error(tr("Can't shutdown - option '-s' not given!"));
|
||||
break;
|
||||
@ -454,35 +471,42 @@ int main(int argc, char *argv[])
|
||||
LastActivity = 1; // not 0, see below!
|
||||
break;
|
||||
default:
|
||||
if (*Interact) {
|
||||
switch ((*Interact)->ProcessKey(key)) {
|
||||
case osMenu: DELETENULL(Menu);
|
||||
Menu = new cMenuMain(ReplayControl);
|
||||
break;
|
||||
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);
|
||||
DELETENULL(ReplayControl);
|
||||
Menu = new cMenuMain(ReplayControl, osRecordings);
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
Menu = new cMenuMain(false, osRecordings);
|
||||
break;
|
||||
case osReplay: DELETENULL(Menu);
|
||||
DELETENULL(ReplayControl);
|
||||
ReplayControl = new cReplayControl;
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
cControl::Launch(new cReplayControl);
|
||||
break;
|
||||
case osStopReplay:
|
||||
DELETENULL(*Interact);
|
||||
DELETENULL(ReplayControl);
|
||||
DELETENULL(Menu);
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
break;
|
||||
case osSwitchDvb:
|
||||
DELETENULL(*Interact);
|
||||
DELETENULL(Menu);
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
Interface->Info(tr("Switching primary DVB..."));
|
||||
cDevice::SetPrimaryDevice(Setup.PrimaryDVB);
|
||||
break;
|
||||
case osBack:
|
||||
case osEnd: DELETENULL(*Interact);
|
||||
case osEnd: if (Interact == Menu)
|
||||
DELETENULL(Menu);
|
||||
else
|
||||
cControl::Shutdown();
|
||||
Temp = NULL;
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
@ -519,8 +543,6 @@ int main(int argc, char *argv[])
|
||||
channel->Switch();
|
||||
break;
|
||||
}
|
||||
// Menu Control:
|
||||
case kMenu: Menu = new cMenuMain(ReplayControl); break;
|
||||
// Viewing Control:
|
||||
case kOk: LastChannel = -1; break; // forces channel display
|
||||
default: break;
|
||||
@ -529,16 +551,14 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
if (!Menu) {
|
||||
EITScanner.Process();
|
||||
/*XXX+
|
||||
if (!cVideoCutter::Active() && cVideoCutter::Ended()) {
|
||||
if (cVideoCutter::Error())
|
||||
if (!cCutter::Active() && cCutter::Ended()) {
|
||||
if (cCutter::Error())
|
||||
Interface->Error(tr("Editing process failed!"));
|
||||
else
|
||||
Interface->Info(tr("Editing process finished"));
|
||||
}
|
||||
XXX*/
|
||||
}
|
||||
if (!*Interact && ((!cRecordControls::Active() /*XXX+&& !cVideoCutter::Active()XXX*/) || ForceShutdown)) {
|
||||
if (!Interact && ((!cRecordControls::Active() && !cCutter::Active()) || ForceShutdown)) {
|
||||
time_t Now = time(NULL);
|
||||
if (Now - LastActivity > ACTIVITYTIMEOUT) {
|
||||
// Shutdown:
|
||||
@ -598,9 +618,9 @@ int main(int argc, char *argv[])
|
||||
if (Interrupted)
|
||||
isyslog("caught signal %d", Interrupted);
|
||||
cRecordControls::Shutdown();
|
||||
//XXX+cVideoCutter::Stop();
|
||||
cCutter::Stop();
|
||||
delete Menu;
|
||||
delete ReplayControl;
|
||||
cControl::Shutdown();
|
||||
delete Interface;
|
||||
cOsd::Shutdown();
|
||||
PluginManager.Shutdown(true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user