Support for non-cycle-free setups (e.g. where two VDRs mutually share

their DVB cards through streamdev-client/-server).
Must be enabled in streamdev-server setup. Obsoletes recursion patches.
This commit is contained in:
Frank Schmirler 2011-12-11 17:03:09 +01:00
parent 6a971b9145
commit ba7c61fb39
21 changed files with 89 additions and 182 deletions

View File

@ -1,6 +1,9 @@
VDR Plugin 'streamdev' Revision History
---------------------------------------
- support for non-cycle-free setups (e.g. where two VDRs mutually share
their DVB cards through streamdev-client/-server). Must be enabled in
streamdev-server setup. Obsoletes recursion patches.
- API change of VDR 1.7.22
- VDR 1.7.22 obsoletes cap_net_raw patch. Added cap_net_raw patch for VDR
1.7.5 - 1.7.21.

7
README
View File

@ -337,6 +337,13 @@ port where you want the server to listen for incoming connections. The server
will be activated when you push the OK button inside the setup menu, so there's
no need to restart VDR.
If both, streamdev-client and streamdev-server are installed, the additional
option "Loop prevention" will show up in the streamdev-server setup. If enabled,
streamdev-client won't be considered when streamdev-server is looking for a
device which is able to receive some channel. This is required if two or more
VDRs mutually share their DVB devices through streamdev. Otherwise you would
end up in a loop.
3.4 Usage VDR-to-VDR client:
----------------------------

View File

