summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorFrank Schmirler <vdr@schmirler.de>2011-03-07 21:37:08 +0100
committerFrank Schmirler <vdr@schmirler.de>2011-03-07 23:04:18 +0100
commitc06970123cd68bd1b2f2695326596430d236f230 (patch)
tree3f4a4d933a4e095abe5b9d1a68b58a8bf5475a0b /server
parentee7929bd39101f877ee731c96c457b5e38565b37 (diff)
downloadvdr-plugin-streamdev-c06970123cd68bd1b2f2695326596430d236f230.tar.gz
vdr-plugin-streamdev-c06970123cd68bd1b2f2695326596430d236f230.tar.bz2
Live TV must be switched in VDR main thread (fixes #568).
Diffstat (limited to 'server')
-rw-r--r--server/connection.c85
-rw-r--r--server/connection.h6
-rw-r--r--server/server.c13
-rw-r--r--server/server.h1
-rw-r--r--server/streamdev-server.c5
-rw-r--r--server/streamdev-server.h1
6 files changed, 83 insertions, 28 deletions
diff --git a/server/connection.c b/server/connection.c
index 78a023a..3bf0ad5 100644
--- a/server/connection.c
+++ b/server/connection.c
@@ -8,11 +8,60 @@
#include "common.h"
#include <vdr/tools.h>
+#include <vdr/thread.h>
#include <vdr/transfer.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
+class cSwitchLive {
+private:
+ cMutex mutex;
+ cCondWait switched;
+ cDevice *device;
+ const cChannel *channel;
+public:
+ cDevice* Switch(cDevice *Device, const cChannel *Channel);
+ void Switch(void);
+ cSwitchLive(void);
+};
+
+cSwitchLive::cSwitchLive(): device(NULL), channel(NULL)
+{
+}
+
+cDevice* cSwitchLive::Switch(cDevice *Device, const cChannel *Channel)
+{
+ mutex.Lock();
+ device = Device;
+ channel = Channel;
+ mutex.Unlock();
+ switched.Wait();
+ return device;
+}
+
+void cSwitchLive::Switch(void)
+{
+ mutex.Lock();
+ if (channel && device) {
+ cDevice::SetAvoidDevice(device);
+ if (!Channels.SwitchTo(cDevice::CurrentChannel())) {
+ if (StreamdevServerSetup.SuspendMode == smAlways) {
+ Channels.SwitchTo(channel->Number());
+ Skins.Message(mtInfo, tr("Streaming active"));
+ }
+ else {
+ esyslog("streamdev: Can't receive channel %d (%s) from device %d. Moving live TV to other device failed (PrimaryDevice=%d, ActualDevice=%d)", channel->Number(), channel->Name(), device->CardIndex(), cDevice::PrimaryDevice()->CardIndex(), cDevice::ActualDevice()->CardIndex());
+ device = NULL;
+ }
+ }
+ // make sure we don't come in here next time
+ channel = NULL;
+ switched.Signal();
+ }
+ mutex.Unlock();
+}
+
cServerConnection::cServerConnection(const char *Protocol, int Type):
cTBSocket(Type),
m_Protocol(Protocol),
@@ -22,10 +71,12 @@ cServerConnection::cServerConnection(const char *Protocol, int Type):
m_WriteBytes(0),
m_WriteIndex(0)
{
+ m_SwitchLive = new cSwitchLive();
}
cServerConnection::~cServerConnection()
{
+ delete m_SwitchLive;
}
const cChannel* cServerConnection::ChannelFromString(const char *String, int *Apid, int *Dpid) {
@@ -302,34 +353,7 @@ cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
&& UsedByLiveTV(device)) {
// now we would have to switch away live tv...let's see if live tv
// can be handled by another device
-#if VDRVERSNUM >= 10516
- cDevice::SetAvoidDevice(device);
- if (!Channels.SwitchTo(cDevice::CurrentChannel())) {
- if (StreamdevServerSetup.SuspendMode == smAlways) {
- Channels.SwitchTo(Channel->Number());
- Skins.QueueMessage(mtInfo, tr("Streaming active"));
- }
- else {
- dsyslog("streamdev: GetDevice: Live TV not suspended");
- device = NULL;
- }
- }
-#else
- const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel());
- cDevice *newdev = current ? CheckDevice(current, 0, true, device) : NULL;
- if (newdev) {
- dsyslog("streamdev: GetDevice: Trying to move live TV to device %d", newdev->CardIndex());
- newdev->SwitchChannel(current, true);
- }
- else if (StreamdevServerSetup.SuspendMode == smAlways) {
- Channels.SwitchTo(Channel->Number());
- Skins.QueueMessage(mtInfo, tr("Streaming active"));
- }
- else {
- dsyslog("streamdev: GetDevice: Live TV not suspended");
- device = NULL;
- }
-#endif
+ device = m_SwitchLive->Switch(device, Channel);
}
if (!device) {
@@ -371,3 +395,8 @@ bool cServerConnection::ProvidesChannel(const cChannel *Channel, int Priority)
}
return device;
}
+
+void cServerConnection::MainThreadHook()
+{
+ m_SwitchLive->Switch();
+}
diff --git a/server/connection.h b/server/connection.h
index 01a070c..6cc6764 100644
--- a/server/connection.h
+++ b/server/connection.h
@@ -15,6 +15,7 @@ typedef std::pair<std::string,std::string> tStrStr;
class cChannel;
class cDevice;
+class cSwitchLive;
/* Basic capabilities of a straight text-based protocol, most functions
virtual to support more complicated protocols */
@@ -33,6 +34,8 @@ private:
uint m_WriteBytes;
uint m_WriteIndex;
+ cSwitchLive *m_SwitchLive;
+
tStrStrMap m_Headers;
/* Check if a device would be available for transfering the given
@@ -108,6 +111,9 @@ public:
/* Test if a call to GetDevice would return a usable device. */
bool ProvidesChannel(const cChannel *Channel, int Priority);
+ /* Do things which must be done in VDR's main loop */
+ void MainThreadHook();
+
virtual void Flushed(void) {}
virtual void Detach(void) = 0;
diff --git a/server/server.c b/server/server.c
index 1bdb20a..c7fa96f 100644
--- a/server/server.c
+++ b/server/server.c
@@ -121,7 +121,9 @@ void cStreamdevServer::Action(void)
cServerConnection *client = c->Accept();
if (!client)
continue;
+ Lock();
m_Clients.Add(client);
+ Unlock();
if (m_Clients.Count() > StreamdevServerSetup.MaxClients) {
esyslog("streamdev: too many clients, rejecting %s:%d",
@@ -153,17 +155,21 @@ void cStreamdevServer::Action(void)
isyslog("streamdev: closing streamdev connection to %s:%d",
s->RemoteIp().c_str(), s->RemotePort());
s->Close();
+ Lock();
m_Clients.Del(s);
+ Unlock();
}
s = next;
}
}
+ Lock();
while (m_Clients.Count() > 0) {
cServerConnection *s = m_Clients.First();
s->Close();
m_Clients.Del(s);
}
+ Unlock();
while (m_Servers.Count() > 0) {
cServerComponent *c = m_Servers.First();
@@ -171,3 +177,10 @@ void cStreamdevServer::Action(void)
m_Servers.Del(c);
}
}
+
+void cStreamdevServer::MainThreadHook(void)
+{
+ cThreadLock lock(m_Instance);
+ for (cServerConnection *s = m_Clients.First(); s; s = m_Clients.Next(s))
+ s->MainThreadHook();
+}
diff --git a/server/server.h b/server/server.h
index a44df1c..dfe9cc1 100644
--- a/server/server.h
+++ b/server/server.h
@@ -36,6 +36,7 @@ public:
static void Initialize(void);
static void Destruct(void);
static bool Active(void);
+ static void MainThreadHook(void);
};
inline bool cStreamdevServer::Active(void)
diff --git a/server/streamdev-server.c b/server/streamdev-server.c
index b444df7..f31576c 100644
--- a/server/streamdev-server.c
+++ b/server/streamdev-server.c
@@ -130,6 +130,11 @@ cOsdObject *cPluginStreamdevServer::MainMenuAction(void)
return NULL;
}
+void cPluginStreamdevServer::MainThreadHook(void)
+{
+ cStreamdevServer::MainThreadHook();
+}
+
cMenuSetupPage *cPluginStreamdevServer::SetupMenu(void)
{
return new cStreamdevServerMenuSetupPage;
diff --git a/server/streamdev-server.h b/server/streamdev-server.h
index 4083689..f1be8aa 100644
--- a/server/streamdev-server.h
+++ b/server/streamdev-server.h
@@ -26,6 +26,7 @@ public:
virtual cString Active(void);
virtual const char *MainMenuEntry(void);
virtual cOsdObject *MainMenuAction(void);
+ virtual void MainThreadHook(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
};