mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Version 0.98
- Completed storing the current audio volume in the setup.conf file (thanks to Andy Grobb). - Fixed closing the progress display with the "Back" key when in trick mode and Setup.ShowReplayMode is enabled (thanks to Stefan Huelswitt). - New SVDRP commands LSTR and DELR to list and delete recordings (thanks to Thomas Heiligenmann). - Fixed a crash when pressing the '2' button while replaying a DVD. - Updated 'channels.conf' for the "Bundesliga" channels of Premiere World (thanks to Mel Schchner). - Changed the tuning code to use FrontendInfo to detect the type of DVB card. - Removed the recursion stuff from cThread (cMutex already does this). - Fixed handling the repeat function in the channel display. - Avoiding multiple EPG entries for the same event (thanks to Rolf Hakenes for some valuable information on how to do this). - A recording on the primary interface can now be stopped to make it continue on an other free DVB card (if one is free at the moment). See MANUAL for details. - Added some missing teletext PIDs (thanks to Norbert Schmidt). - Added PTS to the converted PCM audio when replaying a DVD (thanks to Andreas Schultz). Now the audio and video of a DVD replayed over the DVB card's A/V out should always be in sync. - Fixed handling the "Power" key in case Setup.MinUserInactivity is set to 0 to disable automatic shutdown. - Added a fifth parameter to the 'shutdown' call that indicates the reason for this shutdown request (see INSTALL). - Fixed releasing 'index' memory after recording or playback. - Fixed ejecting a DVD while it is being replayed. - Removed all video overlay stuff from cDvbApi and SVDRP. Guido Fiala's new 'kvdr' version 0.4 now does these things itself. As a consequence of this you will now need to use kvdr 0.4 or later. - The device /dev/video is now opened only if necessary (to GRAB an image), allowing other programs (like 'kvdr', for instance) to use that device.
This commit is contained in:
parent
8465398c6d
commit
6e1fd83555
14
CONTRIBUTORS
14
CONTRIBUTORS
@ -23,6 +23,8 @@ Guido Fiala <gfiala@s.netic.de>
|
||||
for implementing the SVDRP command 'HITK'
|
||||
for implementing image grabbing
|
||||
for implementing overlay capabilities (see his 'kvdr' tool at http://www.s.netic.de/gfiala)
|
||||
(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
|
||||
|
||||
Robert Schneider <Robert.Schneider@lotus.com>
|
||||
@ -109,12 +111,13 @@ Ulrich R
|
||||
27500
|
||||
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
||||
|
||||
Helmut Schächner <schaechner@yahoo.com>
|
||||
Mel Schächner <schaechner@yahoo.com>
|
||||
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
||||
|
||||
Andreas Schultz <aschultz@warp10.net>
|
||||
for adding support for replaying DVDs (much of this was derived from
|
||||
dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>)
|
||||
for adding PTS to the converted PCM audio when replaying a DVD
|
||||
|
||||
Aaron Holtzman
|
||||
for writing 'ac3dec'
|
||||
@ -150,3 +153,12 @@ Andreas Share <a.share@t-online.de>
|
||||
|
||||
Simon Bauschulte <SemiSchwabe@Brutzel.de>
|
||||
for his support in keeping the Premiere World channels up to date in 'channels.conf'
|
||||
|
||||
Andy Grobb <Charly98@01019freenet.de>
|
||||
for completing storing the current audio volume in the setup.conf file
|
||||
|
||||
Thomas Heiligenmann <thomas@heiligenmann.de>
|
||||
for implementing the SVDRP commands LSTR and DELR
|
||||
|
||||
Norbert Schmidt <nschmidt-nrw@t-online.de>
|
||||
for filling in some missing teletext PIDs
|
||||
|
39
HISTORY
39
HISTORY
@ -595,7 +595,7 @@ Video Disk Recorder Revision History
|
||||
- When setting an editing mark while the progress display is not active, the
|
||||
display will now be turned on for a short while to indicate the successful
|
||||
setting of the mark.
|
||||
- Updated 'channels.conf' for Premiere World (thanks to Helmut Schächner).
|
||||
- Updated 'channels.conf' for Premiere World (thanks to Mel Schächner).
|
||||
Check your timers if you use this channels.conf file, since the sequence of
|
||||
several PW channels has been changed.
|
||||
- Changed the color of "Info" messages to "black on green" and that of the
|
||||
@ -825,8 +825,43 @@ Video Disk Recorder Revision History
|
||||
- The menu timeout now also works when pressing the "Back" button during replay
|
||||
to enter the "Recordings" menu.
|
||||
- Updated 'channels.conf' for the "Bundesliga" channels of Premiere World
|
||||
(thanks to Helmut Schächner).
|
||||
(thanks to Mel Schächner).
|
||||
- Fixed reading timers.conf and channels.conf that contain blanks after numeric
|
||||
values.
|
||||
- Fixed handling trick modes near the beginning and end of a recording.
|
||||
- Pressing the "Back" button while replaying a DVD now leads to the DVD menu.
|
||||
|
||||
2001-11-04: Version 0.98
|
||||
|
||||
- Completed storing the current audio volume in the setup.conf file (thanks
|
||||
to Andy Grobb).
|
||||
- Fixed closing the progress display with the "Back" key when in trick mode
|
||||
and Setup.ShowReplayMode is enabled (thanks to Stefan Huelswitt).
|
||||
- New SVDRP commands LSTR and DELR to list and delete recordings (thanks to
|
||||
Thomas Heiligenmann).
|
||||
- Fixed a crash when pressing the '2' button while replaying a DVD.
|
||||
- Updated 'channels.conf' for the "Bundesliga" channels of Premiere World
|
||||
(thanks to Mel Schächner).
|
||||
- Changed the tuning code to use FrontendInfo to detect the type of DVB card.
|
||||
- Removed the recursion stuff from cThread (cMutex already does this).
|
||||
- Fixed handling the repeat function in the channel display.
|
||||
- Avoiding multiple EPG entries for the same event (thanks to Rolf Hakenes
|
||||
for some valuable information on how to do this).
|
||||
- A recording on the primary interface can now be stopped to make it continue
|
||||
on an other free DVB card (if one is free at the moment). See MANUAL for
|
||||
details.
|
||||
- Added some missing teletext PIDs (thanks to Norbert Schmidt).
|
||||
- Added PTS to the converted PCM audio when replaying a DVD (thanks to Andreas
|
||||
Schultz). Now the audio and video of a DVD replayed over the DVB card's A/V
|
||||
out should always be in sync.
|
||||
- Fixed handling the "Power" key in case Setup.MinUserInactivity is set to 0 to
|
||||
disable automatic shutdown.
|
||||
- Added a fifth parameter to the 'shutdown' call that indicates the reason for
|
||||
this shutdown request (see INSTALL).
|
||||
- Fixed releasing 'index' memory after recording or playback.
|
||||
- Fixed ejecting a DVD while it is being replayed.
|
||||
- Removed all video overlay stuff from cDvbApi and SVDRP. Guido Fiala's new
|
||||
'kvdr' version 0.4 now does these things itself. As a consequence of this you
|
||||
will now need to use kvdr 0.4 or later.
|
||||
- The device /dev/video is now opened only if necessary (to GRAB an image),
|
||||
allowing other programs (like 'kvdr', for instance) to use that device.
|
||||
|
10
INSTALL
10
INSTALL
@ -25,7 +25,7 @@ directory ../DVD (seen from the VDR directory). Adjust the definition
|
||||
of DVDDIR in the Makefile if necessary.
|
||||
You can find 'libdvdread' at
|
||||
|
||||
http://www.dtek.chalmers.se/groups/dvd/downloads.html
|
||||
http://www.dtek.chalmers.se/groups/dvd/downloads.shtml
|
||||
|
||||
If you want to replay CSS encrypted DVDs you also need to get the 'libdvdcss'
|
||||
library from
|
||||
@ -127,7 +127,7 @@ active, the user has been inactive for at least MinUserInactivity minutes
|
||||
and the next timer event is at least MinEventTimeout minutes in the future
|
||||
(see the Setup parameters in MANUAL).
|
||||
|
||||
The command given in the '-s' option will be called with four parameters.
|
||||
The command given in the '-s' option will be called with five parameters.
|
||||
The first one is the time (in UTC) of the next timer event (as a time_t
|
||||
type number), and the second one is the number of seconds from the current
|
||||
time until the next timer event. Your program can choose which one to use
|
||||
@ -153,6 +153,12 @@ contains the file name of the recording as defined in the timer (or an empty
|
||||
string if no timer is present). These can be used by the shutdown program to
|
||||
show that information on some display interface etc.
|
||||
|
||||
The fifth parameter indicates the reason why the shutdown was requested.
|
||||
'0' means this is an automatic shutdown due to some timeout, while '1' means
|
||||
that this is a user requested shutdown (resulting from pressing the "Power"
|
||||
key). The shutdown program may use this information to decide whether or
|
||||
not to actually perform the system shutdown.
|
||||
|
||||
If a timer is currently recording, the parameters will reflect the start
|
||||
time of that timer. This means that the first parameter will be a time in
|
||||
the past, and the second parameter will be a negative number. This only
|
||||
|
14
MANUAL
14
MANUAL
@ -310,6 +310,20 @@ Video Disk Recorder User's Manual
|
||||
A timer can also be programmed by pressing the "Red" button on the "Schedule",
|
||||
"Now", "Next" or "Event" menus.
|
||||
|
||||
* Stopping a recording on the primary DVB interface
|
||||
|
||||
If the primary DVB interface is currently recording, the user can't switch
|
||||
the channel or replay another recording on that interface. However, if there
|
||||
is an other DVB interface that is currently not recording and provides the
|
||||
necessary conditional access facilities to continue the recording that is
|
||||
currently being performed on the primary DVB interface, the Main menu will
|
||||
contain an option that allows you to stop recording on the primary DVB
|
||||
interface. Select that option to stop the ongoing recording and thus free the
|
||||
primary DVB interface to allow channel switching or replaying. The interrupted
|
||||
recording will be continued on an other free DVB interface. There may be a
|
||||
short discontinuity at that point when replaying that recording later, so you
|
||||
may want to place such an action for instance in a commercial break.
|
||||
|
||||
* Parameters in the "Setup" menu
|
||||
|
||||
Select "Setup" from the "Main" menu to enter the setup menu. From there you can
|
||||
|
@ -2,19 +2,19 @@ RTL:12188:h:0:27500:163:104:105:0:12003
|
||||
Sat.1:12480:v:0:27500:1791:1792:34:0:46
|
||||
Pro-7:12480:v:0:27500:255:256;257:32:0:898
|
||||
RTL2:12188:h:0:27500:166:128:68:0:12020
|
||||
ARD:11837:h:0:27500:101:102:0:0:28106
|
||||
BR3:11837:h:0:27500:201:202:0:0:28107
|
||||
ARD:11837:h:0:27500:101:102:104:0:28106
|
||||
BR3:11837:h:0:27500:201:202:204:0:28107
|
||||
Hessen-3:11837:h:0:27500:301:302:0:0:28108
|
||||
N3:12110:h:0:27500:2401:2402:0:0:28224
|
||||
SR3:11837:h:0:27500:501:502:0:0:28110
|
||||
N3:12110:h:0:27500:2401:2402:2404:0:28224
|
||||
SR3:11837:h:0:27500:501:502:504:0:28110
|
||||
WDR:11837:h:0:27500:601:602:0:0:28111
|
||||
BR-alpha:11837:h:0:27500:701:702:0:0:28112
|
||||
SWR BW:11837:h:0:27500:801:802:0:0:28113
|
||||
Phoenix:11837:h:0:27500:901:902:0:0:28114
|
||||
BR-alpha:11837:h:0:27500:701:702:704:0:28112
|
||||
SWR BW:11837:h:0:27500:801:802:804:0:28113
|
||||
Phoenix:11837:h:0:27500:901:902:904:0:28114
|
||||
ZDF:11954:h:0:27500:110:120:130:0:28006
|
||||
3sat:11954:h:0:27500:210:220:230:0:28007
|
||||
KiKa:11954:h:0:27500:310:320:0:0:28008
|
||||
arte:11836:h:0:27500:401:402:0:0:28109
|
||||
KiKa:11954:h:0:27500:310:320:330:0:28008
|
||||
arte:11836:h:0:27500:401:402:404:0:28109
|
||||
ORF1:12692:h:0:22000:160:161:165:3:13001
|
||||
ORF2:12692:h:0:22000:500:501:505:3:13002
|
||||
ORF Sat:11954:h:0:27500:506:507:0:0:28010
|
||||
@ -42,10 +42,10 @@ EinsFestival:12110:h:0:27500:201:202:0:0:28202
|
||||
EinsMuXx:12110:h:0:27500:301:302:0:0:28203
|
||||
ZDF Theaterkanal:11954:h:0:27500:1110:1120:0:0:28016
|
||||
ZDF.doku:11954:h:0:27500:660:670:0:0:28014
|
||||
MDR:12110:h:0:27500:401:402:0:0:28204
|
||||
MDR:12110:h:0:27500:401:402:404:0:28204
|
||||
NICK-PARAMOUNT:12246:v:0:27500:167:108:0:0:29312
|
||||
ORB:12110:h:0:27500:501:502:0:0:28205
|
||||
B1:12110:h:0:27500:601:602:0:0:28206
|
||||
ORB:12110:h:0:27500:501:502:504:0:28205
|
||||
B1:12110:h:0:27500:601:602:604:0:28206
|
||||
ARD Online-Kanal:12722:h:0:22000:0:701:0:0:0
|
||||
:Premiere World
|
||||
Premiere World:11797:h:0:27500:255:256:32:0:8
|
||||
@ -117,14 +117,14 @@ Cockpitkanal:11720:h:0:27500:2559:2560:0:3:242
|
||||
Boxengasse:11720:h:0:27500:2047:2048:0:3:240
|
||||
:Premiere World Bundesliga
|
||||
Superdom:11758:h:0:27500:2815:8192:0:3:18
|
||||
BuLi-Konferenz:11758:h:0:27500:3071:3072,3073:0:3:215
|
||||
BuLi-Konferenz:11758:h:0:27500:3327:3328,3329:0:3:215
|
||||
BuLi-Spiel 1:11719:h:0:27500:255:256,257:0:3:17
|
||||
BuLi-Spiel 2:11719:h:0:27500:2047:2048,2049:0:3:240
|
||||
BuLi-Spiel 3:11719:h:0:27500:3327:3328,3329:0:3:241
|
||||
BuLi-Spiel 4:11719:h:0:27500:2303:2304,2305:0:3:242
|
||||
BuLi-Spiel 5:11719:h:0:27500:3583:3584,3585:0:3:243
|
||||
BuLi-Spiel 6:11719:h:0:27500:2559:2560,2561:0:3:244
|
||||
BuLi-Spiel 7:11758:h:0:27500:2815:2816,2817:0:3:214
|
||||
BuLi-Spiel 3:11719:h:0:27500:2303:2304,2305:0:3:241
|
||||
BuLi-Spiel 4:11719:h:0:27500:2559:2560,2561:0:3:242
|
||||
BuLi-Spiel 5:11719:h:0:27500:2815:2816,2817:0:3:243
|
||||
BuLi-Spiel 6:11719:h:0:27500:3071:3072,3073:0:3:244
|
||||
BuLi-Spiel 7:11758:h:0:27500:3071:3072,3073:0:3:214
|
||||
:
|
||||
TV Niepokalanow:11876:h:0:27500:305:321:0:0:20601
|
||||
Mosaico:11934:v:0:27500:165:100:0:0:29010
|
||||
|
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.84 2001/10/07 15:13:23 kls Exp $
|
||||
* $Id: config.h 1.85 2001/10/27 09:56:04 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -18,7 +18,7 @@
|
||||
#include "eit.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "0.97"
|
||||
#define VDRVERSION "0.98"
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
|
625
dvbapi.c
625
dvbapi.c
@ -7,7 +7,7 @@
|
||||
* DVD support initially written by Andreas Schultz <aschultz@warp10.net>
|
||||
* based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si>
|
||||
*
|
||||
* $Id: dvbapi.c 1.132 2001/10/21 13:36:27 kls Exp $
|
||||
* $Id: dvbapi.c 1.137 2001/11/04 12:05:36 kls Exp $
|
||||
*/
|
||||
|
||||
//#define DVDDEBUG 1
|
||||
@ -200,6 +200,7 @@ cIndexFile::~cIndexFile()
|
||||
if (f >= 0)
|
||||
close(f);
|
||||
delete fileName;
|
||||
delete index;
|
||||
}
|
||||
|
||||
bool cIndexFile::CatchUp(int Index)
|
||||
@ -713,7 +714,10 @@ protected:
|
||||
void TrickSpeed(int Increment);
|
||||
virtual void Empty(bool Block = false);
|
||||
virtual void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00) {}
|
||||
virtual void PlayExternalDolby(const uchar *b, int MaxLength);
|
||||
virtual void Output(void);
|
||||
void putFrame(cFrame *Frame);
|
||||
void putFrame(unsigned char *Data, int Length, eFrameType Type = ftUnknown);
|
||||
public:
|
||||
cPlayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev);
|
||||
virtual ~cPlayBuffer();
|
||||
@ -759,6 +763,28 @@ cPlayBuffer::~cPlayBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
void cPlayBuffer::PlayExternalDolby(const uchar *b, int MaxLength)
|
||||
{
|
||||
if (dolbyDev) {
|
||||
if (b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01) {
|
||||
if (b[3] == 0xBD) { // dolby
|
||||
int l = b[4] * 256 + b[5] + 6;
|
||||
int written = b[8] + 9; // skips the PES header
|
||||
int n = min(l - written, MaxLength);
|
||||
while (n > 0) {
|
||||
int w = fwrite(&b[written], 1, n, dolbyDev);
|
||||
if (w < 0) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
n -= w;
|
||||
written += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cPlayBuffer::Output(void)
|
||||
{
|
||||
dsyslog(LOG_INFO, "output thread started (pid=%d)", getpid());
|
||||
@ -771,6 +797,9 @@ void cPlayBuffer::Output(void)
|
||||
}
|
||||
const cFrame *frame = Get();
|
||||
if (frame) {
|
||||
if (frame->Type() == ftDolby)
|
||||
PlayExternalDolby(frame->Data(), frame->Count());
|
||||
else {
|
||||
StripAudioPackets((uchar *)frame->Data(), frame->Count(), (playMode == pmFast || playMode == pmSlow) ? 0x00 : audioTrack);//XXX
|
||||
const uchar *p = frame->Data();
|
||||
int r = frame->Count();
|
||||
@ -789,6 +818,7 @@ void cPlayBuffer::Output(void)
|
||||
}
|
||||
writeIndex = frame->Index();
|
||||
backTrace.Add(frame->Index(), frame->Count());
|
||||
}
|
||||
Drop(frame);
|
||||
}
|
||||
}
|
||||
@ -796,6 +826,20 @@ void cPlayBuffer::Output(void)
|
||||
dsyslog(LOG_INFO, "output thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
void cPlayBuffer::putFrame(cFrame *Frame)
|
||||
{
|
||||
while (Busy() && !blockInput) {
|
||||
if (Put(Frame))
|
||||
return;
|
||||
}
|
||||
delete Frame; // caller relies on frame being put, otherwise this would be a memory leak!
|
||||
}
|
||||
|
||||
void cPlayBuffer::putFrame(unsigned char *Data, int Length, eFrameType Type)
|
||||
{
|
||||
putFrame(new cFrame(Data, Length, Type));
|
||||
}
|
||||
|
||||
void cPlayBuffer::TrickSpeed(int Increment)
|
||||
{
|
||||
int nts = trickSpeed + Increment;
|
||||
@ -1089,11 +1133,8 @@ void cReplayBuffer::Input(void)
|
||||
}
|
||||
else // allows replay even if the index file is missing
|
||||
r = read(replayFile, b, sizeof(b));
|
||||
if (r > 0) {
|
||||
cFrame *frame = new cFrame(b, r, readIndex);
|
||||
while (Busy() && !blockInput && !Put(frame))
|
||||
;
|
||||
}
|
||||
if (r > 0)
|
||||
putFrame(new cFrame(b, r, ftUnknown, readIndex));
|
||||
else if (r == 0)
|
||||
eof = true;
|
||||
else if (r < 0 && FATALERRNO) {
|
||||
@ -1117,19 +1158,8 @@ void cReplayBuffer::StripAudioPackets(uchar *b, int Length, uchar Except)
|
||||
int l = b[i + 4] * 256 + b[i + 5] + 6;
|
||||
switch (c) {
|
||||
case 0xBD: // dolby
|
||||
if (Except && dolbyDev) {
|
||||
int written = b[i + 8] + 9; // skips the PES header
|
||||
int n = l - written;
|
||||
while (n > 0) {
|
||||
int w = fwrite(&b[i + written], 1, n, dolbyDev);
|
||||
if (w < 0) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
n -= w;
|
||||
written += w;
|
||||
}
|
||||
}
|
||||
if (Except && dolbyDev)
|
||||
PlayExternalDolby(&b[i], Length - i);
|
||||
// continue with deleting the data - otherwise it disturbs DVB replay
|
||||
case 0xC0 ... 0xC1: // audio
|
||||
if (c == 0xC1)
|
||||
@ -1290,10 +1320,166 @@ bool cReplayBuffer::NextFile(uchar FileNumber, int FileOffset)
|
||||
}
|
||||
|
||||
#ifdef DVDSUPPORT
|
||||
|
||||
#define SYSTEM_HEADER 0xBB
|
||||
#define PROG_STREAM_MAP 0xBC
|
||||
#ifndef PRIVATE_STREAM1
|
||||
#define PRIVATE_STREAM1 0xBD
|
||||
#endif
|
||||
#define PADDING_STREAM 0xBE
|
||||
#ifndef PRIVATE_STREAM2
|
||||
#define PRIVATE_STREAM2 0xBF
|
||||
#endif
|
||||
#define AUDIO_STREAM_S 0xC0
|
||||
#define AUDIO_STREAM_E 0xDF
|
||||
#define VIDEO_STREAM_S 0xE0
|
||||
#define VIDEO_STREAM_E 0xEF
|
||||
#define ECM_STREAM 0xF0
|
||||
#define EMM_STREAM 0xF1
|
||||
#define DSM_CC_STREAM 0xF2
|
||||
#define ISO13522_STREAM 0xF3
|
||||
#define PROG_STREAM_DIR 0xFF
|
||||
|
||||
#define cOPENDVD 0
|
||||
#define cOPENTITLE 1
|
||||
#define cOPENCHAPTER 2
|
||||
#define cOUTCELL 3
|
||||
#define cREADFRAME 4
|
||||
#define cOUTPACK 5
|
||||
#define cOUTFRAMES 6
|
||||
|
||||
#define aAC3 0x80
|
||||
#define aLPCM 0xA0
|
||||
|
||||
// --- cAC3toPCM -------------------------------------------------------------
|
||||
|
||||
class cAC3toPCM {
|
||||
private:
|
||||
enum { AC3_STOP, AC3_START, AC3_PLAY } ac3stat;
|
||||
uchar *ac3data;
|
||||
int ac3inp;
|
||||
int ac3outp;
|
||||
public:
|
||||
cAC3toPCM(void);
|
||||
~cAC3toPCM();
|
||||
void Clear(void);
|
||||
void Put(unsigned char *sector, int length);
|
||||
cFrame *Get(int size, uchar PTSflags = 0, uchar *PTSdata = 0);
|
||||
};
|
||||
|
||||
cAC3toPCM::cAC3toPCM(void)
|
||||
{
|
||||
ac3dec_init();
|
||||
ac3data = new uchar[AC3_BUFFER_SIZE];
|
||||
Clear();
|
||||
}
|
||||
|
||||
cAC3toPCM::~cAC3toPCM()
|
||||
{
|
||||
delete ac3data;
|
||||
}
|
||||
|
||||
void cAC3toPCM::Clear(void)
|
||||
{
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp = 0;
|
||||
}
|
||||
|
||||
void cAC3toPCM::Put(unsigned char *sector, int length)
|
||||
{
|
||||
ac3dec_decode_data(sector, sector + length, ac3stat == AC3_START, &ac3inp, &ac3outp, (char *)ac3data);
|
||||
ac3stat = AC3_PLAY;
|
||||
}
|
||||
|
||||
// data=PCM samples, 16 bit, LSB first, 48kHz, stereo
|
||||
cFrame *cAC3toPCM::Get(int size, uchar PTSflags, uchar *PTSdata)
|
||||
{
|
||||
if (ac3inp == ac3outp)
|
||||
return NULL;
|
||||
|
||||
#define MAXSIZE 2022
|
||||
|
||||
uchar buffer[2048];
|
||||
uchar *data;
|
||||
|
||||
if (size > 0) {
|
||||
int p_size = (size > MAXSIZE) ? MAXSIZE : size;
|
||||
int length = 10; // default header bytes
|
||||
int header = 0;
|
||||
int stuffb = 0;
|
||||
|
||||
switch (PTSflags) {
|
||||
case 2: header = 5; // additional header bytes
|
||||
stuffb = 1;
|
||||
break;
|
||||
case 3: header = 10;
|
||||
break;
|
||||
default: header = 0;
|
||||
}
|
||||
|
||||
// header = 0; //XXX ???
|
||||
stuffb = 0; //XXX ???
|
||||
|
||||
length += header;
|
||||
length += stuffb;
|
||||
|
||||
buffer[0] = 0x00;
|
||||
buffer[1] = 0x00;
|
||||
buffer[2] = 0x01;
|
||||
buffer[3] = PRIVATE_STREAM1;
|
||||
|
||||
buffer[6] = 0x80;
|
||||
buffer[7] = PTSflags << 6;
|
||||
buffer[8] = header + stuffb;
|
||||
|
||||
if (header)
|
||||
memcpy(&buffer[9], (void *)PTSdata, header);
|
||||
|
||||
// add stuffing
|
||||
data = buffer + 9 + header;
|
||||
for (int cnt = 0; cnt < stuffb; cnt++)
|
||||
data[cnt] = 0xff;
|
||||
length += stuffb;
|
||||
|
||||
// add data
|
||||
data = buffer + 9 + header + stuffb + 7;
|
||||
int cnt = 0;
|
||||
while (p_size) {
|
||||
if (ac3outp != ac3inp) { // data in the buffer
|
||||
data[cnt ^ 1] = ac3data[ac3outp]; // swab because ac3dec delivers wrong byteorder (the "xor" (^) is a swab!)
|
||||
p_size--;
|
||||
cnt++;
|
||||
length++;
|
||||
ac3outp = (ac3outp + 1) % AC3_BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
data = buffer + 9 + header + stuffb;
|
||||
data[0] = aLPCM; // substream ID
|
||||
data[1] = 0x00; // other stuff (see DVB specs), ignored by driver
|
||||
data[2] = 0x00;
|
||||
data[3] = 0x00;
|
||||
data[4] = 0x00;
|
||||
data[5] = 0x00;
|
||||
data[6] = 0x00;
|
||||
|
||||
buffer[4] = (length >> 8) & 0xff;
|
||||
buffer[5] = length & 0xff;
|
||||
|
||||
length += 6;
|
||||
|
||||
return new cFrame(buffer, length);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- cDVDplayBuffer --------------------------------------------------------
|
||||
|
||||
class cDVDplayBuffer : public cPlayBuffer {
|
||||
private:
|
||||
cAC3toPCM AC3toPCM;
|
||||
uchar audioTrack;
|
||||
|
||||
cDVD *dvd;//XXX necessary???
|
||||
@ -1308,7 +1494,6 @@ private:
|
||||
int doplay;
|
||||
int cyclestate;
|
||||
int prevcycle;
|
||||
int brakeCounter;
|
||||
int skipCnt;
|
||||
|
||||
tt_srpt_t *tt_srpt;
|
||||
@ -1335,11 +1520,6 @@ private:
|
||||
int logAudioTrack;
|
||||
int maxAudioTrack;
|
||||
|
||||
enum { AC3_STOP, AC3_START, AC3_PLAY } ac3stat;
|
||||
uchar *ac3data;
|
||||
int ac3inp;
|
||||
int ac3outp;
|
||||
int lpcm_count;
|
||||
int is_nav_pack(unsigned char *buffer);
|
||||
void Close(void);
|
||||
virtual void Empty(bool Block = false);
|
||||
@ -1350,10 +1530,7 @@ private:
|
||||
int GetStuffingLen(const uchar *Data);
|
||||
int GetPacketLength(const uchar *Data);
|
||||
int GetPESHeaderLength(const uchar *Data);
|
||||
int SendPCM(int size);
|
||||
void playDecodedAC3(void);
|
||||
void handleAC3(unsigned char *sector, int length);
|
||||
void putFrame(unsigned char *sector, int length);
|
||||
void handleAC3(unsigned char *sector, int length, uchar PTSflags, uchar *PTSdata);
|
||||
unsigned int getAudioStream(unsigned int StreamId);
|
||||
void setChapid(void);
|
||||
void NextState(int State) { prevcycle = cyclestate; cyclestate = State; }
|
||||
@ -1369,17 +1546,6 @@ public:
|
||||
virtual void ToggleAudioTrack(void);
|
||||
};
|
||||
|
||||
#define cOPENDVD 0
|
||||
#define cOPENTITLE 1
|
||||
#define cOPENCHAPTER 2
|
||||
#define cOUTCELL 3
|
||||
#define cREADFRAME 4
|
||||
#define cOUTPACK 5
|
||||
#define cOUTFRAMES 6
|
||||
|
||||
#define aAC3 0x80
|
||||
#define aLPCM 0xA0
|
||||
|
||||
cDVDplayBuffer::cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD *DvD, int title)
|
||||
:cPlayBuffer(DvbApi, VideoDev, AudioDev)
|
||||
{
|
||||
@ -1389,15 +1555,10 @@ cDVDplayBuffer::cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD
|
||||
angle = 0;
|
||||
cyclestate = cOPENDVD;
|
||||
prevcycle = 0;
|
||||
brakeCounter = 0;
|
||||
skipCnt = 0;
|
||||
logAudioTrack = 0;
|
||||
canToggleAudioTrack = true;//XXX determine from cDVD!
|
||||
ac3dec_init();
|
||||
data = new uchar[1024 * DVD_VIDEO_LB_LEN];
|
||||
ac3data = new uchar[AC3_BUFFER_SIZE];
|
||||
ac3inp = ac3outp = 0;
|
||||
ac3stat = AC3_START;
|
||||
canDoTrickMode = true;
|
||||
dvbApi->SetModeReplay();
|
||||
Start();
|
||||
@ -1408,7 +1569,6 @@ cDVDplayBuffer::~cDVDplayBuffer()
|
||||
Stop();
|
||||
Close();
|
||||
dvbApi->SetModeNormal(false);
|
||||
delete ac3data;
|
||||
delete data;
|
||||
}
|
||||
|
||||
@ -1449,8 +1609,7 @@ void cDVDplayBuffer::ToggleAudioTrack(void)
|
||||
#ifdef DVDDEBUG
|
||||
dsyslog(LOG_INFO, "DVB: Audio Stream ID changed to: %x", audioTrack);
|
||||
#endif
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp;
|
||||
AC3toPCM.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1869,141 +2028,21 @@ int cDVDplayBuffer::ScanVideoPacket(const uchar *Data, int Count, uchar *Picture
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SYSTEM_HEADER 0xBB
|
||||
#define PROG_STREAM_MAP 0xBC
|
||||
#ifndef PRIVATE_STREAM1
|
||||
#define PRIVATE_STREAM1 0xBD
|
||||
#endif
|
||||
#define PADDING_STREAM 0xBE
|
||||
#ifndef PRIVATE_STREAM2
|
||||
#define PRIVATE_STREAM2 0xBF
|
||||
#endif
|
||||
#define AUDIO_STREAM_S 0xC0
|
||||
#define AUDIO_STREAM_E 0xDF
|
||||
#define VIDEO_STREAM_S 0xE0
|
||||
#define VIDEO_STREAM_E 0xEF
|
||||
#define ECM_STREAM 0xF0
|
||||
#define EMM_STREAM 0xF1
|
||||
#define DSM_CC_STREAM 0xF2
|
||||
#define ISO13522_STREAM 0xF3
|
||||
#define PROG_STREAM_DIR 0xFF
|
||||
|
||||
// data=PCM samples, 16 bit, LSB first, 48kHz, stereo
|
||||
int cDVDplayBuffer::SendPCM(int size)
|
||||
void cDVDplayBuffer::handleAC3(unsigned char *sector, int length, uchar PTSflags, uchar *PTSdata)
|
||||
{
|
||||
|
||||
#define MAXSIZE 2032
|
||||
|
||||
uchar buffer[MAXSIZE + 16];
|
||||
int length = 0;
|
||||
int p_size;
|
||||
|
||||
if (ac3inp == ac3outp)
|
||||
return 1;
|
||||
|
||||
while (size > 0) {
|
||||
if (size >= MAXSIZE)
|
||||
p_size = MAXSIZE;
|
||||
else
|
||||
p_size = size;
|
||||
length = 10;
|
||||
|
||||
while (p_size) {
|
||||
if (ac3outp != ac3inp) { // data in the buffer
|
||||
buffer[(length + 6) ^ 1] = ac3data[ac3outp]; // swab because ac3dec delivers wrong byteorder
|
||||
// XXX there is no 'swab' here??? (kls)
|
||||
p_size--;
|
||||
length++;
|
||||
ac3outp = (ac3outp + 1) % AC3_BUFFER_SIZE;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
buffer[0] = 0x00;
|
||||
buffer[1] = 0x00;
|
||||
buffer[2] = 0x01;
|
||||
buffer[3] = PRIVATE_STREAM1;
|
||||
|
||||
buffer[4] = (length >> 8) & 0xff;
|
||||
buffer[5] = length & 0xff;
|
||||
|
||||
buffer[6] = 0x80;
|
||||
buffer[7] = 0x00;
|
||||
buffer[8] = 0x00;
|
||||
|
||||
buffer[9] = aLPCM; // substream ID
|
||||
buffer[10] = 0x00; // other stuff (see DVD specs), ignored by driver
|
||||
buffer[11] = 0x00;
|
||||
buffer[12] = 0x00;
|
||||
buffer[13] = 0x00;
|
||||
buffer[14] = 0x00;
|
||||
buffer[15] = 0x00;
|
||||
|
||||
length += 6;
|
||||
|
||||
putFrame(buffer, length);
|
||||
size -= MAXSIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cDVDplayBuffer::playDecodedAC3(void)
|
||||
{
|
||||
int ac3_datasize = (AC3_BUFFER_SIZE + ac3inp - ac3outp) % AC3_BUFFER_SIZE;
|
||||
|
||||
if (ac3_datasize) {
|
||||
if (ac3_datasize > 1024 * 48)
|
||||
SendPCM(3096);
|
||||
else if (ac3_datasize > 1024 * 32)
|
||||
SendPCM(1536);
|
||||
else if (ac3_datasize > 1024 * 16 && !(lpcm_count % 2))
|
||||
SendPCM(1536);
|
||||
else if (ac3_datasize && !(lpcm_count % 4))
|
||||
SendPCM(1536);
|
||||
lpcm_count++;
|
||||
}
|
||||
else
|
||||
lpcm_count=0;
|
||||
}
|
||||
|
||||
void cDVDplayBuffer::handleAC3(unsigned char *sector, int length)
|
||||
{
|
||||
if (dolbyDev) {
|
||||
while (length > 0) {
|
||||
int w = fwrite(sector, 1, length , dolbyDev);
|
||||
if (w < 0) {
|
||||
LOG_ERROR;
|
||||
break;
|
||||
}
|
||||
length -= w;
|
||||
sector += w;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ac3stat == AC3_PLAY)
|
||||
ac3dec_decode_data(sector, sector + length, 0, &ac3inp, &ac3outp, (char *)ac3data);
|
||||
else if (ac3stat == AC3_START) {
|
||||
ac3dec_decode_data(sector, sector + length, 1, &ac3inp, &ac3outp, (char *)ac3data);
|
||||
ac3stat = AC3_PLAY;
|
||||
}
|
||||
}
|
||||
//playDecodedAC3();
|
||||
}
|
||||
|
||||
void cDVDplayBuffer::putFrame(unsigned char *sector, int length)
|
||||
{
|
||||
cFrame *frame = new cFrame(sector, length);
|
||||
while (Busy() && !blockInput && !Put(frame))
|
||||
;
|
||||
#define PCM_FRAME_SIZE 1536
|
||||
AC3toPCM.Put(sector, length);
|
||||
cFrame *frame;
|
||||
if ((frame = AC3toPCM.Get(PCM_FRAME_SIZE, PTSflags, PTSdata)) != NULL)
|
||||
putFrame(frame);
|
||||
while ((frame = AC3toPCM.Get(PCM_FRAME_SIZE)) != NULL)
|
||||
putFrame(frame);
|
||||
}
|
||||
|
||||
int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
{
|
||||
//XXX kls 2001-11-03: do we really need all these different return values?
|
||||
uchar pt = 1;
|
||||
#if 0
|
||||
uchar *osect = sector;
|
||||
#endif
|
||||
|
||||
//make sure we got a PS packet header
|
||||
if (!PacketStart(§or, DVD_VIDEO_LB_LEN) && GetPacketType(sector) != 0xBA) {
|
||||
@ -2017,6 +2056,8 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
int datalen = r;
|
||||
|
||||
sector[6] &= 0x8f;
|
||||
uchar PTSflags = sector[7] >> 6;
|
||||
uchar *PTSdata = sector + 9;
|
||||
uchar *data = sector;
|
||||
|
||||
switch (GetPacketType(sector)) {
|
||||
@ -2025,6 +2066,7 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
ScanVideoPacket(sector, r, &pt);
|
||||
if (trickMode && pt != 1)
|
||||
return pt;
|
||||
putFrame(sector, r, ftVideo);
|
||||
break;
|
||||
}
|
||||
case AUDIO_STREAM_S ... AUDIO_STREAM_E: {
|
||||
@ -2033,6 +2075,7 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
return 1;
|
||||
if (audioTrack != GetPacketType(sector))
|
||||
return 5;
|
||||
putFrame(sector, r, ftAudio);
|
||||
break;
|
||||
}
|
||||
case PRIVATE_STREAM1:
|
||||
@ -2060,14 +2103,15 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
if (audioTrack == *data) {
|
||||
switch (audioTrack & 0xF8) {
|
||||
case aAC3:
|
||||
if (dolbyDev)
|
||||
putFrame(sector, r, ftDolby);
|
||||
data += 4;
|
||||
// correct a3 data lenght - FIXME: why 13 ???
|
||||
datalen -= 13;
|
||||
handleAC3(data, datalen);
|
||||
datalen -= 13; // 3 (mandatory header) + 6 (PS header) + 4 (AC3 header) = 13
|
||||
handleAC3(data, datalen, PTSflags, PTSdata);
|
||||
break;
|
||||
case aLPCM:
|
||||
// write(audio, sector+14 , sector[19]+(sector[18]<<8)+6);
|
||||
putFrame(sector, GetPacketLength(sector));
|
||||
putFrame(sector, GetPacketLength(sector), ftAudio);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2096,9 +2140,6 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode)
|
||||
return pt;
|
||||
}
|
||||
}
|
||||
putFrame(sector, r);
|
||||
if ((audioTrack & 0xF8) == aAC3)
|
||||
playDecodedAC3();
|
||||
return pt;
|
||||
}
|
||||
|
||||
@ -2106,8 +2147,7 @@ void cDVDplayBuffer::Empty(bool Block)
|
||||
{
|
||||
if (!(blockInput || blockOutput)) {
|
||||
cPlayBuffer::Empty(true);
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp;
|
||||
AC3toPCM.Clear();
|
||||
}
|
||||
if (!Block)
|
||||
cPlayBuffer::Empty(false);
|
||||
@ -2149,9 +2189,7 @@ void cDVDplayBuffer::SkipSeconds(int Seconds)
|
||||
Empty(true);
|
||||
chapid = newchapid;
|
||||
NextState(cOPENCHAPTER);
|
||||
if (ac3stat != AC3_STOP)
|
||||
ac3stat = AC3_START;
|
||||
ac3outp = ac3inp;
|
||||
AC3toPCM.Clear();
|
||||
Empty(false);
|
||||
Play();
|
||||
}
|
||||
@ -2488,6 +2526,7 @@ char *cDvbApi::audioCommand = NULL;
|
||||
|
||||
cDvbApi::cDvbApi(int n)
|
||||
{
|
||||
frontendType = FrontendType(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
|
||||
vPid = aPid1 = aPid2 = dPid1 = dPid2 = 0;
|
||||
siProcessor = NULL;
|
||||
recordBuffer = NULL;
|
||||
@ -2518,10 +2557,6 @@ cDvbApi::cDvbApi(int n)
|
||||
fd_video = OstOpen(DEV_OST_VIDEO, n, O_RDWR | O_NONBLOCK);
|
||||
fd_audio = OstOpen(DEV_OST_AUDIO, n, O_RDWR | O_NONBLOCK);
|
||||
|
||||
// Devices that may not be available, and are not necessary for normal operation:
|
||||
|
||||
videoDev = OstOpen(DEV_VIDEO, n, O_RDWR);
|
||||
|
||||
// Devices that will be dynamically opened and closed when necessary:
|
||||
|
||||
fd_dvr = -1;
|
||||
@ -2536,15 +2571,14 @@ cDvbApi::cDvbApi(int n)
|
||||
siProcessor = new cSIProcessor(OstName(DEV_OST_DEMUX, n));
|
||||
if (!dvbApi[0]) // only the first one shall set the system time
|
||||
siProcessor->SetUseTSTime(Setup.SetSystemTime);
|
||||
FrontendInfo feinfo;
|
||||
CHECK(ioctl(fd_frontend, FE_GET_INFO, &feinfo));
|
||||
frontendType = feinfo.type;
|
||||
}
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: can't open video device %d", n);
|
||||
cols = rows = 0;
|
||||
|
||||
ovlGeoSet = ovlStat = ovlFbSet = false;
|
||||
ovlBrightness = ovlColour = ovlHue = ovlContrast = 32768;
|
||||
ovlClipCount = 0;
|
||||
|
||||
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
|
||||
initscr();
|
||||
keypad(stdscr, true);
|
||||
@ -2573,7 +2607,6 @@ cDvbApi::~cDvbApi()
|
||||
StopReplay();
|
||||
StopRecord();
|
||||
StopTransfer();
|
||||
OvlO(false); //Overlay off!
|
||||
// We're not explicitly closing any device files here, since this sometimes
|
||||
// caused segfaults. Besides, the program is about to terminate anyway...
|
||||
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
|
||||
@ -2688,17 +2721,15 @@ const cSchedules *cDvbApi::Schedules(cThreadLock *ThreadLock) const
|
||||
|
||||
bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
|
||||
{
|
||||
if (videoDev < 0)
|
||||
return false;
|
||||
int result = 0;
|
||||
// just do this once?
|
||||
int videoDev = OstOpen(DEV_VIDEO, CardIndex(), O_RDWR);
|
||||
if (videoDev >= 0) {
|
||||
struct video_mbuf mbuf;
|
||||
result |= ioctl(videoDev, VIDIOCGMBUF, &mbuf);
|
||||
if (result == 0) {
|
||||
int msize = mbuf.size;
|
||||
// gf: this needs to be a protected member of cDvbApi! //XXX kls: WHY???
|
||||
unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0);
|
||||
if (!mem || mem == (unsigned char *)-1)
|
||||
return false;
|
||||
if (mem && mem != (unsigned char *)-1) {
|
||||
// set up the size and RGB
|
||||
struct video_capability vc;
|
||||
result |= ioctl(videoDev, VIDIOCGCAP, &vc);
|
||||
@ -2714,7 +2745,6 @@ bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX,
|
||||
vm.height = vc.maxheight;
|
||||
}
|
||||
vm.format = VIDEO_PALETTE_RGB24;
|
||||
// this needs to be done every time:
|
||||
result |= ioctl(videoDev, VIDIOCMCAPTURE, &vm);
|
||||
result |= ioctl(videoDev, VIDIOCSYNC, &vm.frame);
|
||||
// make RGB out of BGR:
|
||||
@ -2771,172 +2801,16 @@ bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX,
|
||||
LOG_ERROR_STR(FileName);
|
||||
result |= 1;
|
||||
}
|
||||
|
||||
if (ovlStat && ovlGeoSet) {
|
||||
// switch the Overlay on again (gf: why have i to do anything again?)
|
||||
OvlG(ovlSizeX, ovlSizeY, ovlPosX, ovlPosY);
|
||||
}
|
||||
if (ovlFbSet)
|
||||
OvlP(ovlBrightness, ovlColour, ovlHue, ovlContrast);
|
||||
|
||||
munmap(mem, msize);
|
||||
}
|
||||
else
|
||||
result |= 1;
|
||||
}
|
||||
close(videoDev);
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
bool cDvbApi::OvlF(int SizeX, int SizeY, int FbAddr, int Bpp, int Palette)
|
||||
{
|
||||
if (videoDev < 0)
|
||||
return false;
|
||||
int result = 0;
|
||||
// get the actual X-Server settings???
|
||||
// plausibility-check problem: can't be verified w/o X-server!!!
|
||||
if (SizeX <= 0 || SizeY <= 0 || FbAddr == 0 || Bpp / 8 > 4 ||
|
||||
Bpp / 8 <= 0 || Palette <= 0 || Palette > 13 || ovlClipCount < 0 ||
|
||||
SizeX > 4096 || SizeY > 4096) {
|
||||
ovlFbSet = ovlGeoSet = false;
|
||||
OvlO(false);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
dsyslog(LOG_INFO, "OvlF: %d %d %x %d %d", SizeX, SizeY, FbAddr, Bpp, Palette);
|
||||
// this is the problematic part!
|
||||
struct video_buffer vb;
|
||||
result |= ioctl(videoDev, VIDIOCGFBUF, &vb);
|
||||
vb.base = (void*)FbAddr;
|
||||
vb.depth = Bpp;
|
||||
vb.height = SizeY;
|
||||
vb.width = SizeX;
|
||||
vb.bytesperline = ((vb.depth + 1) / 8) * vb.width;
|
||||
//now the real thing: setting the framebuffer
|
||||
result |= ioctl(videoDev, VIDIOCSFBUF, &vb);
|
||||
if (result) {
|
||||
ovlFbSet = ovlGeoSet = false;
|
||||
ovlClipCount = 0;
|
||||
OvlO(false);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
ovlFbSizeX = SizeX;
|
||||
ovlFbSizeY = SizeY;
|
||||
ovlBpp = Bpp;
|
||||
ovlPalette = Palette;
|
||||
ovlFbSet = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cDvbApi::OvlG(int SizeX, int SizeY, int PosX, int PosY)
|
||||
{
|
||||
if (videoDev < 0)
|
||||
return false;
|
||||
int result = 0;
|
||||
// get the actual X-Server settings???
|
||||
struct video_capability vc;
|
||||
result |= ioctl(videoDev, VIDIOCGCAP, &vc);
|
||||
if (!ovlFbSet)
|
||||
return false;
|
||||
if (SizeX < vc.minwidth || SizeY < vc.minheight ||
|
||||
SizeX > vc.maxwidth || SizeY>vc.maxheight
|
||||
// || PosX > FbSizeX || PosY > FbSizeY
|
||||
// PosX < -SizeX || PosY < -SizeY ||
|
||||
) {
|
||||
ovlGeoSet = false;
|
||||
OvlO(false);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
struct video_window vw;
|
||||
result |= ioctl(videoDev, VIDIOCGWIN, &vw);
|
||||
vw.x = PosX;
|
||||
vw.y = PosY;
|
||||
vw.width = SizeX;
|
||||
vw.height = SizeY;
|
||||
vw.chromakey = ovlPalette;
|
||||
#ifndef VID_TYPE_CHROMAKEY // name changed somewhere down the road in kernel 2.4.x
|
||||
#define VID_TYPE_CHROMAKEY VIDEO_WINDOW_CHROMAKEY
|
||||
#endif
|
||||
vw.flags = VID_TYPE_CHROMAKEY; // VIDEO_WINDOW_INTERLACE; //VIDEO_CLIP_BITMAP;
|
||||
vw.clips = ovlClipRects;
|
||||
vw.clipcount = ovlClipCount;
|
||||
result |= ioctl(videoDev, VIDIOCSWIN, &vw);
|
||||
if (result) {
|
||||
ovlGeoSet = false;
|
||||
ovlClipCount = 0;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
ovlSizeX = SizeX;
|
||||
ovlSizeY = SizeY;
|
||||
ovlPosX = PosX;
|
||||
ovlPosY = PosY;
|
||||
ovlGeoSet = true;
|
||||
ovlStat = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cDvbApi::OvlC(int ClipCount, CRect *cr)
|
||||
{
|
||||
if (videoDev < 0)
|
||||
return false;
|
||||
if (ovlGeoSet && ovlFbSet) {
|
||||
for (int i = 0; i < ClipCount; i++) {
|
||||
ovlClipRects[i].x = cr[i].x;
|
||||
ovlClipRects[i].y = cr[i].y;
|
||||
ovlClipRects[i].width = cr[i].width;
|
||||
ovlClipRects[i].height = cr[i].height;
|
||||
ovlClipRects[i].next = &(ovlClipRects[i + 1]);
|
||||
}
|
||||
ovlClipCount = ClipCount;
|
||||
//use it:
|
||||
return OvlG(ovlSizeX, ovlSizeY, ovlPosX, ovlPosY);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cDvbApi::OvlP(__u16 Brightness, __u16 Colour, __u16 Hue, __u16 Contrast)
|
||||
{
|
||||
if (videoDev < 0)
|
||||
return false;
|
||||
int result = 0;
|
||||
ovlBrightness = Brightness;
|
||||
ovlColour = Colour;
|
||||
ovlHue = Hue;
|
||||
ovlContrast = Contrast;
|
||||
struct video_picture vp;
|
||||
if (!ovlFbSet)
|
||||
return false;
|
||||
result |= ioctl(videoDev, VIDIOCGPICT, &vp);
|
||||
vp.brightness = Brightness;
|
||||
vp.colour = Colour;
|
||||
vp.hue = Hue;
|
||||
vp.contrast = Contrast;
|
||||
vp.depth = ovlBpp;
|
||||
vp.palette = ovlPalette; // gf: is this always ok? VIDEO_PALETTE_RGB565;
|
||||
result |= ioctl(videoDev, VIDIOCSPICT, &vp);
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
bool cDvbApi::OvlO(bool Value)
|
||||
{
|
||||
if (videoDev < 0)
|
||||
return false;
|
||||
int result = 0;
|
||||
if (!ovlGeoSet && Value)
|
||||
return false;
|
||||
int one = 1;
|
||||
int zero = 0;
|
||||
result |= ioctl(videoDev, VIDIOCCAPTURE, Value ? &one : &zero);
|
||||
ovlStat = Value;
|
||||
if (result) {
|
||||
ovlStat = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_OSD
|
||||
void cDvbApi::SetColor(eDvbColor colorFg, eDvbColor colorBg)
|
||||
{
|
||||
@ -3257,7 +3131,8 @@ eSetChannelResult cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char
|
||||
|
||||
bool ChannelSynced = false;
|
||||
|
||||
if (fd_sec >= 0) { // DVB-S
|
||||
switch (frontendType) {
|
||||
case FE_QPSK: { // DVB-S
|
||||
|
||||
// Frequency offsets:
|
||||
|
||||
@ -3316,7 +3191,8 @@ eSetChannelResult cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: timeout while tuning");
|
||||
}
|
||||
else if (fd_frontend >= 0) { // DVB-C
|
||||
break;
|
||||
case FE_QAM: { // DVB-C
|
||||
|
||||
// Frequency and symbol rate:
|
||||
|
||||
@ -3344,8 +3220,15 @@ eSetChannelResult cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char
|
||||
else
|
||||
esyslog(LOG_ERR, "ERROR: timeout while tuning");
|
||||
}
|
||||
else {
|
||||
esyslog(LOG_ERR, "ERROR: attempt to set channel without DVB-S or DVB-C device");
|
||||
break;
|
||||
case FE_OFDM: { // DVB-T
|
||||
//XXX TODO: implement DVB-T tuning (anybody with a DVB-T card out there?)
|
||||
esyslog(LOG_ERR, "ERROR: DVB-T tuning support not yet implemented");
|
||||
return scrFailed;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
esyslog(LOG_ERR, "ERROR: attempt to set channel with unknown DVB frontend type");
|
||||
return scrFailed;
|
||||
}
|
||||
|
||||
|
30
dvbapi.h
30
dvbapi.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbapi.h 1.53 2001/09/23 11:01:46 kls Exp $
|
||||
* $Id: dvbapi.h 1.58 2001/11/04 11:39:42 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBAPI_H
|
||||
@ -34,12 +34,6 @@
|
||||
#include "eit.h"
|
||||
#include "thread.h"
|
||||
|
||||
// Overlay facilities
|
||||
#define MAXCLIPRECTS 100
|
||||
typedef struct CRect {
|
||||
signed short x, y, width, height;
|
||||
};
|
||||
|
||||
#define FRAMESPERSEC 25
|
||||
|
||||
// The maximum file size is limited by the range that can be covered
|
||||
@ -89,7 +83,7 @@ class cDvbApi {
|
||||
#endif //DVDSUPPORT
|
||||
friend class cTransferBuffer;
|
||||
private:
|
||||
int videoDev;
|
||||
FrontendType frontendType;
|
||||
int fd_osd, fd_frontend, fd_sec, fd_dvr, fd_audio, fd_video, fd_demuxa1, fd_demuxa2, fd_demuxd1, fd_demuxd2, fd_demuxv, fd_demuxt;
|
||||
int vPid, aPid1, aPid2, dPid1, dPid2;
|
||||
bool SetPid(int fd, dmxPesType_t PesType, int Pid, dmxOutput_t Output);
|
||||
@ -154,21 +148,6 @@ public:
|
||||
|
||||
bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
|
||||
|
||||
// Overlay facilities
|
||||
|
||||
private:
|
||||
bool ovlStat, ovlGeoSet, ovlFbSet;
|
||||
int ovlSizeX, ovlSizeY, ovlPosX, ovlPosY, ovlBpp, ovlPalette, ovlClips, ovlClipCount;
|
||||
int ovlFbSizeX, ovlFbSizeY;
|
||||
__u16 ovlBrightness, ovlColour, ovlHue, ovlContrast;
|
||||
struct video_clip ovlClipRects[MAXCLIPRECTS];
|
||||
public:
|
||||
bool OvlF(int SizeX, int SizeY, int FbAddr, int Bpp, int Palette);
|
||||
bool OvlG(int SizeX, int SizeY, int PosX, int PosY);
|
||||
bool OvlC(int ClipCount, CRect *Cr);
|
||||
bool OvlP(__u16 Brightness, __u16 Color, __u16 Hue, __u16 Contrast);
|
||||
bool OvlO(bool Value);
|
||||
|
||||
// On Screen Display facilities
|
||||
|
||||
private:
|
||||
@ -233,8 +212,6 @@ private:
|
||||
cPlayBuffer *replayBuffer;
|
||||
int ca;
|
||||
int priority;
|
||||
int Ca(void) { return ca; }
|
||||
// Returns the ca of the current recording session (0..MAXDVBAPI).
|
||||
int Priority(void) { return priority; }
|
||||
// Returns the priority of the current recording session (0..MAXPRIORITY),
|
||||
// or -1 if no recording is currently active.
|
||||
@ -243,6 +220,8 @@ private:
|
||||
void SetModeReplay(void);
|
||||
void SetModeNormal(bool FromRecording);
|
||||
public:
|
||||
int Ca(void) { return ca; }
|
||||
// Returns the ca of the current recording session (0..MAXDVBAPI).
|
||||
int SecondsToFrames(int Seconds);
|
||||
// Returns the number of frames corresponding to the given number of seconds.
|
||||
bool Recording(void);
|
||||
@ -330,6 +309,7 @@ public:
|
||||
void SetVolume(int Volume, bool Absolute = false);
|
||||
// Sets the volume to the given value, either absolutely or relative to
|
||||
// the current volume.
|
||||
static int CurrentVolume(void) { return PrimaryDvbApi ? PrimaryDvbApi->volume : 0; }
|
||||
};
|
||||
|
||||
class cEITScanner {
|
||||
|
37
eit.c
37
eit.c
@ -16,7 +16,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: eit.c 1.28 2001/10/19 13:13:25 kls Exp $
|
||||
* $Id: eit.c 1.29 2001/10/28 13:51:22 kls Exp $
|
||||
***************************************************************************/
|
||||
|
||||
#include "eit.h"
|
||||
@ -189,6 +189,7 @@ cEventInfo::cEventInfo(unsigned short serviceid, unsigned short eventid)
|
||||
bIsPresent = bIsFollowing = false;
|
||||
lDuration = 0;
|
||||
tTime = 0;
|
||||
uTableID = 0;
|
||||
uEventID = eventid;
|
||||
uServiceID = serviceid;
|
||||
nChannelNumber = 0;
|
||||
@ -231,6 +232,12 @@ bool cEventInfo::IsFollowing() const
|
||||
{
|
||||
return bIsFollowing;
|
||||
}
|
||||
|
||||
void cEventInfo::SetTableID(unsigned char tableid)
|
||||
{
|
||||
uTableID = tableid;
|
||||
}
|
||||
|
||||
/** */
|
||||
void cEventInfo::SetFollowing(bool foll)
|
||||
{
|
||||
@ -246,6 +253,12 @@ const char * cEventInfo::GetDate() const
|
||||
|
||||
return szDate;
|
||||
}
|
||||
|
||||
const unsigned char cEventInfo::GetTableID(void) const
|
||||
{
|
||||
return uTableID;
|
||||
}
|
||||
|
||||
/** */
|
||||
const char * cEventInfo::GetTimeString() const
|
||||
{
|
||||
@ -545,21 +558,26 @@ unsigned short cSchedule::GetServiceID() const
|
||||
return uServiceID;
|
||||
}
|
||||
/** */
|
||||
const cEventInfo * cSchedule::GetEvent(unsigned short uEventID) const
|
||||
const cEventInfo * cSchedule::GetEvent(unsigned short uEventID, time_t tTime) const
|
||||
{
|
||||
// Returns either the event info with the given uEventID or, if that one can't
|
||||
// be found, the one with the given tTime (or NULL if neither can be found)
|
||||
cEventInfo *pe = Events.First();
|
||||
cEventInfo *pt = NULL;
|
||||
while (pe != NULL)
|
||||
{
|
||||
if (pe->GetEventID() == uEventID)
|
||||
return pe;
|
||||
if (tTime > 0 && pe->GetTime() == tTime) // 'tTime < 0' is apparently used with NVOD channels
|
||||
pt = pe;
|
||||
|
||||
pe = Events.Next(pe);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return pt;
|
||||
}
|
||||
/** */
|
||||
const cEventInfo * cSchedule::GetEvent(time_t tTime) const
|
||||
const cEventInfo * cSchedule::GetEventAround(time_t tTime) const
|
||||
{
|
||||
cEventInfo *pe = Events.First();
|
||||
while (pe != NULL)
|
||||
@ -759,7 +777,7 @@ int cEIT::ProcessEIT(unsigned char *buffer)
|
||||
if (!rEvent)
|
||||
break;
|
||||
}
|
||||
pEvent = (cEventInfo *)pSchedule->GetEvent((unsigned short)VdrProgramInfo->EventID);
|
||||
pEvent = (cEventInfo *)pSchedule->GetEvent((unsigned short)VdrProgramInfo->EventID, VdrProgramInfo->StartTime);
|
||||
if (!pEvent) {
|
||||
// If we don't have that event ID yet, we create a new one.
|
||||
// Otherwise we copy the information into the existing event anyway, because the data might have changed.
|
||||
@ -767,6 +785,14 @@ int cEIT::ProcessEIT(unsigned char *buffer)
|
||||
pEvent = (cEventInfo *)pSchedule->GetEvent((unsigned short)VdrProgramInfo->EventID);
|
||||
if (!pEvent)
|
||||
break;
|
||||
pEvent->SetTableID(tid);
|
||||
}
|
||||
else {
|
||||
// We have found an existing event, either through its event ID or its start time.
|
||||
// If the new event comes from a table that belongs to an "other TS" and the existing
|
||||
// one comes from a "actual TS" table, lets skip it.
|
||||
if ((tid == 0x4F || tid == 0x60) && (pEvent->GetTableID() == 0x4E || pEvent->GetTableID() == 0x50))
|
||||
continue;
|
||||
}
|
||||
if (rEvent) {
|
||||
pEvent->SetTitle(rEvent->GetTitle());
|
||||
@ -774,6 +800,7 @@ int cEIT::ProcessEIT(unsigned char *buffer)
|
||||
pEvent->SetExtendedDescription(rEvent->GetExtendedDescription());
|
||||
}
|
||||
else {
|
||||
pEvent->SetTableID(tid);
|
||||
pEvent->SetTitle(VdrProgramInfo->ShortName);
|
||||
pEvent->SetSubtitle(VdrProgramInfo->ShortText);
|
||||
pEvent->SetExtendedDescription(VdrProgramInfo->ExtendedName);
|
||||
|
9
eit.h
9
eit.h
@ -16,7 +16,7 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* $Id: eit.h 1.11 2001/09/22 11:43:21 kls Exp $
|
||||
* $Id: eit.h 1.12 2001/10/28 12:33:10 kls Exp $
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __EIT_H
|
||||
@ -29,6 +29,7 @@ class cEventInfo : public cListObject {
|
||||
friend class cSchedule;
|
||||
friend class cEIT;
|
||||
private:
|
||||
unsigned char uTableID; // Table ID this event came from
|
||||
unsigned short uServiceID; // Service ID of program for that event
|
||||
bool bIsFollowing; // true if this is the next event on this channel
|
||||
bool bIsPresent; // true if this is the present event running
|
||||
@ -40,6 +41,7 @@ private:
|
||||
time_t tTime; // Start time
|
||||
int nChannelNumber; // the actual channel number from VDR's channel list (used in cMenuSchedule for sorting by channel number)
|
||||
protected:
|
||||
void SetTableID(unsigned char tableid);
|
||||
void SetFollowing(bool foll);
|
||||
void SetPresent(bool pres);
|
||||
void SetTitle(const char *string);
|
||||
@ -52,6 +54,7 @@ protected:
|
||||
cEventInfo(unsigned short serviceid, unsigned short eventid);
|
||||
public:
|
||||
~cEventInfo();
|
||||
const unsigned char GetTableID(void) const;
|
||||
const char *GetTimeString(void) const;
|
||||
const char *GetEndTimeString(void) const;
|
||||
const char *GetDate(void) const;
|
||||
@ -90,8 +93,8 @@ public:
|
||||
const cEventInfo *GetPresentEvent(void) const;
|
||||
const cEventInfo *GetFollowingEvent(void) const;
|
||||
unsigned short GetServiceID(void) const;
|
||||
const cEventInfo *GetEvent(unsigned short uEventID) const;
|
||||
const cEventInfo *GetEvent(time_t tTime) const;
|
||||
const cEventInfo *GetEvent(unsigned short uEventID, time_t tTime = 0) const;
|
||||
const cEventInfo *GetEventAround(time_t tTime) const;
|
||||
const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
|
||||
int NumEvents(void) const { return Events.Count(); }
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
|
11
i18n.c
11
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.44 2001/09/30 11:31:43 kls Exp $
|
||||
* $Id: i18n.c 1.45 2001/10/28 16:04:58 kls Exp $
|
||||
*
|
||||
* Slovenian translations provided by Miha Setina <mihasetina@softhome.net>
|
||||
* Italian translations provided by Alberto Carraro <bertocar@tin.it>
|
||||
@ -376,6 +376,15 @@ const tPhrase Phrases[] = {
|
||||
"Arrêter l'enregistrement?",
|
||||
"Stoppe opptak?",
|
||||
},
|
||||
{ "on primary interface",
|
||||
"auf dem primären Interface",
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
"", // TODO
|
||||
},
|
||||
{ "Cancel editing?",
|
||||
"Schneiden abbrechen?",
|
||||
"Zelite prekiniti urejanje?",
|
||||
|
76
menu.c
76
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.131 2001/10/21 14:28:14 kls Exp $
|
||||
* $Id: menu.c 1.139 2001/11/04 10:37:18 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -1808,11 +1808,15 @@ eOSState cMenuCommands::ProcessKey(eKeys Key)
|
||||
// --- cMenuMain -------------------------------------------------------------
|
||||
|
||||
#define STOP_RECORDING tr(" Stop recording ")
|
||||
#define ON_PRIMARY_INTERFACE tr("on primary interface")
|
||||
|
||||
cMenuMain::cMenuMain(bool Replaying, eOSState State)
|
||||
:cOsdMenu(tr("Main"))
|
||||
{
|
||||
digit = 0;
|
||||
|
||||
// Basic menu items:
|
||||
|
||||
Add(new cOsdItem(hk(tr("Schedule")), osSchedule));
|
||||
Add(new cOsdItem(hk(tr("Channels")), osChannels));
|
||||
Add(new cOsdItem(hk(tr("Timers")), osTimers));
|
||||
@ -1824,8 +1828,20 @@ cMenuMain::cMenuMain(bool Replaying, eOSState State)
|
||||
Add(new cOsdItem(hk(tr("Setup")), osSetup));
|
||||
if (Commands.Count())
|
||||
Add(new cOsdItem(hk(tr("Commands")), osCommands));
|
||||
|
||||
// Replay control:
|
||||
|
||||
if (Replaying)
|
||||
Add(new cOsdItem(tr(" Stop replaying"), osStopReplay));
|
||||
|
||||
// Record control:
|
||||
|
||||
if (cRecordControls::StopPrimary()) {
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%s%s", STOP_RECORDING, ON_PRIMARY_INTERFACE);
|
||||
Add(new cOsdItem(buffer, osStopRecord));
|
||||
}
|
||||
|
||||
const char *s = NULL;
|
||||
while ((s = cRecordControls::GetInstantId(s)) != NULL) {
|
||||
char *buffer = NULL;
|
||||
@ -1833,8 +1849,14 @@ cMenuMain::cMenuMain(bool Replaying, eOSState State)
|
||||
Add(new cOsdItem(buffer, osStopRecord));
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
// Editing control:
|
||||
|
||||
if (cVideoCutter::Active())
|
||||
Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit));
|
||||
|
||||
// Color buttons:
|
||||
|
||||
const char *DVDbutton =
|
||||
#ifdef DVDSUPPORT
|
||||
cDVD::DiscOk() ? tr("Eject") : NULL;
|
||||
@ -1845,6 +1867,9 @@ cMenuMain::cMenuMain(bool Replaying, eOSState State)
|
||||
Display();
|
||||
lastActivity = time(NULL);
|
||||
SetHasHotkeys();
|
||||
|
||||
// Initial submenus:
|
||||
|
||||
switch (State) {
|
||||
case osRecordings: AddSubMenu(new cMenuRecordings); break;
|
||||
#ifdef DVDSUPPORT
|
||||
@ -1882,6 +1907,10 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
case osStopRecord: if (Interface->Confirm(tr("Stop recording?"))) {
|
||||
cOsdItem *item = Get(Current());
|
||||
if (item) {
|
||||
const char *s = item->Text() + strlen(STOP_RECORDING);
|
||||
if (strcmp(s, ON_PRIMARY_INTERFACE) == 0)
|
||||
cRecordControls::StopPrimary(true);
|
||||
else
|
||||
cRecordControls::Stop(item->Text() + strlen(STOP_RECORDING));
|
||||
return osEnd;
|
||||
}
|
||||
@ -1908,6 +1937,14 @@ eOSState cMenuMain::ProcessKey(eKeys Key)
|
||||
#ifdef DVDSUPPORT
|
||||
case kYellow: if (!HasSubMenu()) {
|
||||
if (cDVD::DiscOk()) {
|
||||
// We need to stop replaying a DVD before ejecting,
|
||||
// otherwise the replay thread crashes. Currently
|
||||
// checking LastReplayed() is pretty much the only way
|
||||
// of finding out whether we are currently replaying a DVD
|
||||
// (i.e. if LastReplayed() returns non-NULL, we are either
|
||||
// replaying a normal recording, or nothing at all):
|
||||
if (!cReplayControl::LastReplayed())
|
||||
cDvbApi::PrimaryDvbApi->StopReplay();
|
||||
cDVD::Eject();
|
||||
state = osEnd;
|
||||
}
|
||||
@ -2062,7 +2099,9 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft:
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
withInfo = false;
|
||||
if (group < 0) {
|
||||
@ -2072,7 +2111,7 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
}
|
||||
if (group >= 0) {
|
||||
int SaveGroup = group;
|
||||
if (Key == kRight)
|
||||
if (NORMALKEY(Key) == kRight)
|
||||
group = Channels.GetNextGroup(group) ;
|
||||
else
|
||||
group = Channels.GetPrevGroup(group < 1 ? 1 : group);
|
||||
@ -2101,8 +2140,10 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
case kOk: if (group >= 0)
|
||||
Channels.SwitchTo(Channels.Get(Channels.GetNextNormal(group))->number);
|
||||
return osEnd;
|
||||
default: Interface->PutKey(Key);
|
||||
default: if (NORMALKEY(Key) == kUp || NORMALKEY(Key) == kDown || (Key & (k_Repeat | k_Release)) == 0) {
|
||||
Interface->PutKey(Key);
|
||||
return osEnd;
|
||||
}
|
||||
};
|
||||
if (time_ms() - lastTime < INFOTIMEOUT) {
|
||||
DisplayInfo();
|
||||
@ -2166,7 +2207,7 @@ bool cRecordControl::GetEventInfo(void)
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(channel->pnr);
|
||||
if (Schedule) {
|
||||
eventInfo = Schedule->GetEvent(Time);
|
||||
eventInfo = Schedule->GetEventAround(Time);
|
||||
if (eventInfo) {
|
||||
if (seconds > 0)
|
||||
dsyslog(LOG_INFO, "got EPG info after %d seconds", seconds);
|
||||
@ -2260,6 +2301,19 @@ void cRecordControls::Stop(cDvbApi *DvbApi)
|
||||
}
|
||||
}
|
||||
|
||||
bool cRecordControls::StopPrimary(bool DoIt)
|
||||
{
|
||||
if (cDvbApi::PrimaryDvbApi->Recording()) {
|
||||
cDvbApi *dvbApi = cDvbApi::GetDvbApi(cDvbApi::PrimaryDvbApi->Ca(), 0);
|
||||
if (dvbApi) {
|
||||
if (DoIt)
|
||||
Stop(cDvbApi::PrimaryDvbApi);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *cRecordControls::GetInstantId(const char *LastInstantId)
|
||||
{
|
||||
for (int i = 0; i < MAXDVBAPI; i++) {
|
||||
@ -2354,7 +2408,8 @@ cReplayControl::cReplayControl(void)
|
||||
timeSearchActive = false;
|
||||
if (fileName) {
|
||||
marks.Load(fileName);
|
||||
dvbApi->StartReplay(fileName);
|
||||
if (!dvbApi->StartReplay(fileName))
|
||||
Interface->Error(tr("Channel locked (recording)!"));
|
||||
}
|
||||
#ifdef DVDSUPPORT
|
||||
else if (dvd)
|
||||
@ -2418,9 +2473,6 @@ void cReplayControl::Hide(void)
|
||||
if (visible) {
|
||||
Interface->Close();
|
||||
needsFastResponse = visible = false;
|
||||
if (!modeOnly)
|
||||
ShowMode();
|
||||
else
|
||||
modeOnly = false;
|
||||
}
|
||||
}
|
||||
@ -2664,6 +2716,7 @@ void cReplayControl::MarkMove(bool Forward)
|
||||
|
||||
void cReplayControl::EditCut(void)
|
||||
{
|
||||
if (fileName) {
|
||||
Hide();
|
||||
if (!cVideoCutter::Active()) {
|
||||
if (!cVideoCutter::Start(fileName))
|
||||
@ -2673,6 +2726,8 @@ void cReplayControl::EditCut(void)
|
||||
}
|
||||
else
|
||||
Interface->Error(tr("Editing process already active!"));
|
||||
ShowMode();
|
||||
}
|
||||
}
|
||||
|
||||
void cReplayControl::EditTest(void)
|
||||
@ -2700,6 +2755,7 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
|
||||
if (visible) {
|
||||
if (timeoutShow && time(NULL) > timeoutShow) {
|
||||
Hide();
|
||||
ShowMode();
|
||||
timeoutShow = 0;
|
||||
}
|
||||
else if (!modeOnly)
|
||||
@ -2749,8 +2805,10 @@ eOSState cReplayControl::ProcessKey(eKeys Key)
|
||||
switch (Key) {
|
||||
// Menu control:
|
||||
case kMenu: Hide(); return osMenu; // allow direct switching to menu
|
||||
case kOk: if (visible && !modeOnly)
|
||||
case kOk: if (visible && !modeOnly) {
|
||||
Hide();
|
||||
DoShowMode = true;
|
||||
}
|
||||
else
|
||||
Show();
|
||||
break;
|
||||
|
3
menu.h
3
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.33 2001/10/21 14:26:01 kls Exp $
|
||||
* $Id: menu.h 1.34 2001/10/28 15:21:04 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef _MENU_H
|
||||
@ -92,6 +92,7 @@ public:
|
||||
static bool Start(cTimer *Timer = NULL);
|
||||
static void Stop(const char *InstantId);
|
||||
static void Stop(cDvbApi *DvbApi);
|
||||
static bool StopPrimary(bool DoIt = false);
|
||||
static const char *GetInstantId(const char *LastInstantId);
|
||||
static void Process(time_t t);
|
||||
static bool Active(void);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
||||
* LinuxDVB driver (see linuxtv.org).
|
||||
*
|
||||
* $Id: ringbuffer.c 1.4 2001/08/05 12:17:45 kls Exp $
|
||||
* $Id: ringbuffer.c 1.5 2001/11/03 09:50:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ringbuffer.h"
|
||||
@ -215,9 +215,10 @@ int cRingBufferLinear::Get(uchar *Data, int Count)
|
||||
|
||||
// --- cFrame ----------------------------------------------------------------
|
||||
|
||||
cFrame::cFrame(const uchar *Data, int Count, int Index)
|
||||
cFrame::cFrame(const uchar *Data, int Count, eFrameType Type, int Index)
|
||||
{
|
||||
count = Count;
|
||||
type = Type;
|
||||
index = Index;
|
||||
data = new uchar[count];
|
||||
if (data)
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ringbuffer.h 1.4 2001/08/05 11:12:06 kls Exp $
|
||||
* $Id: ringbuffer.h 1.5 2001/11/03 10:41:33 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RINGBUFFER_H
|
||||
@ -75,18 +75,22 @@ public:
|
||||
virtual ~cRingBufferLinear();
|
||||
};
|
||||
|
||||
enum eFrameType { ftUnknown, ftVideo, ftAudio, ftDolby };
|
||||
|
||||
class cFrame {
|
||||
friend class cRingBufferFrame;
|
||||
private:
|
||||
cFrame *next;
|
||||
uchar *data;
|
||||
int count;
|
||||
eFrameType type;
|
||||
int index;
|
||||
public:
|
||||
cFrame(const uchar *Data, int Count, int Index = -1);
|
||||
cFrame(const uchar *Data, int Count, eFrameType = ftUnknown, int Index = -1);
|
||||
~cFrame();
|
||||
const uchar *Data(void) const { return data; }
|
||||
int Count(void) const { return count; }
|
||||
eFrameType Type(void) const { return type; }
|
||||
int Index(void) const { return index; }
|
||||
};
|
||||
|
||||
|
183
svdrp.c
183
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.25 2001/10/07 15:13:42 kls Exp $
|
||||
* $Id: svdrp.c 1.27 2001/11/04 11:25:05 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -27,6 +27,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include "config.h"
|
||||
#include "dvbapi.h"
|
||||
#include "interface.h"
|
||||
#include "tools.h"
|
||||
|
||||
@ -120,6 +121,12 @@ const char *HelpPages[] = {
|
||||
" it returns the current channel number and name.",
|
||||
"DELC <number>\n"
|
||||
" Delete channel.",
|
||||
"DELR <number>\n"
|
||||
" Delete the recording with the given number. Before a recording can be\n"
|
||||
" deleted, an LSTR command must have been executed in order to retrieve\n"
|
||||
" the recording numbers. The numbers don't change during subsequent DELR\n"
|
||||
" commands. CAUTION: THERE IS NO CONFIRMATION PROMPT WHEN DELETING A\n"
|
||||
" RECORDING - BE SURE YOU KNOW WHAT YOU ARE DOING!",
|
||||
"DELT <number>\n"
|
||||
" Delete timer.",
|
||||
"GRAB <filename> [ jpeg | pnm [ <quality> [ <sizex> <sizey> ] ] ]\n"
|
||||
@ -137,6 +144,9 @@ const char *HelpPages[] = {
|
||||
" containing the given string as part of their name are listed.",
|
||||
"LSTE\n"
|
||||
" List EPG data.",
|
||||
"LSTR [ <number> ]\n"
|
||||
" List recordings. Without option, all recordings are listed. Otherwise\n"
|
||||
" the summary for the given recording is listed.",
|
||||
"LSTT [ <number> ]\n"
|
||||
" List timers. Without option, all timers are listed. Otherwise\n"
|
||||
" only the given timer is listed.",
|
||||
@ -174,16 +184,6 @@ const char *HelpPages[] = {
|
||||
" zero, this means that the timer is currently recording and has started\n"
|
||||
" at the given time. The first value in the resulting line is the number\n"
|
||||
" of the timer.",
|
||||
"OVLF <sizex> <sizey> <fbaddr> <bpp> <palette>\n"
|
||||
" Set the size, address depth and palette of the overlay.",
|
||||
"OVLG <sizex> <sizey> <posx> <posy>\n"
|
||||
" Set the size and position of the overlay.",
|
||||
"OVLC <clipcount> <base16-CRect-array>\n"
|
||||
" Set the overlay clipping rectangles.",
|
||||
"OVLP <brightness> <colour> <hue> <contrast>\n"
|
||||
" Set the picture parameters for the overlay.",
|
||||
"OVLO 0 | 1\n"
|
||||
" Switch the overlay on or off.",
|
||||
"UPDT <settings>\n"
|
||||
" Updates a timer. Settings must be in the same format as returned\n"
|
||||
" by the LSTT command. If a timer with the same channel, day, start\n"
|
||||
@ -278,7 +278,6 @@ bool cSVDRP::Send(const char *s, int length)
|
||||
if (wbytes < 0) {
|
||||
LOG_ERROR;
|
||||
file.Close();
|
||||
cDvbApi::PrimaryDvbApi->OvlO(false);
|
||||
}
|
||||
else //XXX while...???
|
||||
esyslog(LOG_ERR, "Wrote %d bytes to client while expecting %d\n", wbytes, length);
|
||||
@ -380,6 +379,27 @@ void cSVDRP::CmdDELC(const char *Option)
|
||||
Reply(502, "DELC not yet implemented");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdDELR(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
if (isnumber(Option)) {
|
||||
cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
|
||||
if (recording) {
|
||||
if (recording->Delete())
|
||||
Reply(250, "Recording \"%s\" deleted", Option);
|
||||
else
|
||||
Reply(554, "Error while deleting recording!");
|
||||
}
|
||||
else
|
||||
Reply(550, "Recording \"%s\" not found%s", Option, Recordings.Count() ? "" : " (use LSTR before deleting)");
|
||||
}
|
||||
else
|
||||
Reply(501, "Error in recording number \"%s\"", Option);
|
||||
}
|
||||
else
|
||||
Reply(501, "Missing recording number");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdDELT(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
@ -589,6 +609,38 @@ void cSVDRP::CmdLSTE(const char *Option)
|
||||
Reply(451, "Can't get EPG data");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdLSTR(const char *Option)
|
||||
{
|
||||
bool recordings = Recordings.Load();
|
||||
if (*Option) {
|
||||
if (isnumber(Option)) {
|
||||
cRecording *recording = Recordings.Get(strtol(Option, NULL, 10) - 1);
|
||||
if (recording) {
|
||||
if (recording->Summary()) {
|
||||
char *summary = strdup(recording->Summary());
|
||||
Reply(250, "%s", strreplace(summary,'\n','|'));
|
||||
delete summary;
|
||||
}
|
||||
else
|
||||
Reply(550, "No summary availabe");
|
||||
}
|
||||
else
|
||||
Reply(550, "Recording \"%s\" not found", Option);
|
||||
}
|
||||
else
|
||||
Reply(501, "Error in recording number \"%s\"", Option);
|
||||
}
|
||||
else if (recordings) {
|
||||
cRecording *recording = Recordings.First();
|
||||
while (recording) {
|
||||
Reply(recording == Recordings.Last() ? 250 : -250, "%d %s", recording->Index() + 1, recording->Title(' ', true));
|
||||
recording = Recordings.Next(recording);
|
||||
}
|
||||
}
|
||||
else
|
||||
Reply(550, "No recordings available");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdLSTT(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
@ -767,106 +819,6 @@ void cSVDRP::CmdNEXT(const char *Option)
|
||||
Reply(550, "No active timers");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdOVLF(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
int SizeX = 0, SizeY = 0, Bpp = 0, Palette = 0, FbAddr = 0;
|
||||
if (5 == sscanf(Option, "%d %d %x %d %d", &SizeX, &SizeY, &FbAddr, &Bpp, &Palette)) {
|
||||
//somehow_set_overlay_geometry;
|
||||
if (cDvbApi::PrimaryDvbApi->OvlF(SizeX, SizeY, FbAddr, Bpp, Palette))
|
||||
Reply(250, "Overlay framebuffer set");
|
||||
else
|
||||
Reply(451, "Illegal overlay framebuffer settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Could not parse overlay framebuffer settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Missing overlay framebuffer settings");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdOVLG(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
int SizeX = 0, SizeY = 0, PosX = 0, PosY = 0;
|
||||
if (4 == sscanf(Option, "%d %d %d %d", &SizeX, &SizeY, &PosX, &PosY)) {
|
||||
//somehow_set_overlay_geometry;
|
||||
if (cDvbApi::PrimaryDvbApi->OvlG(SizeX, SizeY, PosX, PosY))
|
||||
Reply(250, "Overlay geometry set");
|
||||
else
|
||||
Reply(451, "Illegal overlay geometry settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Could not parse overlay geometry settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Missing overlay geometry settings");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdOVLC(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
int ClipCount = 0;
|
||||
unsigned char s[2 * MAXCLIPRECTS * sizeof(CRect) + 2];
|
||||
if (2 == sscanf(Option, "%d %s", &ClipCount, s)) {
|
||||
// Base16-decoding of CRect-array:
|
||||
unsigned char *p = (unsigned char*)ovlClipRects;
|
||||
int i = 0, size = sizeof(CRect)*ClipCount;
|
||||
for (int j = 0; i < size; i++) {
|
||||
p[i] = (s[j++] - 65);
|
||||
p[i] += (s[j++] - 65) << 4;
|
||||
}
|
||||
if (((unsigned)ClipCount == (i / sizeof(CRect))) && (ClipCount >= 0)) {
|
||||
// apply it:
|
||||
if (cDvbApi::PrimaryDvbApi->OvlC(ClipCount, ovlClipRects))
|
||||
Reply(250, "Overlay-Clipping set");
|
||||
else
|
||||
Reply(451, "Illegal overlay clipping settings");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Reply(501, "Error parsing Overlay-Clipping settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Missing Clipping settings");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdOVLP(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
int Brightness = 0, Colour = 0, Hue = 0, Contrast = 0;
|
||||
if (4 == sscanf(Option, "%d %d %d %d", &Brightness, &Colour, &Hue, &Contrast)) {
|
||||
//somehow_set_overlay_picture_settings;
|
||||
if (cDvbApi::PrimaryDvbApi->OvlP(Brightness, Colour, Hue, Contrast))
|
||||
Reply(250, "Overlay picture settings set");
|
||||
else
|
||||
Reply(451, "Illegal overlay picture settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Could not parse overlay picture settings");
|
||||
}
|
||||
else
|
||||
Reply(501, "Missing overlay picture settings");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdOVLO(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
int Value;
|
||||
if (1 == sscanf(Option, "%d", &Value)) {
|
||||
//somehow_set_overlay_picture_settings;
|
||||
if (cDvbApi::PrimaryDvbApi->OvlO(Value))
|
||||
Reply(250, "Overlay capture set");
|
||||
else
|
||||
Reply(451, "Error setting overlay capture");
|
||||
}
|
||||
else
|
||||
Reply(501, "Could not parse status");
|
||||
}
|
||||
else
|
||||
Reply(501, "Missing overlay capture status");
|
||||
}
|
||||
|
||||
void cSVDRP::CmdUPDT(const char *Option)
|
||||
{
|
||||
if (*Option) {
|
||||
@ -910,12 +862,14 @@ void cSVDRP::Execute(char *Cmd)
|
||||
s = skipspace(s);
|
||||
if (CMD("CHAN")) CmdCHAN(s);
|
||||
else if (CMD("DELC")) CmdDELC(s);
|
||||
else if (CMD("DELR")) CmdDELR(s);
|
||||
else if (CMD("DELT")) CmdDELT(s);
|
||||
else if (CMD("GRAB")) CmdGRAB(s);
|
||||
else if (CMD("HELP")) CmdHELP(s);
|
||||
else if (CMD("HITK")) CmdHITK(s);
|
||||
else if (CMD("LSTC")) CmdLSTC(s);
|
||||
else if (CMD("LSTE")) CmdLSTE(s);
|
||||
else if (CMD("LSTR")) CmdLSTR(s);
|
||||
else if (CMD("LSTT")) CmdLSTT(s);
|
||||
else if (CMD("MESG")) CmdMESG(s);
|
||||
else if (CMD("MODC")) CmdMODC(s);
|
||||
@ -925,11 +879,6 @@ void cSVDRP::Execute(char *Cmd)
|
||||
else if (CMD("NEWC")) CmdNEWC(s);
|
||||
else if (CMD("NEWT")) CmdNEWT(s);
|
||||
else if (CMD("NEXT")) CmdNEXT(s);
|
||||
else if (CMD("OVLF")) CmdOVLF(s);
|
||||
else if (CMD("OVLG")) CmdOVLG(s);
|
||||
else if (CMD("OVLC")) CmdOVLC(s);
|
||||
else if (CMD("OVLP")) CmdOVLP(s);
|
||||
else if (CMD("OVLO")) CmdOVLO(s);
|
||||
else if (CMD("UPDT")) CmdUPDT(s);
|
||||
else if (CMD("QUIT")) Close();
|
||||
else Reply(500, "Command unrecognized: \"%s\"", Cmd);
|
||||
|
13
svdrp.h
13
svdrp.h
@ -4,13 +4,13 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: svdrp.h 1.11 2001/09/14 14:35:34 kls Exp $
|
||||
* $Id: svdrp.h 1.13 2001/11/04 11:20:46 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SVDRP_H
|
||||
#define __SVDRP_H
|
||||
|
||||
#include "dvbapi.h"
|
||||
#include "recording.h"
|
||||
#include "tools.h"
|
||||
|
||||
class cSocket {
|
||||
@ -30,7 +30,7 @@ class cSVDRP {
|
||||
private:
|
||||
cSocket socket;
|
||||
cFile file;
|
||||
CRect ovlClipRects[MAXCLIPRECTS];
|
||||
cRecordings Recordings;
|
||||
uint numChars;
|
||||
char cmdLine[MAXPARSEBUFFER];
|
||||
char *message;
|
||||
@ -40,12 +40,14 @@ private:
|
||||
void Reply(int Code, const char *fmt, ...);
|
||||
void CmdCHAN(const char *Option);
|
||||
void CmdDELC(const char *Option);
|
||||
void CmdDELR(const char *Option);
|
||||
void CmdDELT(const char *Option);
|
||||
void CmdGRAB(const char *Option);
|
||||
void CmdHELP(const char *Option);
|
||||
void CmdHITK(const char *Option);
|
||||
void CmdLSTC(const char *Option);
|
||||
void CmdLSTE(const char *Option);
|
||||
void CmdLSTR(const char *Option);
|
||||
void CmdLSTT(const char *Option);
|
||||
void CmdMESG(const char *Option);
|
||||
void CmdMODC(const char *Option);
|
||||
@ -55,11 +57,6 @@ private:
|
||||
void CmdNEWC(const char *Option);
|
||||
void CmdNEWT(const char *Option);
|
||||
void CmdNEXT(const char *Option);
|
||||
void CmdOVLF(const char *Option);
|
||||
void CmdOVLG(const char *Option);
|
||||
void CmdOVLC(const char *Option);
|
||||
void CmdOVLP(const char *Option);
|
||||
void CmdOVLO(const char *Option);
|
||||
void CmdUPDT(const char *Option);
|
||||
void Execute(char *Cmd);
|
||||
public:
|
||||
|
33
thread.c
33
thread.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: thread.c 1.15 2001/10/21 12:25:31 kls Exp $
|
||||
* $Id: thread.c 1.16 2001/10/27 13:23:06 kls Exp $
|
||||
*/
|
||||
|
||||
#include "thread.h"
|
||||
@ -99,8 +99,7 @@ cThread::cThread(void)
|
||||
signalHandlerInstalled = true;
|
||||
}
|
||||
running = false;
|
||||
parentPid = threadPid = lockingPid = 0;
|
||||
locked = 0;
|
||||
parentPid = threadPid = 0;
|
||||
}
|
||||
|
||||
cThread::~cThread()
|
||||
@ -159,24 +158,6 @@ void cThread::Cancel(int WaitSeconds)
|
||||
pthread_cancel(thread);
|
||||
}
|
||||
|
||||
bool cThread::Lock(void)
|
||||
{
|
||||
if (getpid() != lockingPid || !locked) {
|
||||
Mutex.Lock();
|
||||
lockingPid = getpid();
|
||||
}
|
||||
locked++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void cThread::Unlock(void)
|
||||
{
|
||||
if (!--locked) {
|
||||
lockingPid = 0;
|
||||
Mutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void cThread::WakeUp(void)
|
||||
{
|
||||
kill(parentPid, SIGIO); // makes any waiting 'select()' call return immediately
|
||||
@ -228,17 +209,13 @@ bool cThreadLock::Lock(cThread *Thread)
|
||||
{
|
||||
if (Thread && !thread) {
|
||||
thread = Thread;
|
||||
locked = Thread->Lock();
|
||||
return locked;
|
||||
Thread->Lock();
|
||||
locked = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cThreadLock::Locked(void)
|
||||
{
|
||||
return locked;
|
||||
}
|
||||
|
||||
// --- cPipe -----------------------------------------------------------------
|
||||
|
||||
// cPipe::Open() and cPipe::Close() are based on code originally received from
|
||||
|
12
thread.h
12
thread.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: thread.h 1.10 2001/10/20 10:25:19 kls Exp $
|
||||
* $Id: thread.h 1.11 2001/10/27 13:22:20 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __THREAD_H
|
||||
@ -45,9 +45,8 @@ class cThread {
|
||||
friend class cThreadLock;
|
||||
private:
|
||||
pthread_t thread;
|
||||
cMutex Mutex;
|
||||
pid_t parentPid, threadPid, lockingPid;
|
||||
int locked;
|
||||
cMutex mutex;
|
||||
pid_t parentPid, threadPid;
|
||||
bool running;
|
||||
static time_t lastPanic;
|
||||
static int panicLevel;
|
||||
@ -55,8 +54,8 @@ private:
|
||||
static bool signalHandlerInstalled;
|
||||
static void SignalHandler(int signum);
|
||||
static void *StartThread(cThread *Thread);
|
||||
bool Lock(void);
|
||||
void Unlock(void);
|
||||
void Lock(void) { mutex.Lock(); }
|
||||
void Unlock(void) { mutex.Unlock(); }
|
||||
protected:
|
||||
void WakeUp(void);
|
||||
virtual void Action(void) = 0;
|
||||
@ -84,7 +83,6 @@ public:
|
||||
cThreadLock(cThread *Thread = NULL);
|
||||
~cThreadLock();
|
||||
bool Lock(cThread *Thread);
|
||||
bool Locked(void);
|
||||
};
|
||||
|
||||
#define LOCK_THREAD cThreadLock ThreadLock(this)
|
||||
|
10
vdr.c
10
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/people/kls/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.86 2001/10/20 11:18:38 kls Exp $
|
||||
* $Id: vdr.c 1.89 2001/11/03 12:23:45 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -483,7 +483,7 @@ int main(int argc, char *argv[])
|
||||
time_t Now = time(NULL);
|
||||
if (Now - LastActivity > ACTIVITYTIMEOUT) {
|
||||
// Shutdown:
|
||||
if (Shutdown && Setup.MinUserInactivity && Now - LastActivity > Setup.MinUserInactivity * 60) {
|
||||
if (Shutdown && (Setup.MinUserInactivity || LastActivity == 1) && Now - LastActivity > Setup.MinUserInactivity * 60) {
|
||||
cTimer *timer = Timers.GetNextActiveTimer();
|
||||
time_t Next = timer ? timer->StartTime() : 0;
|
||||
time_t Delta = timer ? Next - Now : 0;
|
||||
@ -503,11 +503,12 @@ int main(int argc, char *argv[])
|
||||
dsyslog(LOG_INFO, "next timer event at %s", ctime(&Next));
|
||||
if (WatchdogTimeout > 0)
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
if (Interface->Confirm(tr("Press any key to cancel shutdown"), LastActivity == 1 ? 5 : SHUTDOWNWAIT, true)) {
|
||||
bool UserShutdown = key == kPower;
|
||||
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 : "";
|
||||
char *cmd;
|
||||
asprintf(&cmd, "%s %ld %ld %d '%s'", Shutdown, Next, Delta, Channel, File);
|
||||
asprintf(&cmd, "%s %ld %ld %d '%s' %d", Shutdown, Next, Delta, Channel, File, UserShutdown);
|
||||
isyslog(LOG_INFO, "executing '%s'", cmd);
|
||||
SystemExec(cmd);
|
||||
delete cmd;
|
||||
@ -529,6 +530,7 @@ int main(int argc, char *argv[])
|
||||
if (Interrupted)
|
||||
isyslog(LOG_INFO, "caught signal %d", Interrupted);
|
||||
Setup.CurrentChannel = cDvbApi::CurrentChannel();
|
||||
Setup.CurrentVolume = cDvbApi::CurrentVolume();
|
||||
Setup.Save();
|
||||
cVideoCutter::Stop();
|
||||
delete Menu;
|
||||
|
Loading…
x
Reference in New Issue
Block a user