diff options
author | Frank Schmirler <vdr@schmirler.de> | 2010-12-02 09:57:17 +0100 |
---|---|---|
committer | Mikko Matilainen <mikkom@iki.fi> | 2011-03-22 21:16:18 +0200 |
commit | 6ea5efe93960fc761dbb5e0b2d93d9b5818d5d7c (patch) | |
tree | 836d96c9a4688a01745719787a7a0e83804356f8 /server | |
parent | 0a860a1e3e45ee83563b09beb93ede0e99eb75fb (diff) | |
download | vdr-plugin-streamdev-6ea5efe93960fc761dbb5e0b2d93d9b5818d5d7c.tar.gz vdr-plugin-streamdev-6ea5efe93960fc761dbb5e0b2d93d9b5818d5d7c.tar.bz2 |
Snapshot 2010-09-15
Diffstat (limited to 'server')
-rw-r--r-- | server/Makefile | 82 | ||||
-rw-r--r-- | server/connection.c | 221 | ||||
-rw-r--r-- | server/connection.h | 31 | ||||
-rw-r--r-- | server/connectionHTTP.c | 9 | ||||
-rw-r--r-- | server/connectionHTTP.h | 19 | ||||
-rw-r--r-- | server/connectionIGMP.c | 8 | ||||
-rw-r--r-- | server/connectionVTP.c | 52 | ||||
-rw-r--r-- | server/connectionVTP.h | 6 | ||||
-rw-r--r-- | server/livestreamer.c | 60 | ||||
-rw-r--r-- | server/livestreamer.h | 6 | ||||
-rw-r--r-- | server/menuHTTP.c | 23 | ||||
-rw-r--r-- | server/menuHTTP.h | 12 | ||||
-rw-r--r-- | server/po/de_DE.po | 83 | ||||
-rw-r--r-- | server/po/fi_FI.po | 83 | ||||
-rw-r--r-- | server/po/fr_FR.po | 83 | ||||
-rw-r--r-- | server/po/it_IT.po | 85 | ||||
-rw-r--r-- | server/po/lt_LT.po | 83 | ||||
-rw-r--r-- | server/po/ru_RU.po | 83 | ||||
-rw-r--r-- | server/po/sk_SK.po | 85 | ||||
-rw-r--r-- | server/setup.c | 29 | ||||
-rw-r--r-- | server/setup.h | 4 | ||||
-rw-r--r-- | server/streamdev-server.c | 143 | ||||
-rw-r--r-- | server/streamdev-server.h | 33 | ||||
-rw-r--r-- | server/streamer.c | 11 | ||||
-rw-r--r-- | server/streamer.h | 8 |
25 files changed, 1197 insertions, 145 deletions
diff --git a/server/Makefile b/server/Makefile new file mode 100644 index 0000000..8f512ac --- /dev/null +++ b/server/Makefile @@ -0,0 +1,82 @@ +# +# Makefile for a Video Disk Recorder plugin +# +# $Id: Makefile,v 1.2 2010/07/19 13:49:31 schmirl Exp $ + +# The official name of this plugin. +# This name will be used in the '-P...' option of VDR to load the plugin. +# By default the main source file also carries this name. +# +PLUGIN = streamdev-server + +### Includes and Defines (add further entries here): + +DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' + +### The object files (add further files here): + +COMMONOBJS = ../common.o + +SERVEROBJS = $(PLUGIN).o \ + server.o component.o connection.o \ + componentVTP.o connectionVTP.o \ + componentHTTP.o connectionHTTP.o menuHTTP.o \ + componentIGMP.o connectionIGMP.o \ + streamer.o livestreamer.o livefilter.o recplayer.o \ + suspend.o setup.o + +### The main target: + +.PHONY: all i18n clean +all: libvdr-$(PLUGIN).so i18n + +### Implicit rules: + +%.o: %.c + $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $< + +### Dependencies: + +MAKEDEP = $(CXX) -MM -MG +DEPFILE = .dependencies + +$(DEPFILE): Makefile + @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SERVEROBJS:%.o=%.c) $(COMMONOBJS:%.o=%.c) > $@ + +-include $(DEPFILE) + +### Internationalization (I18N): + +PODIR = po +LOCALEDIR = $(VDRDIR)/locale +I18Npo = $(wildcard $(PODIR)/*.po) +I18Nmsgs = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file)))))) +I18Npot = $(PODIR)/$(PLUGIN).pot + +%.mo: %.po + msgfmt -c -o $@ $< + +$(I18Npot): $(SERVEROBJS:%.o=%.c) + xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --msgid-bugs-address='<http://www.vdr-developer.org/mantisbt/>' -o $@ $^ + +%.po: $(I18Npot) + msgmerge -U --no-wrap --no-location --backup=none -q $@ $< + @touch $@ + +$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo + @mkdir -p $(dir $@) + cp $< $@ + +i18n: $(I18Nmsgs) + +### Targets: + +libvdr-$(PLUGIN).so: $(SERVEROBJS) $(COMMONOBJS) \ + ../tools/sockettools.a ../remux/remux.a ../libdvbmpeg/libdvbmpegtools.a + +%.so: + $(CXX) $(CXXFLAGS) -shared $^ -o $@ + @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION) + +clean: + @-rm -f $(COMMONOBJS) $(SERVEROBJS) $(DEPFILE) $(PODIR)/*.mo $(PODIR)/*.pot *.so *.tgz core* *~ diff --git a/server/connection.c b/server/connection.c index eccb3c4..2ba99f3 100644 --- a/server/connection.c +++ b/server/connection.c @@ -1,5 +1,5 @@ /* - * $Id: connection.c,v 1.13 2009/09/18 10:43:26 schmirl Exp $ + * $Id: connection.c,v 1.16 2010/08/03 10:51:53 schmirl Exp $ */ #include "server/connection.h" @@ -8,6 +8,7 @@ #include "common.h" #include <vdr/tools.h> +#include <vdr/transfer.h> #include <string.h> #include <stdarg.h> #include <errno.h> @@ -27,7 +28,7 @@ cServerConnection::~cServerConnection() { } -const cChannel* cServerConnection::ChannelFromString(const char *String, int *Apid) { +const cChannel* cServerConnection::ChannelFromString(const char *String, int *Apid, int *Dpid) { const cChannel *channel = NULL; char *string = strdup(String); char *ptr, *end; @@ -58,7 +59,8 @@ const cChannel* cServerConnection::ChannelFromString(const char *String, int *Ap } if (channel != NULL && apididx > 0) { - int apid = 0, index = 1; + int apid = 0, dpid = 0; + int index = 1; for (int i = 0; channel->Apid(i) != 0; ++i, ++index) { if (index == apididx) { @@ -70,7 +72,7 @@ const cChannel* cServerConnection::ChannelFromString(const char *String, int *Ap if (apid == 0) { for (int i = 0; channel->Dpid(i) != 0; ++i, ++index) { if (index == apididx) { - apid = channel->Dpid(i); + dpid = channel->Dpid(i); break; } } @@ -78,6 +80,8 @@ const cChannel* cServerConnection::ChannelFromString(const char *String, int *Ap if (Apid != NULL) *Apid = apid; + if (Dpid != NULL) + *Dpid = dpid; } free(string); @@ -181,75 +185,172 @@ bool cServerConnection::Respond(const char *Message, bool Last, ...) m_Pending = !Last; return true; } - + +#if APIVERSNUM >= 10700 +static int GetClippedNumProvidedSystems(int AvailableBits, cDevice *Device) +{ + int MaxNumProvidedSystems = 1 << AvailableBits; + int NumProvidedSystems = Device->NumProvidedSystems(); + if (NumProvidedSystems > MaxNumProvidedSystems) { + esyslog("ERROR: device %d supports %d modulation systems but cDevice::GetDevice() currently only supports %d delivery systems which should be fixed", Device->CardIndex() + 1, NumProvidedSystems, MaxNumProvidedSystems); + NumProvidedSystems = MaxNumProvidedSystems; + } + else if (NumProvidedSystems <= 0) { + esyslog("ERROR: device %d reported an invalid number (%d) of supported delivery systems - assuming 1", Device->CardIndex() + 1, NumProvidedSystems); + NumProvidedSystems = 1; + } + return NumProvidedSystems; +} +#endif + +/* + * copy of cDevice::GetDevice(...) but without side effects (not detaching receivers) + */ +cDevice* cServerConnection::CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice) +{ + //cDevice *AvoidDevice = avoidDevice; + //avoidDevice = NULL; + // Collect the current priorities of all CAM slots that can decrypt the channel: + int NumCamSlots = CamSlots.Count(); + int SlotPriority[NumCamSlots]; + int NumUsableSlots = 0; + if (Channel->Ca() >= CA_ENCRYPTED_MIN) { + for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) { + SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used + if (CamSlot->ModuleStatus() == msReady) { + if (CamSlot->ProvidesCa(Channel->Caids())) { + if (!ChannelCamRelations.CamChecked(Channel->GetChannelID(), CamSlot->SlotNumber())) { + SlotPriority[CamSlot->Index()] = CamSlot->Priority(); + NumUsableSlots++; + } + } + } + } + if (!NumUsableSlots) + return NULL; // no CAM is able to decrypt this channel + } + + bool NeedsDetachReceivers = false; + cDevice *d = NULL; + //cCamSlot *s = NULL; + + uint32_t Impact = 0xFFFFFFFF; // we're looking for a device with the least impact + for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) { + if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY) + continue; // there is no CAM available in this slot + for (int i = 0; i < cDevice::NumDevices(); i++) { + cDevice *device = cDevice::GetDevice(i); + if (device == AvoidDevice) + continue; // we've been asked to skip this device + if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device->CardIndex() + 1) + continue; // a specific card was requested, but not this one + if (NumUsableSlots && !CamSlots.Get(j)->Assign(device, true)) + continue; // CAM slot can't be used with this device + bool ndr; + if (device->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job + if (NumUsableSlots && device->CamSlot() && device->CamSlot() != CamSlots.Get(j)) + ndr = true; // using a different CAM slot requires detaching receivers + // Put together an integer number that reflects the "impact" using + // this device would have on the overall system. Each condition is represented + // by one bit in the number (or several bits, if the condition is actually + // a numeric value). The sequence in which the conditions are listed corresponds + // to their individual severity, where the one listed first will make the most + // difference, because it results in the most significant bit of the result. + uint32_t imp = 0; + imp <<= 1; imp |= LiveView ? !device->IsPrimaryDevice() || ndr : 0; // prefer the primary device for live viewing if we don't need to detach existing receivers + imp <<= 1; imp |= !device->Receiving() && (device != cTransferControl::ReceiverDevice() || device->IsPrimaryDevice()) || ndr; // use receiving devices if we don't need to detach existing receivers, but avoid primary device in local transfer mode + imp <<= 1; imp |= device->Receiving(); // avoid devices that are receiving +#if APIVERSNUM >= 10700 + imp <<= 2; imp |= GetClippedNumProvidedSystems(2, device) - 1; // avoid cards which support multiple delivery systems +#endif + imp <<= 1; imp |= device == cTransferControl::ReceiverDevice(); // avoid the Transfer Mode receiver device + imp <<= 8; imp |= min(max(device->Priority() + MAXPRIORITY, 0), 0xFF); // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) + imp <<= 8; imp |= min(max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF); // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) + imp <<= 1; imp |= ndr; // avoid devices if we need to detach existing receivers + imp <<= 1; imp |= device->IsPrimaryDevice(); // avoid the primary device + imp <<= 1; imp |= NumUsableSlots ? 0 : device->HasCi(); // avoid cards with Common Interface for FTA channels + imp <<= 1; imp |= device->HasDecoder(); // avoid full featured cards + imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel + if (imp < Impact) { + // This device has less impact than any previous one, so we take it. + Impact = imp; + d = device; + NeedsDetachReceivers = ndr; + } + } + } + if (!NumUsableSlots) + break; // no CAM necessary, so just one loop over the devices + } + return d; +} + cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority) { - cDevice *device = NULL; - - /*Dprintf("+ Statistics:\n"); - Dprintf("+ Current Channel: %d\n", cDevice::CurrentChannel()); - Dprintf("+ Current Device: %d\n", cDevice::ActualDevice()->CardIndex()); - Dprintf("+ Transfer Mode: %s\n", cDevice::ActualDevice() - == cDevice::PrimaryDevice() ? "false" : "true"); - Dprintf("+ Replaying: %s\n", cDevice::PrimaryDevice()->Replaying() ? "true" - : "false");*/ - - Dprintf(" * GetDevice(const cChannel*, int)\n"); - Dprintf(" * -------------------------------\n"); - - device = cDevice::GetDevice(Channel, Priority, false); - - Dprintf(" * Found following device: %p (%d)\n", device, - device ? device->CardIndex() + 1 : 0); - if (device == cDevice::ActualDevice()) - Dprintf(" * is actual device\n"); - if (!cSuspendCtl::IsActive() && StreamdevServerSetup.SuspendMode != smAlways) - Dprintf(" * NOT suspended\n"); - - if (!device || (device == cDevice::ActualDevice() + const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel()); + + // turn off the streams of this connection + Detach(); + // This call may detach receivers of the device it returns + cDevice *device = cDevice::GetDevice(Channel, Priority, false); + + if (device && device == cDevice::ActualDevice() && !cSuspendCtl::IsActive() - && StreamdevServerSetup.SuspendMode != smAlways)) { + && StreamdevServerSetup.SuspendMode != smAlways + && current != NULL + && !TRANSPONDER(Channel, current)) { + // 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); + cDevice *newdev = cDevice::GetDevice(current, 0, true); +#else + cDevice *newdev = CheckDevice(current, 0, true, device); +#endif + if (newdev) + newdev->SwitchChannel(current, true); + else + device = NULL; + } + + if (!device) { + // can't switch - continue the current stream + Attach(); + dsyslog("streamdev: GetDevice failed for channel %s at priority %d", Channel->Name(), Priority); + } + return device; +} + +bool cServerConnection::ProvidesChannel(const cChannel *Channel, int Priority) +{ + const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel()); + + cDevice *device = CheckDevice(Channel, Priority, false); + if (!device || (device == cDevice::ActualDevice() + && !cSuspendCtl::IsActive() + && StreamdevServerSetup.SuspendMode != smAlways + && current != NULL + && !TRANSPONDER(Channel, current))) { // mustn't switch actual device // maybe a device would be free if THIS connection did turn off its streams? - Dprintf(" * trying again...\n"); - const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel()); - isyslog("streamdev-server: Detaching current receiver"); Detach(); - device = cDevice::GetDevice(Channel, Priority, false); + device = CheckDevice(Channel, Priority, false); Attach(); - Dprintf(" * Found following device: %p (%d)\n", device, - device ? device->CardIndex() + 1 : 0); - if (device == cDevice::ActualDevice()) - Dprintf(" * is actual device\n"); - if (!cSuspendCtl::IsActive() - && StreamdevServerSetup.SuspendMode != smAlways) - Dprintf(" * NOT suspended\n"); - if (current && !TRANSPONDER(Channel, current)) - Dprintf(" * NOT same transponder\n"); - if (device && (device == cDevice::ActualDevice() - && !cSuspendCtl::IsActive() + if (device && device == cDevice::ActualDevice() + && !cSuspendCtl::IsActive() && StreamdevServerSetup.SuspendMode != smAlways && current != NULL - && !TRANSPONDER(Channel, current))) { + && !TRANSPONDER(Channel, current)) { // now we would have to switch away live tv...let's see if live tv // can be handled by another device - cDevice *newdev = NULL; - for (int i = 0; i < cDevice::NumDevices(); ++i) { - cDevice *dev = cDevice::GetDevice(i); - if (dev->ProvidesChannel(current, 0) && dev != device) { - newdev = dev; - break; - } - } - Dprintf(" * Found device for live tv: %p (%d)\n", newdev, - newdev ? newdev->CardIndex() + 1 : 0); - if (newdev == NULL || newdev == device) - // no suitable device to continue live TV, giving up... + cDevice *newdev = CheckDevice(current, 0, true, device); + if (!newdev) { device = NULL; - else - newdev->SwitchChannel(current, true); + dsyslog("streamdev: Not providing channel %s at priority %d - live TV not suspended", Channel->Name(), Priority); + } } + else if (!device) + dsyslog("streamdev: No device provides channel %s at priority %d", Channel->Name(), Priority); } - return device; } diff --git a/server/connection.h b/server/connection.h index 73cb3d5..22301b1 100644 --- a/server/connection.h +++ b/server/connection.h @@ -1,5 +1,5 @@ /* - * $Id: connection.h,v 1.8 2009/09/18 10:43:26 schmirl Exp $ + * $Id: connection.h,v 1.10 2010/08/03 10:46:41 schmirl Exp $ */ #ifndef VDR_STREAMDEV_SERVER_CONNECTION_H @@ -8,6 +8,11 @@ #include "tools/socket.h" #include "common.h" +#include <map> + +typedef std::map<std::string,std::string> tStrStrMap; +typedef std::pair<std::string,std::string> tStrStr; + class cChannel; class cDevice; @@ -28,6 +33,13 @@ private: uint m_WriteBytes; uint m_WriteIndex; + tStrStrMap m_Headers; + + /* Check if a device would be available for transfering the given + channel. This call has no side effects except for temporarily + detaching this connection's receivers. */ + cDevice *CheckDevice(const cChannel *Channel, int Priority, bool LiveView, const cDevice *AvoidDevice = NULL); + protected: /* Will be called when a command terminated by a newline has been received */ @@ -41,7 +53,10 @@ protected: virtual bool Respond(const char *Message, bool Last = true, ...); //__attribute__ ((format (printf, 2, 4))); - static const cChannel *ChannelFromString(const char *String, int *Apid = NULL); + /* Add a request header */ + void SetHeader(const char *Name, const char *Value, const char *Prefix = "") { m_Headers.insert(tStrStr(std::string(Prefix) + Name, Value)); } + + static const cChannel *ChannelFromString(const char *String, int *Apid = NULL, int *Dpid = NULL); public: /* If you derive, specify a short string such as HTTP for Protocol, which @@ -81,14 +96,24 @@ public: /* Will make the socket close after sending all queued output data */ void DeferClose(void) { m_DeferClose = true; } - /* Will retrieve an unused device for transmitting data. Use the returned + /* 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); + /* Test if a call to GetDevice would return a usable device. */ + bool ProvidesChannel(const cChannel *Channel, int Priority); + virtual void Flushed(void) {} virtual void Detach(void) = 0; virtual void Attach(void) = 0; + + /* This connections protocol name */ + virtual const char* Protocol(void) const { return m_Protocol; } + + /* std::map with additional information */ + const tStrStrMap& Headers(void) const { return m_Headers; } }; inline bool cServerConnection::HasData(void) const diff --git a/server/connectionHTTP.c b/server/connectionHTTP.c index 16a2af7..54ccf5a 100644 --- a/server/connectionHTTP.c +++ b/server/connectionHTTP.c @@ -1,5 +1,5 @@ /* - * $Id: connectionHTTP.c,v 1.20 2010/07/22 14:18:18 schmirl Exp $ + * $Id: connectionHTTP.c,v 1.21 2010/08/03 10:46:41 schmirl Exp $ */ #include <ctype.h> @@ -149,7 +149,9 @@ bool cConnectionHTTP::ProcessRequest(void) if (m_ChannelList) return Respond("%s", true, m_ChannelList->HttpHeader().c_str()); else if (m_Channel != NULL) { - cDevice *device = GetDevice(m_Channel, 0); + cDevice *device = NULL; + if (ProvidesChannel(m_Channel, 0)) + device = GetDevice(m_Channel, 0); if (device != NULL) { device->SwitchChannel(m_Channel, false); m_LiveStreamer = new cStreamdevLiveStreamer(0, this); @@ -186,8 +188,7 @@ bool cConnectionHTTP::ProcessRequest(void) if (m_ChannelList) return Respond("%s", true, m_ChannelList->HttpHeader().c_str()); else if (m_Channel != NULL) { - cDevice *device = GetDevice(m_Channel, 0); - if (device != NULL) { + if (ProvidesChannel(m_Channel, 0)) { if (m_StreamType == stEXT) { // TODO return Respond("HTTP/1.0 200 OK") diff --git a/server/connectionHTTP.h b/server/connectionHTTP.h index 0548959..56f89b0 100644 --- a/server/connectionHTTP.h +++ b/server/connectionHTTP.h @@ -1,5 +1,5 @@ /* - * $Id: connectionHTTP.h,v 1.6 2008/10/14 11:05:48 schmirl Exp $ + * $Id: connectionHTTP.h,v 1.7 2010/07/19 13:49:31 schmirl Exp $ */ #ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H @@ -8,6 +8,7 @@ #include "connection.h" #include "server/livestreamer.h" +#include <map> #include <tools/select.h> class cChannel; @@ -23,26 +24,19 @@ private: hsFinished, }; - enum eHTTPJob { - hjTransfer, - hjListing, - }; - - std::string m_Request; - std::string m_Host; std::string m_Authorization; - //std::map<std::string,std::string> m_Headers; TODO: later? eHTTPStatus m_Status; - eHTTPJob m_Job; // job: transfer cStreamdevLiveStreamer *m_LiveStreamer; - std::string m_StreamerParameter; const cChannel *m_Channel; - int m_Apid; + int m_Apid[2]; + int m_Dpid[2]; eStreamType m_StreamType; // job: listing cChannelList *m_ChannelList; + cChannelList* ChannelListFromString(const std::string &PathInfo, const std::string &Filebase, const std::string &Fileext) const; + bool ProcessURI(const std::string &PathInfo); protected: bool ProcessRequest(void); @@ -56,7 +50,6 @@ public: virtual bool CanAuthenticate(void); virtual bool Command(char *Cmd); - bool CmdGET(const std::string &Opts); virtual bool Abort(void) const; virtual void Flushed(void); diff --git a/server/connectionIGMP.c b/server/connectionIGMP.c index dc08798..708f41c 100644 --- a/server/connectionIGMP.c +++ b/server/connectionIGMP.c @@ -1,5 +1,5 @@ /* - * $Id: connectionIGMP.c,v 1.1 2009/02/13 10:39:22 schmirl Exp $ + * $Id: connectionIGMP.c,v 1.3 2010/08/03 10:46:41 schmirl Exp $ */ #include <ctype.h> @@ -25,13 +25,15 @@ cConnectionIGMP::~cConnectionIGMP() bool cConnectionIGMP::Start(cChannel *Channel, in_addr_t Dst) { if (Channel != NULL) { - cDevice *device = GetDevice(Channel, 0); + cDevice *device = NULL; + if (ProvidesChannel(Channel, 0)) + device = GetDevice(Channel, 0); if (device != NULL) { device->SwitchChannel(Channel, false); struct in_addr ip; ip.s_addr = Dst; if (Connect(inet_ntoa(ip), m_ClientPort)) { - m_LiveStreamer = new cStreamdevLiveStreamer(0); + m_LiveStreamer = new cStreamdevLiveStreamer(0, this); if (m_LiveStreamer->SetChannel(Channel, m_StreamType)) { m_LiveStreamer->SetDevice(device); if (!SetDSCP()) diff --git a/server/connectionVTP.c b/server/connectionVTP.c index 7ff60e5..0f92db0 100644 --- a/server/connectionVTP.c +++ b/server/connectionVTP.c @@ -1,5 +1,5 @@ /* - * $Id: connectionVTP.c,v 1.27 2010/01/29 12:03:02 schmirl Exp $ + * $Id: connectionVTP.c,v 1.31 2010/08/18 10:26:54 schmirl Exp $ */ #include "server/connectionVTP.h" @@ -746,6 +746,8 @@ cConnectionVTP::cConnectionVTP(void): m_StreamType(stTSPIDS), m_FiltersSupport(false), m_RecPlayer(NULL), + m_TuneChannel(NULL), + m_TunePriority(0), m_LSTEHandler(NULL), m_LSTCHandler(NULL), m_LSTTHandler(NULL), @@ -836,6 +838,7 @@ bool cConnectionVTP::Command(char *Cmd) else if (strcasecmp(Cmd, "READ") == 0) return CmdREAD(param); else if (strcasecmp(Cmd, "TUNE") == 0) return CmdTUNE(param); else if (strcasecmp(Cmd, "PLAY") == 0) return CmdPLAY(param); + else if (strcasecmp(Cmd, "PRIO") == 0) return CmdPRIO(param); else if (strcasecmp(Cmd, "ADDP") == 0) return CmdADDP(param); else if (strcasecmp(Cmd, "DELP") == 0) return CmdDELP(param); else if (strcasecmp(Cmd, "ADDF") == 0) return CmdADDF(param); @@ -881,8 +884,8 @@ bool cConnectionVTP::CmdCAPS(char *Opts) return Respond(220, "Capability \"%s\" accepted", Opts); } - if (strcasecmp(Opts, "EXTERN") == 0) { - m_StreamType = stExtern; + if (strcasecmp(Opts, "EXT") == 0) { + m_StreamType = stEXT; return Respond(220, "Capability \"%s\" accepted", Opts); } @@ -894,6 +897,11 @@ bool cConnectionVTP::CmdCAPS(char *Opts) return Respond(220, "Capability \"%s\" accepted", Opts); } + // Command PRIO is known + if (strcasecmp(Opts, "PRIO") == 0) { + return Respond(220, "Capability \"%s\" accepted", Opts); + } + return Respond(561, "Capability \"%s\" not known", Opts); } @@ -911,9 +919,15 @@ bool cConnectionVTP::CmdPROV(char *Opts) if ((chan = ChannelFromString(Opts)) == NULL) return Respond(550, "Undefined channel \"%s\"", Opts); - return GetDevice(chan, prio) != NULL - ? Respond(220, "Channel available") - : Respond(560, "Channel not available"); + if (ProvidesChannel(chan, prio)) { + m_TuneChannel = chan; + m_TunePriority = prio; + return Respond(220, "Channel available"); + } + else { + m_TuneChannel = NULL; + return Respond(560, "Channel not available"); + } } bool cConnectionVTP::CmdPORT(char *Opts) @@ -1067,18 +1081,23 @@ bool cConnectionVTP::CmdTUNE(char *Opts) { const cChannel *chan; cDevice *dev; + int prio = m_TunePriority; if ((chan = ChannelFromString(Opts)) == NULL) return Respond(550, "Undefined channel \"%s\"", Opts); - if ((dev = GetDevice(chan, 0)) == NULL) + if (chan != m_TuneChannel) { + esyslog("streamdev-server TUNE %s: Priority unknown - using 0", Opts); + prio = 0; + } + if ((dev = GetDevice(chan, prio)) == NULL) return Respond(560, "Channel not available"); if (!dev->SwitchChannel(chan, false)) return Respond(560, "Channel not available"); delete m_LiveStreamer; - m_LiveStreamer = new cStreamdevLiveStreamer(1); + m_LiveStreamer = new cStreamdevLiveStreamer(prio, this); m_LiveStreamer->SetChannel(chan, m_StreamType); m_LiveStreamer->SetDevice(dev); if(m_LiveSocket) @@ -1119,6 +1138,22 @@ bool cConnectionVTP::CmdPLAY(char *Opts) } } +bool cConnectionVTP::CmdPRIO(char *Opts) +{ + int prio; + char *end; + + prio = strtoul(Opts, &end, 10); + if (end == Opts || (*end != '\0' && *end != ' ')) + return Respond(500, "Use: PRIO Priority"); + + if (m_LiveStreamer) { + m_LiveStreamer->SetPriority(prio); + return Respond(220, "Priority changed to %d", prio); + } + return Respond(550, "Priority not applicable"); +} + bool cConnectionVTP::CmdADDP(char *Opts) { int pid; @@ -1243,6 +1278,7 @@ bool cConnectionVTP::CmdSUSP(void) else if (StreamdevServerSetup.SuspendMode == smOffer && StreamdevServerSetup.AllowSuspend) { cControl::Launch(new cSuspendCtl); + cControl::Attach(); return Respond(220, "Server is suspended"); } else return Respond(550, "Client may not suspend server"); diff --git a/server/connectionVTP.h b/server/connectionVTP.h index b938fe6..ee842fe 100644 --- a/server/connectionVTP.h +++ b/server/connectionVTP.h @@ -31,6 +31,11 @@ private: bool m_FiltersSupport; RecPlayer *m_RecPlayer; + // Priority is only known in PROV command + // Store in here for later use in TUNE call + const cChannel *m_TuneChannel; + int m_TunePriority; + // Members adopted for SVDRP cLSTEHandler *m_LSTEHandler; cLSTCHandler *m_LSTCHandler; @@ -59,6 +64,7 @@ public: bool CmdREAD(char *Opts); bool CmdTUNE(char *Opts); bool CmdPLAY(char *Opts); + bool CmdPRIO(char *Opts); bool CmdADDP(char *Opts); bool CmdDELP(char *Opts); bool CmdADDF(char *Opts); diff --git a/server/livestreamer.c b/server/livestreamer.c index ab7c6b4..1286abd 100644 --- a/server/livestreamer.c +++ b/server/livestreamer.c @@ -289,7 +289,7 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i if (written != TS_SIZE) siBuffer.ReportOverflow(TS_SIZE - written); if (pmtPid != prevPmtPid) { - m_Streamer->SetPids(pmtPid); + m_Streamer->SetPid(pmtPid, true); Add(pmtPid, 0x02); pmtVersion = -1; } @@ -335,10 +335,9 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i // --- cStreamdevLiveStreamer ------------------------------------------------- -cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority, std::string Parameter): - cStreamdevStreamer("streamdev-livestreaming"), +cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority, const cServerConnection *Connection): + cStreamdevStreamer("streamdev-livestreaming", Connection), m_Priority(Priority), - m_Parameter(Parameter), m_NumPids(0), m_StreamType(stTSPIDS), m_Channel(NULL), @@ -435,53 +434,58 @@ bool cStreamdevLiveStreamer::SetPids(int Pid, const int *Pids1, const int *Pids2 return true; } +void cStreamdevLiveStreamer::SetPriority(int Priority) +{ + m_Priority = Priority; + StartReceiver(); +} + void cStreamdevLiveStreamer::StartReceiver(void) { - DELETENULL(m_Receiver); - if (m_NumPids > 0) { + if (m_Device != NULL && m_NumPids > 0 && IsRunning()) { Dprintf("Creating Receiver to respect changed pids\n"); + cReceiver *current = m_Receiver; m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->GetChannelID(), m_Priority, m_Pids); - if (IsRunning() && m_Device != NULL) { - Dprintf("Attaching new receiver\n"); - Attach(); - } + cThreadLock ThreadLock(m_Device); + Attach(); + delete current; } + else + DELETENULL(m_Receiver); } -bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType StreamType, int Apid) +bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid, const int *Dpid) { Dprintf("Initializing Remuxer for full channel transfer\n"); //printf("ca pid: %d\n", Channel->Ca()); m_Channel = Channel; m_StreamType = StreamType; - int apid[2] = { Apid, 0 }; - const int *Apids = Apid ? apid : m_Channel->Apids(); - const int *Dpids = Apid ? NULL : m_Channel->Dpids(); + const int *Apids = Apid ? Apid : m_Channel->Apids(); + const int *Dpids = Dpid ? Dpid : m_Channel->Dpids(); switch (m_StreamType) { case stES: { int pid = ISRADIO(m_Channel) ? m_Channel->Apid(0) : m_Channel->Vpid(); - if (Apid != 0) - pid = Apid; + if (Apid && Apid[0]) + pid = Apid[0]; + else if (Dpid && Dpid[0]) + pid = Dpid[0]; m_Remux = new cTS2ESRemux(pid); return SetPids(pid); } case stPES: - m_Remux = new cTS2PESRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(), - m_Channel->Spids()); + m_Remux = new cTS2PESRemux(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids()); return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids()); case stPS: - m_Remux = new cTS2PSRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(), - m_Channel->Spids()); + m_Remux = new cTS2PSRemux(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids()); return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids()); - case stExtern: - m_Remux = new cExternRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(), - m_Channel->Spids(), m_Parameter); + case stEXT: + m_Remux = new cExternRemux(Connection(), m_Channel, Apids, Dpids); // fall through case stTS: // This should never happen, but ... @@ -634,12 +638,10 @@ void cStreamdevFilterStreamer::SetDevice(cDevice *Device) { Dprintf("cStreamdevFilterStreamer::SetDevice()\n"); LOCK_THREAD; - if(Device != m_Device) { - Detach(); - m_Device = Device; - //m_Channel = NULL; - Attach(); - } + Detach(); + m_Device = Device; + //m_Channel = NULL; + Attach(); } bool cStreamdevFilterStreamer::SetFilter(u_short Pid, u_char Tid, u_char Mask, bool On) diff --git a/server/livestreamer.h b/server/livestreamer.h index 92448bb..71feb4c 100644 --- a/server/livestreamer.h +++ b/server/livestreamer.h @@ -18,7 +18,6 @@ class cStreamdevLiveReceiver; class cStreamdevLiveStreamer: public cStreamdevStreamer { private: int m_Priority; - std::string m_Parameter; int m_Pids[MAXRECEIVEPIDS + 1]; int m_NumPids; eStreamType m_StreamType; @@ -32,13 +31,14 @@ private: bool HasPid(int Pid); public: - cStreamdevLiveStreamer(int Priority, std::string Parameter = ""); + cStreamdevLiveStreamer(int Priority, const cServerConnection *Connection); 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, int Apid = 0); + bool SetChannel(const cChannel *Channel, eStreamType StreamType, const int* Apid = NULL, const int* Dpid = NULL); + void SetPriority(int Priority); virtual int Put(const uchar *Data, int Count); virtual uchar *Get(int &Count); diff --git a/server/menuHTTP.c b/server/menuHTTP.c index 84a4fb7..d7fb817 100644 --- a/server/menuHTTP.c +++ b/server/menuHTTP.c @@ -2,7 +2,7 @@ #include "server/menuHTTP.h" //**************************** cChannelIterator ************** -cChannelIterator::cChannelIterator(cChannel *First): channel(First) +cChannelIterator::cChannelIterator(const cChannel *First): channel(First) {} const cChannel* cChannelIterator::Next() @@ -19,7 +19,7 @@ cListAll::cListAll(): cChannelIterator(Channels.First()) const cChannel* cListAll::NextChannel(const cChannel *Channel) { if (Channel) - Channel = Channels.Next(Channel); + Channel = SkipFakeGroups(Channels.Next(Channel)); return Channel; } @@ -46,14 +46,19 @@ const cChannel* cListGroups::NextChannel(const cChannel *Channel) } // // ********************* cListGroup **************** -cListGroup::cListGroup(const cChannel *Group): cChannelIterator((Group && Group->GroupSep() && Channels.Next(Group) && !Channels.Next(Group)->GroupSep()) ? Channels.Next(Group) : NULL) +cListGroup::cListGroup(const cChannel *Group): cChannelIterator(GetNextChannelInGroup(Group)) {} -const cChannel* cListGroup::NextChannel(const cChannel *Channel) +const cChannel* cListGroup::GetNextChannelInGroup(const cChannel *Channel) { if (Channel) - Channel = Channels.Next(Channel); - return (Channel && !Channel->GroupSep()) ? Channel : NULL; + Channel = SkipFakeGroups(Channels.Next(Channel)); + return Channel && !Channel->GroupSep() ? Channel : NULL; +} + +const cChannel* cListGroup::NextChannel(const cChannel *Channel) +{ + return GetNextChannelInGroup(Channel); } // // ********************* cListTree **************** @@ -68,7 +73,7 @@ const cChannel* cListTree::NextChannel(const cChannel *Channel) if (currentGroup == selectedGroup) { if (Channel) - Channel = Channels.Next(Channel); + Channel = SkipFakeGroups(Channels.Next(Channel)); if (Channel && Channel->GroupSep()) currentGroup = Channel; } @@ -205,8 +210,8 @@ std::string cHtmlChannelList::StreamTypeMenu() (std::string) "[<a href=\"/PES/" + self + "\">PES</a>] "); typeMenu += (streamType == stES ? (std::string) "[ES] " : (std::string) "[<a href=\"/ES/" + self + "\">ES</a>] "); - typeMenu += (streamType == stExtern ? (std::string) "[Extern] " : - (std::string) "[<a href=\"/Extern/" + self + "\">Extern</a>] "); + typeMenu += (streamType == stEXT ? (std::string) "[EXT] " : + (std::string) "[<a href=\"/EXT/" + self + "\">EXT</a>] "); return typeMenu; } diff --git a/server/menuHTTP.h b/server/menuHTTP.h index cbd7b59..4ef6363 100644 --- a/server/menuHTTP.h +++ b/server/menuHTTP.h @@ -13,9 +13,10 @@ class cChannelIterator const cChannel *channel; protected: virtual const cChannel* NextChannel(const cChannel *Channel) = 0; + static inline const cChannel* SkipFakeGroups(const cChannel *Channel); public: const cChannel* Next(); - cChannelIterator(cChannel *First); + cChannelIterator(const cChannel *First); virtual ~cChannelIterator() {}; }; @@ -48,6 +49,8 @@ class cListGroups: public cChannelIterator class cListGroup: public cChannelIterator { + private: + static const cChannel* GetNextChannelInGroup(const cChannel *Channel); protected: virtual const cChannel* NextChannel(const cChannel *Channel); public: @@ -140,4 +143,11 @@ class cM3uChannelList: public cChannelList virtual ~cM3uChannelList(); }; +inline const cChannel* cChannelIterator::SkipFakeGroups(const cChannel* Group) +{ + while (Group && Group->GroupSep() && !*Group->Name()) + Group = Channels.Next(Group); + return Group; +} + #endif diff --git a/server/po/de_DE.po b/server/po/de_DE.po new file mode 100644 index 0000000..5fb611d --- /dev/null +++ b/server/po/de_DE.po @@ -0,0 +1,83 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2008 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Frank Schmirler <vdrdev@schmirler.de>, 2008 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev 0.5.0\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\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" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "VDR Streaming Server" +msgstr "VDR Streaming Server" + +msgid "Streaming active" +msgstr "Streamen im Gange" + +msgid "Suspend Live TV" +msgstr "Live-TV pausieren" + +msgid "Offer suspend mode" +msgstr "Pausieren anbieten" + +msgid "Always suspended" +msgstr "Immer pausiert" + +msgid "Never suspended" +msgstr "Nie pausiert" + +msgid "Common Settings" +msgstr "Allgemeines" + +msgid "Maximum Number of Clients" +msgstr "Maximalanzahl an Clients" + +msgid "Suspend behaviour" +msgstr "Pausierverhalten" + +msgid "Client may suspend" +msgstr "Client darf pausieren" + +msgid "VDR-to-VDR Server" +msgstr "VDR-zu-VDR Server" + +msgid "Start VDR-to-VDR Server" +msgstr "VDR-zu-VDR Server starten" + +msgid "VDR-to-VDR Server Port" +msgstr "Port des VDR-zu-VDR Servers" + +msgid "Bind to IP" +msgstr "Binde an IP" + +msgid "HTTP Server" +msgstr "HTTP Server" + +msgid "Start HTTP Server" +msgstr "HTTP Server starten" + +msgid "HTTP Server Port" +msgstr "Port des HTTP Servers" + +msgid "HTTP Streamtype" +msgstr "HTTP Streamtyp" + +msgid "Multicast Streaming Server" +msgstr "Multicast Streaming Server" + +msgid "Start IGMP Server" +msgstr "IGMP Server starten" + +msgid "Multicast Client Port" +msgstr "Port des Multicast Clients" + +msgid "Multicast Streamtype" +msgstr "Multicast Streamtyp" + diff --git a/server/po/fi_FI.po b/server/po/fi_FI.po new file mode 100644 index 0000000..99c6ee5 --- /dev/null +++ b/server/po/fi_FI.po @@ -0,0 +1,83 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2008 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Rolf Ahrenberg <rahrenbe@cc.hut.fi>, 2008 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev 0.5.0\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\n" +"PO-Revision-Date: 2008-03-30 02:11+0200\n" +"Last-Translator: Rolf Ahrenberg <rahrenbe@cc.hut.fi>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "VDR Streaming Server" +msgstr "VDR-suoratoistopalvelin" + +msgid "Streaming active" +msgstr "Suoratoistopalvelin aktiivinen" + +msgid "Suspend Live TV" +msgstr "Pysyt suora TV-lhetys" + +msgid "Offer suspend mode" +msgstr "tyrkyt" + +msgid "Always suspended" +msgstr "aina" + +msgid "Never suspended" +msgstr "ei koskaan" + +msgid "Common Settings" +msgstr "Yleiset asetukset" + +msgid "Maximum Number of Clients" +msgstr "Suurin sallittu asiakkaiden mr" + +msgid "Suspend behaviour" +msgstr "Pysytystoiminto" + +msgid "Client may suspend" +msgstr "Asiakas saa pysytt palvelimen" + +msgid "VDR-to-VDR Server" +msgstr "VDR-palvelin" + +msgid "Start VDR-to-VDR Server" +msgstr "Kynnist VDR-palvelin" + +msgid "VDR-to-VDR Server Port" +msgstr "VDR-palvelimen portti" + +msgid "Bind to IP" +msgstr "Sido osoitteeseen" + +msgid "HTTP Server" +msgstr "HTTP-palvelin" + +msgid "Start HTTP Server" +msgstr "Kynnist HTTP-palvelin" + +msgid "HTTP Server Port" +msgstr "HTTP-palvelimen portti" + +msgid "HTTP Streamtype" +msgstr "HTTP-lhetysmuoto" + +msgid "Multicast Streaming Server" +msgstr "Multicast-suoratoistopalvelin" + +msgid "Start IGMP Server" +msgstr "Kynnist IGMP-palvelin" + +msgid "Multicast Client Port" +msgstr "Multicast-portti" + +msgid "Multicast Streamtype" +msgstr "Multicast-lhetysmuoto" + diff --git a/server/po/fr_FR.po b/server/po/fr_FR.po new file mode 100644 index 0000000..c4b458e --- /dev/null +++ b/server/po/fr_FR.po @@ -0,0 +1,83 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2008 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Frank Schmirler <vdrdev@schmirler.de>, 2008 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev 0.5.0\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\n" +"PO-Revision-Date: 2008-03-30 02:11+0200\n" +"Last-Translator: micky979 <micky979@free.fr>\n" +"Language-Team: <vdr@linuxtv.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "VDR Streaming Server" +msgstr "Serveur de streaming VDR" + +msgid "Streaming active" +msgstr "Streaming actif" + +msgid "Suspend Live TV" +msgstr "Suspendre Live TV" + +msgid "Offer suspend mode" +msgstr "Offrir le mode suspendre" + +msgid "Always suspended" +msgstr "Toujours suspendre" + +msgid "Never suspended" +msgstr "Jamais suspendre" + +msgid "Common Settings" +msgstr "Paramtres communs" + +msgid "Maximum Number of Clients" +msgstr "Nombre maximun de clients" + +msgid "Suspend behaviour" +msgstr "Suspendre" + +msgid "Client may suspend" +msgstr "Le client peut suspendre" + +msgid "VDR-to-VDR Server" +msgstr "VDR-to-VDR Serveur" + +msgid "Start VDR-to-VDR Server" +msgstr "Dmarrer le serveur VDR-to-VDR" + +msgid "VDR-to-VDR Server Port" +msgstr "Port du serveur VDR-to-VDR" + +msgid "Bind to IP" +msgstr "Attacher aux IP" + +msgid "HTTP Server" +msgstr "Serveur HTTP" + +msgid "Start HTTP Server" +msgstr "Dmarrer le serveur HTTP" + +msgid "HTTP Server Port" +msgstr "Port du serveur HTTP" + +msgid "HTTP Streamtype" +msgstr "Type de Streaming HTTP" + +msgid "Multicast Streaming Server" +msgstr "" + +msgid "Start IGMP Server" +msgstr "" + +msgid "Multicast Client Port" +msgstr "" + +msgid "Multicast Streamtype" +msgstr "" + diff --git a/server/po/it_IT.po b/server/po/it_IT.po new file mode 100644 index 0000000..c5eed57 --- /dev/null +++ b/server/po/it_IT.po @@ -0,0 +1,85 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2008 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Alberto Carraro <bertocar@tin.it>, 2001 +# Antonio Ospite <ospite@studenti.unina.it>, 2003 +# Sean Carlos <seanc@libero.it>, 2005 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev 0.5.0\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\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" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-15\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "VDR Streaming Server" +msgstr "Server trasmissione VDR" + +msgid "Streaming active" +msgstr "Trasmissione attiva" + +msgid "Suspend Live TV" +msgstr "Sospendi TV dal vivo" + +msgid "Offer suspend mode" +msgstr "Offri mod. sospensione" + +msgid "Always suspended" +msgstr "Sempre sospeso" + +msgid "Never suspended" +msgstr "Mai sospeso" + +msgid "Common Settings" +msgstr "Impostazioni comuni" + +msgid "Maximum Number of Clients" +msgstr "Numero massimo di Client" + +msgid "Suspend behaviour" +msgstr "Tipo sospensione" + +msgid "Client may suspend" +msgstr "Permetti sospensione al Client" + +msgid "VDR-to-VDR Server" +msgstr "Server VDR-a-VDR" + +msgid "Start VDR-to-VDR Server" +msgstr "Avvia Server VDR-a-VDR" + +msgid "VDR-to-VDR Server Port" +msgstr "Porta Server VDR-a-VDR" + +msgid "Bind to IP" +msgstr "IP associati" + +msgid "HTTP Server" +msgstr "Server HTTP" + +msgid "Start HTTP Server" +msgstr "Avvia Server HTTP" + +msgid "HTTP Server Port" +msgstr "Porta Server HTTP" + +msgid "HTTP Streamtype" +msgstr "Tipo flusso HTTP" + +msgid "Multicast Streaming Server" +msgstr "Server trasmissione Multicast" + +msgid "Start IGMP Server" +msgstr "Avvia Server IGMP" + +msgid "Multicast Client Port" +msgstr "Porta Client Multicast" + +msgid "Multicast Streamtype" +msgstr "Tipo flusso Multicast" + diff --git a/server/po/lt_LT.po b/server/po/lt_LT.po new file mode 100644 index 0000000..f12de4d --- /dev/null +++ b/server/po/lt_LT.po @@ -0,0 +1,83 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2008 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Frank Schmirler <vdrdev@schmirler.de>, 2008 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev 0.5.0\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\n" +"PO-Revision-Date: 2009-11-26 21:57+0200\n" +"Last-Translator: Valdemaras Pipiras <varas@ambernet.lt>\n" +"Language-Team: Lietuvių\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "VDR Streaming Server" +msgstr "VDR transliavimo serveris" + +msgid "Streaming active" +msgstr "Transliavimas vyksta" + +msgid "Suspend Live TV" +msgstr "Pristabdyti Live TV" + +msgid "Offer suspend mode" +msgstr "Klausti dėl sustabdymo" + +msgid "Always suspended" +msgstr "Visada stabdyti" + +msgid "Never suspended" +msgstr "Niekada nestabdyti" + +msgid "Common Settings" +msgstr "Bendri nustatymai" + +msgid "Maximum Number of Clients" +msgstr "Maksimalus klientų skaičius" + +msgid "Suspend behaviour" +msgstr "Pristabdyti veikimą" + +msgid "Client may suspend" +msgstr "Klientas gali pristabdyti" + +msgid "VDR-to-VDR Server" +msgstr "VDR-su-VDR Serveris" + +msgid "Start VDR-to-VDR Server" +msgstr "Paleisti VDR-su-VDR serverį" + +msgid "VDR-to-VDR Server Port" +msgstr "VDR-su-VDR Serverio portas" + +msgid "Bind to IP" +msgstr "Pririšti IP" + +msgid "HTTP Server" +msgstr "HTTP Serveris" + +msgid "Start HTTP Server" +msgstr "Paleisti HTTP serverį" + +msgid "HTTP Server Port" +msgstr "HTTP serverio portas" + +msgid "HTTP Streamtype" +msgstr "HTTP transliavimo tipas" + +msgid "Multicast Streaming Server" +msgstr "Multicast transliavimo serveris" + +msgid "Start IGMP Server" +msgstr "Paleisti IGMP serverį" + +msgid "Multicast Client Port" +msgstr "Multicast kliento portas" + +msgid "Multicast Streamtype" +msgstr "Multicast transliavimo tipas" + diff --git a/server/po/ru_RU.po b/server/po/ru_RU.po new file mode 100644 index 0000000..21abeaf --- /dev/null +++ b/server/po/ru_RU.po @@ -0,0 +1,83 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2008 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Frank Schmirler <vdrdev@schmirler.de>, 2008 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev 0.5.0\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\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" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "VDR Streaming Server" +msgstr "VDR Streaming " + +msgid "Streaming active" +msgstr " " + +msgid "Suspend Live TV" +msgstr " Live TV" + +msgid "Offer suspend mode" +msgstr " " + +msgid "Always suspended" +msgstr " " + +msgid "Never suspended" +msgstr " " + +msgid "Common Settings" +msgstr "" + +msgid "Maximum Number of Clients" +msgstr ". " + +msgid "Suspend behaviour" +msgstr " " + +msgid "Client may suspend" +msgstr " " + +msgid "VDR-to-VDR Server" +msgstr "VDR-to-VDR " + +msgid "Start VDR-to-VDR Server" +msgstr " VDR-to-VDR " + +msgid "VDR-to-VDR Server Port" +msgstr "VDR-to-VDR " + +msgid "Bind to IP" +msgstr " IP" + +msgid "HTTP Server" +msgstr "HTTP " + +msgid "Start HTTP Server" +msgstr " HTTP " + +msgid "HTTP Server Port" +msgstr "HTTP " + +msgid "HTTP Streamtype" +msgstr " HTTP " + +msgid "Multicast Streaming Server" +msgstr "" + +msgid "Start IGMP Server" +msgstr "" + +msgid "Multicast Client Port" +msgstr "" + +msgid "Multicast Streamtype" +msgstr "" + diff --git a/server/po/sk_SK.po b/server/po/sk_SK.po new file mode 100644 index 0000000..78d98c9 --- /dev/null +++ b/server/po/sk_SK.po @@ -0,0 +1,85 @@ +# VDR streamdev plugin language source file. +# Copyright (C) 2009 streamdev development team. See http://streamdev.vdr-developer.org +# This file is distributed under the same license as the VDR streamdev package. +# Milan Hrala <hrala.milan@gmail.com>, 2009 +# +msgid "" +msgstr "" +"Project-Id-Version: streamdev_SK\n" +"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n" +"POT-Creation-Date: 2010-06-14 13:06+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: Milan Hrala <hrala.milan@gmail.com>\n" +"Language-Team: Slovak <hrala.milan@gmail.com>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-2\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Slovak\n" +"X-Poedit-Country: SLOVAKIA\n" + +msgid "VDR Streaming Server" +msgstr "VDR prdov server" + +msgid "Streaming active" +msgstr "streamovanie aktivne" + +msgid "Suspend Live TV" +msgstr "Pozastavenie ivho vysielania" + +msgid "Offer suspend mode" +msgstr "Vber remu pozastavenia" + +msgid "Always suspended" +msgstr "Vdy pozastavi" + +msgid "Never suspended" +msgstr "Nikdy nepozastavi" + +msgid "Common Settings" +msgstr "Veobecn nastavenia" + +msgid "Maximum Number of Clients" +msgstr "Maximly poet klientov" + +msgid "Suspend behaviour" +msgstr "Sprvanie preruenia" + +msgid "Client may suspend" +msgstr "Klient me pozastavi" + +msgid "VDR-to-VDR Server" +msgstr "VDR-do-VDR server" + +msgid "Start VDR-to-VDR Server" +msgstr "Spusti VDR-do-VDR Server" + +msgid "VDR-to-VDR Server Port" +msgstr "Port serveru pre VDR-do-VDR" + +msgid "Bind to IP" +msgstr "viaza na IP" + +msgid "HTTP Server" +msgstr "server HTTP" + +msgid "Start HTTP Server" +msgstr "Spusti HTTP Server" + +msgid "HTTP Server Port" +msgstr "Port serveru HTTP" + +msgid "HTTP Streamtype" +msgstr "typ prdu HTTP" + +msgid "Multicast Streaming Server" +msgstr "Multicast prdov server" + +msgid "Start IGMP Server" +msgstr "Spusti IGMP Server" + +msgid "Multicast Client Port" +msgstr "Port klienta Multicast" + +msgid "Multicast Streamtype" +msgstr "Multicast typ streamu" + diff --git a/server/setup.c b/server/setup.c index db709db..8c9b8ad 100644 --- a/server/setup.c +++ b/server/setup.c @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.9 2009/10/13 06:38:47 schmirl Exp $ + * $Id: setup.c,v 1.10 2010/07/19 13:49:31 schmirl Exp $ */ #include <vdr/menuitems.h> @@ -50,7 +50,7 @@ const char* cStreamdevServerMenuSetupPage::StreamTypes[st_Count - 1] = { "PES", "PS", "ES", - "Extern" + "EXT" }; const char* cStreamdevServerMenuSetupPage::SuspendModes[sm_Count] = { @@ -62,15 +62,25 @@ const char* cStreamdevServerMenuSetupPage::SuspendModes[sm_Count] = { cStreamdevServerMenuSetupPage::cStreamdevServerMenuSetupPage(void) { m_NewSetup = StreamdevServerSetup; + Set(); +} + +cStreamdevServerMenuSetupPage::~cStreamdevServerMenuSetupPage() { +} + +void cStreamdevServerMenuSetupPage::Set(void) { static const char* modes[sm_Count]; for (int i = 0; i < sm_Count; i++) modes[i] = tr(SuspendModes[i]); + int current = Current(); + Clear(); AddCategory (tr("Common Settings")); Add(new cMenuEditIntItem (tr("Maximum Number of Clients"), &m_NewSetup.MaxClients, 0, 100)); Add(new cMenuEditStraItem(tr("Suspend behaviour"), &m_NewSetup.SuspendMode, sm_Count, modes)); - Add(new cMenuEditBoolItem(tr("Client may suspend"), &m_NewSetup.AllowSuspend)); + if (m_NewSetup.SuspendMode == smOffer) + Add(new cMenuEditBoolItem(tr("Client may suspend"), &m_NewSetup.AllowSuspend)); AddCategory (tr("VDR-to-VDR Server")); Add(new cMenuEditBoolItem(tr("Start VDR-to-VDR Server"), &m_NewSetup.StartVTPServer)); @@ -87,10 +97,8 @@ cStreamdevServerMenuSetupPage::cStreamdevServerMenuSetupPage(void) { Add(new cMenuEditIntItem (tr("Multicast Client Port"), &m_NewSetup.IGMPClientPort, 0, 65535)); Add(new cMenuEditStraItem(tr("Multicast Streamtype"), &m_NewSetup.IGMPStreamType, st_Count - 1, StreamTypes)); Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.IGMPBindIP)); - SetCurrent(Get(1)); -} - -cStreamdevServerMenuSetupPage::~cStreamdevServerMenuSetupPage() { + SetCurrent(Get(current)); + Display(); } void cStreamdevServerMenuSetupPage::AddCategory(const char *Title) { @@ -139,3 +147,10 @@ void cStreamdevServerMenuSetupPage::Store(void) { cStreamdevServer::Initialize(); } +eOSState cStreamdevServerMenuSetupPage::ProcessKey(eKeys Key) { + int oldMode = m_NewSetup.SuspendMode; + eOSState state = cMenuSetupPage::ProcessKey(Key); + if (oldMode != m_NewSetup.SuspendMode) + Set(); + return state; +} diff --git a/server/setup.h b/server/setup.h index d22ab34..9f06aac 100644 --- a/server/setup.h +++ b/server/setup.h @@ -1,5 +1,5 @@ /* - * $Id: setup.h,v 1.3 2009/09/18 10:43:26 schmirl Exp $ + * $Id: setup.h,v 1.4 2010/07/19 13:49:31 schmirl Exp $ */ #ifndef VDR_STREAMDEV_SETUPSERVER_H @@ -37,8 +37,10 @@ private: cStreamdevServerSetup m_NewSetup; void AddCategory(const char *Title); + void Set(); protected: virtual void Store(void); + virtual eOSState ProcessKey(eKeys Key); public: cStreamdevServerMenuSetupPage(void); diff --git a/server/streamdev-server.c b/server/streamdev-server.c new file mode 100644 index 0000000..b444df7 --- /dev/null +++ b/server/streamdev-server.c @@ -0,0 +1,143 @@ +/* + * streamdev.c: A plugin for the Video Disk Recorder + * + * See the README file for copyright information and how to reach the author. + * + * $Id: streamdev-server.c,v 1.2 2010/07/19 13:49:32 schmirl Exp $ + */ + +#include <getopt.h> +#include <vdr/tools.h> +#include "streamdev-server.h" +#include "server/setup.h" +#include "server/server.h" +#include "server/suspend.h" + +#if !defined(APIVERSNUM) || APIVERSNUM < 10509 +#error "VDR-1.5.9 API version or greater is required!" +#endif + +const char *cPluginStreamdevServer::DESCRIPTION = trNOOP("VDR Streaming Server"); + +cPluginStreamdevServer::cPluginStreamdevServer(void) +{ +} + +cPluginStreamdevServer::~cPluginStreamdevServer() +{ + free(opt_auth); + free(opt_remux); +} + +const char *cPluginStreamdevServer::Description(void) +{ + return tr(DESCRIPTION); +} + +const char *cPluginStreamdevServer::CommandLineHelp(void) +{ + // return a string that describes all known command line options. + return + " -a <LOGIN:PASSWORD>, --auth=<LOGIN:PASSWORD> Credentials for HTTP authentication.\n" + " -r <CMD>, --remux=<CMD> Define an external command for remuxing.\n" + ; +} + +bool cPluginStreamdevServer::ProcessArgs(int argc, char *argv[]) +{ + // implement command line argument processing here if applicable. + static const struct option long_options[] = { + { "auth", required_argument, NULL, 'a' }, + { "remux", required_argument, NULL, 'r' }, + { NULL, 0, NULL, 0 } + }; + + int c; + while((c = getopt_long(argc, argv, "a:r:", long_options, NULL)) != -1) { + switch (c) { + case 'a': + { + if (opt_auth) + free(opt_auth); + int l = strlen(optarg); + cBase64Encoder Base64((uchar*) optarg, l, l * 4 / 3 + 3); + const char *s = Base64.NextLine(); + if (s) + opt_auth = strdup(s); + } + break; + case 'r': + if (opt_remux) + free(opt_remux); + opt_remux = strdup(optarg); + break; + default: + return false; + } + } + return true; +} + +bool cPluginStreamdevServer::Start(void) +{ + I18nRegister(PLUGIN_NAME_I18N); + if (!StreamdevHosts.Load(STREAMDEVHOSTSPATH, true, true)) { + esyslog("streamdev-server: error while loading %s", STREAMDEVHOSTSPATH); + fprintf(stderr, "streamdev-server: error while loading %s\n", STREAMDEVHOSTSPATH); + if (access(STREAMDEVHOSTSPATH, F_OK) != 0) { + fprintf(stderr, " Please install streamdevhosts.conf into the path " + "printed above. Without it\n" + " no client will be able to access your streaming-" + "server. An example can be\n" + " found together with this plugin's sources.\n"); + } + return false; + } + if (!opt_remux) + opt_remux = strdup(DEFAULT_EXTERNREMUX); + + cStreamdevServer::Initialize(); + + return true; +} + +void cPluginStreamdevServer::Stop(void) +{ + cStreamdevServer::Destruct(); +} + +cString cPluginStreamdevServer::Active(void) +{ + if (cStreamdevServer::Active()) + { + static const char *Message = NULL; + if (!Message) Message = tr("Streaming active"); + return Message; + } + return NULL; +} + +const char *cPluginStreamdevServer::MainMenuEntry(void) +{ + if (StreamdevServerSetup.SuspendMode == smOffer && !cSuspendCtl::IsActive()) + return tr("Suspend Live TV"); + return NULL; +} + +cOsdObject *cPluginStreamdevServer::MainMenuAction(void) +{ + cControl::Launch(new cSuspendCtl); + return NULL; +} + +cMenuSetupPage *cPluginStreamdevServer::SetupMenu(void) +{ + return new cStreamdevServerMenuSetupPage; +} + +bool cPluginStreamdevServer::SetupParse(const char *Name, const char *Value) +{ + return StreamdevServerSetup.SetupParse(Name, Value); +} + +VDRPLUGINCREATOR(cPluginStreamdevServer); // Don't touch this! diff --git a/server/streamdev-server.h b/server/streamdev-server.h new file mode 100644 index 0000000..4083689 --- /dev/null +++ b/server/streamdev-server.h @@ -0,0 +1,33 @@ +/* + * $Id: streamdev-server.h,v 1.2 2010/07/19 13:49:32 schmirl Exp $ + */ + +#ifndef VDR_STREAMDEVSERVER_H +#define VDR_STREAMDEVSERVER_H + +#include "common.h" + +#include <vdr/plugin.h> + +class cPluginStreamdevServer : public cPlugin { +private: + static const char *DESCRIPTION; + +public: + cPluginStreamdevServer(void); + virtual ~cPluginStreamdevServer(); + + virtual const char *Version(void) { return VERSION; } + virtual const char *Description(void); + virtual const char *CommandLineHelp(void); + virtual bool ProcessArgs(int argc, char *argv[]); + virtual bool Start(void); + virtual void Stop(void); + virtual cString Active(void); + virtual const char *MainMenuEntry(void); + virtual cOsdObject *MainMenuAction(void); + virtual cMenuSetupPage *SetupMenu(void); + virtual bool SetupParse(const char *Name, const char *Value); +}; + +#endif // VDR_STREAMDEVSERVER_H diff --git a/server/streamer.c b/server/streamer.c index 42e7efa..ec7d3c3 100644 --- a/server/streamer.c +++ b/server/streamer.c @@ -1,5 +1,5 @@ /* - * $Id: streamer.c,v 1.19 2009/06/19 06:32:45 schmirl Exp $ + * $Id: streamer.c,v 1.21 2010/07/30 10:01:11 schmirl Exp $ */ #include <vdr/ringbuffer.h> @@ -46,6 +46,9 @@ void cStreamdevWriter::Action(void) uchar *block = NULL; int count, offset = 0; +#if APIVERSNUM >= 10705 + SetPriority(-3); +#endif sel.Clear(); sel.Add(*m_Socket, true); while (Running()) { @@ -100,8 +103,9 @@ void cStreamdevWriter::Action(void) // --- cStreamdevStreamer ----------------------------------------------------- -cStreamdevStreamer::cStreamdevStreamer(const char *Name): +cStreamdevStreamer::cStreamdevStreamer(const char *Name, const cServerConnection *Connection): cThread(Name), + m_Connection(Connection), m_Writer(NULL), m_RingBuffer(new cStreamdevBuffer(STREAMERBUFSIZE, TS_SIZE * 2, true, "streamdev-streamer")), @@ -148,6 +152,9 @@ void cStreamdevStreamer::Stop(void) void cStreamdevStreamer::Action(void) { +#if APIVERSNUM >= 10705 + SetPriority(-3); +#endif while (Running()) { int got; uchar *block = m_RingBuffer->Get(got); diff --git a/server/streamer.h b/server/streamer.h index 6561bc2..988775a 100644 --- a/server/streamer.h +++ b/server/streamer.h @@ -1,5 +1,5 @@ /* - * $Id: streamer.h,v 1.11 2009/06/19 06:32:45 schmirl Exp $ + * $Id: streamer.h,v 1.12 2010/07/19 13:49:32 schmirl Exp $ */ #ifndef VDR_STREAMDEV_STREAMER_H @@ -11,6 +11,7 @@ class cTBSocket; class cStreamdevStreamer; +class cServerConnection; #ifndef TS_SIZE #define TS_SIZE 188 @@ -64,6 +65,7 @@ public: class cStreamdevStreamer: public cThread { private: + const cServerConnection *m_Connection; cStreamdevWriter *m_Writer; cStreamdevBuffer *m_RingBuffer; cStreamdevBuffer *m_SendBuffer; @@ -74,9 +76,11 @@ protected: bool IsRunning(void) const { return m_Writer; } public: - cStreamdevStreamer(const char *Name); + cStreamdevStreamer(const char *Name, const cServerConnection *Connection = NULL); virtual ~cStreamdevStreamer(); + const cServerConnection* Connection(void) const { return m_Connection; } + virtual void Start(cTBSocket *Socket); virtual void Stop(void); bool Abort(void); |