summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorFrank Schmirler <vdr@schmirler.de>2014-06-07 00:24:27 +0200
committerFrank Schmirler <vdr@schmirler.de>2014-06-07 00:24:27 +0200
commite5550175658b3f4617d460e9fd04b3d70de366e6 (patch)
tree8a40f4e4b7f65abf21b77d5dc77db859e70efc71 /server
parent7be0c81a81f2a9e9be56f1cac83a0ff3e3d1179a (diff)
downloadvdr-plugin-streamdev-e5550175658b3f4617d460e9fd04b3d70de366e6.tar.gz
vdr-plugin-streamdev-e5550175658b3f4617d460e9fd04b3d70de366e6.tar.bz2
Revised class responsibilities: Moved live TV related functions to livestreamer
Diffstat (limited to 'server')
-rw-r--r--server/connection.c72
-rw-r--r--server/connection.h26
-rw-r--r--server/connectionHTTP.c18
-rw-r--r--server/connectionIGMP.c15
-rw-r--r--server/connectionVTP.c22
-rw-r--r--server/livestreamer.c82
-rw-r--r--server/livestreamer.h27
-rw-r--r--server/streamdev-server.c29
-rw-r--r--server/streamdev-server.h14
9 files changed, 168 insertions, 137 deletions
diff --git a/server/connection.c b/server/connection.c
index 1cd1d21..764ca02 100644
--- a/server/connection.c
+++ b/server/connection.c
@@ -9,17 +9,10 @@
#include <vdr/tools.h>
#include <vdr/thread.h>
-#include <vdr/transfer.h>
#include <string.h>
#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),
m_Protocol(Protocol),
@@ -28,9 +21,7 @@ cServerConnection::cServerConnection(const char *Protocol, int Type):
m_ReadBytes(0),
m_WriteBytes(0),
m_WriteIndex(0),
- m_Streamer(NULL),
- m_OccupiedDev(NULL),
- m_SwitchTo(NULL)
+ m_Streamer(NULL)
{
}
@@ -206,66 +197,5 @@ bool cServerConnection::Close()
return cTBSocket::Close();
}
-bool cServerConnection::UsedByLiveTV(cDevice *device)
-{
- return device == cTransferControl::ReceiverDevice() ||
- (device->IsPrimaryDevice() && device->HasDecoder() && !device->Replaying());
-}
-
-cDevice *cServerConnection::SwitchDevice(const cChannel *Channel, int Priority)
-{
- // turn off the streams of this connection
- Detach();
-
- cDevice *device = cDevice::GetDevice(Channel, Priority, false);
- if (!device) {
- // can't switch - continue the current stream
- Attach();
- 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)) {
- // 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;
-}
-
-bool cServerConnection::ProvidesChannel(const cChannel *Channel, int Priority)
-{
- cDevice *device = cDevice::GetDevice(Channel, Priority, false, true);
- if (!device)
- dsyslog("streamdev: No device provides channel %d (%s) at priority %d", Channel->Number(), Channel->Name(), Priority);
- return device;
-}
-
-void cServerConnection::MainThreadHook()
-{
- if (m_SwitchTo)
- {
- // switched away live TV. Try previous channel on other device first
- if (!Channels.SwitchTo(cDevice::CurrentChannel())) {
- // switch to streamdev channel otherwise
- Channels.SwitchTo(m_SwitchTo->Number());
- Skins.Message(mtInfo, tr("Streaming active"));
- }
- m_OccupiedDev->SetOccupied(0);
- m_SwitchTo = NULL;
- }
-}
-
cString cServerConnection::ToText() const
{ return cString::sprintf("%s\t%s:%d", Protocol(), RemoteIp().c_str(), RemotePort()); }
diff --git a/server/connection.h b/server/connection.h
index 1c40fb6..e7379be 100644
--- a/server/connection.h
+++ b/server/connection.h
@@ -16,7 +16,6 @@ typedef std::map<std::string,std::string> tStrStrMap;
typedef std::pair<std::string,std::string> tStrStr;
class cChannel;
-class cDevice;
/* Basic capabilities of a straight text-based protocol, most functions
virtual to support more complicated protocols */
@@ -37,17 +36,8 @@ private:
cStreamdevStreamer *m_Streamer;
- /* 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;
-
tStrStrMap m_Headers;
- /* Test if device is in use as the transfer mode receiver device
- or a FF card, displaying live TV from internal tuner */
- static bool UsedByLiveTV(cDevice *device);
-
protected:
/* Will be called when a command terminated by a newline has been
received */
@@ -113,24 +103,8 @@ public:
/* Close the socket */
virtual bool Close(void);
- /* Check if a device would be available for transferring the given
- channel. This call has no side effects. */
- static cDevice *CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice = NULL);
-
- /* 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);
-
- /* Do things which must be done in VDR's main loop */
- void MainThreadHook();
-
virtual void Flushed(void) {}
- virtual void Attach(void) { if (m_Streamer != NULL) m_Streamer->Attach(); }
- virtual void Detach(void) { if (m_Streamer != NULL) m_Streamer->Detach(); }
-
/* This connections protocol name */
virtual const char* Protocol(void) const { return m_Protocol; }
diff --git a/server/connectionHTTP.c b/server/connectionHTTP.c
index 0f89a95..bcb4b58 100644
--- a/server/connectionHTTP.c
+++ b/server/connectionHTTP.c
@@ -173,14 +173,10 @@ bool cConnectionHTTP::ProcessRequest(void)
if (m_MenuList)
return Respond("%s", true, m_MenuList->HttpHeader().c_str());
else if (m_Channel != NULL) {
- cDevice *device = NULL;
- if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority))
- device = SwitchDevice(m_Channel, StreamdevServerSetup.HTTPPriority);
- if (device != NULL) {
- cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.HTTPPriority, this);
- SetStreamer(liveStreamer);
- if (liveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL)) {
- liveStreamer->SetDevice(device);
+ if (cStreamdevLiveStreamer::ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority)) {
+ cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(this, m_Channel, StreamdevServerSetup.HTTPPriority, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL);
+ if (liveStreamer->GetDevice()) {
+ SetStreamer(liveStreamer);
if (!SetDSCP())
LOG_ERROR_STR("unable to set DSCP sockopt");
if (m_StreamType == stEXT) {
@@ -194,6 +190,7 @@ bool cConnectionHTTP::ProcessRequest(void)
}
}
SetStreamer(NULL);
+ delete liveStreamer;
}
return HttpResponse(503, true);
}
@@ -233,10 +230,9 @@ bool cConnectionHTTP::ProcessRequest(void)
return Respond("%s", true, m_MenuList->HttpHeader().c_str());
}
else if (m_Channel != NULL) {
- if (ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority)) {
+ if (cStreamdevLiveStreamer::ProvidesChannel(m_Channel, StreamdevServerSetup.HTTPPriority)) {
if (m_StreamType == stEXT) {
- cStreamdevLiveStreamer *liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.HTTPPriority, this);
- liveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL);
+ cStreamdevLiveStreamer *liveStreamer = new cStreamdevLiveStreamer(this, m_Channel, IDLEPRIORITY, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL);
SetStreamer(liveStreamer);
return Respond("HTTP/1.0 200 OK");
} else if (m_StreamType == stES && (m_Apid[0] || m_Dpid[0] || ISRADIO(m_Channel))) {
diff --git a/server/connectionIGMP.c b/server/connectionIGMP.c
index b73324b..ced2209 100644
--- a/server/connectionIGMP.c
+++ b/server/connectionIGMP.c
@@ -40,22 +40,19 @@ bool cConnectionIGMP::SetChannel(cChannel *Channel, in_addr_t Dst)
void cConnectionIGMP::Welcome()
{
- cDevice *device = NULL;
- if (ProvidesChannel(m_Channel, StreamdevServerSetup.IGMPPriority))
- device = SwitchDevice(m_Channel, StreamdevServerSetup.IGMPPriority);
- if (device != NULL) {
- cStreamdevLiveStreamer * liveStreamer = new cStreamdevLiveStreamer(StreamdevServerSetup.IGMPPriority, this);
- SetStreamer(liveStreamer);
- if (liveStreamer->SetChannel(m_Channel, m_StreamType)) {
- liveStreamer->SetDevice(device);
+ if (cStreamdevLiveStreamer::ProvidesChannel(m_Channel, StreamdevServerSetup.IGMPPriority)) {
+ cStreamdevLiveStreamer * liveStreamer = new cStreamdevLiveStreamer(this, m_Channel, StreamdevServerSetup.IGMPPriority, m_StreamType);
+ if (liveStreamer->GetDevice()) {
+ SetStreamer(liveStreamer);
if (!SetDSCP())
LOG_ERROR_STR("unable to set DSCP sockopt");
Dprintf("streamer start\n");
liveStreamer->Start(this);
}
else {
- esyslog("streamdev-server IGMP: SetChannel failed");
SetStreamer(NULL);
+ delete liveStreamer;
+ esyslog("streamdev-server IGMP: SetChannel failed");
}
}
else
diff --git a/server/connectionVTP.c b/server/connectionVTP.c
index 7ea1768..802748e 100644
--- a/server/connectionVTP.c
+++ b/server/connectionVTP.c
@@ -787,12 +787,12 @@ void cConnectionVTP::Reject(void)
void cConnectionVTP::Detach(void)
{
if (m_FilterStreamer) m_FilterStreamer->Detach();
- cServerConnection::Detach();
+ if (m_LiveSocket && Streamer()) ((cStreamdevLiveStreamer *) Streamer())->Detach();
}
void cConnectionVTP::Attach(void)
{
- cServerConnection::Attach();
+ if (m_LiveSocket && Streamer()) ((cStreamdevLiveStreamer *) Streamer())->Attach();
if (m_FilterStreamer) m_FilterStreamer->Attach();
}
@@ -936,7 +936,7 @@ bool cConnectionVTP::CmdPROV(char *Opts)
LOOP_PREVENTION(chan);
- if (ProvidesChannel(chan, prio)) {
+ if (cStreamdevLiveStreamer::ProvidesChannel(chan, prio)) {
m_TuneChannel = chan;
m_TunePriority = prio;
return Respond(220, "Channel available");
@@ -945,7 +945,7 @@ bool cConnectionVTP::CmdPROV(char *Opts)
// so get our own receiver temporarily out of the way
if (m_ClientVersion == 0) {
Detach();
- bool provided = ProvidesChannel(chan, prio);
+ bool provided = cStreamdevLiveStreamer::ProvidesChannel(chan, prio);
Attach();
if (provided) {
m_TuneChannel = chan;
@@ -1117,16 +1117,18 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
if (chan != m_TuneChannel) {
isyslog("streamdev-server TUNE %s: Priority unknown - using 0", Opts);
prio = 0;
- if (!ProvidesChannel(chan, prio))
+ if (!cStreamdevLiveStreamer::ProvidesChannel(chan, prio))
return Respond(560, "Channel not available (ProvidesChannel)");
}
- if ((dev = SwitchDevice(chan, prio)) == NULL)
- return Respond(560, "Channel not available (SwitchDevice)");
- cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(prio, this);
+ cStreamdevLiveStreamer* liveStreamer = new cStreamdevLiveStreamer(this, chan, prio, m_StreamType);
+ if ((dev = liveStreamer->GetDevice()) == NULL) {
+ SetStreamer(NULL);
+ delete liveStreamer;
+ return Respond(560, "Channel not available (SwitchDevice)");
+ }
SetStreamer(liveStreamer);
- liveStreamer->SetChannel(chan, m_StreamType);
- liveStreamer->SetDevice(dev);
+
if(m_LiveSocket)
liveStreamer->Start(m_LiveSocket);
diff --git a/server/livestreamer.c b/server/livestreamer.c
index c06710a..bb21ef1 100644
--- a/server/livestreamer.c
+++ b/server/livestreamer.c
@@ -8,6 +8,7 @@
#include "remux/ts2es.h"
#include "remux/extern.h"
+#include <vdr/transfer.h>
#include <vdr/ringbuffer.h>
#include "server/livestreamer.h"
@@ -16,6 +17,12 @@
using namespace Streamdev;
+// 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
+
// --- cStreamdevLiveReceiver -------------------------------------------------
class cStreamdevLiveReceiver: public cReceiver {
@@ -328,19 +335,28 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
// --- cStreamdevLiveStreamer -------------------------------------------------
-cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority, const cServerConnection *Connection):
+cStreamdevLiveStreamer::cStreamdevLiveStreamer(const cServerConnection *Connection, const cChannel *Channel, int Priority, eStreamType StreamType, const int* Apid, const int *Dpid) :
cStreamdevStreamer("streamdev-livestreaming", Connection),
m_Priority(Priority),
m_NumPids(0),
m_StreamType(stTSPIDS),
- m_Channel(NULL),
+ m_Channel(Channel),
m_Device(NULL),
m_Receiver(NULL),
m_PatFilter(NULL),
- m_Remux(NULL)
+ m_Remux(NULL),
+ m_SwitchLive(false)
{
m_ReceiveBuffer = new cStreamdevBuffer(LIVEBUFSIZE, TS_SIZE *2, true, "streamdev-livestreamer"),
m_ReceiveBuffer->SetTimeouts(0, 100);
+ if (Priority == IDLEPRIORITY) {
+ SetChannel(Channel, StreamType, Apid, Dpid);
+ }
+ else {
+ m_Device = SwitchDevice(Channel, Priority);
+ if (m_Device)
+ SetChannel(Channel, StreamType, Apid, Dpid);
+ }
}
cStreamdevLiveStreamer::~cStreamdevLiveStreamer()
@@ -613,6 +629,66 @@ void cStreamdevLiveStreamer::Detach(void)
}
}
+bool cStreamdevLiveStreamer::UsedByLiveTV(cDevice *device)
+{
+ return device == cTransferControl::ReceiverDevice() ||
+ (device->IsPrimaryDevice() && device->HasDecoder() && !device->Replaying());
+}
+
+cDevice *cStreamdevLiveStreamer::SwitchDevice(const cChannel *Channel, int Priority)
+{
+ // turn off the streams of this connection
+ Detach();
+
+ cDevice *device = cDevice::GetDevice(Channel, Priority, false);
+ if (!device) {
+ // can't switch - continue the current stream
+ Attach();
+ 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)) {
+ // make sure VDR main loop doesn't switch back
+ device->SetOccupied(STREAMDEVTUNETIMEOUT);
+ if (device->SwitchChannel(Channel, false)) {
+ // switched away live TV
+ m_SwitchLive = true;
+ }
+ 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;
+}
+
+bool cStreamdevLiveStreamer::ProvidesChannel(const cChannel *Channel, int Priority)
+{
+ cDevice *device = cDevice::GetDevice(Channel, Priority, false, true);
+ if (!device)
+ dsyslog("streamdev: No device provides channel %d (%s) at priority %d", Channel->Number(), Channel->Name(), Priority);
+ return device;
+}
+
+void cStreamdevLiveStreamer::MainThreadHook()
+{
+ if (m_SwitchLive) {
+ // switched away live TV. Try previous channel on other device first
+ if (!Channels.SwitchTo(cDevice::CurrentChannel())) {
+ // switch to streamdev channel otherwise
+ Channels.SwitchTo(m_Channel->Number());
+ Skins.Message(mtInfo, tr("Streaming active"));
+ }
+ if (m_Device)
+ m_Device->SetOccupied(0);
+ m_SwitchLive = false;
+ }
+}
+
std::string cStreamdevLiveStreamer::Report(void)
{
std::string result;
diff --git a/server/livestreamer.h b/server/livestreamer.h
index b83bb99..4e89cf8 100644
--- a/server/livestreamer.h
+++ b/server/livestreamer.h
@@ -5,6 +5,7 @@
#include <vdr/receiver.h>
#include "server/streamer.h"
+#include "server/streamdev-server.h"
#include "common.h"
#define LIVEBUFSIZE (20000 * TS_SIZE)
@@ -17,7 +18,7 @@ class cStreamdevLiveReceiver;
// --- cStreamdevLiveStreamer -------------------------------------------------
-class cStreamdevLiveStreamer: public cStreamdevStreamer {
+class cStreamdevLiveStreamer: public cStreamdevStreamer, public cMainThreadHookSubscriber {
private:
int m_Priority;
int m_Pids[MAXRECEIVEPIDS + 1];
@@ -29,10 +30,22 @@ private:
cStreamdevBuffer *m_ReceiveBuffer;
cStreamdevPatFilter *m_PatFilter;
Streamdev::cTSRemux *m_Remux;
+ bool m_SwitchLive;
void StartReceiver(void);
bool HasPid(int Pid);
+ /* Test if device is in use as the transfer mode receiver device
+ or a FF card, displaying live TV from internal tuner */
+ static bool UsedByLiveTV(cDevice *device);
+
+ /* Find a suitable device and tune it to the requested channel. */
+ cDevice *SwitchDevice(const cChannel *Channel, int Priority);
+
+ void SetDevice(cDevice *Device) { m_Device = Device; }
+
+ bool SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid = NULL, const int* Dpid = NULL);
+
protected:
virtual uchar* GetFromReceiver(int &Count) { return m_ReceiveBuffer->Get(Count); }
virtual void DelFromReceiver(int Count) { m_ReceiveBuffer->Del(Count); }
@@ -41,13 +54,11 @@ protected:
virtual void Action(void);
public:
- cStreamdevLiveStreamer(int Priority, const cServerConnection *Connection);
+ cStreamdevLiveStreamer(const cServerConnection *Connection, const cChannel *Channel, int Priority, eStreamType StreamType, const int* Apid = NULL, const int* Dpid = NULL);
virtual ~cStreamdevLiveStreamer();
- void SetDevice(cDevice *Device) { m_Device = Device; }
bool SetPid(int Pid, bool On);
bool SetPids(int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL);
- bool SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid = NULL, const int* Dpid = NULL);
void SetPriority(int Priority);
void GetSignal(int *DevNum, int *Strength, int *Quality) const;
virtual cString ToText() const;
@@ -61,6 +72,14 @@ public:
virtual void Attach(void);
virtual void Detach(void);
+ cDevice *GetDevice() const { return m_Device; }
+
+ /* Test if a call to GetDevice would return a usable device. */
+ static bool ProvidesChannel(const cChannel *Channel, int Priority);
+
+ /* Do things which must be done in VDR's main loop */
+ void MainThreadHook();
+
// Statistical purposes:
virtual std::string Report(void);
};
diff --git a/server/streamdev-server.c b/server/streamdev-server.c
index e5c6e45..f3e62df 100644
--- a/server/streamdev-server.c
+++ b/server/streamdev-server.c
@@ -18,6 +18,29 @@
#error "VDR-1.7.25 or greater required to compile server! Use 'make client' to compile client only."
#endif
+cList<cMainThreadHookSubscriber> cMainThreadHookSubscriber::m_Subscribers;
+cMutex cMainThreadHookSubscriber::m_Mutex;
+
+const cList<cMainThreadHookSubscriber>& cMainThreadHookSubscriber::Subscribers(cMutexLock& Lock)
+{
+ Lock.Lock(&m_Mutex);
+ return m_Subscribers;
+}
+
+cMainThreadHookSubscriber::cMainThreadHookSubscriber()
+{
+ m_Mutex.Lock();
+ m_Subscribers.Add(this);
+ m_Mutex.Unlock();
+}
+
+cMainThreadHookSubscriber::~cMainThreadHookSubscriber()
+{
+ m_Mutex.Lock();
+ m_Subscribers.Del(this, false);
+ m_Mutex.Unlock();
+}
+
const char *cPluginStreamdevServer::DESCRIPTION = trNOOP("VDR Streaming Server");
cPluginStreamdevServer::cPluginStreamdevServer(void)
@@ -139,9 +162,9 @@ void cPluginStreamdevServer::MainThreadHook(void)
m_Suspend = false;
}
- cThreadLock lock;
- const cList<cServerConnection>& clients = cStreamdevServer::Clients(lock);
- for (cServerConnection *s = clients.First(); s; s = clients.Next(s))
+ cMutexLock lock;
+ const cList<cMainThreadHookSubscriber>& subs = cMainThreadHookSubscriber::Subscribers(lock);
+ for (cMainThreadHookSubscriber *s = subs.First(); s; s = subs.Next(s))
s->MainThreadHook();
}
diff --git a/server/streamdev-server.h b/server/streamdev-server.h
index a89f6c7..e149fd3 100644
--- a/server/streamdev-server.h
+++ b/server/streamdev-server.h
@@ -7,8 +7,22 @@
#include "common.h"
+#include <vdr/tools.h>
#include <vdr/plugin.h>
+class cMainThreadHookSubscriber: public cListObject {
+private:
+ static cList<cMainThreadHookSubscriber> m_Subscribers;
+ static cMutex m_Mutex;
+public:
+ static const cList<cMainThreadHookSubscriber>& Subscribers(cMutexLock& Lock);
+
+ virtual void MainThreadHook() = 0;
+
+ cMainThreadHookSubscriber();
+ virtual ~cMainThreadHookSubscriber();
+};
+
class cPluginStreamdevServer : public cPlugin {
private:
static const char *DESCRIPTION;