summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorFrank Schmirler <vdr@schmirler.de>2013-11-01 15:33:19 +0100
committerFrank Schmirler <vdr@schmirler.de>2013-11-01 15:33:19 +0100
commit1d4a7e06b4e5cc5a1f115d9d361c2c7b60699ff9 (patch)
tree967c4816a6c04429c682310857a3bee6fa5391ae /server
parent458a21a62ad445ce79a55a8bb03b66c2ba280747 (diff)
downloadvdr-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.c27
-rw-r--r--server/connection.h8
-rw-r--r--server/connectionHTTP.c3
-rw-r--r--server/connectionIGMP.c5
-rw-r--r--server/connectionVTP.c7
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);