diff options
author | Frank Schmirler <vdr@schmirler.de> | 2013-11-01 15:33:19 +0100 |
---|---|---|
committer | Frank Schmirler <vdr@schmirler.de> | 2013-11-01 15:33:19 +0100 |
commit | 1d4a7e06b4e5cc5a1f115d9d361c2c7b60699ff9 (patch) | |
tree | 967c4816a6c04429c682310857a3bee6fa5391ae /server | |
parent | 458a21a62ad445ce79a55a8bb03b66c2ba280747 (diff) | |
download | vdr-plugin-streamdev-1d4a7e06b4e5cc5a1f115d9d361c2c7b60699ff9.tar.gz vdr-plugin-streamdev-1d4a7e06b4e5cc5a1f115d9d361c2c7b60699ff9.tar.bz2 |
Set device occupied when streamdev switches away LiveTV on the server, to
reduce the risk that the VDR main loop immediately switches back, resulting
in a black screen on the client (reported by hummel99)
Diffstat (limited to 'server')
-rw-r--r-- | server/connection.c | 27 | ||||
-rw-r--r-- | server/connection.h | 8 | ||||
-rw-r--r-- | server/connectionHTTP.c | 3 | ||||
-rw-r--r-- | server/connectionIGMP.c | 5 | ||||
-rw-r--r-- | server/connectionVTP.c | 7 |
5 files changed, 33 insertions, 17 deletions
diff --git a/server/connection.c b/server/connection.c index 9c7ae31..e0e7f88 100644 --- a/server/connection.c +++ b/server/connection.c @@ -14,6 +14,11 @@ #include <stdarg.h> #include <errno.h> +// device occupied timeout to prevent VDR main loop to immediately switch back +// when streamdev switched the live TV channel. +// Note that there is still a gap between the GetDevice() and SetOccupied() +// calls where the VDR main loop could strike +#define STREAMDEVTUNETIMEOUT 5 cServerConnection::cServerConnection(const char *Protocol, int Type): cTBSocket(Type), @@ -23,6 +28,7 @@ cServerConnection::cServerConnection(const char *Protocol, int Type): m_ReadBytes(0), m_WriteBytes(0), m_WriteIndex(0), + m_OccupiedDev(NULL), m_SwitchTo(NULL) { } @@ -204,7 +210,7 @@ bool cServerConnection::UsedByLiveTV(cDevice *device) (device->IsPrimaryDevice() && device->HasDecoder() && !device->Replaying()); } -cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority) +cDevice *cServerConnection::SwitchDevice(const cChannel *Channel, int Priority) { // turn off the streams of this connection Detach(); @@ -216,8 +222,22 @@ cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority) dsyslog("streamdev: GetDevice failed for channel %d (%s) at priority %d (PrimaryDevice=%d, ActualDevice=%d)", Channel->Number(), Channel->Name(), Priority, cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex()); } else if (!device->IsTunedToTransponder(Channel) && UsedByLiveTV(device)) { - // switched away live TV - m_SwitchTo = Channel; + // make sure VDR main loop doesn't switch back + device->SetOccupied(STREAMDEVTUNETIMEOUT); + if (device->SwitchChannel(Channel, false)) { + // switched away live TV + m_OccupiedDev = device; + m_SwitchTo = Channel; + } + else { + dsyslog("streamdev: SwitchChannel (live) failed for channel %d (%s) at priority %d (PrimaryDevice=%d, ActualDevice=%d, device=%d)", Channel->Number(), Channel->Name(), Priority, cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex(), device->CardIndex()); + device->SetOccupied(0); + device = NULL; + } + } + else if (!device->SwitchChannel(Channel, false)) { + dsyslog("streamdev: SwitchChannel failed for channel %d (%s) at priority %d (PrimaryDevice=%d, ActualDevice=%d, device=%d)", Channel->Number(), Channel->Name(), Priority, cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex(), device->CardIndex()); + device = NULL; } return device; } @@ -240,6 +260,7 @@ void cServerConnection::MainThreadHook() Channels.SwitchTo(m_SwitchTo->Number()); Skins.Message(mtInfo, tr("Streaming active")); } + m_OccupiedDev->SetOccupied(0); m_SwitchTo = NULL; } } diff --git a/server/connection.h b/server/connection.h index ba1f7bb..e7fb21b 100644 --- a/server/connection.h +++ b/server/connection.h @@ -34,6 +34,8 @@ private: uint m_WriteBytes; uint m_WriteIndex; + /* Set to occupied device when live TV was interrupted */ + cDevice *m_OccupiedDev; /* Set to this connection's current channel when live TV was interrupted */ const cChannel *m_SwitchTo; @@ -106,10 +108,8 @@ public: channel. This call has no side effects. */ static cDevice *CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice = NULL); - /* Will retrieve an unused device for transmitting data. Receivers have - already been attached from the device if necessary. Use the returned - cDevice in a following call to StartTransfer */ - cDevice *GetDevice(const cChannel *Channel, int Priority); + /* Find a suitable device and tune it to the requested channel. */ + cDevice *SwitchDevice(const cChannel *Channel, int Priority); /* Test if a call to GetDevice would return a usable device. */ bool ProvidesChannel(const cChannel *Channel, int Priority); diff --git a/server/connectionHTTP.c b/server/connectionHTTP.c index e00083e..ef8b6ed 100644 --- a/server/connectionHTTP.c +++ b/server/connectionHTTP.c @@ -177,9 +177,8 @@ bool cConnectionHTTP::ProcessRequest(void) else if (m_Channel != NULL) { cDevice *device = NULL; if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority)) - device = GetDevice(m_Channel, StreamdevServerSetup.HTTPPriority); + device = SwitchDevice(m_Channel, StreamdevServerSetup.HTTPPriority); if (device != NULL) { - device->SwitchChannel(m_Channel, false); cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.HTTPPriority, this); m_Streamer = liveStreamer; if (liveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL)) { diff --git a/server/connectionIGMP.c b/server/connectionIGMP.c index 1f8f3d8..ab80a6a 100644 --- a/server/connectionIGMP.c +++ b/server/connectionIGMP.c @@ -44,9 +44,8 @@ void cConnectionIGMP::Welcome() { cDevice *device = NULL; if (ProvidesChannel(m_Channel, StreamdevServerSetup.IGMPPriority)) - device = GetDevice(m_Channel, StreamdevServerSetup.IGMPPriority); + device = SwitchDevice(m_Channel, StreamdevServerSetup.IGMPPriority); if (device != NULL) { - device->SwitchChannel(m_Channel, false); m_LiveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.IGMPPriority, this); if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType)) { m_LiveStreamer->SetDevice(device); @@ -61,7 +60,7 @@ void cConnectionIGMP::Welcome() } } else - esyslog("streamdev-server IGMP: GetDevice failed"); + esyslog("streamdev-server IGMP: SwitchDevice failed"); } bool cConnectionIGMP::Close() diff --git a/server/connectionVTP.c b/server/connectionVTP.c index b3be57e..087d02d 100644 --- a/server/connectionVTP.c +++ b/server/connectionVTP.c @@ -1118,11 +1118,8 @@ bool cConnectionVTP::CmdTUNE(char *Opts) if (!ProvidesChannel(chan, prio)) return Respond(560, "Channel not available (ProvidesChannel)"); } - if ((dev = GetDevice(chan, prio)) == NULL) - return Respond(560, "Channel not available (GetDevice)"); - - if (!dev->SwitchChannel(chan, false)) - return Respond(560, "Channel not available (SwitchChannel)"); + if ((dev = SwitchDevice(chan, prio)) == NULL) + return Respond(560, "Channel not available (SwitchDevice)"); delete m_LiveStreamer; m_LiveStreamer = new cStreamdevLiveStreamer(prio, this); |