From c0ef9a35e2994aad863dfb2195211bb2d9dec766 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Thu, 15 Aug 2002 11:16:34 +0200 Subject: [PATCH] Implemented several replay modes to allow players that play only audio --- CONTRIBUTORS | 1 + HISTORY | 2 ++ PLUGINS.html | 2 +- device.c | 10 +++--- device.h | 27 ++++++++++++---- dvbdevice.c | 89 ++++++++++++++++++++++++++++++++++++---------------- dvbdevice.h | 5 +-- player.c | 5 +-- player.h | 17 +++++----- 9 files changed, 107 insertions(+), 51 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index b7de2aaf..e39f3021 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -140,6 +140,7 @@ Stefan Huelswitt for suggesting to make the config directory available to plugins for suggesting to add an error message if the directory specified in the '-L' option can't be accessed + for implementing several replay modes to allow players that play only audio Ulrich Röder for pointing out that there are channels that have a symbol rate higher than diff --git a/HISTORY b/HISTORY index a3176062..a145e521 100644 --- a/HISTORY +++ b/HISTORY @@ -1408,3 +1408,5 @@ Video Disk Recorder Revision History can now call DeviceNeedsData() to see whether the replay device is ready for further data. A derived cDevice class must implement NeedsData() and shall check if any of its file handles is ready for data. +- Implemented several replay modes to allow players that play only audio (thanks + to Stefan Huelswitt). diff --git a/PLUGINS.html b/PLUGINS.html index c0f6d8ab..105865b0 100644 --- a/PLUGINS.html +++ b/PLUGINS.html @@ -1231,7 +1231,7 @@ The functions to implement replaying capabilites are
 


