From 525edc1ccf5aab98601af5639eb8f2f75ee9e799 Mon Sep 17 00:00:00 2001 From: Frank Schmirler Date: Tue, 29 Jan 2013 00:02:17 +0100 Subject: [PATCH] Implemented multi-device support for streamdev client (closes #1207) --- HISTORY | 1 + README | 46 +++++++-------- client/device.c | 120 +++++++++++++++++--------------------- client/device.h | 12 ++-- client/filter.c | 13 +++-- client/filter.h | 4 +- client/po/de_DE.po | 6 +- client/po/es_ES.po | 6 +- client/po/fi_FI.po | 6 +- client/po/fr_FR.po | 6 +- client/po/it_IT.po | 8 +-- client/po/lt_LT.po | 6 +- client/po/ru_RU.po | 6 +- client/po/sk_SK.po | 6 +- client/setup.c | 14 ++--- client/setup.h | 7 ++- client/socket.c | 12 +++- client/socket.h | 4 +- client/streamdev-client.c | 19 +++--- client/streamdev-client.h | 8 ++- 20 files changed, 154 insertions(+), 156 deletions(-) diff --git a/HISTORY b/HISTORY index 7020f82..7b1a796 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,7 @@ VDR Plugin 'streamdev' Revision History --------------------------------------- +- Implemented multi-device support for streamdev client (suggested by johns) - Basic support for HTTP streaming of recordings - Close writer when streamer is finished - Don't abort VTP connection if filter stream is broken diff --git a/README b/README index e19b765..1505535 100644 --- a/README +++ b/README @@ -376,29 +376,26 @@ type "127001" on your remote. If you want to enter "192.168.1.12", type "192168112". The parameters "Remote IP" and "Remote Port" in the client's setup specify the -address of the remote VDR-to-VDR server to connect to. Activate the client by -setting "Start Client" to yes. It is disabled by default, because it wouldn't -make much sense to start the client without specifying a server anyway. The -client is activated after you push the OK button, so there's no need to restart -VDR. Deactivation on-the-fly is not possible, so in order to deactivate the -client, you will have to restart VDR. However requests to switch channels will -be refused by streamdev-client once it has been deactivated. All other settings -can be changed without restarting VDR. - -The client will try to connect to the server (in case it isn't yet) whenever -a remote channel is requested. Just activate the client and switch to a -channel that's not available by local devices. If anything goes wrong with the -connection between the two, you will see it in the logfile instantly. If you -now switch the client to a channel which isn't covered by it's own local -devices, it will ask the server for it. If the server can (currently) receive -that channel, the client will show it until you switch again, or until the -server needs that card (if no other is free) for a recording on a different -transponder. +address of the remote VDR-to-VDR server to connect to. The client is disabled +by default, because it wouldn't make much sense to start the client without +specifying a server anyway. Activate the client by setting "Simultaneously used +Devices" to at least 1. Streamdev-client will allocate as many VDR devices as +you configure here. Each of these devices opens one connection to the server +and becomes associated with one of the server's devices (typically a DVB card) +on demand. Only the needed PIDs are transferred, and additional PIDs can be turned on during an active transfer. This makes it possible to switch languages, receive -additional channels (for recording on the client) and use plugins that use -receivers themselves (like osdteletext). +additional channels on the same transponder and use plugins that use receivers +themselves (like osdteletext). + +So for viewing live TV a single device is sufficient. But if the client needs +to receive channels from different transponders simultaneously (e.g. for PiP or +client side recordings) a second device becomes necessary. + +To allocate additional devices, just increase the number and push the OK button. +There's no need to restart VDR. Deleting VDR devices on-the-fly is not possible. +However requests to switch channels will be refused by redundant devices. The default timeout of 2 seconds for network operations should be sufficient in most cases. Increase "Timeout" if you get frequent timeout errors in the log. @@ -435,12 +432,9 @@ higher, live TV will use your DVB card until a recordings kicks in. Then the recording will take the DVB card and live TV will be shifted to streamdev (you'll notice a short interruption of live TV). -Note that streamdev-client acts similar to a DVB card. It is possible to receive -multiple channels simultaneously, but only from the same transponder. Just add -additional instances of streamdev-client and you will be able to receive as many -transponders at a time. The same trick allows a client to receive channels from -different servers. To create an additional instance, copy the streamdev-client -binary to a different name (e.g. streamdev-client2): +To receive channels from multiple servers, create additional instances of the +streamdev-client plugin. Simply copy (don't link!) the binary to a different +name (e.g. streamdev-client2): cd VDRPLUGINLIBDIR cp libvdr-streamdev-client.so.1.X.X libvdr-streamdev-client2.so.1.X.X diff --git a/client/device.c b/client/device.c index c42924b..ef16690 100644 --- a/client/device.c +++ b/client/device.c @@ -29,30 +29,28 @@ using namespace std; #define VIDEOBUFSIZE MEGABYTE(3) -cStreamdevDevice *cStreamdevDevice::m_Device = NULL; const cChannel *cStreamdevDevice::m_DenyChannel = NULL; cStreamdevDevice::cStreamdevDevice(void) { - m_Channel = NULL; - m_TSBuffer = NULL; + m_Disabled = false; + m_ClientSocket = new cClientSocket(); + m_Channel = NULL; + m_TSBuffer = NULL; - m_Filters = new cStreamdevFilters; + m_Filters = new cStreamdevFilters(m_ClientSocket); StartSectionHandler(); isyslog("streamdev-client: got device number %d", CardIndex() + 1); - m_Device = this; m_Pids = 0; - m_Priority = -100; } cStreamdevDevice::~cStreamdevDevice() { Dprintf("Device gets destructed\n"); Lock(); - m_Device = NULL; m_Filters->SetConnection(-1); - ClientSocket.Quit(); - ClientSocket.Reset(); + m_ClientSocket->Quit(); + m_ClientSocket->Reset(); Unlock(); Cancel(3); @@ -60,6 +58,7 @@ cStreamdevDevice::~cStreamdevDevice() { StopSectionHandler(); DELETENULL(m_Filters); DELETENULL(m_TSBuffer); + delete m_ClientSocket; } #if APIVERSNUM >= 10700 @@ -84,7 +83,7 @@ bool cStreamdevDevice::IsTunedToTransponder(const cChannel *Channel) const bool cStreamdevDevice::IsTunedToTransponder(const cChannel *Channel) #endif { - return ClientSocket.DataSocket(siLive) != NULL && + return m_ClientSocket->DataSocket(siLive) != NULL && m_Channel != NULL && Channel->Transponder() == m_Channel->Transponder(); } @@ -92,14 +91,14 @@ bool cStreamdevDevice::IsTunedToTransponder(const cChannel *Channel) bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const { #if APIVERSNUM >= 10725 - bool prio = Priority == IDLEPRIORITY || Priority >= this->Priority(); + bool prio = Priority == IDLEPRIORITY || Priority >= m_ClientSocket->Priority(); #else - bool prio = Priority < 0 || Priority > this->Priority(); + bool prio = Priority < 0 || Priority > m_ClientSocket->Priority(); #endif bool res = prio; bool ndr = false; - if (!StreamdevClientSetup.StartClient || Channel == m_DenyChannel) + if (m_Disabled || Channel == m_DenyChannel) return false; Dprintf("ProvidesChannel, Channel=%s, Prio=%d\n", Channel->Name(), Priority); @@ -131,7 +130,7 @@ bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority, } else if (prio) { if (Priority == LIVEPRIORITY) { - if (ClientSocket.ServerVersion() >= 100) { + if (m_ClientSocket->ServerVersion() >= 100) { Priority = StreamdevClientSetup.LivePriority; UpdatePriority(true); } @@ -141,10 +140,10 @@ bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority, } } - res = ClientSocket.ProvidesChannel(Channel, Priority); + res = m_ClientSocket->ProvidesChannel(Channel, Priority); ndr = Receiving(); - if (ClientSocket.ServerVersion() >= 100) + if (m_ClientSocket->ServerVersion() >= 100) UpdatePriority(false); } @@ -175,9 +174,9 @@ bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel, m_Channel = Channel; // Old servers delete cStreamdevLiveStreamer in ABRT. // Delete it now or it will happen after we tuned to new channel - if (ClientSocket.ServerVersion() < 100) + if (m_ClientSocket->ServerVersion() < 100) CloseDvr(); - res = ClientSocket.SetChannelDevice(m_Channel); + res = m_ClientSocket->SetChannelDevice(m_Channel); } Dprintf("setchanneldevice res=%d\n", res); return res; @@ -189,7 +188,7 @@ bool cStreamdevDevice::SetPid(cPidHandle *Handle, int Type, bool On) { bool res = true; if (Handle->pid && (On || !Handle->used)) { - res = ClientSocket.SetPid(Handle->pid, On); + res = m_ClientSocket->SetPid(Handle->pid, On); m_Pids += (!res) ? 0 : On ? 1 : -1; if (m_Pids < 0) @@ -203,8 +202,8 @@ bool cStreamdevDevice::OpenDvr(void) { LOCK_THREAD; CloseDvr(); - if (ClientSocket.CreateDataConnection(siLive)) { - m_TSBuffer = new cTSBuffer(*ClientSocket.DataSocket(siLive), MEGABYTE(2), CardIndex() + 1); + if (m_ClientSocket->CreateDataConnection(siLive)) { + m_TSBuffer = new cTSBuffer(*m_ClientSocket->DataSocket(siLive), MEGABYTE(2), CardIndex() + 1); } else { esyslog("cStreamdevDevice::OpenDvr(): DVR connection FAILED"); @@ -217,26 +216,26 @@ void cStreamdevDevice::CloseDvr(void) { Dprintf("CloseDvr\n"); LOCK_THREAD; - ClientSocket.CloseDvr(); + m_ClientSocket->CloseDvr(); DELETENULL(m_TSBuffer); } bool cStreamdevDevice::GetTSPacket(uchar *&Data) { - if (m_TSBuffer && m_Device) { + if (m_TSBuffer) { Data = m_TSBuffer->Get(); #if 1 // TODO: this should be fixed in vdr cTSBuffer // simple disconnect detection static int m_TSFails = 0; if (!Data) { LOCK_THREAD; - if(!ClientSocket.DataSocket(siLive)) { + if(!m_ClientSocket->DataSocket(siLive)) { return false; // triggers CloseDvr() + OpenDvr() in cDevice } - cPoller Poller(*ClientSocket.DataSocket(siLive)); + cPoller Poller(*m_ClientSocket->DataSocket(siLive)); errno = 0; if (Poller.Poll() && !errno) { char tmp[1]; - if (recv(*ClientSocket.DataSocket(siLive), tmp, 1, MSG_PEEK) == 0 && !errno) { + if (recv(*m_ClientSocket->DataSocket(siLive), tmp, 1, MSG_PEEK) == 0 && !errno) { esyslog("cStreamDevice::GetTSPacket: GetChecked: NOTHING (%d)", m_TSFails); m_TSFails++; if (m_TSFails > 10) { @@ -264,61 +263,50 @@ int cStreamdevDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) { return -1; - if (!ClientSocket.DataSocket(siLiveFilter)) { - if (ClientSocket.CreateDataConnection(siLiveFilter)) { - m_Filters->SetConnection(*ClientSocket.DataSocket(siLiveFilter)); + if (!m_ClientSocket->DataSocket(siLiveFilter)) { + if (m_ClientSocket->CreateDataConnection(siLiveFilter)) { + m_Filters->SetConnection(*m_ClientSocket->DataSocket(siLiveFilter)); } else { isyslog("cStreamdevDevice::OpenFilter: connect failed: %m"); return -1; } } - if (ClientSocket.SetFilter(Pid, Tid, Mask, true)) + if (m_ClientSocket->SetFilter(Pid, Tid, Mask, true)) return m_Filters->OpenFilter(Pid, Tid, Mask); return -1; } -bool cStreamdevDevice::Init(void) { - if (m_Device == NULL && StreamdevClientSetup.StartClient) - new cStreamdevDevice; +bool cStreamdevDevice::ReInit(bool Disable) { + LOCK_THREAD; + m_Disabled = Disable; + m_Filters->SetConnection(-1); + m_Pids = 0; + m_ClientSocket->Quit(); + m_ClientSocket->Reset(); + //DELETENULL(m_TSBuffer); return true; } -bool cStreamdevDevice::ReInit(void) { - if(m_Device) { - m_Device->Lock(); - m_Device->m_Filters->SetConnection(-1); - m_Device->m_Pids = 0; - } - ClientSocket.Quit(); - ClientSocket.Reset(); - if (m_Device != NULL) { - //DELETENULL(m_Device->m_TSBuffer); - m_Device->Unlock(); - } - return StreamdevClientSetup.StartClient ? Init() : true; -} - -void cStreamdevDevice::UpdatePriority(bool SwitchingChannels) { - if (m_Device) { - m_Device->Lock(); - if (ClientSocket.SupportsPrio() && ClientSocket.DataSocket(siLive)) { - int Priority = m_Device->Priority(); +void cStreamdevDevice::UpdatePriority(bool SwitchingChannels) const { + if (!m_Disabled) { + //LOCK_THREAD; + const_cast(this)->Lock(); + if (m_ClientSocket->SupportsPrio() && m_ClientSocket->DataSocket(siLive)) { + int Priority = this->Priority(); // override TRANSFERPRIORITY (-1) with live TV priority from setup - if (m_Device == cDevice::ActualDevice() && Priority == TRANSFERPRIORITY) { - Priority = StreamdevClientSetup.LivePriority; + if (this == cDevice::ActualDevice() && m_ClientSocket->Priority() == TRANSFERPRIORITY) { + int Priority = StreamdevClientSetup.LivePriority; // temporarily lower priority if (SwitchingChannels) Priority--; - if (Priority < 0 && ClientSocket.ServerVersion() < 100) + if (Priority < 0 && m_ClientSocket->ServerVersion() < 100) Priority = 0; - } - if (m_Device->m_Priority != Priority && ClientSocket.SetPriority(Priority)) - m_Device->m_Priority = Priority; + m_ClientSocket->SetPriority(Priority); } - m_Device->Unlock(); + const_cast(this)->Unlock(); } } @@ -330,8 +318,8 @@ cString cStreamdevDevice::DeviceType(void) const { static int dev = -1; static cString devType("STRDev"); int d = -1; - if (ClientSocket.DataSocket(siLive) != NULL) - ClientSocket.GetSignal(NULL, NULL, &d); + if (m_ClientSocket->DataSocket(siLive) != NULL) + m_ClientSocket->GetSignal(NULL, NULL, &d); if (d != dev) { dev = d; devType = d < 0 ? "STRDev" : *cString::sprintf("STRD%2d", d); @@ -341,15 +329,15 @@ cString cStreamdevDevice::DeviceType(void) const { int cStreamdevDevice::SignalStrength(void) const { int strength = -1; - if (ClientSocket.DataSocket(siLive) != NULL) - ClientSocket.GetSignal(&strength, NULL, NULL); + if (m_ClientSocket->DataSocket(siLive) != NULL) + m_ClientSocket->GetSignal(&strength, NULL, NULL); return strength; } int cStreamdevDevice::SignalQuality(void) const { int quality = -1; - if (ClientSocket.DataSocket(siLive) != NULL) - ClientSocket.GetSignal(NULL, &quality, NULL); + if (m_ClientSocket->DataSocket(siLive) != NULL) + m_ClientSocket->GetSignal(NULL, &quality, NULL); return quality; } diff --git a/client/device.h b/client/device.h index 7096ad0..71e42ed 100644 --- a/client/device.h +++ b/client/device.h @@ -17,13 +17,13 @@ class cTBString; class cStreamdevDevice: public cDevice { private: + bool m_Disabled; + cClientSocket *m_ClientSocket; const cChannel *m_Channel; cTSBuffer *m_TSBuffer; cStreamdevFilters *m_Filters; int m_Pids; - int m_Priority; - static cStreamdevDevice *m_Device; static const cChannel *m_DenyChannel; protected: @@ -67,12 +67,10 @@ public: virtual int SignalStrength(void) const; virtual int SignalQuality(void) const; - static void UpdatePriority(bool SwitchingChannels = false); + bool ReInit(bool Disable); + void UpdatePriority(bool SwitchingChannels = false) const; + bool SuspendServer() { return m_ClientSocket->SuspendServer(); } static void DenyChannel(const cChannel *Channel) { m_DenyChannel = Channel; } - static bool Init(void); - static bool ReInit(void); - - static cStreamdevDevice *GetDevice(void) { return m_Device; } }; #endif // VDR_STREAMDEV_DEVICE_H diff --git a/client/filter.c b/client/filter.c index c187e05..8606770 100644 --- a/client/filter.c +++ b/client/filter.c @@ -144,8 +144,9 @@ bool cStreamdevFilter::IsClosed(void) { // --- cStreamdevFilters ----------------------------------------------------- -cStreamdevFilters::cStreamdevFilters(void): +cStreamdevFilters::cStreamdevFilters(cClientSocket *ClientSocket): cThread("streamdev-client: sections assembler") { + m_ClientSocket = ClientSocket; m_TSBuffer = NULL; } @@ -173,7 +174,7 @@ void cStreamdevFilters::CarbageCollect(void) { if (errno == ECONNREFUSED || errno == ECONNRESET || errno == EPIPE) { - ClientSocket.SetFilter(fi->Pid(), fi->Tid(), fi->Mask(), false); + m_ClientSocket->SetFilter(fi->Pid(), fi->Tid(), fi->Mask(), false); Dprintf("cStreamdevFilters::CarbageCollector: filter closed: Pid %4d, Tid %3d, Mask %2x (%d filters left)", (int)fi->Pid(), (int)fi->Tid(), fi->Mask(), Count()-1); @@ -200,7 +201,7 @@ bool cStreamdevFilters::ReActivateFilters(void) bool res = true; CarbageCollect(); for (cStreamdevFilter *fi = First(); fi; fi = Next(fi)) { - res = ClientSocket.SetFilter(fi->Pid(), fi->Tid(), fi->Mask(), true) && res; + res = m_ClientSocket->SetFilter(fi->Pid(), fi->Tid(), fi->Mask(), true) && res; Dprintf("ReActivateFilters(%d, %d, %d) -> %s", fi->Pid(), fi->Tid(), fi->Mask(), res ? "Ok" :"FAIL"); } return res; @@ -251,7 +252,7 @@ void cStreamdevFilters::Action(void) { Dprintf("FATAL ERROR: %m\n"); esyslog("streamdev-client: couldn't send section packet: %m"); } - ClientSocket.SetFilter(f->Pid(), f->Tid(), f->Mask(), false); + m_ClientSocket->SetFilter(f->Pid(), f->Tid(), f->Mask(), false); Del(f); // Filter was closed. // - need to check remaining filters for another match @@ -261,7 +262,7 @@ void cStreamdevFilters::Action(void) { } else { #if 1 // TODO: this should be fixed in vdr cTSBuffer // Check disconnection - int fd = *ClientSocket.DataSocket(siLiveFilter); + int fd = *m_ClientSocket->DataSocket(siLiveFilter); if(fd < 0) break; cPoller Poller(fd); @@ -273,7 +274,7 @@ void cStreamdevFilters::Action(void) { ++fails; if (fails >= 10) { esyslog("cStreamdevFilters::Action(): stream disconnected ?"); - ClientSocket.CloseDataConnection(siLiveFilter); + m_ClientSocket->CloseDataConnection(siLiveFilter); break; } } else { diff --git a/client/filter.h b/client/filter.h index 889006a..a096248 100644 --- a/client/filter.h +++ b/client/filter.h @@ -11,9 +11,11 @@ class cTSBuffer; class cStreamdevFilter; +class cClientSocket; class cStreamdevFilters: public cList, public cThread { private: + cClientSocket *m_ClientSocket; cTSBuffer *m_TSBuffer; protected: @@ -23,7 +25,7 @@ protected: bool ReActivateFilters(void); public: - cStreamdevFilters(void); + cStreamdevFilters(cClientSocket *ClientSocket); virtual ~cStreamdevFilters(); void SetConnection(int Handle); diff --git a/client/po/de_DE.po b/client/po/de_DE.po index 2b817ef..f347fe9 100644 --- a/client/po/de_DE.po +++ b/client/po/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-20 23:46+0100\n" "PO-Revision-Date: 2008-03-30 02:11+0200\n" "Last-Translator: Frank Schmirler \n" "Language-Team: German \n" @@ -31,8 +31,8 @@ msgstr "Konnte Server nicht pausieren!" msgid "Hide Mainmenu Entry" msgstr "Hauptmenüeintrag verstecken" -msgid "Start Client" -msgstr "Client starten" +msgid "Simultaneously used Devices" +msgstr "Gleichzeitig genutzte DVB-Karten" msgid "Remote IP" msgstr "IP der Gegenseite" diff --git a/client/po/es_ES.po b/client/po/es_ES.po index b512e0f..5182453 100644 --- a/client/po/es_ES.po +++ b/client/po/es_ES.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: 2010-06-19 03:58+0100\n" "Last-Translator: Javier Bradineras \n" "Language-Team: Spanish \n" @@ -31,8 +31,8 @@ msgstr "Imposible suspender el servidor!" msgid "Hide Mainmenu Entry" msgstr "Ocultar entrada en menú principal" -msgid "Start Client" -msgstr "Iniciar Cliente" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "Indicar IP del Servidor" diff --git a/client/po/fi_FI.po b/client/po/fi_FI.po index e356147..2416506 100644 --- a/client/po/fi_FI.po +++ b/client/po/fi_FI.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: 2008-03-30 02:11+0200\n" "Last-Translator: Rolf Ahrenberg\n" "Language-Team: Finnish \n" @@ -31,8 +31,8 @@ msgstr "Palvelinta ei onnistuttu pysäyttämään!" msgid "Hide Mainmenu Entry" msgstr "Piilota valinta päävalikosta" -msgid "Start Client" -msgstr "Käynnistä VDR-asiakas" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "Etäkoneen IP-osoite" diff --git a/client/po/fr_FR.po b/client/po/fr_FR.po index 81e228b..7d938f0 100644 --- a/client/po/fr_FR.po +++ b/client/po/fr_FR.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: 2008-03-30 02:11+0200\n" "Last-Translator: micky979 \n" "Language-Team: French \n" @@ -31,8 +31,8 @@ msgstr "Impossible de suspendre le serveur!" msgid "Hide Mainmenu Entry" msgstr "Masquer dans le menu principal" -msgid "Start Client" -msgstr "Démarrage du client" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "Adresse IP du serveur" diff --git a/client/po/it_IT.po b/client/po/it_IT.po index 5961107..c311507 100644 --- a/client/po/it_IT.po +++ b/client/po/it_IT.po @@ -9,14 +9,14 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-06-13 08:50+0200\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: 2012-06-10 20:34+0100\n" "Last-Translator: Diego Pierotto \n" "Language-Team: Italian \n" +"Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -"Language: it\n" msgid "VTP Streaming Client" msgstr "Client trasmissione VTP" @@ -33,8 +33,8 @@ msgstr "Impossibile sospendere il server!" msgid "Hide Mainmenu Entry" msgstr "Nascondi voce menu principale" -msgid "Start Client" -msgstr "Avvia Client" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "Indirizzo IP del Server" diff --git a/client/po/lt_LT.po b/client/po/lt_LT.po index a8f7412..409c267 100644 --- a/client/po/lt_LT.po +++ b/client/po/lt_LT.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: 2009-11-26 21:57+0200\n" "Last-Translator: Valdemaras Pipiras \n" "Language-Team: Lithuanian \n" @@ -31,8 +31,8 @@ msgstr "Negali sustabdyti serverio!" msgid "Hide Mainmenu Entry" msgstr "PaslÄ—pti pagrindinio meniu įraÅ¡Ä…" -msgid "Start Client" -msgstr "Paleisti klientÄ…" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "Nuotolinis IP adresas" diff --git a/client/po/ru_RU.po b/client/po/ru_RU.po index c6528b1..8f5a9b2 100644 --- a/client/po/ru_RU.po +++ b/client/po/ru_RU.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev 0.5.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: 2008-06-26 15:36+0100\n" "Last-Translator: Oleg Roitburd \n" "Language-Team: Russian \n" @@ -31,8 +31,8 @@ msgstr " msgid "Hide Mainmenu Entry" msgstr "ÁßàïâÐâì Ò ÓÛÐÒÝÞÜ ÜÕÝî" -msgid "Start Client" -msgstr "ÁâÐàâ ÚÛØÕÝâÐ" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "ÃÔÐÛÕÝÝëÙ IP" diff --git a/client/po/sk_SK.po b/client/po/sk_SK.po index 54a9419..0037e27 100644 --- a/client/po/sk_SK.po +++ b/client/po/sk_SK.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: streamdev_SK\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2012-03-03 23:57+0100\n" +"POT-Creation-Date: 2013-01-28 22:16+0100\n" "PO-Revision-Date: \n" "Last-Translator: Milan Hrala \n" "Language-Team: Slovak \n" @@ -33,8 +33,8 @@ msgstr "Nepodarilo sa pozastavi msgid "Hide Mainmenu Entry" msgstr "Schova» polo¾ku v hlavnom menu" -msgid "Start Client" -msgstr "Spusti» Klienta" +msgid "Simultaneously used Devices" +msgstr "" msgid "Remote IP" msgstr "Vzdialená IP" diff --git a/client/setup.c b/client/setup.c index 0fc9e9f..691ab35 100644 --- a/client/setup.c +++ b/client/setup.c @@ -5,7 +5,7 @@ #include #include "client/setup.h" -#include "client/device.h" +#include "client/streamdev-client.h" #ifndef MINPRIORITY #define MINPRIORITY -MAXPRIORITY @@ -50,11 +50,12 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) { return true; } -cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) { +cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(cPluginStreamdevClient *Plugin) { + m_Plugin = Plugin; m_NewSetup = StreamdevClientSetup; Add(new cMenuEditBoolItem(tr("Hide Mainmenu Entry"), &m_NewSetup.HideMenuEntry)); - Add(new cMenuEditBoolItem(tr("Start Client"), &m_NewSetup.StartClient)); + Add(new cMenuEditIntItem (tr("Simultaneously used Devices"), &m_NewSetup.StartClient, 0, STREAMDEV_MAXDEVICES)); Add(new cMenuEditIpItem (tr("Remote IP"), m_NewSetup.RemoteIp)); Add(new cMenuEditIntItem (tr("Remote Port"), &m_NewSetup.RemotePort, 0, 65535)); Add(new cMenuEditIntItem (tr("Timeout (s)"), &m_NewSetup.Timeout, 1, 15)); @@ -74,11 +75,6 @@ cStreamdevClientMenuSetupPage::~cStreamdevClientMenuSetupPage() { } void cStreamdevClientMenuSetupPage::Store(void) { - if (m_NewSetup.StartClient != StreamdevClientSetup.StartClient) { - if (m_NewSetup.StartClient) - cStreamdevDevice::Init(); - } - SetupStore("StartClient", m_NewSetup.StartClient); if (strcmp(m_NewSetup.RemoteIp, "") == 0) SetupStore("RemoteIp", "-none-"); @@ -97,6 +93,6 @@ void cStreamdevClientMenuSetupPage::Store(void) { StreamdevClientSetup = m_NewSetup; - cStreamdevDevice::ReInit(); + m_Plugin->Initialize(); } diff --git a/client/setup.h b/client/setup.h index 7bcf889..5401271 100644 --- a/client/setup.h +++ b/client/setup.h @@ -28,15 +28,18 @@ struct cStreamdevClientSetup { extern cStreamdevClientSetup StreamdevClientSetup; +class cPluginStreamdevClient; + class cStreamdevClientMenuSetupPage: public cMenuSetupPage { private: - cStreamdevClientSetup m_NewSetup; + cPluginStreamdevClient *m_Plugin; + cStreamdevClientSetup m_NewSetup; protected: virtual void Store(void); public: - cStreamdevClientMenuSetupPage(void); + cStreamdevClientMenuSetupPage(cPluginStreamdevClient *Plugin); virtual ~cStreamdevClientMenuSetupPage(); }; diff --git a/client/socket.c b/client/socket.c index 19a761a..c0a6d1f 100644 --- a/client/socket.c +++ b/client/socket.c @@ -18,12 +18,11 @@ #include "client/socket.h" #include "common.h" -cClientSocket ClientSocket; - cClientSocket::cClientSocket(void) { memset(m_DataSockets, 0, sizeof(cTBSocket*) * si_Count); m_ServerVersion = 0; + m_Priority = -100; m_Prio = false; m_Abort = false; m_LastSignalUpdate = 0; @@ -284,12 +283,19 @@ bool cClientSocket::SetChannelDevice(const cChannel *Channel) { } bool cClientSocket::SetPriority(int Priority) { + if (Priority == m_Priority) + return true; + if (!CheckConnection()) return false; CMD_LOCK; std::string command = (std::string)"PRIO " + (const char*)itoa(Priority); - return Command(command, 220); + if (!Command(command, 220)) + return false; + + m_Priority = Priority; + return true; } bool cClientSocket::GetSignal(int *SignalStrength, int *SignalQuality, int *Dev) { diff --git a/client/socket.h b/client/socket.h index 69d45d6..69876ce 100644 --- a/client/socket.h +++ b/client/socket.h @@ -23,6 +23,7 @@ private: char m_Buffer[BUFSIZ + 1]; // various uses unsigned int m_ServerVersion; bool m_Prio; // server supports command PRIO + int m_Priority; // current device priority bool m_Abort; // quit command pending time_t m_LastSignalUpdate; @@ -55,6 +56,7 @@ public: bool SetChannelDevice(const cChannel *Channel); bool SupportsPrio() { return m_Prio; } unsigned int ServerVersion() { return m_ServerVersion; } + int Priority() const { return m_Priority; } bool SetPriority(int Priority); bool SetPid(int Pid, bool On); bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On); @@ -66,6 +68,4 @@ public: cTBSocket *DataSocket(eSocketId Id) const; }; -extern class cClientSocket ClientSocket; - #endif // VDR_STREAMDEV_CLIENT_CONNECTION_H diff --git a/client/streamdev-client.c b/client/streamdev-client.c index 088837f..4036eca 100644 --- a/client/streamdev-client.c +++ b/client/streamdev-client.c @@ -16,7 +16,7 @@ const char *cPluginStreamdevClient::DESCRIPTION = trNOOP("VTP Streaming Client"); -cPluginStreamdevClient::cPluginStreamdevClient(void) { +cPluginStreamdevClient::cPluginStreamdevClient(void): m_Devices() { } cPluginStreamdevClient::~cPluginStreamdevClient() { @@ -26,9 +26,13 @@ const char *cPluginStreamdevClient::Description(void) { return tr(DESCRIPTION); } -bool cPluginStreamdevClient::Start(void) { - I18nRegister(PLUGIN_NAME_I18N); - cStreamdevDevice::Init(); +bool cPluginStreamdevClient::Initialize(void) { + for (int i = 0; i < STREAMDEV_MAXDEVICES; i++) { + if (m_Devices[i]) + m_Devices[i]->ReInit(i >= StreamdevClientSetup.StartClient); + else if (i < StreamdevClientSetup.StartClient) + m_Devices[i] = new cStreamdevDevice(); + } return true; } @@ -37,7 +41,7 @@ const char *cPluginStreamdevClient::MainMenuEntry(void) { } cOsdObject *cPluginStreamdevClient::MainMenuAction(void) { - if (ClientSocket.SuspendServer()) + if (StreamdevClientSetup.StartClient && m_Devices[0]->SuspendServer()) Skins.Message(mtInfo, tr("Server is suspended")); else Skins.Message(mtError, tr("Couldn't suspend Server!")); @@ -45,7 +49,7 @@ cOsdObject *cPluginStreamdevClient::MainMenuAction(void) { } cMenuSetupPage *cPluginStreamdevClient::SetupMenu(void) { - return new cStreamdevClientMenuSetupPage; + return new cStreamdevClientMenuSetupPage(this); } bool cPluginStreamdevClient::SetupParse(const char *Name, const char *Value) { @@ -61,7 +65,8 @@ bool cPluginStreamdevClient::Service(const char *Id, void *Data) { } void cPluginStreamdevClient::MainThreadHook(void) { - cStreamdevDevice::UpdatePriority(); + for (int i = 0; i < StreamdevClientSetup.StartClient; i++) + m_Devices[i]->UpdatePriority(); } VDRPLUGINCREATOR(cPluginStreamdevClient); // Don't touch this! diff --git a/client/streamdev-client.h b/client/streamdev-client.h index 77d8af9..65b3582 100644 --- a/client/streamdev-client.h +++ b/client/streamdev-client.h @@ -9,16 +9,20 @@ #include +#define STREAMDEV_MAXDEVICES 8 +class cStreamdevDevice; + class cPluginStreamdevClient : public cPlugin { private: - static const char *DESCRIPTION; + static const char *DESCRIPTION; + cStreamdevDevice *m_Devices[STREAMDEV_MAXDEVICES]; public: cPluginStreamdevClient(void); virtual ~cPluginStreamdevClient(); virtual const char *Version(void) { return VERSION; } virtual const char *Description(void); - virtual bool Start(void); + virtual bool Initialize(void); virtual const char *MainMenuEntry(void); virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void);