diff --git a/HISTORY b/HISTORY index 55af3875..957d30e5 100644 --- a/HISTORY +++ b/HISTORY @@ -1580,7 +1580,7 @@ Video Disk Recorder Revision History - Fixed a bug when pressing the "Blue" button in the main menu without having displayed it (thanks to Oliver Endriss for reporting this one). -2002-10-11: Version 1.1.13 +2002-10-12: Version 1.1.13 - Added cDevice::DeviceNumber() to get the number of a device, not counting any gaps that might be in the index count. @@ -1596,3 +1596,4 @@ Video Disk Recorder Revision History Scheffler). - Fixed switching the video format in the Setup/DVB menu (thanks to Uwe Scheffler for reporting this one). +- Reactivated full handling of second audio PID (even in 'Transfer Mode'). diff --git a/PLUGINS.html b/PLUGINS.html index 106bcc74..991092ee 100644 --- a/PLUGINS.html +++ b/PLUGINS.html @@ -21,18 +21,18 @@ VDR program and present itself to the user. The inside interface provides the plugin code access to VDR's internal data structures and allows it to hook itself into specific areas to perform special actions.

-
  -Important modifications introduced in version 1.1.8 are marked like this. -
-
  +
  Important modifications introduced in version 1.1.9 are marked like this.
-
  +
  Important modifications introduced in version 1.1.11 are marked like this.
-
  +
  Important modifications introduced in version 1.1.12 are marked like this.
+
  +Important modifications introduced in version 1.1.13 are marked like this. +

Part I - The Outside Interface

@@ -964,6 +964,18 @@ bool DevicePoll(cPoller &Poller, int TimeoutMs = 0);

to determine whether the device is ready for further data. +
  +

+If the player can provide more than a single audio track, it can implement the +following functions to make them available: + +


+virtual int NumAudioTracks(void) const; +virtual const char **GetAudioTracks(int *CurrentTrack = NULL); +virtual void SetAudioTrack(int Index); +

+ +

TODO: PlayAudio()???

@@ -1182,9 +1194,9 @@ the cDvbDevice, which is used to access the DVB PCI cards. If the new device can receive, it most likely needs to provide a way of selecting which channel it shall tune to: -
  +
 


-
  +
  virtual bool ProvidesSource(int Source) const;
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL); @@ -1195,6 +1207,20 @@ These functions will be called with the desired source or channel and shall retu this device can provide the requested source or channel and whether tuning to it was successful, repectively.
+
  +

+Audio selection +

+If the device can provide more than a single audio track, it can implement the +following functions to make them available: + +


+virtual int NumAudioTracksDevice(void) const; +virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const; +virtual void SetAudioTrackDevice(int Index); +

+ +

Recording

@@ -1204,7 +1230,7 @@ A device that can be used for recording must implement the functions virtual bool SetPid(cPidHandle *Handle, int Type, bool On); virtual bool OpenDvr(void); virtual void CloseDvr(void); -
  +
  virtual bool GetTSPacket(uchar *&Data);

@@ -1250,7 +1276,6 @@ virtual void SetVideoFormat(bool VideoFormat16_9); virtual void SetVolumeDevice(int Volume);

-
 

On Screen Display

@@ -1266,7 +1291,6 @@ which must return a newly created object of a derived cOsdBase class that implements the functions necessary to display OSD information on your device. The caller of this function will delete the object as soon as it is no longer needed. -

Initializing new devices @@ -1291,7 +1315,7 @@ shut down (delete) all devices when the program terminates. It is therefore important that the devices are created on the heap, using the new operator! -
  +
 

Remote Control

The joy of zapping!