@ -22,6 +22,7 @@ using namespace std;
#define VIDEOBUFSIZE MEGABYTE(3)
cStreamdevDevice *cStreamdevDevice::m_Device = NULL;
const cChannel *cStreamdevDevice::m_DenyChannel = NULL;
cStreamdevDevice::cStreamdevDevice(void) {
m_Channel = NULL;
@ -91,7 +92,7 @@ bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority,
bool prio = Priority < 0 || Priority > this->Priority();
bool ndr = false;
if (!StreamdevClientSetup.StartClient)
if (!StreamdevClientSetup.StartClient || Channel == m_DenyChannel)
return false;
Dprintf("ProvidesChannel, Channel=%s, Prio=%d\n", Channel->Name(), Priority);

View File

@ -26,6 +26,7 @@ private:
bool m_DvrClosed;
static cStreamdevDevice *m_Device;
static const cChannel *m_DenyChannel;
bool OpenDvrInt(void);
void CloseDvrInt(void);
@ -70,6 +71,7 @@ public:
virtual int SignalQuality(void) const;
static void UpdatePriority(void);
static void DenyChannel(const cChannel *Channel) { m_DenyChannel = Channel; }
static bool Init(void);
static bool ReInit(void);

View File

@ -52,6 +52,14 @@ bool cPluginStreamdevClient::SetupParse(const char *Name, const char *Value) {
return StreamdevClientSetup.SetupParse(Name, Value);
}
bool cPluginStreamdevClient::Service(const char *Id, void *Data) {
if (!strcmp(Id, LOOP_PREVENTION_SERVICE)) {
cStreamdevDevice::DenyChannel((const cChannel*) Data);
return true;
}
return false;
}
void cPluginStreamdevClient::MainThreadHook(void) {
cStreamdevDevice::UpdatePriority();
}

View File

@ -23,6 +23,7 @@ public:
virtual cOsdObject *MainMenuAction(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
virtual bool Service(const char *Id, void *Data = NULL);
virtual void MainThreadHook(void);
};

View File

@ -31,6 +31,9 @@
#define MAXPARSEBUFFER KILOBYTE(16)
/* Service ID for loop prevention */
#define LOOP_PREVENTION_SERVICE "StreamdevLoopPrevention"
/* Check if a channel is a radio station. */
#define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff)

View File

@ -1,85 +0,0 @@
# If you have two or more VDRs and you like them to mutually share
# there DVB cards you might need to apply this patch first.
#
# IMPORTANT: As this patch does not only modify streamdev-server but
# also an exported method of VDR, you will need to
#
# !!!!! RECOMPILE VDR AND ALL PLUGINS !!!!!
#
# Why do I need the patch?
# --------------------------
# Before switching channels VDR will consider all of its devices to
# find the one with the least impact. This includes the device provided
# by the streamdev-client plugin. Streamdev-client will forward the
# request to its server which in turn checks all of its devices. Now if
# the server is running streamdev-client, too, the request will again
# be forwarded to its server and finally you will endup in a loop.
#
# What does the patch do?
# -----------------------
# The patch adds the additional parameter "bool DVBCardsOnly" to VDR's
# device selection method cDevice::GetDevice(...). The parameter
# defaults to false which gives you the standard behaviour of GetDevice.
# When set to true, GetDevice will use only those devices with a card
# index < MAXDVBDEVICES, so only real DVB cards will be considered.
# Other devices like streamdev-client or DVB cards provided by plugin
# (Hauppauge PVR) won't be used.
#
# Author: Frank Schmirler (http://vdr.schmirler.de)
#
--- device.h.orig 2006-11-15 12:01:34.000000000 +0100
+++ device.h 2006-11-15 12:02:15.000000000 +0100
@@ -128,7 +128,7 @@
///< Gets the device with the given Index.
///< \param Index must be in the range 0..numDevices-1.
///< \return A pointer to the device, or NULL if the Index was invalid.
- static cDevice *GetDevice(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
+ static cDevice *GetDevice(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL, bool DVBCardsOnly = false);
///< Returns a device that is able to receive the given Channel at the
///< given Priority, with the least impact on active recordings and
///< live viewing.
--- device.c.orig 2006-11-15 12:01:30.000000000 +0100
+++ device.c 2006-11-22 12:28:05.000000000 +0100
@@ -8,6 +8,7 @@
*/
#include "device.h"
+#include "dvbdevice.h"
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -278,11 +279,13 @@
return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
}
-cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers)
+cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers, bool DVBCardsOnly)
{
cDevice *d = NULL;
uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
for (int i = 0; i < numDevices; i++) {
+ if (DVBCardsOnly && device[i]->CardIndex() >= MAXDVBDEVICES)
+ continue;
bool ndr;
if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
// Put together an integer number that reflects the "impact" using
--- PLUGINS/src/streamdev/server/connection.c.orig 2006-11-15 12:10:11.000000000 +0100
+++ PLUGINS/src/streamdev/server/connection.c 2006-11-15 12:10:59.000000000 +0100
@@ -132,7 +132,7 @@
Dprintf(" * GetDevice(const cChannel*, int)\n");
Dprintf(" * -------------------------------\n");
- device = cDevice::GetDevice(Channel, Priority);
+ device = cDevice::GetDevice(Channel, Priority, NULL, true);
Dprintf(" * Found following device: %p (%d)\n", device,
device ? device->CardIndex() + 1 : 0);
@@ -150,7 +150,7 @@
const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel());
isyslog("streamdev-server: Detaching current receiver");
Detach();
- device = cDevice::GetDevice(Channel, Priority);
+ device = cDevice::GetDevice(Channel, Priority, NULL, true);
Attach();
Dprintf(" * Found following device: %p (%d)\n", device,
device ? device->CardIndex() + 1 : 0);

View File

@ -1,88 +0,0 @@
# If you have two or more VDRs and you like them to mutually share
# there DVB cards you might need to apply this patch first.
#
# This is a modified version of the patch for VDRs with BIGPATCH.
# Thanks to p_body@vdrportal.
#
# IMPORTANT: As this patch does not only modify streamdev-server but
# also an exported method of VDR, you will need to
#
# !!!!! RECOMPILE VDR AND ALL PLUGINS !!!!!
#
# Why do I need the patch?
# --------------------------
# Before switching channels VDR will consider all of its devices to
# find the one with the least impact. This includes the device provided
# by the streamdev-client plugin. Streamdev-client will forward the
# request to its server which in turn checks all of its devices. Now if
# the server is running streamdev-client, too, the request will again
# be forwarded to its server and finally you will endup in a loop.
#
# What does the patch do?
# -----------------------
# The patch adds the additional parameter "bool DVBCardsOnly" to VDR's
# device selection method cDevice::GetDevice(...). The parameter
# defaults to false which gives you the standard behaviour of GetDevice.
# When set to true, GetDevice will use only those devices with a card
# index < MAXDVBDEVICES, so only real DVB cards will be considered.
# Other devices like streamdev-client or DVB cards provided by plugin
# (Hauppauge PVR) won't be used.
#
# Author: Frank Schmirler (http://vdr.schmirler.de)
#
--- device.h.orig 2006-11-15 12:01:34.000000000 +0100
+++ device.h 2006-11-15 12:02:15.000000000 +0100
@@ -128,7 +128,7 @@
///< Gets the device with the given Index.
///< \param Index must be in the range 0..numDevices-1.
///< \return A pointer to the device, or NULL if the Index was invalid.
- static cDevice *GetDevice(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL, bool LiveView = false);
+ static cDevice *GetDevice(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL, bool LiveView = false, bool DVBCardsOnly = false);
///< Returns a device that is able to receive the given Channel at the
///< given Priority, with the least impact on active recordings and
///< live viewing.
--- device.c.orig 2006-11-15 12:01:30.000000000 +0100
+++ device.c 2006-11-22 12:28:05.000000000 +0100
@@ -8,6 +8,7 @@
*/
#include "device.h"
+#include "dvbdevice.h"
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
@@ -278,11 +279,13 @@
return (0 <= Index && Index < numDevices) ? device[Index] : NULL;
}
-cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers, bool LiveView)
+cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers, bool LiveView, bool DVBCardsOnly)
{
cDevice *d = NULL;
uint Impact = 0xFFFFFFFF; // we're looking for a device with the least impact
for (int i = 0; i < numDevices; i++) {
+ if (DVBCardsOnly && device[i]->CardIndex() >= MAXDVBDEVICES)
+ continue;
bool ndr;
if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
// Put together an integer number that reflects the "impact" using
--- PLUGINS/src/streamdev/server/connection.c.orig 2006-11-15 12:10:11.000000000 +0100
+++ PLUGINS/src/streamdev/server/connection.c 2006-11-15 12:10:59.000000000 +0100
@@ -132,7 +132,7 @@
Dprintf(" * GetDevice(const cChannel*, int)\n");
Dprintf(" * -------------------------------\n");
- device = cDevice::GetDevice(Channel, Priority);
+ device = cDevice::GetDevice(Channel, Priority, NULL, NULL, true);
Dprintf(" * Found following device: %p (%d)\n", device,
device ? device->CardIndex() + 1 : 0);
@@ -150,7 +150,7 @@
const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel());
isyslog("streamdev-server: Detaching current receiver");
Detach();
- device = cDevice::GetDevice(Channel, Priority);
+ device = cDevice::GetDevice(Channel, Priority, NULL, NULL, true);
Attach();
Dprintf(" * Found following device: %p (%d)\n", device,
device ? device->CardIndex() + 1 : 0);

View File

@ -732,8 +732,24 @@ bool cLSTRHandler::Next(bool &Last)
return false;
}
class cStreamdevLoopPrevention {
private:
bool Unlock;
public:
cStreamdevLoopPrevention(const cChannel* Channel, bool LoopPrevention): Unlock(LoopPrevention) {
if (LoopPrevention)
cPluginManager::CallAllServices(LOOP_PREVENTION_SERVICE, (void *)Channel);
}
~cStreamdevLoopPrevention() {
if (Unlock)
cPluginManager::CallAllServices(LOOP_PREVENTION_SERVICE, NULL);
}
};
// --- cConnectionVTP ---------------------------------------------------------
#define LOOP_PREVENTION(c) cStreamdevLoopPrevention LoopPrevention(c, m_LoopPrevention);
cConnectionVTP::cConnectionVTP(void):
cServerConnection("VTP"),
m_LiveSocket(NULL),
@ -753,6 +769,10 @@ cConnectionVTP::cConnectionVTP(void):
m_LSTTHandler(NULL),
m_LSTRHandler(NULL)
{
m_LoopPrevention = StreamdevServerSetup.LoopPrevention;
if (m_LoopPrevention)
// Loop prevention enabled - but is there anybody out there?
m_LoopPrevention = cPluginManager::CallFirstService(LOOP_PREVENTION_SERVICE);
}
cConnectionVTP::~cConnectionVTP()
@ -921,6 +941,8 @@ bool cConnectionVTP::CmdPROV(char *Opts)
if ((chan = ChannelFromString(Opts)) == NULL)
return Respond(550, "Undefined channel \"%s\"", Opts);
LOOP_PREVENTION(chan);
if (ProvidesChannel(chan, prio)) {
m_TuneChannel = chan;
m_TunePriority = prio;
@ -1088,6 +1110,8 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
if ((chan = ChannelFromString(Opts)) == NULL)
return Respond(550, "Undefined channel \"%s\"", Opts);
LOOP_PREVENTION(chan);
if (chan != m_TuneChannel) {
isyslog("streamdev-server TUNE %s: Priority unknown - using 0", Opts);
prio = 0;

View File

@ -29,6 +29,7 @@ private:
char *m_LastCommand;
eStreamType m_StreamType;
bool m_FiltersSupport;
bool m_LoopPrevention;
RecPlayer *m_RecPlayer;
// Priority is only known in PROV command

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
"Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n"
"Language-Team: <vdr@linuxtv.org>\n"
@ -66,6 +66,9 @@ msgstr "Port des VDR-zu-VDR Servers"
msgid "Bind to IP"
msgstr "Binde an IP"
msgid "Loop Prevention"
msgstr "Schleifen verhindern"
msgid "HTTP Server"
msgstr "HTTP Server"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2010-06-19 03:58+0100\n"
"Last-Translator: Javier Bradineras <jbradi@hotmail.com>\n"
"Language-Team: <vdr@linuxtv.org>\n"
@ -66,6 +66,9 @@ msgstr "Puerto del Servidor VDR-a-VDR"
msgid "Bind to IP"
msgstr "IP asociada"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "Servidor HTTP"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
"Last-Translator: Rolf Ahrenberg\n"
"Language-Team: Finnish <vdr@linuxtv.org>\n"
@ -67,6 +67,9 @@ msgstr "VDR-palvelimen portti"
msgid "Bind to IP"
msgstr "Sido osoitteeseen"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "HTTP-palvelin"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
"Last-Translator: micky979 <micky979@free.fr>\n"
"Language-Team: <vdr@linuxtv.org>\n"
@ -66,6 +66,9 @@ msgstr "Port du serveur VDR-to-VDR"
msgid "Bind to IP"
msgstr "Attacher aux IP"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "Serveur HTTP"

View File

@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2010-06-19 03:58+0100\n"
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
"Language-Team: <vdr@linuxtv.org>\n"
@ -68,6 +68,9 @@ msgstr "Porta Server VDR-a-VDR"
msgid "Bind to IP"
msgstr "IP associati"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "Server HTTP"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2009-11-26 21:57+0200\n"
"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n"
"Language-Team: Lietuvių\n"
@ -66,6 +66,9 @@ msgstr "VDR-su-VDR Serverio portas"
msgid "Bind to IP"
msgstr "Pririšti IP"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "HTTP Serveris"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev 0.5.0\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: 2008-06-26 15:36+0100\n"
"Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"
"Language-Team: <vdr@linuxtv.org>\n"
@ -66,6 +66,9 @@ msgstr "VDR-to-VDR
msgid "Bind to IP"
msgstr "¿àØáÞÕÔØÝØâìáï Ú IP"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "HTTP áÕàÒÕà"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: streamdev_SK\n"
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
"POT-Creation-Date: 2011-12-08 12:50+0100\n"
"POT-Creation-Date: 2011-12-11 11:25+0100\n"
"PO-Revision-Date: \n"
"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n"
"Language-Team: Slovak <hrala.milan@gmail.com>\n"
@ -68,6 +68,9 @@ msgstr "Port serveru pre VDR-do-VDR"
msgid "Bind to IP"
msgstr "viaza» na IP"
msgid "Loop Prevention"
msgstr ""
msgid "HTTP Server"
msgstr "server HTTP"

View File

@ -14,6 +14,7 @@ cStreamdevServerSetup::cStreamdevServerSetup(void) {
MaxClients = 5;
StartVTPServer = true;
VTPServerPort = 2004;
LoopPrevention = false;
StartHTTPServer = true;
HTTPServerPort = 3000;
HTTPStreamType = stTS;
@ -33,6 +34,7 @@ bool cStreamdevServerSetup::SetupParse(const char *Name, const char *Value) {
else if (strcmp(Name, "StartServer") == 0) StartVTPServer = atoi(Value);
else if (strcmp(Name, "ServerPort") == 0) VTPServerPort = atoi(Value);
else if (strcmp(Name, "VTPBindIP") == 0) strcpy(VTPBindIP, Value);
else if (strcmp(Name, "LoopPrevention") == 0) LoopPrevention = atoi(Value);
else if (strcmp(Name, "StartHTTPServer") == 0) StartHTTPServer = atoi(Value);
else if (strcmp(Name, "HTTPServerPort") == 0) HTTPServerPort = atoi(Value);
else if (strcmp(Name, "HTTPStreamType") == 0) HTTPStreamType = atoi(Value);
@ -89,6 +91,8 @@ void cStreamdevServerMenuSetupPage::Set(void) {
Add(new cMenuEditBoolItem(tr("Start VDR-to-VDR Server"), &m_NewSetup.StartVTPServer));
Add(new cMenuEditIntItem (tr("VDR-to-VDR Server Port"), &m_NewSetup.VTPServerPort, 0, 65535));
Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.VTPBindIP));
if (cPluginManager::CallFirstService(LOOP_PREVENTION_SERVICE))
Add(new cMenuEditBoolItem(tr("Loop Prevention"), &m_NewSetup.LoopPrevention));
AddCategory (tr("HTTP Server"));
Add(new cMenuEditBoolItem(tr("Start HTTP Server"), &m_NewSetup.StartHTTPServer));
@ -134,6 +138,7 @@ void cStreamdevServerMenuSetupPage::Store(void) {
SetupStore("StartServer", m_NewSetup.StartVTPServer);
SetupStore("ServerPort", m_NewSetup.VTPServerPort);
SetupStore("VTPBindIP", m_NewSetup.VTPBindIP);
SetupStore("LoopPrevention", m_NewSetup.LoopPrevention);
SetupStore("StartHTTPServer", m_NewSetup.StartHTTPServer);
SetupStore("HTTPServerPort", m_NewSetup.HTTPServerPort);
SetupStore("HTTPStreamType", m_NewSetup.HTTPStreamType);

View File

@ -17,6 +17,7 @@ struct cStreamdevServerSetup {
int StartVTPServer;
int VTPServerPort;
char VTPBindIP[20];
int LoopPrevention;
int StartHTTPServer;
int HTTPServerPort;
int HTTPStreamType;