diff --git a/packages/3rdparty/multimedia/vdr/build b/packages/3rdparty/multimedia/vdr/build index ff78a42264..6faa1aab3b 100755 --- a/packages/3rdparty/multimedia/vdr/build +++ b/packages/3rdparty/multimedia/vdr/build @@ -32,7 +32,7 @@ PLUGINLIBDIR = /usr/lib/vdr VIDEODIR = /storage/videos CONFDIR = /storage/.config/vdr LOCDIR = /usr/share/locale -LIBS += -lz -lexpat -lbz2 -lfontconfig -lfreetype -lxml2 +#LIBS += -lz -lexpat -lbz2 -lfontconfig -lfreetype -lxml2 NO_KBD=yes VDR_USER=root diff --git a/packages/3rdparty/multimedia/vdr/meta b/packages/3rdparty/multimedia/vdr/meta index 5734d817f5..e163a3bf3d 100644 --- a/packages/3rdparty/multimedia/vdr/meta +++ b/packages/3rdparty/multimedia/vdr/meta @@ -20,12 +20,12 @@ ################################################################################ PKG_NAME="vdr" -PKG_VERSION="1.7.33" +PKG_VERSION="2.0.0" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="GPL" PKG_SITE="http://www.tvdr.de" -PKG_URL="ftp://ftp.tvdr.de/vdr/Developer/$PKG_NAME-$PKG_VERSION.tar.bz2" +PKG_URL="ftp://ftp.tvdr.de/vdr/$PKG_NAME-$PKG_VERSION.tar.bz2" PKG_DEPENDS="fontconfig freetype libcap" PKG_BUILD_DEPENDS="toolchain fontconfig freetype libcap libjpeg-turbo bzip2" PKG_PRIORITY="optional" diff --git a/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-01_disable_ca_updates.patch b/packages/3rdparty/multimedia/vdr/patches/vdr-01_disable_ca_updates.patch similarity index 100% rename from packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-01_disable_ca_updates.patch rename to packages/3rdparty/multimedia/vdr/patches/vdr-01_disable_ca_updates.patch diff --git a/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-02_disable_eitscan.patch b/packages/3rdparty/multimedia/vdr/patches/vdr-02_disable_eitscan.patch similarity index 100% rename from packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-02_disable_eitscan.patch rename to packages/3rdparty/multimedia/vdr/patches/vdr-02_disable_eitscan.patch diff --git a/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-10_hannels.conf.terr-fix.patch b/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-10_hannels.conf.terr-fix.patch deleted file mode 100644 index 36cd42d096..0000000000 --- a/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-10_hannels.conf.terr-fix.patch +++ /dev/null @@ -1,16 +0,0 @@ -Description: Removes Ch 14 fom example channels.conf.terr, because the entry is - invalid (reported as Ubuntu Bug #45721) -Author: Thomas Schmidt - -Index: vdr/channels.conf.terr -=================================================================== ---- vdr.orig/channels.conf.terr 2011-12-10 22:22:04.000000000 +0100 -+++ vdr/channels.conf.terr 2011-12-11 01:49:01.000000000 +0100 -@@ -9,7 +9,6 @@ - bid-up.tv (TV):561833:I0C23D0M64B8T2G32Y0:T:27500:6273:6274:0:0:14272:0:0:0 - CBBC (TV):505833:I0C34D0M16B8T2G32Y0:T:27500:620:621,622:0:0:4671:0:0:0 - Cbeebies (TV):529833:I0C34D0M16B8T2G32Y0:T:27500:201:401,402:0:0:16960:0:0:0 --Ch 14 (TV):481833:I0C23D0M64B8T2G32Y0:T:27500:2840:2841:2843:0:0:8800:0:0 - Ch 32 (TV):537833:I0C34D0M16B8T2G32Y0:T:27500:501:502,504:0:0:25984:0:0:0 - Ch 44 (TV):537833:I0C34D0M16B8T2G32Y0:T:27500:501:502,504:0:0:26048:0:0:0 - Channel 4 (TV):481833:I0C23D0M64B8T2G32Y0:T:27500:2827:2828,2830:0:0:8384:0:0:0 diff --git a/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-20_dynamite+externalci+rotorng.patch b/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-20_dynamite+externalci+rotorng.patch deleted file mode 100644 index 079e38dfca..0000000000 --- a/packages/3rdparty/multimedia/vdr/patches/vdr-1.7.33-20_dynamite+externalci+rotorng.patch +++ /dev/null @@ -1,1079 +0,0 @@ -diff --git a/ci.c b/ci.c -index 904697e..1e95313 100644 ---- a/ci.c -+++ b/ci.c -@@ -1571,6 +1571,8 @@ cCamSlot::cCamSlot(cCiAdapter *CiAdapter) - - cCamSlot::~cCamSlot() - { -+ if (ciAdapter && ciAdapter->assignedDevice) -+ ciAdapter->assignedDevice->SetCamSlot(NULL); - CamSlots.Del(this, false); - DeleteAllConnections(); - } -diff --git a/ci.h b/ci.h -index 74e0270..818ea29 100644 ---- a/ci.h -+++ b/ci.h -@@ -72,6 +72,7 @@ public: - }; - - class cDevice; -+class cTSBufferBase; - class cCamSlot; - - enum eModuleStatus { msNone, msReset, msPresent, msReady }; -@@ -115,6 +116,13 @@ public: - ///< The derived class must call Cancel(3) in its destructor. - virtual bool Ready(void); - ///< Returns 'true' if all present CAMs in this adapter are ready. -+#define EXTERNALCI_PATCH -+ virtual cTSBufferBase *GetTSBuffer(int FdDvr) { return NULL; } -+ ///< Derived classes can return a special TS buffer with features -+ ///< like rerouting the stream through an external ci. -+ ///< The caller must delete the buffer. -+ virtual bool SetIdle(bool Idle, bool TestOnly) { return false; } -+ virtual bool IsIdle(void) const { return false; } - }; - - class cTPDU; -diff --git a/device.c b/device.c -index 2678d68..56c2b9c 100644 ---- a/device.c -+++ b/device.c -@@ -69,12 +69,22 @@ int cDevice::currentChannel = 1; - cDevice *cDevice::device[MAXDEVICES] = { NULL }; - cDevice *cDevice::primaryDevice = NULL; - cList cDevice::deviceHooks; -- --cDevice::cDevice(void) -+cDevice *cDevice::nextParentDevice = NULL; -+ -+cDevice::cDevice(cDevice *ParentDevice) - :patPmtParser(true) --{ -- cardIndex = nextCardIndex++; -- dsyslog("new device number %d", CardIndex() + 1); -+,isIdle(false) -+,parentDevice(ParentDevice) -+,subDevice(NULL) -+{ -+ if (!ParentDevice) -+ parentDevice = nextParentDevice; -+ cDevice::nextParentDevice = NULL; -+ if (parentDevice) -+ cardIndex = parentDevice->cardIndex; -+ else -+ cardIndex = nextCardIndex++; -+ dsyslog("new %sdevice number %d", parentDevice ? "sub-" : "", CardIndex() + 1); - - SetDescription("receiver on device %d", CardIndex() + 1); - -@@ -105,10 +115,14 @@ cDevice::cDevice(void) - for (int i = 0; i < MAXRECEIVERS; i++) - receiver[i] = NULL; - -- if (numDevices < MAXDEVICES) -- device[numDevices++] = this; -+ if (!parentDevice) { -+ if (numDevices < MAXDEVICES) -+ device[numDevices++] = this; -+ else -+ esyslog("ERROR: too many devices or \"dynamite\"-unpatched device creator!"); -+ } - else -- esyslog("ERROR: too many devices!"); -+ parentDevice->subDevice = this; - } - - cDevice::~cDevice() -@@ -117,6 +131,29 @@ cDevice::~cDevice() - DetachAllReceivers(); - delete liveSubtitle; - delete dvbSubtitleConverter; -+ if (parentDevice && (parentDevice->subDevice == this)) -+ parentDevice->subDevice = NULL; -+} -+ -+bool cDevice::SetIdle(bool Idle) -+{ -+ if (parentDevice) -+ return parentDevice->SetIdle(Idle); -+ if (isIdle == Idle) -+ return true; -+ if (Receiving(false)) -+ return false; -+ if (Idle) { -+ Detach(player); -+ DetachAllReceivers(); -+ } -+ if (!SetIdleDevice(Idle, true)) -+ return false; -+ isIdle = Idle; -+ if (SetIdleDevice(Idle, false)) -+ return true; -+ isIdle = !Idle; -+ return false; - } - - bool cDevice::WaitForAllDevicesReady(int Timeout) -@@ -155,6 +192,8 @@ int cDevice::NextCardIndex(int n) - - int cDevice::DeviceNumber(void) const - { -+ if (parentDevice) -+ return parentDevice->DeviceNumber(); - for (int i = 0; i < numDevices; i++) { - if (device[i] == this) - return i; -@@ -355,6 +394,8 @@ bool cDevice::HasCi(void) - - void cDevice::SetCamSlot(cCamSlot *CamSlot) - { -+ if (parentDevice) -+ return parentDevice->SetCamSlot(CamSlot); - camSlot = CamSlot; - } - -@@ -567,6 +608,10 @@ void cDevice::DelLivePids(void) - - void cDevice::StartSectionHandler(void) - { -+ if (parentDevice) { -+ parentDevice->StartSectionHandler(); -+ return; -+ } - if (!sectionHandler) { - sectionHandler = new cSectionHandler(this); - AttachFilter(eitFilter = new cEitFilter); -@@ -578,6 +623,10 @@ void cDevice::StartSectionHandler(void) - - void cDevice::StopSectionHandler(void) - { -+ if (parentDevice) { -+ parentDevice->StopSectionHandler(); -+ return; -+ } - if (sectionHandler) { - delete nitFilter; - delete sdtFilter; -@@ -609,12 +658,17 @@ void cDevice::CloseFilter(int Handle) - - void cDevice::AttachFilter(cFilter *Filter) - { -+ if (parentDevice) -+ return parentDevice->AttachFilter(Filter); -+ SetIdle(false); - if (sectionHandler) - sectionHandler->Attach(Filter); - } - - void cDevice::Detach(cFilter *Filter) - { -+ if (parentDevice) -+ return parentDevice->Detach(Filter); - if (sectionHandler) - sectionHandler->Detach(Filter); - } -@@ -776,6 +830,7 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView) - sectionHandler->SetStatus(false); - sectionHandler->SetChannel(NULL); - } -+ SetIdle(false); - // Tell the camSlot about the channel switch and add all PIDs of this - // channel to it, for possible later decryption: - if (camSlot) -@@ -822,19 +877,27 @@ void cDevice::ForceTransferMode(void) - { - if (!cTransferControl::ReceiverDevice()) { - cChannel *Channel = Channels.GetByNumber(CurrentChannel()); -- if (Channel) -+ if (Channel) { -+ SetIdle(false); - SetChannelDevice(Channel, false); // this implicitly starts Transfer Mode -+ } - } - } - - int cDevice::Occupied(void) const - { -+ if (parentDevice) -+ return parentDevice->Occupied(); - int Seconds = occupiedTimeout - time(NULL); - return Seconds > 0 ? Seconds : 0; - } - - void cDevice::SetOccupied(int Seconds) - { -+ if (parentDevice) { -+ parentDevice->SetOccupied(Seconds); -+ return; -+ } - if (Seconds >= 0) - occupiedTimeout = time(NULL) + min(Seconds, MAXOCCUPIEDTIMEOUT); - } -@@ -1209,7 +1272,10 @@ bool cDevice::Transferring(void) const - - bool cDevice::AttachPlayer(cPlayer *Player) - { -+ if (parentDevice) -+ return parentDevice->AttachPlayer(Player); - if (CanReplay()) { -+ SetIdle(false); - if (player) - Detach(player); - DELETENULL(liveSubtitle); -@@ -1228,6 +1294,8 @@ bool cDevice::AttachPlayer(cPlayer *Player) - - void cDevice::Detach(cPlayer *Player) - { -+ if (parentDevice) -+ return parentDevice->Detach(Player); - if (Player && player == Player) { - cPlayer *p = player; - player = NULL; // avoids recursive calls to Detach() -@@ -1247,6 +1315,8 @@ void cDevice::Detach(cPlayer *Player) - - void cDevice::StopReplay(void) - { -+ if (parentDevice) -+ return parentDevice->StopReplay(); - if (player) { - Detach(player); - if (IsPrimaryDevice()) -@@ -1529,6 +1599,8 @@ int cDevice::PlayTs(const uchar *Data, int Length, bool VideoOnly) - - int cDevice::Priority(void) const - { -+ if (parentDevice) -+ return parentDevice->Priority(); - int priority = IDLEPRIORITY; - if (IsPrimaryDevice() && !Replaying() && ActualDevice() == PrimaryDevice()) - priority = TRANSFERPRIORITY; // we use the same value here, no matter whether it's actual Transfer Mode or real live viewing -@@ -1547,6 +1619,8 @@ bool cDevice::Ready(void) - - bool cDevice::Receiving(bool Dummy) const - { -+ if (parentDevice) -+ return parentDevice->Receiving(Dummy); - cMutexLock MutexLock(&mutexReceiver); - for (int i = 0; i < MAXRECEIVERS; i++) { - if (receiver[i]) -@@ -1627,10 +1701,13 @@ bool cDevice::GetTSPacket(uchar *&Data) - - bool cDevice::AttachReceiver(cReceiver *Receiver) - { -+ if (parentDevice) -+ return parentDevice->AttachReceiver(Receiver); - if (!Receiver) - return false; - if (Receiver->device == this) - return true; -+ SetIdle(false); - // activate the following line if you need it - actually the driver should be fixed! - //#define WAIT_FOR_TUNER_LOCK - #ifdef WAIT_FOR_TUNER_LOCK -@@ -1669,6 +1746,8 @@ bool cDevice::AttachReceiver(cReceiver *Receiver) - - void cDevice::Detach(cReceiver *Receiver) - { -+ if (parentDevice) -+ return parentDevice->Detach(Receiver); - if (!Receiver || Receiver->device != this) - return; - bool receiversLeft = false; -@@ -1694,6 +1773,8 @@ void cDevice::Detach(cReceiver *Receiver) - - void cDevice::DetachAll(int Pid) - { -+ if (parentDevice) -+ return parentDevice->DetachAll(Pid); - if (Pid) { - cMutexLock MutexLock(&mutexReceiver); - for (int i = 0; i < MAXRECEIVERS; i++) { -@@ -1706,6 +1787,8 @@ void cDevice::DetachAll(int Pid) - - void cDevice::DetachAllReceivers(void) - { -+ if (parentDevice) -+ return parentDevice->DetachAllReceivers(); - cMutexLock MutexLock(&mutexReceiver); - for (int i = 0; i < MAXRECEIVERS; i++) - Detach(receiver[i]); -@@ -1778,3 +1861,25 @@ uchar *cTSBuffer::Get(void) - } - return NULL; - } -+ -+// --- cDynamicDeviceProbe ------------------------------------------------------- -+ -+cList DynamicDeviceProbes; -+ -+cList cDynamicDeviceProbe::commandQueue; -+ -+void cDynamicDeviceProbe::QueueDynamicDeviceCommand(eDynamicDeviceProbeCommand Cmd, const char *DevPath) -+{ -+ if (DevPath) -+ commandQueue.Add(new cDynamicDeviceProbeItem(Cmd, new cString(DevPath))); -+} -+ -+cDynamicDeviceProbe::cDynamicDeviceProbe(void) -+{ -+ DynamicDeviceProbes.Add(this); -+} -+ -+cDynamicDeviceProbe::~cDynamicDeviceProbe() -+{ -+ DynamicDeviceProbes.Del(this, false); -+} -diff --git a/device.h b/device.h -index e2847d8..3a8aa01 100644 ---- a/device.h -+++ b/device.h -@@ -24,6 +24,7 @@ - #include "spu.h" - #include "thread.h" - #include "tools.h" -+#include - - #define MAXDEVICES 16 // the maximum number of devices in the system - #define MAXPIDHANDLES 64 // the maximum number of different PIDs per device -@@ -169,7 +170,6 @@ private: - static int nextCardIndex; - int cardIndex; - protected: -- cDevice(void); - virtual ~cDevice(); - virtual bool Ready(void); - ///< Returns true if this device is ready. Devices with conditional -@@ -196,9 +196,6 @@ protected: - ///< A derived class must call the MakePrimaryDevice() function of its - ///< base class. - public: -- bool IsPrimaryDevice(void) const { return this == primaryDevice; } -- int CardIndex(void) const { return cardIndex; } -- ///< Returns the card index of this device (0 ... MAXDEVICES - 1). - int DeviceNumber(void) const; - ///< Returns the number of this device (0 ... numDevices). - virtual cString DeviceType(void) const; -@@ -338,6 +335,7 @@ public: - ///< Returns true if the device is currently showing any programme to - ///< the user, either through replaying or live. - -+ virtual bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd) {return false;} - // PID handle facilities - - private: -@@ -423,9 +421,6 @@ public: - ///< shall check whether the channel can be decrypted. - void SetCamSlot(cCamSlot *CamSlot); - ///< Sets the given CamSlot to be used with this device. -- cCamSlot *CamSlot(void) const { return camSlot; } -- ///< Returns the CAM slot that is currently used with this device, -- ///< or NULL if no CAM slot is in use. - - // Image Grab facilities - -@@ -581,9 +576,6 @@ private: - cTsToPes tsToPesSubtitle; - bool isPlayingVideo; - protected: -- const cPatPmtParser *PatPmtParser(void) const { return &patPmtParser; } -- ///< Returns a pointer to the patPmtParser, so that a derived device -- ///< can use the stream information from it. - virtual bool CanReplay(void) const; - ///< Returns true if this device can currently start a replay session. - virtual bool SetPlayMode(ePlayMode PlayMode); -@@ -795,6 +787,38 @@ public: - ///< Detaches all receivers from this device for this pid. - virtual void DetachAllReceivers(void); - ///< Detaches all receivers from this device. -+ -+// --- dynamite subdevice patch start --- -+ friend class cDynamicDevice; -+private: -+ static cDevice *nextParentDevice; -+ ///< Holds the parent device for the next subdevice -+ ///< so the dynamite-plugin can work with unpatched plugins -+ bool isIdle; -+protected: -+ cDevice *parentDevice; -+ cDevice *subDevice; -+ cDevice(cDevice *ParentDevice = NULL); -+ const cPatPmtParser *PatPmtParser(void) const { if (parentDevice) return parentDevice->PatPmtParser(); return &patPmtParser; } -+ ///< Returns a pointer to the patPmtParser, so that a derived device -+ ///< can use the stream information from it. -+public: -+ bool IsPrimaryDevice(void) const { if (parentDevice) return parentDevice->IsPrimaryDevice(); return this == primaryDevice; } -+ int CardIndex(void) const { if (parentDevice) return parentDevice->cardIndex; return cardIndex; } -+ ///< Returns the card index of this device (0 ... MAXDEVICES - 1). -+ cCamSlot *CamSlot(void) const { if (parentDevice) return parentDevice->CamSlot(); return camSlot; } -+ ///< Returns the CAM slot that is currently used with this device, -+ ///< or NULL if no CAM slot is in use. -+ bool IsSubDevice(void) const { return (parentDevice != NULL); } -+ bool HasSubDevice(void) const { return (subDevice != NULL); } -+ cDevice *SubDevice(void) const { return subDevice; } -+ bool IsIdle(void) const { if (parentDevice) return parentDevice->IsIdle(); return isIdle; } -+ bool SetIdle(bool Idle); -+ virtual bool SetIdleDevice(bool Idle, bool TestOnly) { return false; } -+ ///< Called by SetIdle -+ ///< if TestOnly, don't do anything, just return, if the device -+ ///< can be set to the new idle state -+ // --- dynamite subdevice patch end --- - }; - - /// Derived cDevice classes that can receive channels will have to provide -@@ -805,7 +829,14 @@ public: - /// sure the returned data points to a TS packet and automatically - /// re-synchronizes after broken packets. - --class cTSBuffer : public cThread { -+class cTSBufferBase { -+public: -+ cTSBufferBase() {} -+ virtual ~cTSBufferBase() {} -+ virtual uchar *Get(void) = 0; -+ }; -+ -+class cTSBuffer : public cTSBufferBase, public cThread { - private: - int f; - int cardIndex; -@@ -814,8 +845,51 @@ private: - virtual void Action(void); - public: - cTSBuffer(int File, int Size, int CardIndex); -- ~cTSBuffer(); -- uchar *Get(void); -+ virtual ~cTSBuffer(); -+ virtual uchar *Get(void); -+ }; -+ -+/// A plugin that want to create devices handled by the dynamite-plugin needs to create -+/// a cDynamicDeviceProbe derived object on the heap in order to have its Probe() -+/// function called, where it can actually create the appropriate device. -+/// The cDynamicDeviceProbe object must be created in the plugin's constructor, -+/// and deleted in its destructor. -+/// The "DevPath" hasn't to be a physical device or a path in the filesystem. -+/// It can be any string a plugin may react on. -+ -+#define __DYNAMIC_DEVICE_PROBE -+ -+enum eDynamicDeviceProbeCommand { ddpcAttach, ddpcDetach, ddpcService }; -+ -+class cDynamicDeviceProbe : public cListObject { -+ friend class cDynamicDevice; -+private: -+ class cDynamicDeviceProbeItem : public cListObject { -+ public: -+ eDynamicDeviceProbeCommand cmd; -+ cString *devpath; -+ cDynamicDeviceProbeItem(eDynamicDeviceProbeCommand Cmd, cString *DevPath):cmd(Cmd),devpath(DevPath) {} -+ virtual ~cDynamicDeviceProbeItem() { if (devpath) delete devpath; } -+ }; -+ static cList commandQueue; -+ ///< A list where all attach/detach commands are queued -+ ///< so they can be processed in the MainThreadHook of -+ ///< the dynamite plugin. -+public: -+ static void QueueDynamicDeviceCommand(eDynamicDeviceProbeCommand Cmd, const char *DevPath); -+ ///< Plugins which support cDynamicDeviceProbe must use this function -+ ///< to queue the devices they normally create in their Initialize method. -+ ///< These devices are created as subdevices in the Start-method of the dynamite-plugin. -+ cDynamicDeviceProbe(void); -+ virtual ~cDynamicDeviceProbe(); -+ virtual cDevice *Attach(cDevice *ParentDevice, const char *DevPath) = 0; -+ ///< Probes for a device at the given device-path like /dev/dvb/adapter0/frontend0 -+ ///< or /dev/video0 etc. and creates the appropriate -+ ///< object derived from cDevice if applicable. -+ ///< Returns the device that has been created or NULL if not. -+ ///< The dynamite-plugin will delete the device if it is detached. - }; - -+extern cList DynamicDeviceProbes; -+ - #endif //__DEVICE_H -diff --git a/dvbci.c b/dvbci.c -index 5289bbd..baa70bc 100644 ---- a/dvbci.c -+++ b/dvbci.c -@@ -10,41 +10,70 @@ - #include "dvbci.h" - #include - #include --#include "device.h" -+#include "dvbdevice.h" - - // --- cDvbCiAdapter --------------------------------------------------------- - --cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd) -+cDvbCiAdapter::cDvbCiAdapter(cDevice *Device, int Fd, int Adapter, int Frontend) - { - device = Device; - SetDescription("CI adapter on device %d", device->DeviceNumber()); - fd = Fd; -- ca_caps_t Caps; -- if (ioctl(fd, CA_GET_CAP, &Caps) == 0) { -- if ((Caps.slot_type & CA_CI_LINK) != 0) { -- int NumSlots = Caps.slot_num; -- if (NumSlots > 0) { -- for (int i = 0; i < NumSlots; i++) -- new cCamSlot(this); -- Start(); -- } -- else -- esyslog("ERROR: no CAM slots found on device %d", device->DeviceNumber()); -- } -- else -- isyslog("device %d doesn't support CI link layer interface", device->DeviceNumber()); -- } -- else -- esyslog("ERROR: can't get CA capabilities on device %d", device->DeviceNumber()); -+ adapter = Adapter; -+ frontend = Frontend; -+ idle = false; -+ GetNumCamSlots(Device, Fd, this); -+ Start(); - } - - cDvbCiAdapter::~cDvbCiAdapter() - { - Cancel(3); -+ if (device->IsSubDevice() || device->HasSubDevice()) -+ CloseCa(); -+} -+ -+bool cDvbCiAdapter::OpenCa(void) -+{ -+ if (fd >= 0) -+ return true; -+ fd = cDvbDevice::DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR); -+ return (fd >= 0); -+} -+ -+void cDvbCiAdapter::CloseCa(void) -+{ -+ if (fd < 0) -+ return; -+ close(fd); -+ fd = -1; -+} -+ -+bool cDvbCiAdapter::SetIdle(bool Idle, bool TestOnly) -+{ -+ if ((adapter < 0) || (frontend < 0)) -+ return false; -+ if (TestOnly || (idle == Idle)) -+ return true; -+ if (Idle) -+ CloseCa(); -+ else -+ OpenCa(); -+ idle = Idle; -+ return true; -+} -+ -+cTSBufferBase *cDvbCiAdapter::GetTSBuffer(int FdDvr) -+{ -+ if (device) -+ return new cTSBuffer(FdDvr, MEGABYTE(5), device->CardIndex() + 1); -+ return NULL; - } - - int cDvbCiAdapter::Read(uint8_t *Buffer, int MaxLength) - { -+ if (idle || (fd < 0)) -+ return 0; - if (Buffer && MaxLength > 0) { - struct pollfd pfd[1]; - pfd[0].fd = fd; -@@ -61,6 +90,8 @@ int cDvbCiAdapter::Read(uint8_t *Buffer, int MaxLength) - - void cDvbCiAdapter::Write(const uint8_t *Buffer, int Length) - { -+ if (idle || (fd < 0)) -+ return; - if (Buffer && Length > 0) { - if (safe_write(fd, Buffer, Length) != Length) - esyslog("ERROR: can't write to CI adapter on device %d: %m", device->DeviceNumber()); -@@ -69,6 +100,8 @@ void cDvbCiAdapter::Write(const uint8_t *Buffer, int Length) - - bool cDvbCiAdapter::Reset(int Slot) - { -+ if (idle || (fd < 0)) -+ return false; - if (ioctl(fd, CA_RESET, 1 << Slot) != -1) - return true; - else -@@ -78,6 +111,8 @@ bool cDvbCiAdapter::Reset(int Slot) - - eModuleStatus cDvbCiAdapter::ModuleStatus(int Slot) - { -+ if (idle || (fd < 0)) -+ return msNone; - ca_slot_info_t sinfo; - sinfo.num = Slot; - if (ioctl(fd, CA_GET_SLOT_INFO, &sinfo) != -1) { -@@ -99,10 +134,60 @@ bool cDvbCiAdapter::Assign(cDevice *Device, bool Query) - return true; - } - --cDvbCiAdapter *cDvbCiAdapter::CreateCiAdapter(cDevice *Device, int Fd) -+int cDvbCiAdapter::GetNumCamSlots(cDevice *Device, int Fd, cCiAdapter *CiAdapter) - { -- // TODO check whether a CI is actually present? -- if (Device) -- return new cDvbCiAdapter(Device, Fd); -- return NULL; -+ int NumSlots = -1; -+ if (Fd >= 0) { -+ ca_caps_t Caps; -+ if (ioctl(Fd, CA_GET_CAP, &Caps) == 0) { -+ if ((Caps.slot_type & CA_CI_LINK) != 0) { -+ NumSlots = Caps.slot_num; -+ if (NumSlots == 0) -+ esyslog("ERROR: no CAM slots found on device %d", Device->DeviceNumber()); -+ else if (CiAdapter != NULL) { -+ for (int i = 0; i < NumSlots; i++) -+ new cCamSlot(CiAdapter); -+ } -+ else -+ return NumSlots; -+ } -+ else -+ isyslog("device %d doesn't support CI link layer interface", Device->DeviceNumber()); -+ } -+ else -+ esyslog("ERROR: can't get CA capabilities on device %d", Device->DeviceNumber()); -+ } -+ return -1; -+} -+ -+cDvbCiAdapter *cDvbCiAdapter::CreateCiAdapter(cDevice *Device, int Fd, int Adapter, int Frontend) -+{ -+ // don't create a ci-adapter if it's not useable -+ if (Device && (Fd >= 0) && (GetNumCamSlots(Device, Fd, NULL) > 0)) -+ return new cDvbCiAdapter(Device, Fd, Adapter, Frontend); -+ -+ if (Fd >= 0) -+ close(Fd); -+ -+ // try to find an external ci-adapter -+ for (cDvbCiAdapterProbe *cp = DvbCiAdapterProbes.First(); cp; cp = DvbCiAdapterProbes.Next(cp)) { -+ cDvbCiAdapter *ca = cp->Probe(Device); -+ if (ca) -+ return ca; -+ } -+ return NULL; -+} -+ -+// --- cDvbCiAdapterProbe ------------------------------------------------------- -+ -+cList DvbCiAdapterProbes; -+ -+cDvbCiAdapterProbe::cDvbCiAdapterProbe(void) -+{ -+ DvbCiAdapterProbes.Add(this); -+} -+ -+cDvbCiAdapterProbe::~cDvbCiAdapterProbe() -+{ -+ DvbCiAdapterProbes.Del(this, false); - } -diff --git a/dvbci.h b/dvbci.h -index adbe40d..d908b2f 100644 ---- a/dvbci.h -+++ b/dvbci.h -@@ -16,16 +16,48 @@ class cDvbCiAdapter : public cCiAdapter { - private: - cDevice *device; - int fd; -+ int adapter; -+ int frontend; -+ bool idle; -+ -+ bool OpenCa(void); -+ void CloseCa(void); - protected: - virtual int Read(uint8_t *Buffer, int MaxLength); - virtual void Write(const uint8_t *Buffer, int Length); - virtual bool Reset(int Slot); - virtual eModuleStatus ModuleStatus(int Slot); - virtual bool Assign(cDevice *Device, bool Query = false); -- cDvbCiAdapter(cDevice *Device, int Fd); -+ cDvbCiAdapter(cDevice *Device, int Fd, int Adapter = -1, int Frontend = -1); - public: - virtual ~cDvbCiAdapter(); -- static cDvbCiAdapter *CreateCiAdapter(cDevice *Device, int Fd); -+ virtual cTSBufferBase *GetTSBuffer(int FdDvr); -+ static int GetNumCamSlots(cDevice *Device, int Fd, cCiAdapter *CiAdapter); -+ ///< Tests if the CA device is usable for vdr. -+ ///< If CiAdapter is not NULL it will create the CamSlots for the given ci-adapter. -+ virtual bool SetIdle(bool Idle, bool TestOnly); -+ virtual bool IsIdle(void) const { return idle; } -+ static cDvbCiAdapter *CreateCiAdapter(cDevice *Device, int Fd, int Adapter = -1, int Frontend = -1); -+ }; -+ -+// A plugin that implements an external DVB ci-adapter derived from cDvbCiAdapter needs to create -+// a cDvbCiAdapterProbe derived object on the heap in order to have its Probe() -+// function called, where it can actually create the appropriate ci-adapter. -+// The cDvbCiAdapterProbe object must be created in the plugin's constructor, -+// and deleted in its destructor. -+// Every plugin has to track its own list of already used device nodes. -+// The Probes are always called if the base cDvbCiAdapter can't create a ci-adapter on its own. -+ -+class cDvbCiAdapterProbe : public cListObject { -+public: -+ cDvbCiAdapterProbe(void); -+ virtual ~cDvbCiAdapterProbe(); -+ virtual cDvbCiAdapter *Probe(cDevice *Device) = 0; -+ ///< Probes for a DVB ci-adapter for the given Device and creates the appropriate -+ ///< object derived from cDvbCiAdapter if applicable. -+ ///< Returns NULL if no adapter has been created. - }; - -+extern cList DvbCiAdapterProbes; -+ - #endif //__DVBCI_H -diff --git a/dvbdevice.c b/dvbdevice.c -index 43e8544..49b5f61 100644 ---- a/dvbdevice.c -+++ b/dvbdevice.c -@@ -287,9 +287,10 @@ class cDvbTuner : public cThread { - private: - static cMutex bondMutex; - enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked }; -+ bool SendDiseqc; - int frontendType; - const cDvbDevice *device; -- int fd_frontend; -+ mutable int fd_frontend; - int adapter, frontend; - uint32_t subsystemId; - int tuneTimeout; -@@ -300,7 +301,7 @@ private: - const cScr *scr; - bool lnbPowerTurnedOn; - eTunerStatus tunerStatus; -- cMutex mutex; -+ mutable cMutex mutex; - cCondVar locked; - cCondVar newSet; - cDvbTuner *bondedTuner; -@@ -308,11 +309,16 @@ private: - bool SetFrontendType(const cChannel *Channel); - cString GetBondingParams(const cChannel *Channel = NULL) const; - void ClearEventQueue(void) const; -+ dvb_diseqc_master_cmd diseqc_cmd; - bool GetFrontendStatus(fe_status_t &Status) const; - void ExecuteDiseqc(const cDiseqc *Diseqc, unsigned int *Frequency); - void ResetToneAndVoltage(void); - bool SetFrontend(void); - virtual void Action(void); -+ -+ mutable bool isIdle; -+ bool OpenFrontend(void) const; -+ bool CloseFrontend(void); - public: - cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend); - virtual ~cDvbTuner(); -@@ -325,9 +331,13 @@ public: - uint32_t SubsystemId(void) const { return subsystemId; } - bool IsTunedTo(const cChannel *Channel) const; - void SetChannel(const cChannel *Channel); -+ bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd); - bool Locked(int TimeoutMs = 0); - int GetSignalStrength(void) const; - int GetSignalQuality(void) const; -+ -+ bool SetIdle(bool Idle); -+ bool IsIdle(void) const { return isIdle; } - }; - - cMutex cDvbTuner::bondMutex; -@@ -337,6 +347,7 @@ cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int - frontendType = SYS_UNDEFINED; - device = Device; - fd_frontend = Fd_Frontend; -+ SendDiseqc=false; - adapter = Adapter; - frontend = Frontend; - subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend); -@@ -349,6 +360,7 @@ cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int - tunerStatus = tsIdle; - bondedTuner = NULL; - bondedMaster = false; -+ isIdle = false; - SetDescription("tuner on frontend %d/%d", adapter, frontend); - Start(); - } -@@ -366,6 +378,8 @@ cDvbTuner::~cDvbTuner() - ExecuteDiseqc(lastDiseqc, &Frequency); - } - */ -+ if (device && device->IsSubDevice()) -+ CloseFrontend(); - } - - bool cDvbTuner::Bond(cDvbTuner *Tuner) -@@ -510,6 +524,8 @@ bool cDvbTuner::Locked(int TimeoutMs) - - void cDvbTuner::ClearEventQueue(void) const - { -+ if (!OpenFrontend()) -+ return; - cPoller Poller(fd_frontend); - if (Poller.Poll(TUNER_POLL_TIMEOUT)) { - dvb_frontend_event Event; -@@ -710,8 +726,28 @@ static int GetRequiredDeliverySystem(const cChannel *Channel, const cDvbTranspon - return ds; - } - -+bool cDvbTuner::SendDiseqcCmd(dvb_diseqc_master_cmd cmd) -+{ -+ cMutexLock MutexLock(&mutex); -+ cDvbTransponderParameters dtp(channel.Parameters()); -+ -+ // Determine the required frontend type: -+ int frontendType = GetRequiredDeliverySystem(&channel, &dtp); -+ -+ if ((frontendType!=SYS_DVBS2 && frontendType!=SYS_DVBS) || SendDiseqc) -+ return false; -+ if (!OpenFrontend()) -+ return false; -+ diseqc_cmd=cmd; -+ SendDiseqc=true; -+ newSet.Broadcast(); -+ return true; -+} -+ - bool cDvbTuner::SetFrontend(void) - { -+ if (!OpenFrontend()) -+ return false; - #define MAXFRONTENDCMDS 16 - #define SETCMD(c, d) { Frontend[CmdSeq.num].cmd = (c);\ - Frontend[CmdSeq.num].u.data = (d);\ -@@ -857,10 +893,16 @@ void cDvbTuner::Action(void) - bool LostLock = false; - fe_status_t Status = (fe_status_t)0; - while (Running()) { -- fe_status_t NewStatus; -- if (GetFrontendStatus(NewStatus)) -- Status = NewStatus; -+ if (!isIdle) { -+ fe_status_t NewStatus; -+ if (GetFrontendStatus(NewStatus)) -+ Status = NewStatus; -+ } - cMutexLock MutexLock(&mutex); -+ if (SendDiseqc) { -+ CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &diseqc_cmd)); -+ SendDiseqc=false; -+ } - int WaitTime = 1000; - switch (tunerStatus) { - case tsIdle: -@@ -912,6 +954,40 @@ void cDvbTuner::Action(void) - } - } - -+bool cDvbTuner::SetIdle(bool Idle) -+{ -+ if (isIdle == Idle) -+ return true; -+ isIdle = Idle; -+ if (Idle) -+ return CloseFrontend(); -+ return OpenFrontend(); -+} -+ -+bool cDvbTuner::OpenFrontend(void) const -+{ -+ if (fd_frontend >= 0) -+ return true; -+ cMutexLock MutexLock(&mutex); -+ fd_frontend = cDvbDevice::DvbOpen(DEV_DVB_FRONTEND, adapter, frontend, O_RDWR | O_NONBLOCK); -+ if (fd_frontend < 0) -+ return false; -+ isIdle = false; -+ return true; -+} -+ -+bool cDvbTuner::CloseFrontend(void) -+{ -+ if (fd_frontend < 0) -+ return true; -+ cMutexLock MutexLock(&mutex); -+ tunerStatus = tsIdle; -+ newSet.Broadcast(); -+ close(fd_frontend); -+ fd_frontend = -1; -+ return true; -+} -+ - // --- cDvbSourceParam ------------------------------------------------------- - - class cDvbSourceParam : public cSourceParam { -@@ -997,7 +1073,8 @@ const char *DeliverySystemNames[] = { - NULL - }; - --cDvbDevice::cDvbDevice(int Adapter, int Frontend) -+cDvbDevice::cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice) -+:cDevice(ParentDevice) - { - adapter = Adapter; - frontend = Frontend; -@@ -1015,9 +1092,8 @@ cDvbDevice::cDvbDevice(int Adapter, int Frontend) - - // Common Interface: - -- fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR); -- if (fd_ca >= 0) -- ciAdapter = cDvbCiAdapter::CreateCiAdapter(this, fd_ca); -+ int fd_ca = DvbOpen(DEV_DVB_CA, adapter, frontend, O_RDWR); -+ ciAdapter = cDvbCiAdapter::CreateCiAdapter(parentDevice ? parentDevice : this, fd_ca, adapter, frontend); - - // The DVR device (will be opened and closed as needed): - -@@ -1245,7 +1321,11 @@ bool cDvbDevice::BondDevices(const char *Bondings) - if (d >= 0) { - int ErrorDevice = 0; - if (cDevice *Device1 = cDevice::GetDevice(i)) { -+ if (Device1->HasSubDevice()) -+ Device1 = Device1->SubDevice(); - if (cDevice *Device2 = cDevice::GetDevice(d)) { -+ if (Device2->HasSubDevice()) -+ Device2 = Device2->SubDevice(); - if (cDvbDevice *DvbDevice1 = dynamic_cast(Device1)) { - if (cDvbDevice *DvbDevice2 = dynamic_cast(Device2)) { - if (!DvbDevice1->Bond(DvbDevice2)) -@@ -1279,7 +1359,10 @@ bool cDvbDevice::BondDevices(const char *Bondings) - void cDvbDevice::UnBondDevices(void) - { - for (int i = 0; i < cDevice::NumDevices(); i++) { -- if (cDvbDevice *d = dynamic_cast(cDevice::GetDevice(i))) -+ cDevice *dev = cDevice::GetDevice(i); -+ if (dev && dev->HasSubDevice()) -+ dev = dev->SubDevice(); -+ if (cDvbDevice *d = dynamic_cast(dev)) - d->UnBond(); - } - } -@@ -1333,6 +1416,26 @@ bool cDvbDevice::BondingOk(const cChannel *Channel, bool ConsiderOccupied) const - return true; - } - -+bool cDvbDevice::SetIdleDevice(bool Idle, bool TestOnly) -+{ -+ if (TestOnly) { -+ if (ciAdapter) -+ return ciAdapter->SetIdle(Idle, true); -+ return true; -+ } -+ if (!dvbTuner->SetIdle(Idle)) -+ return false; -+ if (ciAdapter && !ciAdapter->SetIdle(Idle, false)) { -+ dvbTuner->SetIdle(!Idle); -+ return false; -+ } -+ if (Idle) -+ StopSectionHandler(); -+ else -+ StartSectionHandler(); -+ return true; -+} -+ - bool cDvbDevice::HasCi(void) - { - return ciAdapter; -@@ -1499,7 +1602,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne - - bool cDvbDevice::ProvidesEIT(void) const - { -- return dvbTuner != NULL; -+ return !IsIdle() && (dvbTuner != NULL) && !dvbTuner->IsIdle() && ((ciAdapter == NULL) || !ciAdapter->IsIdle()); - } - - int cDvbDevice::NumProvidedSystems(void) const -@@ -1544,6 +1647,11 @@ bool cDvbDevice::HasLock(int TimeoutMs) - return dvbTuner ? dvbTuner->Locked(TimeoutMs) : false; - } - -+bool cDvbDevice::SendDiseqcCmd(dvb_diseqc_master_cmd cmd) -+{ -+ return dvbTuner->SendDiseqcCmd(cmd); -+} -+ - void cDvbDevice::SetTransferModeForDolbyDigital(int Mode) - { - setTransferModeForDolbyDigital = Mode; -@@ -1553,8 +1661,12 @@ bool cDvbDevice::OpenDvr(void) - { - CloseDvr(); - fd_dvr = DvbOpen(DEV_DVB_DVR, adapter, frontend, O_RDONLY | O_NONBLOCK, true); -- if (fd_dvr >= 0) -- tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(5), CardIndex() + 1); -+ if (fd_dvr >= 0) { -+ if (ciAdapter) -+ tsBuffer = ciAdapter->GetTSBuffer(fd_dvr); -+ if (tsBuffer == NULL) -+ tsBuffer = new cTSBuffer(fd_dvr, MEGABYTE(5), CardIndex() + 1); -+ } - return fd_dvr >= 0; - } - -diff --git a/dvbdevice.h b/dvbdevice.h -index 7da9c56..6cd4abf 100644 ---- a/dvbdevice.h -+++ b/dvbdevice.h -@@ -107,7 +107,7 @@ class cDvbTuner; - /// The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API. - - class cDvbDevice : public cDevice { --protected: -+public: - static cString DvbName(const char *Name, int Adapter, int Frontend); - static int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError = false); - private: -@@ -127,19 +127,20 @@ private: - int deliverySystems[MAXDELIVERYSYSTEMS]; - int numDeliverySystems; - int numModulations; -- int fd_dvr, fd_ca; -+ int fd_dvr; - static cMutex bondMutex; - cDvbDevice *bondedDevice; - mutable bool needsDetachBondedReceivers; - bool QueryDeliverySystems(int fd_frontend); - public: -- cDvbDevice(int Adapter, int Frontend); -+ cDvbDevice(int Adapter, int Frontend, cDevice *ParentDevice = NULL); - virtual ~cDvbDevice(); - int Adapter(void) const { return adapter; } - int Frontend(void) const { return frontend; } - virtual bool Ready(void); - virtual cString DeviceType(void) const; - virtual cString DeviceName(void) const; -+ virtual bool SetIdleDevice(bool Idle, bool TestOnly); - static bool BondDevices(const char *Bondings); - ///< Bonds the devices as defined in the given Bondings string. - ///< A bonding is a sequence of device numbers (starting at 1), -@@ -193,6 +194,7 @@ protected: - virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); - public: - virtual bool HasLock(int TimeoutMs = 0); -+ virtual bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd); - - // PID handle facilities - -@@ -225,7 +227,7 @@ public: - // Receiver facilities - - private: -- cTSBuffer *tsBuffer; -+ cTSBufferBase *tsBuffer; - protected: - virtual bool OpenDvr(void); - virtual void CloseDvr(void); diff --git a/packages/3rdparty/multimedia/vdr/patches/vdr-44_rotor.patch b/packages/3rdparty/multimedia/vdr/patches/vdr-44_rotor.patch new file mode 100644 index 0000000000..4e7031dc21 --- /dev/null +++ b/packages/3rdparty/multimedia/vdr/patches/vdr-44_rotor.patch @@ -0,0 +1,133 @@ +Description: This patch is needed for the rotor plugin. +Author: Thomas Bergwinkl +Origin: extracted from the rotor plugin 0.1.4-vdr1.5 + +Index: b/device.h +=================================================================== +--- a/device.h ++++ b/device.h +@@ -24,6 +24,8 @@ + #include "spu.h" + #include "thread.h" + #include "tools.h" ++#include ++#include + + #define MAXDEVICES 16 // the maximum number of devices in the system + #define MAXPIDHANDLES 64 // the maximum number of different PIDs per device +@@ -337,6 +339,7 @@ + virtual bool HasProgramme(void) const; + ///< Returns true if the device is currently showing any programme to + ///< the user, either through replaying or live. ++ virtual bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd) {return false;} + + // PID handle facilities + +Index: b/dvbdevice.c +=================================================================== +--- a/dvbdevice.c ++++ b/dvbdevice.c +@@ -283,6 +283,7 @@ + private: + static cMutex bondMutex; + enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked }; ++ bool SendDiseqc; + int frontendType; + const cDvbDevice *device; + int fd_frontend; +@@ -299,6 +300,7 @@ + cMutex mutex; + cCondVar locked; + cCondVar newSet; ++ dvb_diseqc_master_cmd diseqc_cmd; + cDvbTuner *bondedTuner; + bool bondedMaster; + bool SetFrontendType(const cChannel *Channel); +@@ -325,12 +327,16 @@ + bool Locked(int TimeoutMs = 0); + int GetSignalStrength(void) const; + int GetSignalQuality(void) const; ++ bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd); ++private: ++ int GetCurrentDeliverySystem(void); + }; + + cMutex cDvbTuner::bondMutex; + + cDvbTuner::cDvbTuner(const cDvbDevice *Device, int Fd_Frontend, int Adapter, int Frontend) + { ++ SendDiseqc = false; + frontendType = SYS_UNDEFINED; + device = Device; + fd_frontend = Fd_Frontend; +@@ -653,6 +659,35 @@ + return -1; + } + ++int cDvbTuner::GetCurrentDeliverySystem() ++{ ++ dtv_property Frontend[1]; ++ memset(&Frontend, 0, sizeof(Frontend)); ++ dtv_properties CmdSeq; ++ memset(&CmdSeq, 0, sizeof(CmdSeq)); ++ CmdSeq.props = Frontend; ++ Frontend[0].cmd = DTV_DELIVERY_SYSTEM; ++ Frontend[0].u.data = 0; ++ if (ioctl(fd_frontend, FE_GET_PROPERTY, &CmdSeq) < 0) { ++ esyslog("ERROR: frontend %d/%d: %m", adapter, frontend); ++ return SYS_UNDEFINED; ++ } ++ return Frontend[0].u.data; ++} ++ ++bool cDvbTuner::SendDiseqcCmd(dvb_diseqc_master_cmd cmd) ++{ ++ cMutexLock MutexLock(&mutex); ++ int frontendType = GetCurrentDeliverySystem(); ++ if ((frontendType != SYS_DVBS && frontendType != SYS_DVBS2) || SendDiseqc) ++ return false; ++ diseqc_cmd=cmd; ++ SendDiseqc=true; ++ newSet.Broadcast(); ++ return true; ++} ++ ++ + static unsigned int FrequencyToHz(unsigned int f) + { + while (f && f < 1000000) +@@ -874,6 +909,10 @@ + if (GetFrontendStatus(NewStatus)) + Status = NewStatus; + cMutexLock MutexLock(&mutex); ++ if (SendDiseqc) { ++ CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &diseqc_cmd)); ++ SendDiseqc=false; ++ } + int WaitTime = 1000; + switch (tunerStatus) { + case tsIdle: +@@ -1571,6 +1610,11 @@ + return dvbTuner ? dvbTuner->Locked(TimeoutMs) : false; + } + ++bool cDvbDevice::SendDiseqcCmd(dvb_diseqc_master_cmd cmd) ++{ ++ return dvbTuner->SendDiseqcCmd(cmd); ++} ++ + void cDvbDevice::SetTransferModeForDolbyDigital(int Mode) + { + setTransferModeForDolbyDigital = Mode; +Index: b/dvbdevice.h +=================================================================== +--- a/dvbdevice.h ++++ b/dvbdevice.h +@@ -196,6 +196,7 @@ + virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); + public: + virtual bool HasLock(int TimeoutMs = 0) const; ++ virtual bool SendDiseqcCmd(dvb_diseqc_master_cmd cmd); + + // PID handle facilities +