virtual bool HasDecoder(void) const; -virtual int SetPlayMode(bool On); +virtual bool SetPlayMode(ePlayMode PlayMode); virtual void TrickSpeed(int Speed); virtual void Clear(void); virtual void Play(void); diff --git a/device.c b/device.c index 8d678503..40304618 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 1.9 2002/08/15 09:59:57 kls Exp $ + * $Id: device.c 1.10 2002/08/15 10:30:08 kls Exp $ */ #include "device.h" @@ -316,9 +316,9 @@ void cDevice::SetVolume(int Volume, bool Absolute) mute = false; } -int cDevice::SetPlayMode(bool On) +bool cDevice::SetPlayMode(ePlayMode PlayMode) { - return -1; + return false; } void cDevice::TrickSpeed(int Speed) @@ -361,7 +361,7 @@ bool cDevice::AttachPlayer(cPlayer *Player) Detach(player); player = Player; player->device = this; - SetPlayMode(true);//XXX + SetPlayMode(player->playMode); player->Activate(true); return true; } @@ -374,7 +374,7 @@ void cDevice::Detach(cPlayer *Player) player->Activate(false); player->device = NULL; player = NULL; - SetPlayMode(false); + SetPlayMode(pmNone); } } diff --git a/device.h b/device.h index 6bd9828e..bba828a5 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 1.7 2002/08/15 09:22:13 kls Exp $ + * $Id: device.h 1.8 2002/08/15 11:09:21 kls Exp $ */ #ifndef __DEVICE_H @@ -26,6 +26,23 @@ enum eSetChannelResult { scrOk, scrNoTransfer, scrFailed }; +enum ePlayMode { pmNone, // audio/video from decoder + pmAudioVideo, // audio/video from player + pmAudioOnly, // audio only from player, video from decoder + pmExtern_THIS_SHOULD_BE_AVOIDED + // external player (e.g. MPlayer), release the device + // WARNING: USE THIS MODE ONLY AS A LAST RESORT, IF YOU + // ABSOLUTELY, POSITIVELY CAN'T IMPLEMENT YOUR PLAYER + // THE WAY IT IS SUPPOSED TO WORK. FORCING THE DEVICE + // TO RELEASE ITS FILES HANDLES (OR WHATEVER RESOURCES + // IT MAY USE) TO ALLOW AN EXTERNAL PLAYER TO ACCESS + // THEM MEANS THAT SUCH A PLAYER WILL NEED TO HAVE + // DETAILED KNOWLEDGE ABOUT THE INTERNALS OF THE DEVICE + // IN USE. AS A CONSEQUENCE, YOUR PLAYER MAY NOT WORK + // IF A PARTICULAR VDR INSTALLATION USES A DEVICE NOT + // KNOWN TO YOUR PLAYER. + }; + class cChannel; class cPlayer; class cReceiver; @@ -190,11 +207,9 @@ public: private: cPlayer *player; protected: - virtual int SetPlayMode(bool On); - // Sets the device into play mode (On = true) or normal - // viewing mode (On = false). If On is true, it may return a file - // handle that a player can use to poll this device when replaying. - //XXX TODO should be implemented differently + virtual bool SetPlayMode(ePlayMode PlayMode); + // Sets the device into the given play mode. + // Returns true if the operation was successful. public: virtual void TrickSpeed(int Speed); // Sets the device into a mode where replay is done slower. diff --git a/dvbdevice.c b/dvbdevice.c index b37a98db..82587286 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.4 2002/08/15 09:59:33 kls Exp $ + * $Id: dvbdevice.c 1.5 2002/08/15 11:13:46 kls Exp $ */ #include "dvbdevice.h" @@ -81,6 +81,7 @@ cDvbDevice::cDvbDevice(int n) { frontendType = FrontendType(-1); // don't know how else to initialize this - there is no FE_UNKNOWN siProcessor = NULL; + playMode = pmNone; // Devices that are present on all card types: @@ -569,32 +570,65 @@ void cDvbDevice::SetVolumeDevice(int Volume) } } -int cDvbDevice::SetPlayMode(bool On) +bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) { - if (On) { - if (siProcessor) - siProcessor->SetStatus(false); - CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); - CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); - CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); - CHECK(ioctl(fd_audio, AUDIO_PLAY)); - CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); - CHECK(ioctl(fd_video, VIDEO_PLAY)); - return fd_video; - } - else { - CHECK(ioctl(fd_video, VIDEO_STOP, true)); - CHECK(ioctl(fd_audio, AUDIO_STOP, true)); - CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER)); - CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); - CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX)); - CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX)); - CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); - CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); - if (siProcessor) - siProcessor->SetStatus(true); - return -1; + if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) { + // reopen the devices + fd_video = DvbOpen(DEV_DVB_VIDEO, CardIndex(), O_RDWR | O_NONBLOCK); + fd_audio = DvbOpen(DEV_DVB_AUDIO, CardIndex(), O_RDWR | O_NONBLOCK); + SetVideoFormat(Setup.VideoFormat); } + + switch (PlayMode) { + case pmNone: + if (playMode == pmAudioOnly) { + // special "handling" to return from PCM replay + CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); + CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); + CHECK(ioctl(fd_video, VIDEO_PLAY)); + } + CHECK(ioctl(fd_video, VIDEO_STOP, true)); + CHECK(ioctl(fd_audio, AUDIO_STOP, true)); + CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER)); + CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); + CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX)); + CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX)); + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); + CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); + if (siProcessor) + siProcessor->SetStatus(true); + break; + case pmAudioVideo: + if (siProcessor) + siProcessor->SetStatus(false); + CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); + CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); + CHECK(ioctl(fd_audio, AUDIO_PLAY)); + CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); + CHECK(ioctl(fd_video, VIDEO_PLAY)); + break; + case pmAudioOnly: + if (siProcessor) + siProcessor->SetStatus(false); + CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); + CHECK(ioctl(fd_audio, AUDIO_STOP, true)); + CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); + CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); + CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false)); + CHECK(ioctl(fd_audio, AUDIO_PLAY)); + CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false)); + break; + case pmExtern_THIS_SHOULD_BE_AVOIDED: + if (siProcessor) + siProcessor->SetStatus(false); + close(fd_video); + close(fd_audio); + fd_video = fd_audio = -1; + break; + } + playMode = PlayMode; + return true; } void cDvbDevice::TrickSpeed(int Speed) @@ -667,8 +701,9 @@ bool cDvbDevice::NeedsData(int Wait) int cDvbDevice::PlayVideo(const uchar *Data, int Length) { - if (fd_video >= 0) - return write(fd_video, Data, Length); + int fd = playMode == pmAudioOnly ? fd_audio : fd_video; + if (fd >= 0) + return write(fd, Data, Length); return -1; } diff --git a/dvbdevice.h b/dvbdevice.h index 11c963a7..cbc9b164 100644 --- a/dvbdevice.h +++ b/dvbdevice.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.h 1.3 2002/08/15 09:28:36 kls Exp $ + * $Id: dvbdevice.h 1.4 2002/08/15 10:59:25 kls Exp $ */ #ifndef __DVBDEVICE_H @@ -83,7 +83,8 @@ private: // Player facilities protected: - virtual int SetPlayMode(bool On); + ePlayMode playMode; + virtual bool SetPlayMode(ePlayMode PlayMode); public: virtual void TrickSpeed(int Speed); virtual void Clear(void); diff --git a/player.c b/player.c index 3abb79b5..3eecc2d4 100644 --- a/player.c +++ b/player.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: player.c 1.4 2002/08/11 15:49:13 kls Exp $ + * $Id: player.c 1.5 2002/08/15 10:29:17 kls Exp $ */ #include "player.h" @@ -12,9 +12,10 @@ // --- cPlayer --------------------------------------------------------------- -cPlayer::cPlayer(void) +cPlayer::cPlayer(ePlayMode PlayMode) { device = NULL; + playMode = PlayMode; } cPlayer::~cPlayer() diff --git a/player.h b/player.h index 1fd9fdda..1eed0b70 100644 --- a/player.h +++ b/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.6 2002/08/15 09:34:08 kls Exp $ + * $Id: player.h 1.7 2002/08/15 11:10:09 kls Exp $ */ #ifndef __PLAYER_H @@ -17,6 +17,7 @@ class cPlayer { friend class cDevice; private: cDevice *device; + ePlayMode playMode; protected: bool DeviceNeedsData(int Wait = 0) { return device ? device->NeedsData(Wait) : false; } void DeviceTrickSpeed(int Speed) { if (device) device->TrickSpeed(Speed); } @@ -27,17 +28,17 @@ protected: void DeviceStillPicture(const uchar *Data, int Length) { if (device) device->StillPicture(Data, Length); } void Detach(void); virtual void Activate(bool On) {} - // This function is called right after the cPlayer has been attached to - // (On == true) or before it gets detached from (On == false) a cDevice. - // It can be used to do things like starting/stopping a thread. + // This function is called right after the cPlayer has been attached to + // (On == true) or before it gets detached from (On == false) a cDevice. + // It can be used to do things like starting/stopping a thread. int PlayVideo(const uchar *Data, int Length); - // Sends the given Data to the video device and returns the number of - // bytes that have actually been accepted by the video device (or a - // negative value in case of an error). + // Sends the given Data to the video device and returns the number of + // bytes that have actually been accepted by the video device (or a + // negative value in case of an error). int PlayAudio(const uchar *Data, int Length); // XXX+ TODO public: - cPlayer(void); + cPlayer(ePlayMode PlayMode = pmAudioVideo); virtual ~cPlayer(); bool IsAttached(void) { return device != NULL; } virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false) { return false; }