diff --git a/device.c b/device.c index 3c94fa2e..637632b4 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.26 2002/10/07 16:21:46 kls Exp $ + * $Id: device.c 1.27 2002/10/12 13:24:37 kls Exp $ */ #include "device.h" @@ -365,7 +365,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) if (CaDevice) { cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel if (CaDevice->SetChannel(Channel, false) == scrOk) // calling SetChannel() directly, not SwitchChannel()! - cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apid1(), 0, 0, 0));//XXX+ + cControl::Launch(new cTransferControl(CaDevice, Channel->Vpid(), Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2()));//XXX+ else Result = scrNoTransfer; } @@ -398,6 +398,20 @@ void cDevice::SetVolumeDevice(int Volume) { } +int cDevice::NumAudioTracksDevice(void) const +{ + return 0; +} + +const char **cDevice::GetAudioTracksDevice(int *CurrentTrack) const +{ + return NULL; +} + +void cDevice::SetAudioTrackDevice(int Index) +{ +} + bool cDevice::ToggleMute(void) { int OldVolume = volume; @@ -416,6 +430,24 @@ void cDevice::SetVolume(int Volume, bool Absolute) mute = false; } +int cDevice::NumAudioTracks(void) const +{ + return player ? player->NumAudioTracks() : NumAudioTracksDevice(); +} + +const char **cDevice::GetAudioTracks(int *CurrentTrack) const +{ + return player ? player->GetAudioTracks(CurrentTrack) : GetAudioTracksDevice(CurrentTrack); +} + +void cDevice::SetAudioTrack(int Index) +{ + if (player) + player->SetAudioTrack(Index); + else + SetAudioTrackDevice(Index); +} + bool cDevice::SetPlayMode(ePlayMode PlayMode) { return false; diff --git a/device.h b/device.h index 6d79bce4..54dc41e0 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.22 2002/10/06 15:59:08 kls Exp $ + * $Id: device.h 1.23 2002/10/12 11:15:13 kls Exp $ */ #ifndef __DEVICE_H @@ -219,7 +219,7 @@ public: // Sets the output video format to either 16:9 or 4:3 (only useful // if this device has an MPEG decoder). -// Volume facilities +// Audio facilities private: bool mute; @@ -227,6 +227,27 @@ private: protected: virtual void SetVolumeDevice(int Volume); // Sets the audio volume on this device (Volume = 0...255). + virtual int NumAudioTracksDevice(void) const; + // Returns the number of audio tracks that are currently available on this + // device. The default return value is 0, meaning that this device + // doesn't have multiple audio track capabilities. The return value may + // change with every call and need not necessarily be the number of list + // entries returned by GetAudioTracksDevice(). This function is mainly called to + // decide whether there should be an "Audio" button in a menu. + virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const; + // Returns a list of currently available audio tracks. The last entry in the + // list must be NULL. The number of entries does not necessarily have to be + // the same as returned by a previous call to NumAudioTracksDevice(). + // If CurrentTrack is given, it will be set to the index of the current track + // in the returned list. Note that the list must not be changed after it has + // been returned by a call to GetAudioTracksDevice()! The only time the list may + // change is *inside* the GetAudioTracksDevice() function. + // By default the return value is NULL and CurrentTrack, if given, will not + // have any meaning. + virtual void SetAudioTrackDevice(int Index); + // Sets the current audio track to the given value, which should be within the + // range of the list returned by a previous call to GetAudioTracksDevice() + // (otherwise nothing will happen). public: bool IsMute(void) const { return mute; } bool ToggleMute(void); @@ -235,6 +256,21 @@ public: // Sets the volume to the given value, either absolutely or relative to // the current volume. static int CurrentVolume(void) { return primaryDevice ? primaryDevice->volume : 0; }//XXX??? + int NumAudioTracks(void) const; + // Returns the number of audio tracks that are currently available on this + // device or a player attached to it. + const char **GetAudioTracks(int *CurrentTrack = NULL) const; + // Returns a list of currently available audio tracks. The last entry in the + // list is NULL. The number of entries does not necessarily have to be + // the same as returned by a previous call to NumAudioTracks(). + // If CurrentTrack is given, it will be set to the index of the current track + // in the returned list. + // By default the return value is NULL and CurrentTrack, if given, will not + // have any meaning. + void SetAudioTrack(int Index); + // Sets the current audio track to the given value, which should be within the + // range of the list returned by a previous call to GetAudioTracks() (otherwise + // nothing will happen). // Player facilities diff --git a/dvbdevice.c b/dvbdevice.c index 418e3c89..a4a4308d 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.23 2002/10/11 12:49:12 kls Exp $ + * $Id: dvbdevice.c 1.24 2002/10/12 11:15:45 kls Exp $ */ #include "dvbdevice.h" @@ -130,6 +130,8 @@ cDvbDevice::cDvbDevice(int n) else esyslog("ERROR: can't open DVB device %d", n); + aPid1 = aPid2 = 0; + source = -1; frequency = -1; diseqcCommands = NULL; @@ -722,6 +724,8 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) // PID settings: if (TurnOnLivePIDs) { + aPid1 = Channel->Apid1(); + aPid2 = Channel->Apid2(); if (!(AddPid(Channel->Apid1(), ptAudio) && AddPid(Channel->Vpid(), ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached) esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1); return false; @@ -756,6 +760,36 @@ void cDvbDevice::SetVolumeDevice(int Volume) } } +int cDvbDevice::NumAudioTracksDevice(void) const +{ + int n = 0; + if (aPid1) + n++; + if (aPid2 && aPid1 != aPid2) + n++; + return n; +} + +const char **cDvbDevice::GetAudioTracksDevice(int *CurrentTrack) const +{ + if (NumAudioTracks()) { + if (CurrentTrack) + *CurrentTrack = (pidHandles[ptAudio].pid == aPid1) ? 0 : 1; + static const char *audioTracks1[] = { "Audio 1", NULL }; + static const char *audioTracks2[] = { "Audio 1", "Audio 2", NULL }; + return NumAudioTracks() > 1 ? audioTracks2 : audioTracks1; + } + return NULL; +} + +void cDvbDevice::SetAudioTrackDevice(int Index) +{ + if (0 <= Index && Index < NumAudioTracks()) { + DelPid(pidHandles[ptAudio].pid); + AddPid(Index ? aPid2 : aPid1, ptAudio); + } +} + bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) { if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) { diff --git a/dvbdevice.h b/dvbdevice.h index 98456643..b5484dc7 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.13 2002/10/11 12:24:19 kls Exp $ + * $Id: dvbdevice.h 1.14 2002/10/12 11:15:39 kls Exp $ */ #ifndef __DVBDEVICE_H @@ -13,11 +13,6 @@ #ifdef NEWSTRUCT #include #else -#include // FIXME: this is apparently necessary for the ost/... header files - // FIXME: shouldn't every header file include ALL the other header - // FIXME: files it depends on? The sequence in which header files - // FIXME: are included here should not matter - and it should NOT - // FIXME: be necessary to include here! #include #endif #include "device.h" @@ -87,10 +82,15 @@ public: public: virtual void SetVideoFormat(bool VideoFormat16_9); -// Volume facilities +// Audio facilities +private: + int aPid1, aPid2; protected: virtual void SetVolumeDevice(int Volume); + virtual int NumAudioTracksDevice(void) const; + virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const; + virtual void SetAudioTrackDevice(int Index); // EIT facilities diff --git a/dvbplayer.c b/dvbplayer.c index 7edadfbc..927fde4e 100644 --- a/dvbplayer.c +++ b/dvbplayer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbplayer.c 1.13 2002/09/15 13:33:31 kls Exp $ + * $Id: dvbplayer.c 1.14 2002/10/12 12:29:31 kls Exp $ */ #include "dvbplayer.h" @@ -96,6 +96,8 @@ private: ePlayDirs playDir; int trickSpeed; int readIndex, writeIndex; + bool canToggleAudioTrack; + uchar audioTrack; cFrame *readFrame; const cFrame *playFrame; void TrickSpeed(int Increment); @@ -120,6 +122,9 @@ public: void Goto(int Position, bool Still = false); virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false); virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed); + virtual int NumAudioTracks(void) const; + virtual const char **GetAudioTracks(int *CurrentTrack = NULL) const; + virtual void SetAudioTrack(int Index); }; #define MAX_VIDEO_SLOWMOTION 63 // max. arg to pass to VIDEO_SLOWMOTION // TODO is this value correct? @@ -139,6 +144,8 @@ cDvbPlayer::cDvbPlayer(const char *FileName) playMode = pmPlay; playDir = pdForward; trickSpeed = NORMAL_SPEED; + canToggleAudioTrack = false; + audioTrack = 0xC0; readIndex = writeIndex = -1; readFrame = NULL; playFrame = NULL; @@ -216,7 +223,7 @@ void cDvbPlayer::StripAudioPackets(uchar *b, int Length, uchar Except) // continue with deleting the data - otherwise it disturbs DVB replay case 0xC0 ... 0xC1: // audio if (c == 0xC1) - ;//XXX+ canToggleAudioTrack = true; + canToggleAudioTrack = true; if (!Except || c != Except) { int n = l; for (int j = i; j < Length && n--; j++) @@ -353,7 +360,7 @@ void cDvbPlayer::Action(void) continue; } r = ReadFrame(replayFile, b, Length, sizeof(b)); - StripAudioPackets(b, r, 0xC0); //XXX+ audioTrack + StripAudioPackets(b, r, audioTrack); } else // allows replay even if the index file is missing r = read(replayFile, b, sizeof(b)); @@ -623,6 +630,31 @@ bool cDvbPlayer::GetReplayMode(bool &Play, bool &Forward, int &Speed) return true; } +int cDvbPlayer::NumAudioTracks(void) const +{ + return canToggleAudioTrack ? 2 : 1; +} + +const char **cDvbPlayer::GetAudioTracks(int *CurrentTrack = NULL) const +{ + if (NumAudioTracks()) { + if (CurrentTrack) + *CurrentTrack = (audioTrack == 0xC0) ? 0 : 1; + static const char *audioTracks1[] = { "Audio 1", NULL }; + static const char *audioTracks2[] = { "Audio 1", "Audio 2", NULL }; + return NumAudioTracks() > 1 ? audioTracks2 : audioTracks1; + } + return NULL; +} + +void cDvbPlayer::SetAudioTrack(int Index) +{ + if ((audioTrack == 0xC0) != (Index == 0)) { + audioTrack = (Index == 1) ? 0xC1 : 0xC0; + Empty(); + } +} + // --- cDvbPlayerControl ----------------------------------------------------- cDvbPlayerControl::cDvbPlayerControl(const char *FileName) diff --git a/menu.c b/menu.c index 8c6875d9..5ea8663b 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.213 2002/10/12 09:06:57 kls Exp $ + * $Id: menu.c 1.214 2002/10/12 13:34:56 kls Exp $ */ #include "menu.h" @@ -2212,7 +2212,7 @@ void cMenuMain::Set(void) // Color buttons: - SetHelp(tr("Record"), /*XXX+ cDevice::PrimaryDevice()->CanToggleAudioTrack() ? tr("Language") :XXX*/ NULL, NULL, replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL); + SetHelp(tr("Record"), cDevice::PrimaryDevice()->NumAudioTracks() > 1 ? tr("Language") : NULL, NULL, replaying ? tr("Button$Stop") : cReplayControl::LastReplayed() ? tr("Resume") : NULL); Display(); lastActivity = time(NULL); } @@ -2264,13 +2264,17 @@ eOSState cMenuMain::ProcessKey(eKeys Key) state = osRecord; break; case kGreen: if (!HasSubMenu()) { - /*XXX+ - if (cDevice::PrimaryDevice()->CanToggleAudioTrack()) { + int CurrentAudioTrack = -1; + const char **AudioTracks = cDevice::PrimaryDevice()->GetAudioTracks(&CurrentAudioTrack); + if (AudioTracks) { + const char **at = &AudioTracks[CurrentAudioTrack]; + if (!*++at) + at = AudioTracks; Interface->Clear(); - cDevice::PrimaryDevice()->ToggleAudioTrack(); + cDevice::PrimaryDevice()->SetAudioTrack(at - AudioTracks); + //XXX Interface->Info(*at); state = osEnd; } - XXX*/ } break; case kBlue: if (!HasSubMenu()) diff --git a/player.h b/player.h index 12cc2a37..1e1fabfa 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.8 2002/08/16 09:14:12 kls Exp $ + * $Id: player.h 1.9 2002/10/12 11:17:02 kls Exp $ */ #ifndef __PLAYER_H @@ -50,6 +50,27 @@ public: // we are going forward or backward and 'Speed' is -1 if this is normal // play/pause mode, 0 if it is single speed fast/slow forward/back mode // and >0 if this is multi speed mode. + virtual int NumAudioTracks(void) const { return 0; } + // Returns the number of audio tracks that are currently available on this + // player. The default return value is 0, meaning that this player + // doesn't have multiple audio track capabilities. The return value may + // change with every call and need not necessarily be the number of list + // entries returned by GetAudioTracks(). This function is mainly called to + // decide whether there should be an "Audio" button in a menu. + virtual const char **GetAudioTracks(int *CurrentTrack = NULL) const { return NULL; } + // Returns a list of currently available audio tracks. The last entry in the + // list must be NULL. The number of entries does not necessarily have to be + // the same as returned by a previous call to NumAudioTracks(). + // If CurrentTrack is given, it will be set to the index of the current track + // in the returned list. Note that the list must not be changed after it has + // been returned by a call to GetAudioTracks()! The only time the list may + // change is *inside* the GetAudioTracks() function. + // By default the return value is NULL and CurrentTrack, if given, will not + // have any meaning. + virtual void SetAudioTrack(int Index) {} + // Sets the current audio track to the given value, which should be within the + // range of the list returned by a previous call to GetAudioTracks() + // (otherwise nothing will happen). }; class cControl : public cOsdObject { diff --git a/recorder.c b/recorder.c index ba7dc06d..4904014f 100644 --- a/recorder.c +++ b/recorder.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recorder.c 1.2 2002/09/07 13:40:23 kls Exp $ + * $Id: recorder.c 1.3 2002/10/12 13:34:29 kls Exp $ */ #include @@ -119,7 +119,7 @@ void cRecorder::Action(void) r += g; if (r > 0) { int Count = r, Result; - const uchar *p = remux->Process(b, Count, Result, &pictureType); + uchar *p = remux->Process(b, Count, Result, &pictureType); if (p) { //XXX+ active??? see old version (Busy) if (!active && pictureType == I_FRAME) // finish the recording before the next 'I' frame diff --git a/remux.c b/remux.c index 6a2753b1..786bb8fe 100644 --- a/remux.c +++ b/remux.c @@ -8,7 +8,7 @@ * the Linux DVB driver's 'tuxplayer' example and were rewritten to suit * VDR's needs. * - * $Id: remux.c 1.11 2002/08/11 11:48:34 kls Exp $ + * $Id: remux.c 1.12 2002/10/12 13:33:54 kls Exp $ */ /* The calling interface of the 'cRemux::Process()' function is defined @@ -482,17 +482,9 @@ int cRemux::ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &Pic return -1; } -void cRemux::SetAudioPid(int APid) -{ - aPid1 = APid; - vTS2PES->Clear(); - aTS2PES1->Clear(); - resultCount = resultDelivered = 0; -} - #define TS_SYNC_BYTE 0x47 -const uchar *cRemux::Process(const uchar *Data, int &Count, int &Result, uchar *PictureType) +uchar *cRemux::Process(const uchar *Data, int &Count, int &Result, uchar *PictureType) { uchar dummyPictureType; if (!PictureType) @@ -611,7 +603,7 @@ XXX*/ if (synced) { *PictureType = pt; Result = l; - const uchar *p = resultBuffer + resultDelivered; + uchar *p = resultBuffer + resultDelivered; resultDelivered += l; return p; } @@ -629,7 +621,7 @@ XXX*/ return NULL; // no useful data found, wait for more if (synced) { Result = l; - const uchar *p = resultBuffer + resultDelivered; + uchar *p = resultBuffer + resultDelivered; resultDelivered += l; return p; } diff --git a/remux.h b/remux.h index feb11767..83126187 100644 --- a/remux.h +++ b/remux.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.h 1.7 2002/08/09 16:18:02 kls Exp $ + * $Id: remux.h 1.8 2002/10/12 13:30:24 kls Exp $ */ #ifndef __REMUX_H @@ -47,8 +47,7 @@ private: public: cRemux(int VPid, int APid1, int APid2, int DPid1, int DPid2, bool ExitOnFailure = false); ~cRemux(); - void SetAudioPid(int APid); - const uchar *Process(const uchar *Data, int &Count, int &Result, uchar *PictureType = NULL); + uchar *Process(const uchar *Data, int &Count, int &Result, uchar *PictureType = NULL); }; #endif // __REMUX_H diff --git a/transfer.c b/transfer.c index bd4390bc..adb72605 100644 --- a/transfer.c +++ b/transfer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: transfer.c 1.3 2002/09/22 09:50:48 kls Exp $ + * $Id: transfer.c 1.4 2002/10/12 13:32:48 kls Exp $ */ #include "transfer.h" @@ -21,6 +21,8 @@ cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2) { ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, true); remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2); + canToggleAudioTrack = false; + audioTrack = 0xC0; gotBufferReserve = false; active = false; } @@ -86,9 +88,9 @@ void cTransfer::Action(void) if (r > 0) { int Count = r, Result; - const uchar *p = remux->Process(b, Count, Result); + uchar *p = remux->Process(b, Count, Result); if (p) { - //XXX+ StripAudio??? + StripAudioPackets(p, Result, audioTrack); while (Result > 0 && active) { int w = PlayVideo(p, Result); if (w > 0) { @@ -112,15 +114,65 @@ void cTransfer::Action(void) dsyslog("transfer thread ended (pid=%d)", getpid()); } -void cTransfer::SetAudioPid(int APid) +void cTransfer::StripAudioPackets(uchar *b, int Length, uchar Except) { - /*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*/ + for (int i = 0; i < Length - 6; i++) { + if (b[i] == 0x00 && b[i + 1] == 0x00 && b[i + 2] == 0x01) { + uchar c = b[i + 3]; + int l = b[i + 4] * 256 + b[i + 5] + 6; + switch (c) { + case 0xBD: // dolby + if (Except) + ;//XXX+ PlayExternalDolby(&b[i], Length - i); + // continue with deleting the data - otherwise it disturbs DVB replay + case 0xC0 ... 0xC1: // audio + if (c == 0xC1) + canToggleAudioTrack = true; + if (!Except || c != Except) { + int n = l; + for (int j = i; j < Length && n--; j++) + b[j] = 0x00; + } + break; + case 0xE0 ... 0xEF: // video + break; + default: + //esyslog("ERROR: unexpected packet id %02X", c); + l = 0; + } + if (l) + i += l - 1; // the loop increments, too! + } + /*XXX + else + esyslog("ERROR: broken packet header"); + XXX*/ + } +} + +int cTransfer::NumAudioTracks(void) const +{ + return canToggleAudioTrack ? 2 : 1; +} + +const char **cTransfer::GetAudioTracks(int *CurrentTrack = NULL) const +{ + if (NumAudioTracks()) { + if (CurrentTrack) + *CurrentTrack = (audioTrack == 0xC0) ? 0 : 1; + static const char *audioTracks1[] = { "Audio 1", NULL }; + static const char *audioTracks2[] = { "Audio 1", "Audio 2", NULL }; + return NumAudioTracks() > 1 ? audioTracks2 : audioTracks1; + } + return NULL; +} + +void cTransfer::SetAudioTrack(int Index) +{ + if ((audioTrack == 0xC0) != (Index == 0)) { + audioTrack = (Index == 1) ? 0xC1 : 0xC0; + DeviceClear(); + } } // --- cTransferControl ------------------------------------------------------ diff --git a/transfer.h b/transfer.h index 567f21ab..d94c85ab 100644 --- a/transfer.h +++ b/transfer.h @@ -4,7 +4,7 @@ * 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 $ + * $Id: transfer.h 1.3 2002/10/12 12:59:05 kls Exp $ */ #ifndef __TRANSFER_H @@ -20,8 +20,11 @@ class cTransfer : public cReceiver, public cPlayer, public cThread { private: cRingBufferLinear *ringBuffer; cRemux *remux; + bool canToggleAudioTrack; + uchar audioTrack; bool gotBufferReserve; bool active; + void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00); protected: virtual void Activate(bool On); virtual void Receive(uchar *Data, int Length); @@ -29,7 +32,9 @@ protected: public: cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2); virtual ~cTransfer(); - void SetAudioPid(int APid); + virtual int NumAudioTracks(void) const; + virtual const char **GetAudioTracks(int *CurrentTrack = NULL) const; + virtual void SetAudioTrack(int Index); }; class cTransferControl : public cControl {