mirror of
https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
synced 2023-10-10 19:16:51 +02:00
Streamdev 0.5.0-rc1
This commit is contained in:
parent
435f01649c
commit
11b22d9f33
37
CONTRIBUTORS
37
CONTRIBUTORS
@ -12,14 +12,14 @@ The Metzler Brothers
|
|||||||
as a lot of code has been taken from their libdvbmpeg package
|
as a lot of code has been taken from their libdvbmpeg package
|
||||||
|
|
||||||
Angelus (DOm)
|
Angelus (DOm)
|
||||||
for providing italian language texts
|
for providing Italian language texts
|
||||||
for reporting problems with the Elchi-Patch
|
for reporting problems with the Elchi-Patch
|
||||||
|
|
||||||
Michal
|
Michal
|
||||||
for sending a patch to select the HTTP streamtype via remote
|
for sending a patch to select the HTTP streamtype via remote
|
||||||
|
|
||||||
Rolf Ahrenberg
|
Rolf Ahrenberg
|
||||||
for providing finnish language texts
|
for providing Finnish language texts
|
||||||
for adding externremux.sh commandline parameter
|
for adding externremux.sh commandline parameter
|
||||||
for silencing compiler warnings
|
for silencing compiler warnings
|
||||||
for adding PAT, PMT, PCR and EIT to HTTP TS streams
|
for adding PAT, PMT, PCR and EIT to HTTP TS streams
|
||||||
@ -35,6 +35,9 @@ Rolf Ahrenberg
|
|||||||
for improving externremux script termination
|
for improving externremux script termination
|
||||||
for fixing PAT repacker version field
|
for fixing PAT repacker version field
|
||||||
for improving LIMIKUUTIO and PARENTALRATING patch detection
|
for improving LIMIKUUTIO and PARENTALRATING patch detection
|
||||||
|
for suggesting to include the charset in HTTP replies
|
||||||
|
for requesting replacement of asprintf calls
|
||||||
|
for suggesting to change the URL path from EXTERN to EXT
|
||||||
|
|
||||||
Rantanen Teemu
|
Rantanen Teemu
|
||||||
for providing vdr-incompletesections.diff
|
for providing vdr-incompletesections.diff
|
||||||
@ -54,6 +57,7 @@ Udo Richter
|
|||||||
for speeding up cPluginStreamdevServer::Active()
|
for speeding up cPluginStreamdevServer::Active()
|
||||||
for adapting to VDR 1.5.0 API
|
for adapting to VDR 1.5.0 API
|
||||||
for adapting to VDR 1.7.1
|
for adapting to VDR 1.7.1
|
||||||
|
for proper tsplay-0.2 patch detection
|
||||||
|
|
||||||
greenman
|
greenman
|
||||||
for reporting that the log could get flooded on connection failures.
|
for reporting that the log could get flooded on connection failures.
|
||||||
@ -88,10 +92,10 @@ tobi
|
|||||||
for pointing to unused files in the libdvbmpeg directory
|
for pointing to unused files in the libdvbmpeg directory
|
||||||
|
|
||||||
Diego Pierotto
|
Diego Pierotto
|
||||||
for providing italian language texts
|
for providing Italian language texts
|
||||||
|
|
||||||
micky979
|
micky979
|
||||||
for providing french language texts
|
for providing French language texts
|
||||||
|
|
||||||
Tiroler
|
Tiroler
|
||||||
for reporting a problem when switching between encrypted channels
|
for reporting a problem when switching between encrypted channels
|
||||||
@ -100,10 +104,12 @@ Pixelpeter
|
|||||||
for an initial fix to the "switching between ecncrypted channels" problem
|
for an initial fix to the "switching between ecncrypted channels" problem
|
||||||
|
|
||||||
Anssi Hannula
|
Anssi Hannula
|
||||||
for the vdr-1.6.0-ignore_missing_cam.diff patch
|
for the vdr-1.6.0-intcamdevices patch
|
||||||
|
for fixing insecure format strings in LSTX handlers
|
||||||
|
|
||||||
wirbel
|
wirbel
|
||||||
for pointing out that section filtering is optional for VDR devices
|
for pointing out that section filtering is optional for VDR devices
|
||||||
|
for reporting a problem with Makefile defines in VDR 1.7.4+
|
||||||
|
|
||||||
Jori Hamalainen
|
Jori Hamalainen
|
||||||
for extensive testing while making stream compatible to Network Media Tank
|
for extensive testing while making stream compatible to Network Media Tank
|
||||||
@ -111,6 +117,7 @@ Jori Hamalainen
|
|||||||
|
|
||||||
owagner
|
owagner
|
||||||
for pointing out a problem with the encrypted channel switching fix
|
for pointing out a problem with the encrypted channel switching fix
|
||||||
|
for suggesting use of SO_KEEPALIVE socket option to detect dead sockets
|
||||||
|
|
||||||
Joachim König-Baltes
|
Joachim König-Baltes
|
||||||
for fixing Min/MaxPriority parsing
|
for fixing Min/MaxPriority parsing
|
||||||
@ -120,3 +127,23 @@ Artem Makhutov
|
|||||||
|
|
||||||
Alwin Esch
|
Alwin Esch
|
||||||
for adding XBMC support by extending VTP capabilities
|
for adding XBMC support by extending VTP capabilities
|
||||||
|
for adding VDR 1.7.11 parental rating support for VTP LSTE command
|
||||||
|
for adding the DELT FORCE option to delete running timers
|
||||||
|
|
||||||
|
BBlack
|
||||||
|
for reporting that updating recordings list on CmdPLAY is a bad idea
|
||||||
|
|
||||||
|
Milan Hrala
|
||||||
|
for providing Slovak language texts
|
||||||
|
|
||||||
|
Valdemaras Pipiras
|
||||||
|
for providing Lithuanian language texts
|
||||||
|
|
||||||
|
sk8ter
|
||||||
|
for fixing failures when switching between two encrypted channels
|
||||||
|
|
||||||
|
lhanisch
|
||||||
|
for fixing a memory leak in cStreamdevPatFilter::GetPid
|
||||||
|
|
||||||
|
Eric Valette
|
||||||
|
for adding support for EnhancedAC3
|
||||||
|
45
HISTORY
45
HISTORY
@ -1,6 +1,51 @@
|
|||||||
VDR Plugin 'streamdev' Revision History
|
VDR Plugin 'streamdev' Revision History
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
- config option "client may suspend" hidden if not applicable
|
||||||
|
- updated and enhanced README
|
||||||
|
- separated language resources of client and server
|
||||||
|
- restructured build process
|
||||||
|
- added support for HTTP method HEAD
|
||||||
|
- rewrite of externremux.sh, including support for various URL parameters,
|
||||||
|
logging and improved shutdown
|
||||||
|
- start externremux script in a separate process group
|
||||||
|
- changed HTTP URL path for externremux from EXTERN to EXT (suggested by
|
||||||
|
Rolf Ahrenberg)
|
||||||
|
- HTTP headers now have to be emitted by externremux script
|
||||||
|
- pass channel related information and URL parameters to externremux script
|
||||||
|
through environment
|
||||||
|
- implement CGI like interface for externremux script
|
||||||
|
- dropped "Synchronize EPG" feature. Please use epgsync-plugin instead
|
||||||
|
(available from http://vdr.schmirler.de)
|
||||||
|
- proper tsplay-0.2 patch detection. tsplay-0.1 is no longer recognized
|
||||||
|
(thanks to Udo Richter)
|
||||||
|
- added compatibility with VDR 1.6 tsplay-0.1 patch
|
||||||
|
- added support for EnhancedAC3 (thanks to Eric Valette)
|
||||||
|
- fixed a memory leak in cStreamdevPatFilter::GetPid (thanks to lhanisch)
|
||||||
|
- length -1 is the correct value for streams in M3U playlists
|
||||||
|
- switching between two encrypted channels on the same transponder didn't
|
||||||
|
always work (thanks to sk8ter@vdrportal)
|
||||||
|
- added DELT FORCE option to delete running timers (thanks to Alwin Esch)
|
||||||
|
- added VDR 1.7.11 parental rating support for VTP LSTE command (thanks to
|
||||||
|
Alwin Esch)
|
||||||
|
- added Lithuanian translation (thanks to Valdemaras Pipiras)
|
||||||
|
- fixed missing virtual destructor for cTSRemux
|
||||||
|
- added defines for large file support to Makefile as required by VDR 1.7.4+
|
||||||
|
(reported by wirbel@vdrportal)
|
||||||
|
- added Slovak translation (thanks to Milan Hrala)
|
||||||
|
- fixed regression from fix for switching between encrypted channels. It was
|
||||||
|
no longer possible to receive multiple (FTA) streams from the same
|
||||||
|
transponder
|
||||||
|
- silenced warnings concerning asprintf (requested by Rolf Ahrenberg)
|
||||||
|
- don't update recordings list on CmdPLAY (reported by BBlack)
|
||||||
|
- cleaned up common.h / common.c
|
||||||
|
- dropped cStreamdevMenuSetupPage
|
||||||
|
- report charset in HTTP replies (suggested by Rolf Ahrenberg)
|
||||||
|
- use SO_KEEPALIVE option on all sockets do detect dead sockets (thanks to
|
||||||
|
owagner)
|
||||||
|
- enable PatFilter for externremux, so VLC can be used as remuxer or client
|
||||||
|
- fixed insecure format strings in LSTX handlers (thanks to Anssi Hannula)
|
||||||
|
- updated Finish translation (thanks to Rolf Ahrenberg)
|
||||||
- removed redefinitions in includes - caused problems in older compilers
|
- removed redefinitions in includes - caused problems in older compilers
|
||||||
- fixed ts2ps.h defines
|
- fixed ts2ps.h defines
|
||||||
- fixed missing virtual for cTS2PESRemux destructor
|
- fixed missing virtual for cTS2PESRemux destructor
|
||||||
|
149
Makefile
149
Makefile
@ -1,36 +1,57 @@
|
|||||||
#
|
#
|
||||||
# Makefile for a Video Disk Recorder plugin
|
# Makefile for a Video Disk Recorder plugin
|
||||||
#
|
#
|
||||||
# $Id: Makefile,v 1.19 2009/07/01 10:46:15 schmirl Exp $
|
# $Id: Makefile,v 1.21.2.1 2010/06/14 10:40:11 schmirl Exp $
|
||||||
|
|
||||||
# The official name of this plugin.
|
# The main source file name.
|
||||||
# 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
|
PLUGIN = streamdev
|
||||||
|
|
||||||
|
### The C/C++ compiler and options:
|
||||||
|
|
||||||
|
CC ?= gcc
|
||||||
|
CFLAGS ?= -g -O2 -Wall
|
||||||
|
|
||||||
|
CXX ?= g++
|
||||||
|
CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual -Wno-parentheses
|
||||||
|
|
||||||
### The version number of this plugin (taken from the main source file):
|
### The version number of this plugin (taken from the main source file):
|
||||||
|
|
||||||
VERSION = $(shell grep 'const char \*VERSION *=' common.c | awk '{ print $$5 }' | sed -e 's/[";]//g')
|
VERSION = $(shell grep 'const char \*VERSION *=' common.c | awk '{ print $$5 }' | sed -e 's/[";]//g')
|
||||||
|
|
||||||
### The C++ compiler and options:
|
|
||||||
|
|
||||||
CXX ?= g++
|
|
||||||
CXXFLAGS ?= -fPIC -g -O2 -Wall -Woverloaded-virtual -Wno-parentheses
|
|
||||||
|
|
||||||
### The directory environment:
|
### The directory environment:
|
||||||
|
|
||||||
VDRDIR = ../../..
|
VDRDIR = ../../..
|
||||||
LIBDIR = ../../lib
|
LIBDIR = ../../lib
|
||||||
TMPDIR = /tmp
|
TMPDIR = /tmp
|
||||||
|
|
||||||
### Allow user defined options to overwrite defaults:
|
|
||||||
|
|
||||||
-include $(VDRDIR)/Make.config
|
|
||||||
|
|
||||||
### The version number of VDR (taken from VDR's "config.h"):
|
### The version number of VDR (taken from VDR's "config.h"):
|
||||||
|
|
||||||
APIVERSION = $(shell grep 'define APIVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
|
APIVERSION = $(shell grep 'define APIVERSION ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
|
||||||
|
APIVERSNUM = $(shell grep 'define APIVERSNUM ' $(VDRDIR)/config.h | awk '{ print $$3 }' | sed -e 's/"//g')
|
||||||
|
TSPLAYVERSNUM = $(shell grep 'define TSPLAY_PATCH_VERSION ' $(VDRDIR)/device.h | awk '{ print $$3 }')
|
||||||
|
|
||||||
|
### Allow user defined options to overwrite defaults:
|
||||||
|
|
||||||
|
ifeq ($(shell test $(APIVERSNUM) -ge 10713; echo $$?),0)
|
||||||
|
include $(VDRDIR)/Make.global
|
||||||
|
else ifeq ($(shell test $(APIVERSNUM) -ge 10704 -o -n "$(TSPLAYVERSNUM)" ; echo $$?),0)
|
||||||
|
DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
|
||||||
|
CFLAGS += -fPIC
|
||||||
|
CXXFLAGS += -fPIC
|
||||||
|
else
|
||||||
|
CFLAGS += -fPIC
|
||||||
|
CXXFLAGS += -fPIC
|
||||||
|
endif
|
||||||
|
|
||||||
|
-include $(VDRDIR)/Make.config
|
||||||
|
|
||||||
|
### export all vars for sub-makes, using absolute paths
|
||||||
|
|
||||||
|
VDRDIR := $(abspath $(VDRDIR))
|
||||||
|
LIBDIR := $(abspath $(LIBDIR))
|
||||||
|
export
|
||||||
|
unexport PLUGIN
|
||||||
|
|
||||||
### The name of the distribution archive:
|
### The name of the distribution archive:
|
||||||
|
|
||||||
@ -39,98 +60,33 @@ PACKAGE = vdr-$(ARCHIVE)
|
|||||||
|
|
||||||
### Includes and Defines (add further entries here):
|
### Includes and Defines (add further entries here):
|
||||||
|
|
||||||
INCLUDES += -I$(VDRDIR)/include -I.
|
INCLUDES += -I$(VDRDIR)/include -I..
|
||||||
|
|
||||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
DEFINES += -D_GNU_SOURCE
|
||||||
|
|
||||||
### The object files (add further files here):
|
|
||||||
|
|
||||||
COMMONOBJS = common.o \
|
|
||||||
\
|
|
||||||
tools/source.o tools/select.o tools/socket.o tools/tools.o
|
|
||||||
|
|
||||||
CLIENTOBJS = $(PLUGIN)-client.o \
|
|
||||||
\
|
|
||||||
client/socket.o client/device.o client/setup.o \
|
|
||||||
client/filter.o
|
|
||||||
|
|
||||||
|
|
||||||
SERVEROBJS = $(PLUGIN)-server.o \
|
|
||||||
\
|
|
||||||
server/server.o server/component.o server/connection.o \
|
|
||||||
server/componentVTP.o server/componentHTTP.o server/componentIGMP.o \
|
|
||||||
server/connectionVTP.o server/connectionHTTP.o server/connectionIGMP.o \
|
|
||||||
server/streamer.o server/livestreamer.o server/livefilter.o \
|
|
||||||
server/suspend.o server/setup.o server/menuHTTP.o server/recplayer.o \
|
|
||||||
remux/tsremux.o remux/ts2pes.o remux/ts2ps.o remux/ts2es.o remux/extern.o
|
|
||||||
|
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
DEFINES += -DDEBUG
|
DEFINES += -DDEBUG
|
||||||
|
endif
|
||||||
|
ifdef STREAMDEV_DEBUG
|
||||||
|
DEFINES += -DDEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
### The main target:
|
### The main target:
|
||||||
|
|
||||||
.PHONY: all i18n dist clean
|
.PHONY: all client server dist clean
|
||||||
all: libvdr-$(PLUGIN)-client.so libvdr-$(PLUGIN)-server.so i18n
|
all: client server
|
||||||
|
|
||||||
### Implicit rules:
|
|
||||||
|
|
||||||
%.o: %.c
|
|
||||||
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
|
|
||||||
|
|
||||||
# Dependencies:
|
|
||||||
|
|
||||||
MAKEDEP = $(CXX) -MM -MG
|
|
||||||
DEPFILE = .dependencies
|
|
||||||
ifdef GCC3
|
|
||||||
$(DEPFILE): Makefile
|
|
||||||
@rm -f $@
|
|
||||||
@for i in $(CLIENTOBJS:%.o=%.c) $(SERVEROBJS:%.o=%.c) $(COMMONOBJS:%.o=%.c) ; do \
|
|
||||||
$(MAKEDEP) $(DEFINES) $(INCLUDES) -MT "`dirname $$i`/`basename $$i .c`.o" $$i >>$@ ; \
|
|
||||||
done
|
|
||||||
else
|
|
||||||
$(DEPFILE): Makefile
|
|
||||||
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(CLIENTOBJS:%.o=%.c) $(SERVEROBJS:%.o=%.c) \
|
|
||||||
$(COMMONOBJS:%.o=%.c) > $@
|
|
||||||
endif
|
|
||||||
|
|
||||||
-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): $(CLIENTOBJS:%.o=%.c) $(SERVEROBJS:%.o=%.c) $(COMMONOBJS:%.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:
|
### Targets:
|
||||||
|
|
||||||
libdvbmpeg/libdvbmpegtools.a: libdvbmpeg/*.c libdvbmpeg/*.h
|
client:
|
||||||
$(MAKE) -C ./libdvbmpeg libdvbmpegtools.a
|
$(MAKE) -C ./tools
|
||||||
|
$(MAKE) -C ./client
|
||||||
|
|
||||||
libvdr-$(PLUGIN)-client.so: $(CLIENTOBJS) $(COMMONOBJS) libdvbmpeg/libdvbmpegtools.a
|
server:
|
||||||
libvdr-$(PLUGIN)-server.so: $(SERVEROBJS) $(COMMONOBJS) libdvbmpeg/libdvbmpegtools.a
|
$(MAKE) -C ./tools
|
||||||
|
$(MAKE) -C ./libdvbmpeg
|
||||||
%.so:
|
$(MAKE) -C ./remux
|
||||||
$(CXX) $(CXXFLAGS) -shared $^ -o $@
|
$(MAKE) -C ./server
|
||||||
@cp $@ $(LIBDIR)/$@.$(APIVERSION)
|
|
||||||
|
|
||||||
dist: clean
|
dist: clean
|
||||||
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
||||||
@ -141,5 +97,8 @@ dist: clean
|
|||||||
@echo Distribution package created as $(PACKAGE).tgz
|
@echo Distribution package created as $(PACKAGE).tgz
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@-rm -f $(COMMONOBJS) $(CLIENTOBJS) $(SERVEROBJS) $(DEPFILE) $(PODIR)/*.mo $(PODIR)/*.pot *.so *.tgz core* *~
|
$(MAKE) -C ./tools clean
|
||||||
$(MAKE) -C ./libdvbmpeg clean
|
$(MAKE) -C ./libdvbmpeg clean
|
||||||
|
$(MAKE) -C ./remux clean
|
||||||
|
$(MAKE) -C ./client clean
|
||||||
|
$(MAKE) -C ./server clean
|
||||||
|
225
README
225
README
@ -15,9 +15,9 @@ Contents:
|
|||||||
|
|
||||||
1. Description
|
1. Description
|
||||||
2. Installation
|
2. Installation
|
||||||
2.1 VDR 1.4.x and older
|
2.1 Compatibility
|
||||||
2.2 VDR 1.6.0 and above
|
2.2 Compiling
|
||||||
2.3 Updating from streamdev 0.3.x
|
2.3 Updating
|
||||||
3. Usage
|
3. Usage
|
||||||
3.1 Usage HTTP server
|
3.1 Usage HTTP server
|
||||||
3.2 Usage IGMP multicast server
|
3.2 Usage IGMP multicast server
|
||||||
@ -27,7 +27,8 @@ Contents:
|
|||||||
4.1 Plugins for VDR-to-VDR clients
|
4.1 Plugins for VDR-to-VDR clients
|
||||||
4.2 Plugins for Server
|
4.2 Plugins for Server
|
||||||
4.3 Alternatives
|
4.3 Alternatives
|
||||||
5. Known Problems
|
5. externremux.sh
|
||||||
|
6. Known Problems
|
||||||
|
|
||||||
|
|
||||||
1. Description:
|
1. Description:
|
||||||
@ -62,7 +63,7 @@ the PROTOCOL file.
|
|||||||
2. Installation:
|
2. Installation:
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Let's say streamdev's version is 0.4.0 and vdr's version is 1.X.X. If you
|
Let's say streamdev's version is 0.5.0 and vdr's version is 1.X.X. If you
|
||||||
use anything else please exchange the version numbers appropriately (this
|
use anything else please exchange the version numbers appropriately (this
|
||||||
way I don't have to update this section all the times;) ).
|
way I don't have to update this section all the times;) ).
|
||||||
|
|
||||||
@ -79,54 +80,71 @@ If you want to drive additional Input-Devices (with different sources) on the
|
|||||||
client, you can merge the channels.conf files. VDR will detect if the local
|
client, you can merge the channels.conf files. VDR will detect if the local
|
||||||
device or the network device can receive the channels.
|
device or the network device can receive the channels.
|
||||||
|
|
||||||
Last, but not least you have to copy the streamdev folder into the
|
Last, but not least you have to copy the streamdev-server folder into the
|
||||||
"plugins/streamdev" subfolder of VDR's config-directory (which is equal to your
|
"plugins/streamdev-server" subfolder of VDR's config-directory (which is equal
|
||||||
video-directory if not specified otherwise). For example, if you didn't specify
|
to your video-directory if not specified otherwise). For example, if you didn't
|
||||||
a separate config-directory, and specified your video directory as "/video0",
|
specify a separate config-directory, and set your video directory to "/video0",
|
||||||
the directory has to be copied to /video0/plugins/streamdev.
|
the directory has to be copied to /video0/plugins/streamdev-server.
|
||||||
|
|
||||||
The directory contains a file named streamdevhosts.conf which you must adjust
|
The directory contains a file named streamdevhosts.conf which you must adjust
|
||||||
to your needs. The syntax is the same as for svdrphosts.conf, so please consult
|
to your needs. The syntax is the same as for svdrphosts.conf, so please consult
|
||||||
VDR's documentation on how to fill that file, if you can't do it on-the-fly.
|
VDR's documentation on how to fill that file, if you can't do it on-the-fly.
|
||||||
|
|
||||||
There's also a sample externremux.sh script in this directory. It is used by
|
There's also a sample externremux.sh script in this directory. It is used by
|
||||||
streamdev's external remux feature. The sample script uses mencoder. Please
|
streamdev's external remux feature. The sample script uses mencoder by default.
|
||||||
check the script for further information. You can specify a different script
|
Please check the script for further information. You can specify a different
|
||||||
location with the -r parameter. The VDR commandline would then include a
|
script location with the -r parameter. The VDR commandline would then include a
|
||||||
"-P 'streamdev-server -r /usr/local/bin/remux.sh'". Note the additional quotes,
|
"-P 'streamdev-server -r /usr/local/bin/remux.sh'". Note the additional quotes,
|
||||||
as otherwise -r will be passed to VDR and not to streamdev.
|
as otherwise -r will be passed to VDR and not to streamdev.
|
||||||
|
|
||||||
|
|
||||||
2.1 VDR 1.4.x and older:
|
2.1 Compatibility:
|
||||||
------------------------
|
------------------
|
||||||
|
|
||||||
This version is not compatible to VDR releases older than 1.5.9. Take one of
|
This version is not compatible to VDR releases older than 1.5.9. Take one of
|
||||||
the streamdev-0.4.x releases if you are running at least VDR 1.4.x. For older
|
the streamdev-0.4.x releases if you are running at least VDR 1.4.x. For older
|
||||||
VDRs you will probably need one of the streamdev-0.3.x releases.
|
VDRs you will probably need one of the streamdev-0.3.x releases.
|
||||||
|
|
||||||
2.2 VDR 1.6.0 and above:
|
2.2 Compiling:
|
||||||
------------------------
|
--------------
|
||||||
|
|
||||||
cd vdr-1.X.X/PLUGINS/src
|
cd vdr-1.X.X/PLUGINS/src
|
||||||
tar xvfz vdr-streamdev-0.4.0.tgz
|
tar xvfz vdr-streamdev-0.5.0.tgz
|
||||||
ln -s streamdev-0.4.0 streamdev
|
ln -s streamdev-0.5.0 streamdev
|
||||||
cp -r streamdev/streamdev VDRCONFDIR/plugins/
|
cp -r streamdev/streamdev-server VDRCONFDIR/plugins/
|
||||||
cd ../..
|
cd ../..
|
||||||
make [options, if necessary] vdr
|
make [options, if necessary] vdr
|
||||||
make [options, if necessary] plugins
|
make [options, if necessary] plugins
|
||||||
|
|
||||||
2.3 Updating from streamdev 0.3.x
|
To build only the plugin, change into the streamdev source folder and issue
|
||||||
----------------------------------
|
make
|
||||||
|
|
||||||
Starting with streamdev 0.4.0, all additional files are kept in a directory
|
To build only streamdev-server or only streamdev-client, use
|
||||||
called "streamdev" inside VDR's plugin config directory. It is the new default
|
make server
|
||||||
location of externremux.sh and the new place where streamdev-server expects the
|
make client
|
||||||
file "streamdevhosts.conf". You will have to move this file to its new location:
|
|
||||||
|
|
||||||
mv VDRCONFDIR/plugins/streamdevhosts.conf VDRCONFDIR/plugins/streamdev/
|
2.3 Updating:
|
||||||
|
--------------
|
||||||
|
|
||||||
(Directory VDRCONFDIR/plugins/streamdev already exists, as you copied the
|
If you are updating streamdev from an earlier release, you might have to
|
||||||
whole folder from the sources directory as suggested above, right?)
|
perform some additional steps. Check which version you've been running before,
|
||||||
|
then read below for the necessary changes.
|
||||||
|
|
||||||
|
* Location of files:
|
||||||
|
--------------------
|
||||||
|
(Affected: 0.3.x, 0.4.x, 0.4.0pre, 0.5.0pre)
|
||||||
|
|
||||||
|
Starting with streamdev 0.5.0, all additional files are kept in a directory
|
||||||
|
called "streamdev-server" inside VDR's plugin config directory. It is the new
|
||||||
|
default location of externremux.sh and the new place where streamdev-server
|
||||||
|
expects the file "streamdevhosts.conf". You will have to move this file to its
|
||||||
|
new location:
|
||||||
|
|
||||||
|
streamdev 0.3.x:
|
||||||
|
mv VDRCONFDIR/plugins/streamdevhosts.conf VDRCONFDIR/plugins/streamdev-server/
|
||||||
|
|
||||||
|
streamdev 0.4.x, 0.4.0pre and 0.5.0pre:
|
||||||
|
mv VDRCONFDIR/plugins/streamdev VDRCONFDIR/plugins/streamdev-server/
|
||||||
|
|
||||||
Now check the contents of streamdevhosts.conf. Does it contain a "0.0.0.0/0"
|
Now check the contents of streamdevhosts.conf. Does it contain a "0.0.0.0/0"
|
||||||
entry? If your VDR machine is connected to the Internet, this line gives
|
entry? If your VDR machine is connected to the Internet, this line gives
|
||||||
@ -134,6 +152,21 @@ entry? If your VDR machine is connected to the Internet, this line gives
|
|||||||
prevent this (e.g. firewall). You might want to remove this line and enable
|
prevent this (e.g. firewall). You might want to remove this line and enable
|
||||||
HTTP authentication instead.
|
HTTP authentication instead.
|
||||||
|
|
||||||
|
* Handling of externremux script:
|
||||||
|
---------------------------------
|
||||||
|
(Affected: 0.3.x, 0.4.0pre, 0.5.0pre)
|
||||||
|
|
||||||
|
Streamdev server's externremux script became responsible for emitting all HTTP
|
||||||
|
headers. A quick and dirty extension to your current script would be:
|
||||||
|
|
||||||
|
echo -ne 'Content-type: video/mpeg\r\n'
|
||||||
|
echo -ne '\r\n'
|
||||||
|
|
||||||
|
However I encourage you to try the new externremux.sh script shipped with the
|
||||||
|
streamdev source distribution.
|
||||||
|
|
||||||
|
To emphasize the required change in externremux, the URL path for passing the
|
||||||
|
stream through externremux has changed from EXTERN to EXT.
|
||||||
|
|
||||||
3. Usage:
|
3. Usage:
|
||||||
---------
|
---------
|
||||||
@ -172,15 +205,15 @@ listen to with the parameter "HTTP Server Port". The parameter "HTTP Streamtype"
|
|||||||
allows you to specify a default stream type, which is used if no specific type
|
allows you to specify a default stream type, which is used if no specific type
|
||||||
has been requested in the URL (see below). The supported stream types are:
|
has been requested in the URL (see below). The supported stream types are:
|
||||||
|
|
||||||
TS Transport Stream (i.e. a dump from the device)
|
TS Transport Stream (i.e. a dump from the device)
|
||||||
PES Packetized Elemetary Stream (VDR's native recording format)
|
PES Packetized Elemetary Stream (VDR's native recording format)
|
||||||
PS Program Stream (SVCD, DVD like stream)
|
PS Program Stream (SVCD, DVD like stream)
|
||||||
ES Elementary Stream (only Video, if available, otherwise only Audio)
|
ES Elementary Stream (only Video, if available, otherwise only Audio)
|
||||||
EXTERN Pass stream through external script (e.g. for converting with mencoder)
|
EXT Pass stream through external script (e.g. for converting with mencoder)
|
||||||
|
|
||||||
Assuming that you leave the default port (3000), point your web browser to
|
Assuming that you leave the default port (3000), point your web browser to
|
||||||
|
|
||||||
http://hostname:3000/
|
http://hostname:3000/
|
||||||
|
|
||||||
You will be presented a menu with links to various channel lists, including M3U
|
You will be presented a menu with links to various channel lists, including M3U
|
||||||
playlist formats.
|
playlist formats.
|
||||||
@ -188,27 +221,28 @@ playlist formats.
|
|||||||
If you don't want to use the HTML menu or the M3U playlists, you can access the
|
If you don't want to use the HTML menu or the M3U playlists, you can access the
|
||||||
streams directly like this:
|
streams directly like this:
|
||||||
|
|
||||||
http://hostname:3000/3
|
http://hostname:3000/3
|
||||||
http://hostname:3000/S19.2E-0-12480-898
|
http://hostname:3000/S19.2E-0-12480-898
|
||||||
|
|
||||||
The first one will deliver a channel by number on the server, the second one
|
The first one will deliver a channel by number on the server, the second one
|
||||||
will request the channel by unique channel id. In addition, you can specify
|
will request the channel by unique channel id. In addition, you can specify
|
||||||
the desired stream type as a path to the channel.
|
the desired stream type as a path to the channel.
|
||||||
|
|
||||||
http://hostname:3000/TS/3
|
http://hostname:3000/TS/3
|
||||||
http://hostname:3000/PES/S19.2E-0-12480-898
|
http://hostname:3000/PES/S19.2E-0-12480-898
|
||||||
|
|
||||||
The first one would deliver the stream in TS, the second one in PES format.
|
The first one would deliver the stream in TS, the second one in PES format.
|
||||||
Possible values are 'PES', 'TS', 'PS', 'ES' and 'EXTERN'. You need to specify
|
Possible values are 'PES', 'TS', 'PS', 'ES' and 'EXT'. You need to specify
|
||||||
the ES format explicitly if you want to listen to radio channels. Play them
|
the ES format explicitly if you want to listen to radio channels. Play them
|
||||||
back i.e. with mpg123.
|
back i.e. with mpg123.
|
||||||
|
|
||||||
mpg123 http://hostname:3000/ES/200
|
mpg123 http://hostname:3000/ES/200
|
||||||
|
|
||||||
With 'EXTERN' you can also add a parameter which is passed as argument to the
|
With 'EXT' you can also add parameters which are passed as arguments to the
|
||||||
externremux script.
|
externremux script (e.g. http://hostname:3000/EXT;param1=value1;param2=value2/3)
|
||||||
|
Check your externremux.sh script for the parameters it understands. For details
|
||||||
http://hostname:3000/EXTERN;some_parameter/3
|
on how to modify or write your own externremux.sh, please see the chapter upon
|
||||||
|
externremux.sh further down.
|
||||||
|
|
||||||
If you want to access streamdev's HTTP server from the Internet, do *not* grant
|
If you want to access streamdev's HTTP server from the Internet, do *not* grant
|
||||||
access for anyone by allowing any IP in "streamdevhosts.conf". Instead, pass the
|
access for anyone by allowing any IP in "streamdevhosts.conf". Instead, pass the
|
||||||
@ -216,7 +250,7 @@ access for anyone by allowing any IP in "streamdevhosts.conf". Instead, pass the
|
|||||||
as argument. Clients with an IP not accepted by "streamdevhosts.conf" will then
|
as argument. Clients with an IP not accepted by "streamdevhosts.conf" will then
|
||||||
have to login. The VDR commandline will have to look like this:
|
have to login. The VDR commandline will have to look like this:
|
||||||
|
|
||||||
vdr ... -P 'streamdev-server -a vdr:secret' ...
|
vdr ... -P 'streamdev-server -a vdr:secret' ...
|
||||||
|
|
||||||
Note the single quotes, as otherwise "-a" will be passed to VDR and not to
|
Note the single quotes, as otherwise "-a" will be passed to VDR and not to
|
||||||
streamdev-server. The login ("vdr" in the example above) doesn't have to exist
|
streamdev-server. The login ("vdr" in the example above) doesn't have to exist
|
||||||
@ -267,11 +301,11 @@ You might want to increase this up to "number_of_channels + 1". Note that it's
|
|||||||
"number_of_channels", not "maximum_channel_number".
|
"number_of_channels", not "maximum_channel_number".
|
||||||
|
|
||||||
#First 100 channels:
|
#First 100 channels:
|
||||||
bash# sysctl -w sys.net.ipv4.igmp_max_memberships=101
|
bash# sysctl -w net.ipv4.igmp_max_memberships=101
|
||||||
|
|
||||||
#All channels:
|
#All channels:
|
||||||
bash# COUNT=$(grep -c '^[^:]' PATH_TO_YOUR/channels.conf)
|
bash# COUNT=$(grep -c '^[^:]' PATH_TO_YOUR/channels.conf)
|
||||||
bash# sysctl -w sys.net.ipv4.igmp_max_memberships=$COUNT
|
bash# sysctl -w net.ipv4.igmp_max_memberships=$COUNT
|
||||||
|
|
||||||
A multicast server never knows how many clients are actually receiving a stream.
|
A multicast server never knows how many clients are actually receiving a stream.
|
||||||
If a client signals that it leaves a multicast group, the server has to query
|
If a client signals that it leaves a multicast group, the server has to query
|
||||||
@ -337,15 +371,6 @@ With "Filter Streaming" enabled, the client will receive meta information like
|
|||||||
EPG data and service information, just as if the client had its own DVB card.
|
EPG data and service information, just as if the client had its own DVB card.
|
||||||
Link channels and even a client-side EPG scan have been reported to work.
|
Link channels and even a client-side EPG scan have been reported to work.
|
||||||
|
|
||||||
The next parameter, "Synchronize EPG", will have the client synchronize it's
|
|
||||||
program table with the server every now and then, but not regularly. This
|
|
||||||
happens when starting the client, and everytime VDR does its housekeeping
|
|
||||||
tasks. The only thing that's guaranteed is, that there will be a minimum
|
|
||||||
interval of ten seconds between each EPG synchronization. With "Filter
|
|
||||||
Streaming" this option has been obsoleted. If you still need to synchronize
|
|
||||||
EPG as additional information is available from the server, you should use the
|
|
||||||
epgsync-plugin instead (http://vdr.schmirler.de).
|
|
||||||
|
|
||||||
Finally with the maximum and minimum priority, you can keep VDR from considering
|
Finally with the maximum and minimum priority, you can keep VDR from considering
|
||||||
streamdev in certain cases. If for instance you have a streamdev client with its
|
streamdev in certain cases. If for instance you have a streamdev client with its
|
||||||
own DVB card, VDR would normally use streamdev for recording. If this is not
|
own DVB card, VDR would normally use streamdev for recording. If this is not
|
||||||
@ -356,6 +381,21 @@ which streamdev will accept to tune. Setting the minimum priority to a higher
|
|||||||
value than the maximum, you will get two ranges: "up to maximum" and "minimum
|
value than the maximum, you will get two ranges: "up to maximum" and "minimum
|
||||||
and above".
|
and above".
|
||||||
|
|
||||||
|
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):
|
||||||
|
|
||||||
|
cd VDRPLUGINLIBDIR
|
||||||
|
cp libvdr-streamdev-client.so.1.X.X libvdr-streamdev-client2.so.1.X.X
|
||||||
|
|
||||||
|
Now add -Pstreamdev-client2 to the VDR commandline. In the VDR plugin setup
|
||||||
|
a second streamdev-client entry should show up. Both instances have to be
|
||||||
|
configured individually.
|
||||||
|
|
||||||
|
|
||||||
4. Other useful Plugins:
|
4. Other useful Plugins:
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
@ -398,7 +438,58 @@ With its networking option, xineliboutput provides an alternative to streamdev.
|
|||||||
You will get the picture of the server VDR, including its OSD. However you
|
You will get the picture of the server VDR, including its OSD. However you
|
||||||
won't get independent clients, as they all share the same output.
|
won't get independent clients, as they all share the same output.
|
||||||
|
|
||||||
5. Known Problems:
|
5. externremux.sh:
|
||||||
|
------------------
|
||||||
|
|
||||||
|
When selecting streamtype "EXT", the TS stream from VDR is passed through an
|
||||||
|
external program for further processing. By default a script installed at
|
||||||
|
VDRCONFDIR/plugins/streamdev/externremux.sh is expected, however you may
|
||||||
|
specify a different location as parameter -r to the streamdev-server plugin
|
||||||
|
(see chapter upon Installation above).
|
||||||
|
|
||||||
|
The TS stream is passed to the script on stdin, the resulting stream is expected
|
||||||
|
on stdout. The following parameters are passed to the script in the environment:
|
||||||
|
|
||||||
|
* Information on the channel:
|
||||||
|
REMUX_CHANNEL_ID VDR channel ID
|
||||||
|
REMUX_CHANNEL_NAME Channel name
|
||||||
|
REMUX_VTYPE Video type (2 for MPEG-2)
|
||||||
|
REMUX_VPID Video PID (undefined if audio only)
|
||||||
|
REMUX_PPID PCR PID (undefined if equal to VPID)
|
||||||
|
REMUX_TPID Teletext PID (undefined if not available)
|
||||||
|
REMUX_APID Space separated list of audio pids
|
||||||
|
REMUX_ALANG Space separated list of audio languages
|
||||||
|
REMUX_DPID Space separated list of dolby pids
|
||||||
|
REMUX_DLANG Space separated list of dolby languages
|
||||||
|
REMUX_SPID Space separated list of subtitle pids
|
||||||
|
REMUX_SLANG Space separated list of subtitle languages
|
||||||
|
REMUX_PARAM_* All (user supplied) parameters (e.g. REMUX_PARAM_x)
|
||||||
|
|
||||||
|
* Information on the connection (CGI like)
|
||||||
|
REMOTE_ADDR Client IP
|
||||||
|
SERVER_NAME Local IP
|
||||||
|
SERVER_PORT Local port
|
||||||
|
SERVER_PROTOCOL Streamdev protocol (HTTP, VTP, IGMP)
|
||||||
|
SERVER_SOFTWARE Streamdev version
|
||||||
|
All HTTP headers converted to uppercase, '-' replaced by '_' (e.g. USER_AGENT)
|
||||||
|
|
||||||
|
The script should perform the following steps (pseudocode):
|
||||||
|
|
||||||
|
if (SERVER_PROTOCOL == HTTP)
|
||||||
|
write headers (including Content-Type) to STDOUT
|
||||||
|
write empty line to STDOUT
|
||||||
|
if (REQUEST_METHOD == HEAD)
|
||||||
|
exit
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
while (read STDIN)
|
||||||
|
remux to STDOUT
|
||||||
|
wend
|
||||||
|
|
||||||
|
onSIGINT/SIGKILL: cleanup and exit
|
||||||
|
|
||||||
|
|
||||||
|
6. Known Problems:
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
* In VDR-to-VDR setup, the availability of a channel is checked with a different
|
* In VDR-to-VDR setup, the availability of a channel is checked with a different
|
||||||
@ -424,15 +515,9 @@ up. So please consider the logs for the correct value. Remember to fill in
|
|||||||
hexadecimal values if you are using an editor to modify your channels.conf
|
hexadecimal values if you are using an editor to modify your channels.conf
|
||||||
(number 10 becomes an "a", number 11 a "b", ...).
|
(number 10 becomes an "a", number 11 a "b", ...).
|
||||||
|
|
||||||
2. Turn encrypted channels into Free-to-Air channels on the client. Again,
|
2. Apply either patch "patches/vdr-1.6.0-intcamdevices.patch" or patch
|
||||||
either enter the channels menu or edit the client's channels.conf. You will
|
|
||||||
also have to disable automatic channel updates on the client or (if streamdev
|
|
||||||
is the only DVB source) disable streamdev's filter streaming feature. Otherwise
|
|
||||||
VDR will revert the channel into an encrypted one.
|
|
||||||
|
|
||||||
3. Apply either patch "patches/vdr-1.6.0-intcamdevices.patch" or patch
|
|
||||||
"patches/vdr-1.6.0-ignore_missing_cam.diff" to your client VDR. Intcamdevices
|
"patches/vdr-1.6.0-ignore_missing_cam.diff" to your client VDR. Intcamdevices
|
||||||
is the clean solution. But as it modifies the VDR API, so you will need to
|
is the clean solution, but it modifies the VDR API. So you will need to
|
||||||
recompile all of your plugins. The ignore_missing_cam patch is trivial, no need
|
recompile all of your plugins. The ignore_missing_cam patch is trivial, no need
|
||||||
to recompile other plugins. However it is not suitable for clients with a DVB
|
to recompile other plugins. However it is not suitable for clients with a DVB
|
||||||
card of their own.
|
card of their own.
|
||||||
|
84
client/Makefile
Normal file
84
client/Makefile
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#
|
||||||
|
# Makefile for a Video Disk Recorder plugin
|
||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1.2.1 2010/06/14 10:40:11 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-client
|
||||||
|
|
||||||
|
### Includes and Defines (add further entries here):
|
||||||
|
|
||||||
|
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||||
|
|
||||||
|
### The object files (add further files here):
|
||||||
|
|
||||||
|
COMMONOBJS = ../common.o
|
||||||
|
|
||||||
|
CLIENTOBJS = $(PLUGIN).o \
|
||||||
|
device.o filter.o setup.o socket.o
|
||||||
|
|
||||||
|
### The main target:
|
||||||
|
|
||||||
|
.PHONY: all i18n dist 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) $(CLIENTOBJS:%.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): $(CLIENTOBJS:%.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: $(CLIENTOBJS) $(COMMONOBJS) ../tools/sockettools.a
|
||||||
|
|
||||||
|
%.so:
|
||||||
|
$(CXX) $(CXXFLAGS) -shared $^ -o $@
|
||||||
|
@cp $@ $(LIBDIR)/$@.$(APIVERSION)
|
||||||
|
|
||||||
|
dist: clean
|
||||||
|
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
||||||
|
@mkdir $(TMPDIR)/$(ARCHIVE)
|
||||||
|
@cp -a * $(TMPDIR)/$(ARCHIVE)
|
||||||
|
@tar czf $(PACKAGE).tgz --exclude CVS -C $(TMPDIR) $(ARCHIVE)
|
||||||
|
@-rm -rf $(TMPDIR)/$(ARCHIVE)
|
||||||
|
@echo Distribution package created as $(PACKAGE).tgz
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm -f $(COMMONOBJS) $(CLIENTOBJS) $(DEPFILE) $(PODIR)/*.mo $(PODIR)/*.pot *.so *.tgz core* *~
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: device.c,v 1.23 2009/04/06 06:48:59 schmirl Exp $
|
* $Id: device.c,v 1.26 2010/06/08 05:55:17 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "client/device.h"
|
#include "client/device.h"
|
||||||
@ -33,9 +33,6 @@ cStreamdevDevice::cStreamdevDevice(void) {
|
|||||||
m_Device = this;
|
m_Device = this;
|
||||||
m_Pids = 0;
|
m_Pids = 0;
|
||||||
m_DvrClosed = true;
|
m_DvrClosed = true;
|
||||||
|
|
||||||
if (StreamdevClientSetup.SyncEPG)
|
|
||||||
ClientSocket.SynchronizeEPG();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cStreamdevDevice::~cStreamdevDevice() {
|
cStreamdevDevice::~cStreamdevDevice() {
|
||||||
@ -72,7 +69,9 @@ bool cStreamdevDevice::IsTunedToTransponder(const cChannel *Channel)
|
|||||||
{
|
{
|
||||||
bool res = false;
|
bool res = false;
|
||||||
if (ClientSocket.DataSocket(siLive) != NULL
|
if (ClientSocket.DataSocket(siLive) != NULL
|
||||||
&& TRANSPONDER(Channel, m_Channel))
|
&& TRANSPONDER(Channel, m_Channel)
|
||||||
|
&& Channel->Ca() == CA_FTA
|
||||||
|
&& m_Channel->Ca() == CA_FTA)
|
||||||
res = true;
|
res = true;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -123,12 +122,11 @@ bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel,
|
|||||||
if (LiveView)
|
if (LiveView)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (ClientSocket.DataSocket(siLive) != NULL
|
if (ClientSocket.DataSocket(siLive) != NULL
|
||||||
&& TRANSPONDER(Channel, m_Channel)
|
&& TRANSPONDER(Channel, m_Channel)
|
||||||
&& Channel->Ca() < CA_ENCRYPTED_MIN)
|
&& Channel->Ca() == CA_FTA
|
||||||
|
&& m_Channel->Ca() == CA_FTA)
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
|
|
||||||
DetachAllReceivers();
|
DetachAllReceivers();
|
||||||
m_Channel = Channel;
|
m_Channel = Channel;
|
||||||
|
50
client/po/de_DE.po
Normal file
50
client/po/de_DE.po
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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:05+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 "VTP Streaming Client"
|
||||||
|
msgstr "VTP Streaming Client"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "Server pausieren"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "Server ist pausiert"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
msgstr "Konnte Server nicht pausieren!"
|
||||||
|
|
||||||
|
msgid "Hide Mainmenu Entry"
|
||||||
|
msgstr "Hauptmenüeintrag verstecken"
|
||||||
|
|
||||||
|
msgid "Start Client"
|
||||||
|
msgstr "Client starten"
|
||||||
|
|
||||||
|
msgid "Remote IP"
|
||||||
|
msgstr "IP der Gegenseite"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "Port der Gegenseite"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "Filter-Daten streamen"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr "Minimale Priorität"
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr "Maximale Priorität"
|
||||||
|
|
50
client/po/fi_FI.po
Normal file
50
client/po/fi_FI.po
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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:05+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 "VTP Streaming Client"
|
||||||
|
msgstr "VTP-suoratoistoasiakas"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "Pysäytä palvelin"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "Palvelin on pysäytetty"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
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 "Remote IP"
|
||||||
|
msgstr "Etäkoneen IP-osoite"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "Etäkoneen portti"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "Suodatetun tiedon suoratoisto"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr "Pienin prioriteetti"
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr "Suurin prioriteetti"
|
||||||
|
|
50
client/po/fr_FR.po
Normal file
50
client/po/fr_FR.po
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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:05+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 "VTP Streaming Client"
|
||||||
|
msgstr "Client de streaming VTP"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "Suspendre le serveur"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "Le serveur est suspendu"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
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 "Remote IP"
|
||||||
|
msgstr "Adresse IP du serveur"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "Port du serveur"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "Filtre streaming"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr ""
|
||||||
|
|
52
client/po/it_IT.po
Normal file
52
client/po/it_IT.po
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# 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:05+0200\n"
|
||||||
|
"PO-Revision-Date: 2008-04-13 23:42+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 "VTP Streaming Client"
|
||||||
|
msgstr "Client trasmissione VTP"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "Sospendi Server"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "Server sospeso"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
msgstr "Impossibile sospendere il server!"
|
||||||
|
|
||||||
|
msgid "Hide Mainmenu Entry"
|
||||||
|
msgstr "Nascondi voce menu principale"
|
||||||
|
|
||||||
|
msgid "Start Client"
|
||||||
|
msgstr "Avvia Client"
|
||||||
|
|
||||||
|
msgid "Remote IP"
|
||||||
|
msgstr "Indirizzo IP del Server"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "Porta Server Remoto"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "Filtra trasmissione"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr ""
|
||||||
|
|
50
client/po/lt_LT.po
Normal file
50
client/po/lt_LT.po
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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:05+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 "VTP Streaming Client"
|
||||||
|
msgstr "VTP transliavimo standartas"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "Sustabdyti serverį"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "Serveris sustabdytas"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
msgstr "Negali sustabdyti serverio!"
|
||||||
|
|
||||||
|
msgid "Hide Mainmenu Entry"
|
||||||
|
msgstr "Paslėpti pagrindinio meniu įrašą"
|
||||||
|
|
||||||
|
msgid "Start Client"
|
||||||
|
msgstr "Paleisti klientą"
|
||||||
|
|
||||||
|
msgid "Remote IP"
|
||||||
|
msgstr "Nuotolinis IP adresas"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "Nuotolinis portas"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "Filtruoti transliavimą"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr "Minimalus prioritetas"
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr "Maksimalus prioritetas"
|
||||||
|
|
50
client/po/ru_RU.po
Normal file
50
client/po/ru_RU.po
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
# 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:05+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 "VTP Streaming Client"
|
||||||
|
msgstr "VTP Streaming ÚÛØÕÝâ"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "¾áâÐÝÞÒØâì áÕàÒÕà"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "ÁÕàÒÕà ÞáâÐÝÞÒÛÕÝ"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
msgstr "ÝÕ ÜÞÓã ÞáâÐÝÞÒØâì áÕàÒÕà"
|
||||||
|
|
||||||
|
msgid "Hide Mainmenu Entry"
|
||||||
|
msgstr "ÁßàïâÐâì Ò ÓÛÐÒÝÞÜ ÜÕÝî"
|
||||||
|
|
||||||
|
msgid "Start Client"
|
||||||
|
msgstr "ÁâÐàâ ÚÛØÕÝâÐ"
|
||||||
|
|
||||||
|
msgid "Remote IP"
|
||||||
|
msgstr "ÃÔÐÛÕÝÝëÙ IP"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "ÃÔÐÛÕÝÝëÙ ßÞàâ"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "ÄØÛìâà ßÞâÞÚÐ"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr ""
|
||||||
|
|
52
client/po/sk_SK.po
Normal file
52
client/po/sk_SK.po
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# 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:05+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 "VTP Streaming Client"
|
||||||
|
msgstr "VTP prúdový klient"
|
||||||
|
|
||||||
|
msgid "Suspend Server"
|
||||||
|
msgstr "Server pozastavený"
|
||||||
|
|
||||||
|
msgid "Server is suspended"
|
||||||
|
msgstr "Server je doèasne preru¹ený"
|
||||||
|
|
||||||
|
msgid "Couldn't suspend Server!"
|
||||||
|
msgstr "Nepodarilo sa pozastavi» Server!"
|
||||||
|
|
||||||
|
msgid "Hide Mainmenu Entry"
|
||||||
|
msgstr "Schova» polo¾ku v hlavnom menu"
|
||||||
|
|
||||||
|
msgid "Start Client"
|
||||||
|
msgstr "Spusti» Klienta"
|
||||||
|
|
||||||
|
msgid "Remote IP"
|
||||||
|
msgstr "Vzdialená IP"
|
||||||
|
|
||||||
|
msgid "Remote Port"
|
||||||
|
msgstr "Vzdialený port"
|
||||||
|
|
||||||
|
msgid "Filter Streaming"
|
||||||
|
msgstr "filtrova» prúdy"
|
||||||
|
|
||||||
|
msgid "Minimum Priority"
|
||||||
|
msgstr "minimálna priorita"
|
||||||
|
|
||||||
|
msgid "Maximum Priority"
|
||||||
|
msgstr "maximálna priorita"
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: setup.c,v 1.8 2009/02/03 10:26:21 schmirl Exp $
|
* $Id: setup.c,v 1.10 2010/06/08 05:55:17 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/menuitems.h>
|
#include <vdr/menuitems.h>
|
||||||
@ -13,7 +13,6 @@ cStreamdevClientSetup::cStreamdevClientSetup(void) {
|
|||||||
StartClient = false;
|
StartClient = false;
|
||||||
RemotePort = 2004;
|
RemotePort = 2004;
|
||||||
StreamFilters = false;
|
StreamFilters = false;
|
||||||
SyncEPG = false;
|
|
||||||
HideMenuEntry = false;
|
HideMenuEntry = false;
|
||||||
MinPriority = -1;
|
MinPriority = -1;
|
||||||
MaxPriority = MAXPRIORITY;
|
MaxPriority = MAXPRIORITY;
|
||||||
@ -30,7 +29,6 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
|
|||||||
}
|
}
|
||||||
else if (strcmp(Name, "RemotePort") == 0) RemotePort = atoi(Value);
|
else if (strcmp(Name, "RemotePort") == 0) RemotePort = atoi(Value);
|
||||||
else if (strcmp(Name, "StreamFilters") == 0) StreamFilters = atoi(Value);
|
else if (strcmp(Name, "StreamFilters") == 0) StreamFilters = atoi(Value);
|
||||||
else if (strcmp(Name, "SyncEPG") == 0) SyncEPG = atoi(Value);
|
|
||||||
else if (strcmp(Name, "HideMenuEntry") == 0) HideMenuEntry = atoi(Value);
|
else if (strcmp(Name, "HideMenuEntry") == 0) HideMenuEntry = atoi(Value);
|
||||||
else if (strcmp(Name, "MinPriority") == 0) MinPriority = atoi(Value);
|
else if (strcmp(Name, "MinPriority") == 0) MinPriority = atoi(Value);
|
||||||
else if (strcmp(Name, "MaxPriority") == 0) MaxPriority = atoi(Value);
|
else if (strcmp(Name, "MaxPriority") == 0) MaxPriority = atoi(Value);
|
||||||
@ -41,14 +39,13 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
|
|||||||
cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) {
|
cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) {
|
||||||
m_NewSetup = StreamdevClientSetup;
|
m_NewSetup = StreamdevClientSetup;
|
||||||
|
|
||||||
AddBoolEdit (tr("Hide Mainmenu Entry"),m_NewSetup.HideMenuEntry);
|
Add(new cMenuEditBoolItem(tr("Hide Mainmenu Entry"), &m_NewSetup.HideMenuEntry));
|
||||||
AddBoolEdit (tr("Start Client"), m_NewSetup.StartClient);
|
Add(new cMenuEditBoolItem(tr("Start Client"), &m_NewSetup.StartClient));
|
||||||
AddIpEdit (tr("Remote IP"), m_NewSetup.RemoteIp);
|
Add(new cMenuEditIpItem (tr("Remote IP"), m_NewSetup.RemoteIp));
|
||||||
AddShortEdit(tr("Remote Port"), m_NewSetup.RemotePort);
|
Add(new cMenuEditIntItem (tr("Remote Port"), &m_NewSetup.RemotePort, 0, 65535));
|
||||||
AddBoolEdit (tr("Filter Streaming"), m_NewSetup.StreamFilters);
|
Add(new cMenuEditBoolItem(tr("Filter Streaming"), &m_NewSetup.StreamFilters));
|
||||||
AddBoolEdit (tr("Synchronize EPG"), m_NewSetup.SyncEPG);
|
Add(new cMenuEditIntItem (tr("Minimum Priority"), &m_NewSetup.MinPriority, -1, MAXPRIORITY));
|
||||||
AddRangeEdit (tr("Minimum Priority"), m_NewSetup.MinPriority, -1, MAXPRIORITY);
|
Add(new cMenuEditIntItem (tr("Maximum Priority"), &m_NewSetup.MaxPriority, -1, MAXPRIORITY));
|
||||||
AddRangeEdit (tr("Maximum Priority"), m_NewSetup.MaxPriority, -1, MAXPRIORITY);
|
|
||||||
SetCurrent(Get(0));
|
SetCurrent(Get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +65,6 @@ void cStreamdevClientMenuSetupPage::Store(void) {
|
|||||||
SetupStore("RemoteIp", m_NewSetup.RemoteIp);
|
SetupStore("RemoteIp", m_NewSetup.RemoteIp);
|
||||||
SetupStore("RemotePort", m_NewSetup.RemotePort);
|
SetupStore("RemotePort", m_NewSetup.RemotePort);
|
||||||
SetupStore("StreamFilters", m_NewSetup.StreamFilters);
|
SetupStore("StreamFilters", m_NewSetup.StreamFilters);
|
||||||
SetupStore("SyncEPG", m_NewSetup.SyncEPG);
|
|
||||||
SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry);
|
SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry);
|
||||||
SetupStore("MinPriority", m_NewSetup.MinPriority);
|
SetupStore("MinPriority", m_NewSetup.MinPriority);
|
||||||
SetupStore("MaxPriority", m_NewSetup.MaxPriority);
|
SetupStore("MaxPriority", m_NewSetup.MaxPriority);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: setup.h,v 1.5 2009/01/29 07:48:59 schmirl Exp $
|
* $Id: setup.h,v 1.7 2010/06/08 05:55:17 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SETUPCLIENT_H
|
#ifndef VDR_STREAMDEV_SETUPCLIENT_H
|
||||||
@ -16,7 +16,6 @@ struct cStreamdevClientSetup {
|
|||||||
char RemoteIp[20];
|
char RemoteIp[20];
|
||||||
int RemotePort;
|
int RemotePort;
|
||||||
int StreamFilters;
|
int StreamFilters;
|
||||||
int SyncEPG;
|
|
||||||
int HideMenuEntry;
|
int HideMenuEntry;
|
||||||
int MinPriority;
|
int MinPriority;
|
||||||
int MaxPriority;
|
int MaxPriority;
|
||||||
@ -24,7 +23,7 @@ struct cStreamdevClientSetup {
|
|||||||
|
|
||||||
extern cStreamdevClientSetup StreamdevClientSetup;
|
extern cStreamdevClientSetup StreamdevClientSetup;
|
||||||
|
|
||||||
class cStreamdevClientMenuSetupPage: public cStreamdevMenuSetupPage {
|
class cStreamdevClientMenuSetupPage: public cMenuSetupPage {
|
||||||
private:
|
private:
|
||||||
cStreamdevClientSetup m_NewSetup;
|
cStreamdevClientSetup m_NewSetup;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: socket.c,v 1.12 2008/04/08 14:18:16 schmirl Exp $
|
* $Id: socket.c,v 1.13 2010/06/08 05:55:17 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <tools/select.h>
|
#include <tools/select.h>
|
||||||
@ -300,52 +300,6 @@ bool cClientSocket::CloseDvr(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cClientSocket::SynchronizeEPG(void) {
|
|
||||||
std::string buffer;
|
|
||||||
bool result;
|
|
||||||
FILE *epgfd;
|
|
||||||
|
|
||||||
if (!CheckConnection()) return false;
|
|
||||||
|
|
||||||
isyslog("Streamdev: Synchronizing EPG from server\n");
|
|
||||||
|
|
||||||
CMD_LOCK;
|
|
||||||
|
|
||||||
if (!Command("LSTE"))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if ((epgfd = tmpfile()) == NULL) {
|
|
||||||
esyslog("ERROR: Streamdev: Error while processing EPG data: %s",
|
|
||||||
strerror(errno));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((result = Expect(215, &buffer))) {
|
|
||||||
if (buffer[3] == ' ') break;
|
|
||||||
fputs(buffer.c_str() + 4, epgfd);
|
|
||||||
fputc('\n', epgfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
if (errno == 0)
|
|
||||||
esyslog("ERROR: Streamdev: Couldn't fetch EPG data from %s:%d",
|
|
||||||
RemoteIp().c_str(), RemotePort());
|
|
||||||
fclose(epgfd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
rewind(epgfd);
|
|
||||||
if (cSchedules::Read(epgfd))
|
|
||||||
cSchedules::Cleanup(true);
|
|
||||||
else {
|
|
||||||
esyslog("ERROR: Streamdev: Parsing EPG data failed");
|
|
||||||
fclose(epgfd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
fclose(epgfd);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool cClientSocket::Quit(void) {
|
bool cClientSocket::Quit(void) {
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: socket.h,v 1.6 2008/04/07 14:40:40 schmirl Exp $
|
* $Id: socket.h,v 1.7 2010/06/08 05:55:17 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_CLIENT_CONNECTION_H
|
#ifndef VDR_STREAMDEV_CLIENT_CONNECTION_H
|
||||||
@ -48,7 +48,6 @@ public:
|
|||||||
bool SetPid(int Pid, bool On);
|
bool SetPid(int Pid, bool On);
|
||||||
bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
|
bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
|
||||||
bool CloseDvr(void);
|
bool CloseDvr(void);
|
||||||
bool SynchronizeEPG(void);
|
|
||||||
bool SuspendServer(void);
|
bool SuspendServer(void);
|
||||||
bool Quit(void);
|
bool Quit(void);
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: streamdev-client.c,v 1.6 2008/04/08 14:18:15 schmirl Exp $
|
* $Id: streamdev-client.c,v 1.1.2.1 2010/06/14 10:40:11 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "streamdev-client.h"
|
#include "streamdev-client.h"
|
||||||
@ -32,11 +32,6 @@ bool cPluginStreamdevClient::Start(void) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cPluginStreamdevClient::Housekeeping(void) {
|
|
||||||
if (StreamdevClientSetup.StartClient && StreamdevClientSetup.SyncEPG)
|
|
||||||
ClientSocket.SynchronizeEPG();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *cPluginStreamdevClient::MainMenuEntry(void) {
|
const char *cPluginStreamdevClient::MainMenuEntry(void) {
|
||||||
return StreamdevClientSetup.StartClient && !StreamdevClientSetup.HideMenuEntry ? tr("Suspend Server") : NULL;
|
return StreamdevClientSetup.StartClient && !StreamdevClientSetup.HideMenuEntry ? tr("Suspend Server") : NULL;
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamdev-client.h,v 1.1.1.1 2004/12/30 22:43:59 lordjaxom Exp $
|
* $Id: streamdev-client.h,v 1.1.2.1 2010/06/14 10:40:11 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEVCLIENT_H
|
#ifndef VDR_STREAMDEVCLIENT_H
|
||||||
@ -19,7 +19,6 @@ public:
|
|||||||
virtual const char *Version(void) { return VERSION; }
|
virtual const char *Version(void) { return VERSION; }
|
||||||
virtual const char *Description(void);
|
virtual const char *Description(void);
|
||||||
virtual bool Start(void);
|
virtual bool Start(void);
|
||||||
virtual void Housekeeping(void);
|
|
||||||
virtual const char *MainMenuEntry(void);
|
virtual const char *MainMenuEntry(void);
|
||||||
virtual cOsdObject *MainMenuAction(void);
|
virtual cOsdObject *MainMenuAction(void);
|
||||||
virtual cMenuSetupPage *SetupMenu(void);
|
virtual cMenuSetupPage *SetupMenu(void);
|
139
common.c
139
common.c
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: common.c,v 1.10 2009/06/19 06:32:38 schmirl Exp $
|
* $Id: common.c,v 1.11.2.1 2010/06/08 07:47:45 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/channels.h>
|
#include <vdr/channels.h>
|
||||||
@ -10,142 +10,9 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
const char *VERSION = "0.5.0-pre-20090706";
|
const char *VERSION = "0.5.0-rc1";
|
||||||
|
|
||||||
const char *StreamTypes[st_Count] = {
|
const char cMenuEditIpItem::IpCharacters[] = "0123456789.";
|
||||||
"TS",
|
|
||||||
"PES",
|
|
||||||
"PS",
|
|
||||||
"ES",
|
|
||||||
"Extern",
|
|
||||||
"", // used internally only
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *SuspendModes[sm_Count] = {
|
|
||||||
trNOOP("Offer suspend mode"),
|
|
||||||
trNOOP("Always suspended"),
|
|
||||||
trNOOP("Never suspended")
|
|
||||||
};
|
|
||||||
|
|
||||||
const char IpCharacters[] = "0123456789.";
|
|
||||||
|
|
||||||
char *GetNextLine(char *String, uint Length, uint &Offset) {
|
|
||||||
char *last, *first;
|
|
||||||
|
|
||||||
first = String + Offset;
|
|
||||||
for (last = first; last < String + Length; ++last) {
|
|
||||||
if (*last == '\012') {
|
|
||||||
if (*(last - 1) == '\015')
|
|
||||||
*(last - 1) = '\0';
|
|
||||||
|
|
||||||
*last++ = '\0';
|
|
||||||
Dprintf("IN: |%s|\n", first);
|
|
||||||
Offset = last - String;
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cChannel *ChannelFromString(const char *String, int *Apid) {
|
|
||||||
const cChannel *channel = NULL;
|
|
||||||
char *string = strdup(String);
|
|
||||||
char *ptr, *end;
|
|
||||||
int apididx = 0;
|
|
||||||
|
|
||||||
if ((ptr = strrchr(string, '+')) != NULL) {
|
|
||||||
*(ptr++) = '\0';
|
|
||||||
apididx = strtoul(ptr, &end, 10);
|
|
||||||
Dprintf("found apididx: %d\n", apididx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isnumber(string)) {
|
|
||||||
int temp = strtol(String, NULL, 10);
|
|
||||||
if (temp >= 1 && temp <= Channels.MaxNumber())
|
|
||||||
channel = Channels.GetByNumber(temp);
|
|
||||||
} else {
|
|
||||||
channel = Channels.GetByChannelID(tChannelID::FromString(string));
|
|
||||||
|
|
||||||
if (channel == NULL) {
|
|
||||||
int i = 1;
|
|
||||||
while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
|
|
||||||
if (String == channel->Name())
|
|
||||||
break;
|
|
||||||
|
|
||||||
i = channel->Number() + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channel != NULL && apididx > 0) {
|
|
||||||
int apid = 0, index = 1;
|
|
||||||
|
|
||||||
for (int i = 0; channel->Apid(i) != 0; ++i, ++index) {
|
|
||||||
if (index == apididx) {
|
|
||||||
apid = channel->Apid(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (apid == 0) {
|
|
||||||
for (int i = 0; channel->Dpid(i) != 0; ++i, ++index) {
|
|
||||||
if (index == apididx) {
|
|
||||||
apid = channel->Dpid(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Apid != NULL)
|
|
||||||
*Apid = apid;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(string);
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevMenuSetupPage::AddCategory(const char *Title) {
|
|
||||||
char *buffer = NULL;
|
|
||||||
|
|
||||||
asprintf(&buffer, "--- %s -------------------------------------------------"
|
|
||||||
"---------------", Title );
|
|
||||||
|
|
||||||
cOsdItem *item = new cOsdItem(buffer);
|
|
||||||
free(buffer);
|
|
||||||
item->SetSelectable(false);
|
|
||||||
Add(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevMenuSetupPage::AddBoolEdit(const char *Title, int &Value) {
|
|
||||||
Add(new cMenuEditBoolItem(Title, &Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevMenuSetupPage::AddIpEdit(const char *Title, char *Value) {
|
|
||||||
Add(new cMenuEditIpItem(Title, Value));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevMenuSetupPage::AddShortEdit(const char *Title, int &Value) {
|
|
||||||
AddRangeEdit(Title, Value, 0, 65535);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevMenuSetupPage::AddRangeEdit(const char *Title, int &Value,
|
|
||||||
int Min, int Max) {
|
|
||||||
Add(new cMenuEditIntItem(Title, &Value, Min, Max));
|
|
||||||
}
|
|
||||||
|
|
||||||
void cStreamdevMenuSetupPage::AddSuspEdit(const char *Title, int &Value) {
|
|
||||||
static const char *SuspendModesTR[sm_Count] = { NULL };
|
|
||||||
|
|
||||||
if (SuspendModesTR[0] == NULL) {
|
|
||||||
for (int i = 0; i < sm_Count; ++i)
|
|
||||||
SuspendModesTR[i] = tr(SuspendModes[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Add(new cMenuEditStraItem(Title, &Value, sm_Count, SuspendModesTR));
|
|
||||||
}
|
|
||||||
void cStreamdevMenuSetupPage::AddTypeEdit(const char *Title, int &Value) {
|
|
||||||
Add(new cMenuEditStraItem(Title, &Value, st_CountSetup, StreamTypes));
|
|
||||||
}
|
|
||||||
|
|
||||||
cMenuEditIpItem::cMenuEditIpItem(const char *Name, char *Value):
|
cMenuEditIpItem::cMenuEditIpItem(const char *Name, char *Value):
|
||||||
cMenuEditItem(Name) {
|
cMenuEditItem(Name) {
|
||||||
|
46
common.h
46
common.h
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: common.h,v 1.14 2009/07/01 10:46:16 schmirl Exp $
|
* $Id: common.h,v 1.15.2.1 2010/06/11 06:06:01 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_COMMON_H
|
#ifndef VDR_STREAMDEV_COMMON_H
|
||||||
@ -23,42 +23,23 @@
|
|||||||
# define Dprintf(x...)
|
# define Dprintf(x...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# define TRANSPONDER(c1, c2) (c1->Transponder() == c2->Transponder())
|
#define TRANSPONDER(c1, c2) (c1->Transponder() == c2->Transponder())
|
||||||
|
|
||||||
# define MAXPARSEBUFFER KILOBYTE(16)
|
#define MAXPARSEBUFFER KILOBYTE(16)
|
||||||
|
|
||||||
/* Check if a channel is a radio station. */
|
/* Check if a channel is a radio station. */
|
||||||
#define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff)
|
#define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff)
|
||||||
|
|
||||||
class cChannel;
|
class cChannel;
|
||||||
|
|
||||||
char *GetNextLine(char *String, uint Length, uint &Offset);
|
|
||||||
|
|
||||||
const cChannel *ChannelFromString(const char *String, int *Apid = NULL);
|
|
||||||
|
|
||||||
/* Disable logging if BUFCOUNT buffer overflows occur within BUFOVERTIME
|
|
||||||
milliseconds. Enable logging again if there is no error within BUFOVERTIME
|
|
||||||
milliseconds. */
|
|
||||||
#define BUFOVERTIME 5000
|
|
||||||
#define BUFOVERCOUNT 100
|
|
||||||
|
|
||||||
#define POLLFAIL esyslog("Streamdev: Polling failed: %s", strerror(errno))
|
|
||||||
#define WRITEFAIL esyslog("Streamdev: Writing failed: %s", strerror(errno))
|
|
||||||
#define READFAIL esyslog("Streamdev: Reading failed: %s", strerror(errno))
|
|
||||||
#define CHECKPOLL(x) if ((x)<0){POLLFAIL; return false;}
|
|
||||||
#define CHECKWRITE(x) if ((x)<0) { WRITEFAIL; return false; }
|
|
||||||
#define CHECKREAD(x) if ((x)<0) { READFAIL; return false; }
|
|
||||||
|
|
||||||
enum eStreamType {
|
enum eStreamType {
|
||||||
stTS,
|
stTS,
|
||||||
stPES,
|
stPES,
|
||||||
stPS,
|
stPS,
|
||||||
stES,
|
stES,
|
||||||
stExtern,
|
stEXT,
|
||||||
stTSPIDS,
|
stTSPIDS,
|
||||||
|
st_Count
|
||||||
#define st_CountSetup (stExtern+1)
|
|
||||||
#define st_Count (stTSPIDS+1)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eSuspendMode {
|
enum eSuspendMode {
|
||||||
@ -77,25 +58,10 @@ enum eSocketId {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern const char *VERSION;
|
extern const char *VERSION;
|
||||||
extern const char *StreamTypes[st_Count];
|
|
||||||
extern const char *SuspendModes[sm_Count];
|
|
||||||
extern const char IpCharacters[];
|
|
||||||
|
|
||||||
class cStreamdevMenuSetupPage: public cMenuSetupPage {
|
|
||||||
protected:
|
|
||||||
void AddCategory(const char *Title);
|
|
||||||
virtual void Store(void) = 0;
|
|
||||||
|
|
||||||
void AddBoolEdit(const char *Title, int &Value);
|
|
||||||
void AddIpEdit(const char *Title, char *Value);
|
|
||||||
void AddShortEdit(const char *Title, int &Value);
|
|
||||||
void AddRangeEdit(const char *Title, int &Value, int Min, int Max);
|
|
||||||
void AddSuspEdit(const char *Title, int &Value);
|
|
||||||
void AddTypeEdit(const char *Title, int &Value);
|
|
||||||
};
|
|
||||||
|
|
||||||
class cMenuEditIpItem: public cMenuEditItem {
|
class cMenuEditIpItem: public cMenuEditItem {
|
||||||
private:
|
private:
|
||||||
|
static const char IpCharacters[];
|
||||||
char *value;
|
char *value;
|
||||||
int curNum;
|
int curNum;
|
||||||
int pos;
|
int pos;
|
||||||
|
@ -1,25 +1,34 @@
|
|||||||
INCS = -I.
|
#
|
||||||
CFLAGS = -g -Wall -O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -fPIC
|
# Makefile for a Video Disk Recorder plugin
|
||||||
MFLAG = -M
|
#
|
||||||
OBJS = ctools.o ringbuffy.o remux.o transform.o
|
# $Id: Makefile,v 1.3.4.1 2010/06/14 10:40:13 schmirl Exp $
|
||||||
SRC = $(wildcard *.c)
|
|
||||||
|
|
||||||
DESTDIR = /usr/local
|
### The object files (add further files here):
|
||||||
|
|
||||||
|
OBJS = ctools.o remux.o ringbuffy.o transform.o
|
||||||
|
|
||||||
|
### The main target:
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
clean:
|
|
||||||
- rm -f *.o *~ *.a .depend
|
|
||||||
|
|
||||||
libdvbmpegtools.a: $(OBJS)
|
libdvbmpegtools.a: $(OBJS)
|
||||||
ar -rcs libdvbmpegtools.a $(OBJS)
|
ar -rcs libdvbmpegtools.a $(OBJS)
|
||||||
|
|
||||||
%.o: %.c
|
### Implicit rules:
|
||||||
$(CC) -c $(CFLAGS) $(INCS) $(DEFINES) $<
|
|
||||||
|
|
||||||
.depend:
|
%.o: %.c
|
||||||
$(CXX) $(DEFINES) $(MFLAG) $(SRC) $(INCS)> .depend
|
$(CC) $(CFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
### Dependencies:
|
||||||
|
|
||||||
|
MAKEDEP = $(CC) -MM -MG
|
||||||
|
DEPFILE = .dependencies
|
||||||
|
|
||||||
-include .depend
|
$(DEPFILE): Makefile
|
||||||
|
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
||||||
|
|
||||||
|
-include $(DEPFILE)
|
||||||
|
|
||||||
|
### Targets:
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm -f $(OBJS) $(DEPFILE) *.a core* *~
|
||||||
|
106
po/fi_FI.po.bak
106
po/fi_FI.po.bak
@ -1,106 +0,0 @@
|
|||||||
# 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: 2009-01-31 13:34+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=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
|
|
||||||
msgid "VTP Streaming Client"
|
|
||||||
msgstr "VTP-suoratoistoasiakas"
|
|
||||||
|
|
||||||
msgid "Suspend Server"
|
|
||||||
msgstr "Pysäytä palvelin"
|
|
||||||
|
|
||||||
msgid "Server is suspended"
|
|
||||||
msgstr "Palvelin on pysäytetty"
|
|
||||||
|
|
||||||
msgid "Couldn't suspend Server!"
|
|
||||||
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 "Remote IP"
|
|
||||||
msgstr "Etäkoneen IP-osoite"
|
|
||||||
|
|
||||||
msgid "Remote Port"
|
|
||||||
msgstr "Etäkoneen portti"
|
|
||||||
|
|
||||||
msgid "Filter Streaming"
|
|
||||||
msgstr "Suodatetun tiedon suoratoisto"
|
|
||||||
|
|
||||||
msgid "Synchronize EPG"
|
|
||||||
msgstr "Päivitä ohjelmaopas"
|
|
||||||
|
|
||||||
msgid "Minimum Priority"
|
|
||||||
msgstr "Pienin prioriteetti"
|
|
||||||
|
|
||||||
msgid "Maximum Priority"
|
|
||||||
msgstr "Suurin prioriteetti"
|
|
||||||
|
|
||||||
msgid "VDR Streaming Server"
|
|
||||||
msgstr "VDR-suoratoistopalvelin"
|
|
||||||
|
|
||||||
msgid "Streaming active"
|
|
||||||
msgstr "Suoratoistopalvelin aktiivinen"
|
|
||||||
|
|
||||||
msgid "Suspend Live TV"
|
|
||||||
msgstr "Pysäytä suora TV-lähetys"
|
|
||||||
|
|
||||||
msgid "Common Settings"
|
|
||||||
msgstr "Yleiset asetukset"
|
|
||||||
|
|
||||||
msgid "Maximum Number of Clients"
|
|
||||||
msgstr "Suurin sallittu asiakkaiden määrä"
|
|
||||||
|
|
||||||
msgid "Suspend behaviour"
|
|
||||||
msgstr "Pysäytystoiminto"
|
|
||||||
|
|
||||||
msgid "Client may suspend"
|
|
||||||
msgstr "Asiakas saa pysäyttää palvelimen"
|
|
||||||
|
|
||||||
msgid "VDR-to-VDR Server"
|
|
||||||
msgstr "VDR-palvelin"
|
|
||||||
|
|
||||||
msgid "Start VDR-to-VDR Server"
|
|
||||||
msgstr "Käynnistä 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 "Käynnistä HTTP-palvelin"
|
|
||||||
|
|
||||||
msgid "HTTP Server Port"
|
|
||||||
msgstr "HTTP-palvelimen portti"
|
|
||||||
|
|
||||||
msgid "HTTP Streamtype"
|
|
||||||
msgstr "HTTP-lähetysmuoto"
|
|
||||||
|
|
||||||
msgid "Offer suspend mode"
|
|
||||||
msgstr "tyrkytä"
|
|
||||||
|
|
||||||
msgid "Always suspended"
|
|
||||||
msgstr "aina"
|
|
||||||
|
|
||||||
msgid "Never suspended"
|
|
||||||
msgstr "ei koskaan"
|
|
34
remux/Makefile
Normal file
34
remux/Makefile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# Makefile for a Video Disk Recorder plugin
|
||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1.2.1 2010/06/14 10:40:18 schmirl Exp $
|
||||||
|
|
||||||
|
### The object files (add further files here):
|
||||||
|
|
||||||
|
OBJS = tsremux.o ts2es.o ts2pes.o ts2ps.o extern.o
|
||||||
|
|
||||||
|
### The main target:
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
remux.a: $(OBJS)
|
||||||
|
ar -rcs remux.a $^
|
||||||
|
|
||||||
|
### Implicit rules:
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
### Dependencies:
|
||||||
|
|
||||||
|
MAKEDEP = $(CXX) -MM -MG
|
||||||
|
DEPFILE = .dependencies
|
||||||
|
|
||||||
|
$(DEPFILE): Makefile
|
||||||
|
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
||||||
|
|
||||||
|
-include $(DEPFILE)
|
||||||
|
|
||||||
|
### Targets:
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm -f $(OBJS) $(DEPFILE) *.a core* *~
|
130
remux/extern.c
130
remux/extern.c
@ -1,14 +1,19 @@
|
|||||||
#include "remux/extern.h"
|
#include "remux/extern.h"
|
||||||
#include "server/server.h"
|
#include "server/server.h"
|
||||||
|
#include "server/connection.h"
|
||||||
#include "server/streamer.h"
|
#include "server/streamer.h"
|
||||||
|
#include <vdr/channels.h>
|
||||||
#include <vdr/tools.h>
|
#include <vdr/tools.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
namespace Streamdev {
|
namespace Streamdev {
|
||||||
|
|
||||||
|
#define MAXENV 63
|
||||||
|
|
||||||
class cTSExt: public cThread {
|
class cTSExt: public cThread {
|
||||||
private:
|
private:
|
||||||
cRingBufferLinear *m_ResultBuffer;
|
cRingBufferLinear *m_ResultBuffer;
|
||||||
@ -20,7 +25,7 @@ protected:
|
|||||||
virtual void Action(void);
|
virtual void Action(void);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cTSExt(cRingBufferLinear *ResultBuffer, std::string Parameter);
|
cTSExt(cRingBufferLinear *ResultBuffer, const cServerConnection *Connection, const cChannel *Channel, const int *Apids, const int *Dpids);
|
||||||
virtual ~cTSExt();
|
virtual ~cTSExt();
|
||||||
|
|
||||||
void Put(const uchar *Data, int Count);
|
void Put(const uchar *Data, int Count);
|
||||||
@ -29,7 +34,7 @@ public:
|
|||||||
} // namespace Streamdev
|
} // namespace Streamdev
|
||||||
using namespace Streamdev;
|
using namespace Streamdev;
|
||||||
|
|
||||||
cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, std::string Parameter):
|
cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, const cServerConnection *Connection, const cChannel *Channel, const int *Apids, const int *Dpids):
|
||||||
m_ResultBuffer(ResultBuffer),
|
m_ResultBuffer(ResultBuffer),
|
||||||
m_Active(false),
|
m_Active(false),
|
||||||
m_Process(-1),
|
m_Process(-1),
|
||||||
@ -62,6 +67,115 @@ cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, std::string Parameter):
|
|||||||
|
|
||||||
if (m_Process == 0) {
|
if (m_Process == 0) {
|
||||||
// child process
|
// child process
|
||||||
|
char *env[MAXENV + 1];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
#define ADDENV(x...) if (asprintf(&env[i++], x) < 0) i--
|
||||||
|
|
||||||
|
// add channel ID, name and pids to environment
|
||||||
|
ADDENV("REMUX_CHANNEL_ID=%s", *Channel->GetChannelID().ToString());
|
||||||
|
ADDENV("REMUX_CHANNEL_NAME=%s", Channel->Name());
|
||||||
|
#if APIVERSNUM >= 10701
|
||||||
|
ADDENV("REMUX_VTYPE=%d", Channel->Vtype());
|
||||||
|
#endif
|
||||||
|
if (Channel->Vpid())
|
||||||
|
ADDENV("REMUX_VPID=%d", Channel->Vpid());
|
||||||
|
if (Channel->Ppid() != Channel->Vpid())
|
||||||
|
ADDENV("REMUX_PPID=%d", Channel->Ppid());
|
||||||
|
if (Channel->Tpid())
|
||||||
|
ADDENV("REMUX_TPID=%d", Channel->Tpid());
|
||||||
|
|
||||||
|
std::string buffer;
|
||||||
|
if (Apids && *Apids) {
|
||||||
|
for (const int *pid = Apids; *pid; pid++)
|
||||||
|
(buffer += (const char *) itoa(*pid)) += (*(pid + 1) ? " " : "");
|
||||||
|
ADDENV("REMUX_APID=%s", buffer.c_str());
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
for (const int *pid = Apids; *pid; pid++) {
|
||||||
|
int j;
|
||||||
|
for (j = 0; Channel->Apid(j) && Channel->Apid(j) != *pid; j++)
|
||||||
|
;
|
||||||
|
(buffer += Channel->Alang(j)) += (*(pid + 1) ? " " : "");
|
||||||
|
}
|
||||||
|
ADDENV("REMUX_ALANG=%s", buffer.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Dpids && *Dpids) {
|
||||||
|
buffer.clear();
|
||||||
|
for (const int *pid = Dpids; *pid; pid++)
|
||||||
|
(buffer += (const char *) itoa(*pid)) += (*(pid + 1) ? " " : "");
|
||||||
|
ADDENV("REMUX_DPID=%s", buffer.c_str());
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
for (const int *pid = Dpids; *pid; pid++) {
|
||||||
|
int j;
|
||||||
|
for (j = 0; Channel->Dpid(j) && Channel->Dpid(j) != *pid; j++)
|
||||||
|
;
|
||||||
|
(buffer += Channel->Dlang(j)) += (*(pid + 1) ? " " : "");
|
||||||
|
}
|
||||||
|
ADDENV("REMUX_DLANG=%s", buffer.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Channel->Spid(0)) {
|
||||||
|
buffer.clear();
|
||||||
|
for (const int *pid = Channel->Spids(); *pid; pid++)
|
||||||
|
(buffer += (const char *) itoa(*pid)) += (*(pid + 1) ? " " : "");
|
||||||
|
ADDENV("REMUX_SPID=%s", buffer.c_str());
|
||||||
|
|
||||||
|
buffer.clear();
|
||||||
|
for (int j = 0; Channel->Spid(j); j++)
|
||||||
|
(buffer += Channel->Slang(j)) += (Channel->Spid(j + 1) ? " " : "");
|
||||||
|
ADDENV("REMUX_SLANG=%s", buffer.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Connection) {
|
||||||
|
// add vars for a CGI like interface
|
||||||
|
// the following vars are not implemented:
|
||||||
|
// REMOTE_HOST, REMOTE_IDENT, REMOTE_USER
|
||||||
|
// CONTENT_TYPE, CONTENT_LENGTH,
|
||||||
|
// SCRIPT_NAME, PATH_TRANSLATED, GATEWAY_INTERFACE
|
||||||
|
ADDENV("REMOTE_ADDR=%s", Connection->RemoteIp().c_str());
|
||||||
|
ADDENV("SERVER_NAME=%s", Connection->LocalIp().c_str());
|
||||||
|
ADDENV("SERVER_PORT=%d", Connection->LocalPort());
|
||||||
|
ADDENV("SERVER_PROTOCOL=%s", Connection->Protocol());
|
||||||
|
ADDENV("SERVER_SOFTWARE=%s", VERSION);
|
||||||
|
|
||||||
|
for (tStrStrMap::const_iterator it = Connection->Headers().begin(); it != Connection->Headers().end(); it++) {
|
||||||
|
if (i >= MAXENV) {
|
||||||
|
esyslog("streamdev-server: Too many headers for externremux.sh");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ADDENV("%s=%s", it->first.c_str(), it->second.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for section parameters: /path;param1=value1;param2=value2/
|
||||||
|
std::string::size_type begin, end;
|
||||||
|
std::string path = Connection->Headers().at("PATH_INFO");
|
||||||
|
begin = path.find(';', 0);
|
||||||
|
begin = path.find_first_not_of(';', begin);
|
||||||
|
end = path.find_first_of(";/", begin);
|
||||||
|
while (begin != std::string::npos && path[begin] != '/') {
|
||||||
|
std::string param = path.substr(begin, end - begin);
|
||||||
|
std::string::size_type e = param.find('=');
|
||||||
|
|
||||||
|
if (i >= MAXENV) {
|
||||||
|
esyslog("streamdev-server: Too many parameters for externremux.sh");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (e > 0 && e != std::string::npos) {
|
||||||
|
ADDENV("REMUX_PARAM_%s", param.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
esyslog("streamdev-server: Invalid externremux.sh parameter %s", param.c_str());
|
||||||
|
|
||||||
|
begin = path.find_first_not_of(';', end);
|
||||||
|
end = path.find_first_of(";/", begin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env[i] = NULL;
|
||||||
|
|
||||||
dup2(inpipe[0], STDIN_FILENO);
|
dup2(inpipe[0], STDIN_FILENO);
|
||||||
close(inpipe[1]);
|
close(inpipe[1]);
|
||||||
dup2(outpipe[1], STDOUT_FILENO);
|
dup2(outpipe[1], STDOUT_FILENO);
|
||||||
@ -71,9 +185,11 @@ cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, std::string Parameter):
|
|||||||
for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
|
for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
|
||||||
close(i); //close all dup'ed filedescriptors
|
close(i); //close all dup'ed filedescriptors
|
||||||
|
|
||||||
std::string cmd = std::string(opt_remux) + " " + Parameter;
|
if (setpgid(0, 0) == -1)
|
||||||
if (execl("/bin/sh", "sh", "-c", cmd.c_str(), NULL) == -1) {
|
esyslog("streamdev-server: externremux setpgid failed: %m");
|
||||||
esyslog("streamdev-server: externremux script '%s' execution failed: %m", cmd.c_str());
|
|
||||||
|
if (execle("/bin/sh", "sh", "-c", opt_remux, NULL, env) == -1) {
|
||||||
|
esyslog("streamdev-server: externremux script '%s' execution failed: %m", opt_remux);
|
||||||
_exit(-1);
|
_exit(-1);
|
||||||
}
|
}
|
||||||
// should never be reached
|
// should never be reached
|
||||||
@ -172,9 +288,9 @@ void cTSExt::Put(const uchar *Data, int Count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cExternRemux::cExternRemux(int VPid, const int *APids, const int *Dpids, const int *SPids, std::string Parameter):
|
cExternRemux::cExternRemux(const cServerConnection *Connection, const cChannel *Channel, const int *Apids, const int *Dpids):
|
||||||
m_ResultBuffer(new cRingBufferLinear(WRITERBUFSIZE, TS_SIZE * 2)),
|
m_ResultBuffer(new cRingBufferLinear(WRITERBUFSIZE, TS_SIZE * 2)),
|
||||||
m_Remux(new cTSExt(m_ResultBuffer, Parameter))
|
m_Remux(new cTSExt(m_ResultBuffer, Connection, Channel, Apids, Dpids))
|
||||||
{
|
{
|
||||||
m_ResultBuffer->SetTimeouts(500, 100);
|
m_ResultBuffer->SetTimeouts(500, 100);
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
#include <vdr/ringbuffer.h>
|
#include <vdr/ringbuffer.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class cChannel;
|
||||||
|
class cServerConnection;
|
||||||
|
|
||||||
namespace Streamdev {
|
namespace Streamdev {
|
||||||
|
|
||||||
class cTSExt;
|
class cTSExt;
|
||||||
@ -15,7 +18,7 @@ private:
|
|||||||
cTSExt *m_Remux;
|
cTSExt *m_Remux;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cExternRemux(int VPid, const int *APids, const int *Dpids, const int *SPids, std::string Parameter);
|
cExternRemux(const cServerConnection *Connection, const cChannel *Channel, const int *APids, const int *Dpids);
|
||||||
virtual ~cExternRemux();
|
virtual ~cExternRemux();
|
||||||
|
|
||||||
int Put(const uchar *Data, int Count);
|
int Put(const uchar *Data, int Count);
|
||||||
|
@ -11,6 +11,8 @@ namespace Streamdev {
|
|||||||
|
|
||||||
class cTSRemux {
|
class cTSRemux {
|
||||||
public:
|
public:
|
||||||
|
virtual ~cTSRemux() {};
|
||||||
|
|
||||||
virtual int Put(const uchar *Data, int Count) = 0;
|
virtual int Put(const uchar *Data, int Count) = 0;
|
||||||
virtual uchar *Get(int &Count) = 0;
|
virtual uchar *Get(int &Count) = 0;
|
||||||
virtual void Del(int Count) = 0;
|
virtual void Del(int Count) = 0;
|
||||||
|
82
server/Makefile
Normal file
82
server/Makefile
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#
|
||||||
|
# Makefile for a Video Disk Recorder plugin
|
||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1.2.1 2010/06/14 10:40:20 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 $@ $(LIBDIR)/$@.$(APIVERSION)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm -f $(COMMONOBJS) $(SERVEROBJS) $(DEPFILE) $(PODIR)/*.mo $(PODIR)/*.pot *.so *.tgz core* *~
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connection.c,v 1.12 2009/02/13 10:39:22 schmirl Exp $
|
* $Id: connection.c,v 1.13.2.1 2010/06/11 06:06:02 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connection.h"
|
#include "server/connection.h"
|
||||||
@ -27,6 +27,66 @@ cServerConnection::~cServerConnection()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cChannel* cServerConnection::ChannelFromString(const char *String, int *Apid, int *Dpid) {
|
||||||
|
const cChannel *channel = NULL;
|
||||||
|
char *string = strdup(String);
|
||||||
|
char *ptr, *end;
|
||||||
|
int apididx = 0;
|
||||||
|
|
||||||
|
if ((ptr = strrchr(string, '+')) != NULL) {
|
||||||
|
*(ptr++) = '\0';
|
||||||
|
apididx = strtoul(ptr, &end, 10);
|
||||||
|
Dprintf("found apididx: %d\n", apididx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isnumber(string)) {
|
||||||
|
int temp = strtol(String, NULL, 10);
|
||||||
|
if (temp >= 1 && temp <= Channels.MaxNumber())
|
||||||
|
channel = Channels.GetByNumber(temp);
|
||||||
|
} else {
|
||||||
|
channel = Channels.GetByChannelID(tChannelID::FromString(string));
|
||||||
|
|
||||||
|
if (channel == NULL) {
|
||||||
|
int i = 1;
|
||||||
|
while ((channel = Channels.GetByNumber(i, 1)) != NULL) {
|
||||||
|
if (String == channel->Name())
|
||||||
|
break;
|
||||||
|
|
||||||
|
i = channel->Number() + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel != NULL && apididx > 0) {
|
||||||
|
int apid = 0, dpid = 0;
|
||||||
|
int index = 1;
|
||||||
|
|
||||||
|
for (int i = 0; channel->Apid(i) != 0; ++i, ++index) {
|
||||||
|
if (index == apididx) {
|
||||||
|
apid = channel->Apid(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (apid == 0) {
|
||||||
|
for (int i = 0; channel->Dpid(i) != 0; ++i, ++index) {
|
||||||
|
if (index == apididx) {
|
||||||
|
dpid = channel->Dpid(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Apid != NULL)
|
||||||
|
*Apid = apid;
|
||||||
|
if (Dpid != NULL)
|
||||||
|
*Dpid = dpid;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(string);
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
bool cServerConnection::Read(void)
|
bool cServerConnection::Read(void)
|
||||||
{
|
{
|
||||||
int b;
|
int b;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connection.h,v 1.7 2009/02/13 10:39:22 schmirl Exp $
|
* $Id: connection.h,v 1.8.2.1 2010/06/11 06:06:02 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
|
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
|
||||||
@ -8,6 +8,11 @@
|
|||||||
#include "tools/socket.h"
|
#include "tools/socket.h"
|
||||||
#include "common.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 cChannel;
|
||||||
class cDevice;
|
class cDevice;
|
||||||
|
|
||||||
@ -28,6 +33,8 @@ private:
|
|||||||
uint m_WriteBytes;
|
uint m_WriteBytes;
|
||||||
uint m_WriteIndex;
|
uint m_WriteIndex;
|
||||||
|
|
||||||
|
tStrStrMap m_Headers;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/* Will be called when a command terminated by a newline has been
|
/* Will be called when a command terminated by a newline has been
|
||||||
received */
|
received */
|
||||||
@ -41,6 +48,11 @@ protected:
|
|||||||
virtual bool Respond(const char *Message, bool Last = true, ...);
|
virtual bool Respond(const char *Message, bool Last = true, ...);
|
||||||
//__attribute__ ((format (printf, 2, 4)));
|
//__attribute__ ((format (printf, 2, 4)));
|
||||||
|
|
||||||
|
/* 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:
|
public:
|
||||||
/* If you derive, specify a short string such as HTTP for Protocol, which
|
/* If you derive, specify a short string such as HTTP for Protocol, which
|
||||||
will be displayed in error messages */
|
will be displayed in error messages */
|
||||||
@ -87,6 +99,12 @@ public:
|
|||||||
|
|
||||||
virtual void Detach(void) = 0;
|
virtual void Detach(void) = 0;
|
||||||
virtual void Attach(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
|
inline bool cServerConnection::HasData(void) const
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionHTTP.c,v 1.17 2009/06/19 06:32:45 schmirl Exp $
|
* $Id: connectionHTTP.c,v 1.17.2.1 2010/06/11 06:06:02 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -13,13 +13,13 @@ cConnectionHTTP::cConnectionHTTP(void):
|
|||||||
cServerConnection("HTTP"),
|
cServerConnection("HTTP"),
|
||||||
m_Status(hsRequest),
|
m_Status(hsRequest),
|
||||||
m_LiveStreamer(NULL),
|
m_LiveStreamer(NULL),
|
||||||
m_StreamerParameter(""),
|
|
||||||
m_Channel(NULL),
|
m_Channel(NULL),
|
||||||
m_Apid(0),
|
|
||||||
m_StreamType((eStreamType)StreamdevServerSetup.HTTPStreamType),
|
m_StreamType((eStreamType)StreamdevServerSetup.HTTPStreamType),
|
||||||
m_ChannelList(NULL)
|
m_ChannelList(NULL)
|
||||||
{
|
{
|
||||||
Dprintf("constructor hsRequest\n");
|
Dprintf("constructor hsRequest\n");
|
||||||
|
m_Apid[0] = m_Apid[1] = 0;
|
||||||
|
m_Dpid[0] = m_Dpid[1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cConnectionHTTP::~cConnectionHTTP()
|
cConnectionHTTP::~cConnectionHTTP()
|
||||||
@ -37,30 +37,64 @@ bool cConnectionHTTP::Command(char *Cmd)
|
|||||||
Dprintf("command %s\n", Cmd);
|
Dprintf("command %s\n", Cmd);
|
||||||
switch (m_Status) {
|
switch (m_Status) {
|
||||||
case hsRequest:
|
case hsRequest:
|
||||||
Dprintf("Request\n");
|
// parse METHOD PATH[?QUERY] VERSION
|
||||||
m_Request = Cmd;
|
{
|
||||||
m_Status = hsHeaders;
|
char *p, *q, *v;
|
||||||
return true;
|
p = strchr(Cmd, ' ');
|
||||||
|
if (p) {
|
||||||
|
*p = 0;
|
||||||
|
v = strchr(++p, ' ');
|
||||||
|
if (v) {
|
||||||
|
*v = 0;
|
||||||
|
SetHeader("REQUEST_METHOD", Cmd);
|
||||||
|
q = strchr(p, '?');
|
||||||
|
if (q)
|
||||||
|
*q = 0;
|
||||||
|
SetHeader("QUERY_STRING", q ? ++q : "");
|
||||||
|
SetHeader("PATH_INFO", p);
|
||||||
|
m_Status = hsHeaders;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
case hsHeaders:
|
case hsHeaders:
|
||||||
if (*Cmd == '\0') {
|
if (*Cmd == '\0') {
|
||||||
m_Status = hsBody;
|
m_Status = hsBody;
|
||||||
return ProcessRequest();
|
return ProcessRequest();
|
||||||
}
|
}
|
||||||
if (strncasecmp(Cmd, "Host:", 5) == 0) {
|
else if (isspace(*Cmd)) {
|
||||||
Dprintf("Host-Header\n");
|
; //TODO: multi-line header
|
||||||
m_Host = (std::string) skipspace(Cmd + 5);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else if (strncasecmp(Cmd, "Authorization:", 14) == 0) {
|
else {
|
||||||
Cmd = skipspace(Cmd + 14);
|
// convert header name to CGI conventions:
|
||||||
if (strncasecmp(Cmd, "Basic", 5) == 0) {
|
// uppercase, '-' replaced with '_', prefix "HTTP_"
|
||||||
Dprintf("'Authorization Basic'-Header\n");
|
char *p;
|
||||||
m_Authorization = (std::string) skipspace(Cmd + 5);
|
for (p = Cmd; *p != 0 && *p != ':'; p++) {
|
||||||
return true;
|
if (*p == '-')
|
||||||
|
*p = '_';
|
||||||
|
else
|
||||||
|
*p = toupper(*p);
|
||||||
|
}
|
||||||
|
if (*p == ':') {
|
||||||
|
*p = 0;
|
||||||
|
p = skipspace(++p);
|
||||||
|
// don't disclose Authorization header
|
||||||
|
if (strcmp(Cmd, "AUTHORIZATION") == 0) {
|
||||||
|
char *q;
|
||||||
|
for (q = p; *q != 0 && *q != ' '; q++)
|
||||||
|
*q = toupper(*q);
|
||||||
|
if (p != q) {
|
||||||
|
*q = 0;
|
||||||
|
SetHeader("AUTH_TYPE", p);
|
||||||
|
m_Authorization = (std::string) skipspace(++q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SetHeader(Cmd, p, "HTTP_");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dprintf("header\n");
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
// skip additional blank lines
|
// skip additional blank lines
|
||||||
@ -73,10 +107,31 @@ bool cConnectionHTTP::Command(char *Cmd)
|
|||||||
|
|
||||||
bool cConnectionHTTP::ProcessRequest(void)
|
bool cConnectionHTTP::ProcessRequest(void)
|
||||||
{
|
{
|
||||||
|
// keys for Headers() hash
|
||||||
|
const static std::string AUTH_TYPE("AUTH_TYPE");
|
||||||
|
const static std::string REQUEST_METHOD("REQUEST_METHOD");
|
||||||
|
const static std::string PATH_INFO("PATH_INFO");
|
||||||
|
|
||||||
Dprintf("process\n");
|
Dprintf("process\n");
|
||||||
if (!StreamdevHosts.Acceptable(RemoteIpAddr()))
|
if (!StreamdevHosts.Acceptable(RemoteIpAddr())) {
|
||||||
{
|
bool authOk = opt_auth && !m_Authorization.empty();
|
||||||
if (!opt_auth || m_Authorization.empty() || m_Authorization.compare(opt_auth) != 0) {
|
if (authOk) {
|
||||||
|
tStrStrMap::const_iterator it = Headers().find(AUTH_TYPE);
|
||||||
|
|
||||||
|
if (it == Headers().end()) {
|
||||||
|
// no authorization header present
|
||||||
|
authOk = false;
|
||||||
|
}
|
||||||
|
else if (it->second.compare("BASIC") == 0) {
|
||||||
|
// basic auth
|
||||||
|
authOk &= m_Authorization.compare(opt_auth) == 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// unsupported auth type
|
||||||
|
authOk = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!authOk) {
|
||||||
isyslog("streamdev-server: HTTP authorization required");
|
isyslog("streamdev-server: HTTP authorization required");
|
||||||
DeferClose();
|
DeferClose();
|
||||||
return Respond("HTTP/1.0 401 Authorization Required")
|
return Respond("HTTP/1.0 401 Authorization Required")
|
||||||
@ -84,28 +139,22 @@ bool cConnectionHTTP::ProcessRequest(void)
|
|||||||
&& Respond("");
|
&& Respond("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_Request.substr(0, 4) == "GET " && CmdGET(m_Request.substr(4))) {
|
|
||||||
switch (m_Job) {
|
|
||||||
case hjListing:
|
|
||||||
if (m_ChannelList)
|
|
||||||
return Respond("%s", true, m_ChannelList->HttpHeader().c_str());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case hjTransfer:
|
if (Headers().at(REQUEST_METHOD).compare("GET") == 0 && ProcessURI(Headers().at(PATH_INFO))) {
|
||||||
if (m_Channel == NULL) {
|
if (m_ChannelList)
|
||||||
DeferClose();
|
return Respond("%s", true, m_ChannelList->HttpHeader().c_str());
|
||||||
return Respond("HTTP/1.0 404 not found");
|
else if (m_Channel != NULL) {
|
||||||
}
|
|
||||||
|
|
||||||
m_LiveStreamer = new cStreamdevLiveStreamer(0, m_StreamerParameter);
|
|
||||||
cDevice *device = GetDevice(m_Channel, 0);
|
cDevice *device = GetDevice(m_Channel, 0);
|
||||||
if (device != NULL) {
|
if (device != NULL) {
|
||||||
device->SwitchChannel(m_Channel, false);
|
device->SwitchChannel(m_Channel, false);
|
||||||
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid)) {
|
m_LiveStreamer = new cStreamdevLiveStreamer(0, this);
|
||||||
|
if (m_LiveStreamer->SetChannel(m_Channel, m_StreamType, m_Apid[0] ? m_Apid : NULL, m_Dpid[0] ? m_Dpid : NULL)) {
|
||||||
m_LiveStreamer->SetDevice(device);
|
m_LiveStreamer->SetDevice(device);
|
||||||
if (!SetDSCP())
|
if (!SetDSCP())
|
||||||
LOG_ERROR_STR("unable to set DSCP sockopt");
|
LOG_ERROR_STR("unable to set DSCP sockopt");
|
||||||
if (m_StreamType == stES && (m_Apid != 0 || ISRADIO(m_Channel))) {
|
if (m_StreamType == stEXT) {
|
||||||
|
return Respond("HTTP/1.0 200 OK");
|
||||||
|
} else if (ISRADIO(m_Channel) || (m_StreamType == stES && (m_Apid[0] || m_Dpid[0]))) {
|
||||||
return Respond("HTTP/1.0 200 OK")
|
return Respond("HTTP/1.0 200 OK")
|
||||||
&& Respond("Content-Type: audio/mpeg")
|
&& Respond("Content-Type: audio/mpeg")
|
||||||
&& Respond("icy-name: %s", true, m_Channel->Name())
|
&& Respond("icy-name: %s", true, m_Channel->Name())
|
||||||
@ -116,12 +165,46 @@ bool cConnectionHTTP::ProcessRequest(void)
|
|||||||
&& Respond("");
|
&& Respond("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DELETENULL(m_LiveStreamer);
|
||||||
}
|
}
|
||||||
DELETENULL(m_LiveStreamer);
|
|
||||||
DeferClose();
|
DeferClose();
|
||||||
return Respond("HTTP/1.0 409 Channel not available")
|
return Respond("HTTP/1.0 409 Channel not available")
|
||||||
&& Respond("");
|
&& Respond("");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
DeferClose();
|
||||||
|
return Respond("HTTP/1.0 404 not found")
|
||||||
|
&& Respond("");
|
||||||
|
}
|
||||||
|
} else if (Headers().at(REQUEST_METHOD).compare("HEAD") == 0 && ProcessURI(Headers().at(PATH_INFO))) {
|
||||||
|
DeferClose();
|
||||||
|
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 (m_StreamType == stEXT) {
|
||||||
|
// TODO
|
||||||
|
return Respond("HTTP/1.0 200 OK")
|
||||||
|
&& Respond("");
|
||||||
|
} else if (ISRADIO(m_Channel) || (m_StreamType == stES && (m_Apid[0] || m_Dpid[0]))) {
|
||||||
|
return Respond("HTTP/1.0 200 OK")
|
||||||
|
&& Respond("Content-Type: audio/mpeg")
|
||||||
|
&& Respond("icy-name: %s", true, m_Channel->Name())
|
||||||
|
&& Respond("");
|
||||||
|
} else {
|
||||||
|
return Respond("HTTP/1.0 200 OK")
|
||||||
|
&& Respond("Content-Type: video/mpeg")
|
||||||
|
&& Respond("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Respond("HTTP/1.0 409 Channel not available")
|
||||||
|
&& Respond("");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return Respond("HTTP/1.0 404 not found")
|
||||||
|
&& Respond("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DeferClose();
|
DeferClose();
|
||||||
@ -136,78 +219,108 @@ void cConnectionHTTP::Flushed(void)
|
|||||||
if (m_Status != hsBody)
|
if (m_Status != hsBody)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (m_Job) {
|
if (m_ChannelList) {
|
||||||
case hjListing:
|
if (m_ChannelList->HasNext()) {
|
||||||
if (m_ChannelList) {
|
if (!Respond("%s", true, m_ChannelList->Next().c_str()))
|
||||||
if (m_ChannelList->HasNext()) {
|
|
||||||
if (!Respond("%s", true, m_ChannelList->Next().c_str()))
|
|
||||||
DeferClose();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
DELETENULL(m_ChannelList);
|
|
||||||
m_Status = hsFinished;
|
|
||||||
DeferClose();
|
DeferClose();
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// should never be reached
|
else {
|
||||||
esyslog("streamdev-server cConnectionHTTP::Flushed(): no channel list");
|
DELETENULL(m_ChannelList);
|
||||||
m_Status = hsFinished;
|
m_Status = hsFinished;
|
||||||
break;
|
DeferClose();
|
||||||
|
}
|
||||||
case hjTransfer:
|
return;
|
||||||
|
}
|
||||||
|
else if (m_Channel != NULL) {
|
||||||
Dprintf("streamer start\n");
|
Dprintf("streamer start\n");
|
||||||
m_LiveStreamer->Start(this);
|
m_LiveStreamer->Start(this);
|
||||||
m_Status = hsFinished;
|
m_Status = hsFinished;
|
||||||
break;
|
}
|
||||||
|
else {
|
||||||
|
// should never be reached
|
||||||
|
esyslog("streamdev-server cConnectionHTTP::Flushed(): no job to do");
|
||||||
|
m_Status = hsFinished;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cConnectionHTTP::CmdGET(const std::string &Opts)
|
cChannelList* cConnectionHTTP::ChannelListFromString(const std::string& Path, const std::string& Filebase, const std::string& Fileext) const
|
||||||
{
|
{
|
||||||
const char *ptr, *sp, *pp, *fp, *xp, *qp, *ep;
|
// keys for Headers() hash
|
||||||
const cChannel *chan;
|
const static std::string QUERY_STRING("QUERY_STRING");
|
||||||
int apid = 0;
|
const static std::string HOST("HTTP_HOST");
|
||||||
|
|
||||||
ptr = Opts.c_str();
|
const std::string query = Headers().at(QUERY_STRING);
|
||||||
|
|
||||||
// find begin of URL
|
std::string groupTarget;
|
||||||
sp = skipspace(ptr);
|
cChannelIterator *iterator = NULL;
|
||||||
// find end of URL (\0 or first space character)
|
|
||||||
for (ep = sp; *ep && !isspace(*ep); ep++)
|
if (Filebase.compare("tree") == 0) {
|
||||||
;
|
const cChannel* c = NULL;
|
||||||
// find begin of query string (first ?)
|
size_t groupIndex = query.find("group=");
|
||||||
for (qp = sp; qp < ep && *qp != '?'; qp++)
|
if (groupIndex != std::string::npos)
|
||||||
;
|
c = cChannelList::GetGroup(atoi(query.c_str() + groupIndex + 6));
|
||||||
// find begin of filename (last /)
|
iterator = new cListTree(c);
|
||||||
for (fp = qp; fp > sp && *fp != '/'; --fp)
|
groupTarget = Filebase + Fileext;
|
||||||
;
|
} else if (Filebase.compare("groups") == 0) {
|
||||||
// find begin of section params (first ;)
|
iterator = new cListGroups();
|
||||||
for (pp = sp; pp < fp && *pp != ';'; pp++)
|
groupTarget = (std::string) "group" + Fileext;
|
||||||
;
|
} else if (Filebase.compare("group") == 0) {
|
||||||
// find filename extension (first .)
|
const cChannel* c = NULL;
|
||||||
for (xp = fp; xp < qp && *xp != '.'; xp++)
|
size_t groupIndex = query.find("group=");
|
||||||
;
|
if (groupIndex != std::string::npos)
|
||||||
if (qp - xp > 5) // too long for a filename extension
|
c = cChannelList::GetGroup(atoi(query.c_str() + groupIndex + 6));
|
||||||
xp = qp;
|
iterator = new cListGroup(c);
|
||||||
|
} else if (Filebase.compare("channels") == 0) {
|
||||||
|
iterator = new cListChannels();
|
||||||
|
} else if (Filebase.compare("all") == 0 ||
|
||||||
|
(Filebase.empty() && Fileext.empty())) {
|
||||||
|
iterator = new cListAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iterator) {
|
||||||
|
if (Filebase.empty() || Fileext.compare(".htm") == 0 || Fileext.compare(".html") == 0) {
|
||||||
|
std::string self = Filebase + Fileext;
|
||||||
|
if (!query.empty())
|
||||||
|
self += '?' + query;
|
||||||
|
return new cHtmlChannelList(iterator, m_StreamType, self.c_str(), groupTarget.c_str());
|
||||||
|
} else if (Fileext.compare(".m3u") == 0) {
|
||||||
|
std::string base;
|
||||||
|
tStrStrMap::const_iterator it = Headers().find(HOST);
|
||||||
|
if (it != Headers().end())
|
||||||
|
base = "http://" + it->second + "/";
|
||||||
|
else
|
||||||
|
base = (std::string) "http://" + LocalIp() + ":" +
|
||||||
|
(const char*) itoa(StreamdevServerSetup.HTTPServerPort) + "/";
|
||||||
|
base += Path;
|
||||||
|
return new cM3uChannelList(iterator, base.c_str());
|
||||||
|
} else {
|
||||||
|
delete iterator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cConnectionHTTP::ProcessURI(const std::string& PathInfo)
|
||||||
|
{
|
||||||
|
std::string filespec, fileext;
|
||||||
|
size_t file_pos = PathInfo.rfind('/');
|
||||||
|
|
||||||
|
if (file_pos != std::string::npos) {
|
||||||
|
size_t ext_pos = PathInfo.rfind('.');
|
||||||
|
// file basename with leading / stripped off
|
||||||
|
filespec = PathInfo.substr(file_pos + 1, ext_pos - file_pos - 1);
|
||||||
|
if (ext_pos != std::string::npos)
|
||||||
|
// file extension including leading .
|
||||||
|
fileext = PathInfo.substr(ext_pos);
|
||||||
|
}
|
||||||
|
if (fileext.length() > 5) {
|
||||||
|
//probably not an extension
|
||||||
|
filespec += fileext;
|
||||||
|
fileext.clear();
|
||||||
|
}
|
||||||
|
|
||||||
std::string type, filespec, fileext, query;
|
|
||||||
// Streamtype with leading / stripped off
|
// Streamtype with leading / stripped off
|
||||||
if (pp > sp)
|
std::string type = PathInfo.substr(1, PathInfo.find_first_of("/;", 1) - 1);
|
||||||
type = Opts.substr(sp - ptr + 1, pp - sp - 1);
|
|
||||||
// Section parameters with leading ; stripped off
|
|
||||||
if (fp > pp)
|
|
||||||
m_StreamerParameter = Opts.substr(pp - ptr + 1, fp - pp - 1);
|
|
||||||
// file basename with leading / stripped off
|
|
||||||
if (xp > fp)
|
|
||||||
filespec = Opts.substr(fp - ptr + 1, xp - fp - 1);
|
|
||||||
// file extension including leading .
|
|
||||||
fileext = Opts.substr(xp - ptr, qp - xp);
|
|
||||||
// query string including leading ?
|
|
||||||
query = Opts.substr(qp - ptr, ep - qp);
|
|
||||||
|
|
||||||
Dprintf("before channelfromstring: type(%s) param(%s) filespec(%s) fileext(%s) query(%s)\n", type.c_str(), m_StreamerParameter.c_str(), filespec.c_str(), fileext.c_str(), query.c_str());
|
|
||||||
|
|
||||||
const char* pType = type.c_str();
|
const char* pType = type.c_str();
|
||||||
if (strcasecmp(pType, "PS") == 0) {
|
if (strcasecmp(pType, "PS") == 0) {
|
||||||
m_StreamType = stPS;
|
m_StreamType = stPS;
|
||||||
@ -217,80 +330,19 @@ bool cConnectionHTTP::CmdGET(const std::string &Opts)
|
|||||||
m_StreamType = stTS;
|
m_StreamType = stTS;
|
||||||
} else if (strcasecmp(pType, "ES") == 0) {
|
} else if (strcasecmp(pType, "ES") == 0) {
|
||||||
m_StreamType = stES;
|
m_StreamType = stES;
|
||||||
} else if (strcasecmp(pType, "Extern") == 0) {
|
} else if (strcasecmp(pType, "EXT") == 0) {
|
||||||
m_StreamType = stExtern;
|
m_StreamType = stEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string groupTarget;
|
Dprintf("before channelfromstring: type(%s) filespec(%s) fileext(%s)\n", type.c_str(), filespec.c_str(), fileext.c_str());
|
||||||
cChannelIterator *iterator = NULL;
|
|
||||||
|
|
||||||
if (filespec.compare("tree") == 0) {
|
if ((m_ChannelList = ChannelListFromString(PathInfo.substr(0, file_pos), filespec.c_str(), fileext.c_str())) != NULL) {
|
||||||
const cChannel* c = NULL;
|
Dprintf("Channel list requested\n");
|
||||||
size_t groupIndex = query.find("group=");
|
return true;
|
||||||
if (groupIndex != std::string::npos)
|
} else if ((m_Channel = ChannelFromString(filespec.c_str(), &m_Apid[0], &m_Dpid[0])) != NULL) {
|
||||||
c = cChannelList::GetGroup(atoi(query.c_str() + groupIndex + 6));
|
Dprintf("Channel found. Apid/Dpid is %d/%d\n", m_Apid[0], m_Dpid[0]);
|
||||||
iterator = new cListTree(c);
|
return true;
|
||||||
groupTarget = filespec + fileext;
|
|
||||||
} else if (filespec.compare("groups") == 0) {
|
|
||||||
iterator = new cListGroups();
|
|
||||||
groupTarget = (std::string) "group" + fileext;
|
|
||||||
} else if (filespec.compare("group") == 0) {
|
|
||||||
const cChannel* c = NULL;
|
|
||||||
size_t groupIndex = query.find("group=");
|
|
||||||
if (groupIndex != std::string::npos)
|
|
||||||
c = cChannelList::GetGroup(atoi(query.c_str() + groupIndex + 6));
|
|
||||||
iterator = new cListGroup(c);
|
|
||||||
} else if (filespec.compare("channels") == 0) {
|
|
||||||
iterator = new cListChannels();
|
|
||||||
} else if (filespec.compare("all") == 0 ||
|
|
||||||
(filespec.empty() && fileext.empty())) {
|
|
||||||
iterator = new cListAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iterator) {
|
|
||||||
if (filespec.empty() || fileext.compare(".htm") == 0 || fileext.compare(".html") == 0) {
|
|
||||||
m_ChannelList = new cHtmlChannelList(iterator, m_StreamType, (filespec + fileext + query).c_str(), groupTarget.c_str());
|
|
||||||
m_Job = hjListing;
|
|
||||||
} else if (fileext.compare(".m3u") == 0) {
|
|
||||||
std::string base;
|
|
||||||
if (*(m_Host.c_str()))
|
|
||||||
base = "http://" + m_Host + "/";
|
|
||||||
else
|
|
||||||
base = (std::string) "http://" + LocalIp() + ":" +
|
|
||||||
(const char*) itoa(StreamdevServerSetup.HTTPServerPort) + "/";
|
|
||||||
if (type.empty())
|
|
||||||
{
|
|
||||||
switch (m_StreamType)
|
|
||||||
{
|
|
||||||
case stTS: base += "TS/"; break;
|
|
||||||
case stPS: base += "PS/"; break;
|
|
||||||
case stPES: base += "PES/"; break;
|
|
||||||
case stES: base += "ES/"; break;
|
|
||||||
case stExtern: base += "Extern/"; break;
|
|
||||||
default: break;
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
base += type;
|
|
||||||
if (!m_StreamerParameter.empty())
|
|
||||||
base += ";" + m_StreamerParameter;
|
|
||||||
base += "/";
|
|
||||||
}
|
|
||||||
m_ChannelList = new cM3uChannelList(iterator, base.c_str());
|
|
||||||
m_Job = hjListing;
|
|
||||||
} else {
|
|
||||||
delete iterator;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if ((chan = ChannelFromString(filespec.c_str(), &apid)) != NULL) {
|
|
||||||
m_Channel = chan;
|
|
||||||
m_Apid = apid;
|
|
||||||
Dprintf("Apid is %d\n", apid);
|
|
||||||
m_Job = hjTransfer;
|
|
||||||
} else
|
} else
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Dprintf("after channelfromstring\n");
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionHTTP.h,v 1.6 2008/10/14 11:05:48 schmirl Exp $
|
* $Id: connectionHTTP.h,v 1.6.2.1 2010/06/11 06:06:02 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
|
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
|
||||||
@ -8,6 +8,7 @@
|
|||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
#include "server/livestreamer.h"
|
#include "server/livestreamer.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <tools/select.h>
|
#include <tools/select.h>
|
||||||
|
|
||||||
class cChannel;
|
class cChannel;
|
||||||
@ -23,26 +24,19 @@ private:
|
|||||||
hsFinished,
|
hsFinished,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eHTTPJob {
|
|
||||||
hjTransfer,
|
|
||||||
hjListing,
|
|
||||||
};
|
|
||||||
|
|
||||||
std::string m_Request;
|
|
||||||
std::string m_Host;
|
|
||||||
std::string m_Authorization;
|
std::string m_Authorization;
|
||||||
//std::map<std::string,std::string> m_Headers; TODO: later?
|
|
||||||
eHTTPStatus m_Status;
|
eHTTPStatus m_Status;
|
||||||
eHTTPJob m_Job;
|
|
||||||
// job: transfer
|
// job: transfer
|
||||||
cStreamdevLiveStreamer *m_LiveStreamer;
|
cStreamdevLiveStreamer *m_LiveStreamer;
|
||||||
std::string m_StreamerParameter;
|
|
||||||
const cChannel *m_Channel;
|
const cChannel *m_Channel;
|
||||||
int m_Apid;
|
int m_Apid[2];
|
||||||
|
int m_Dpid[2];
|
||||||
eStreamType m_StreamType;
|
eStreamType m_StreamType;
|
||||||
// job: listing
|
// job: listing
|
||||||
cChannelList *m_ChannelList;
|
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:
|
protected:
|
||||||
bool ProcessRequest(void);
|
bool ProcessRequest(void);
|
||||||
|
|
||||||
@ -56,7 +50,6 @@ public:
|
|||||||
virtual bool CanAuthenticate(void);
|
virtual bool CanAuthenticate(void);
|
||||||
|
|
||||||
virtual bool Command(char *Cmd);
|
virtual bool Command(char *Cmd);
|
||||||
bool CmdGET(const std::string &Opts);
|
|
||||||
|
|
||||||
virtual bool Abort(void) const;
|
virtual bool Abort(void) const;
|
||||||
virtual void Flushed(void);
|
virtual void Flushed(void);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionIGMP.c,v 1.1 2009/02/13 10:39:22 schmirl Exp $
|
* $Id: connectionIGMP.c,v 1.1.4.1 2010/06/11 06:06:02 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -31,7 +31,7 @@ bool cConnectionIGMP::Start(cChannel *Channel, in_addr_t Dst)
|
|||||||
struct in_addr ip;
|
struct in_addr ip;
|
||||||
ip.s_addr = Dst;
|
ip.s_addr = Dst;
|
||||||
if (Connect(inet_ntoa(ip), m_ClientPort)) {
|
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)) {
|
if (m_LiveStreamer->SetChannel(Channel, m_StreamType)) {
|
||||||
m_LiveStreamer->SetDevice(device);
|
m_LiveStreamer->SetDevice(device);
|
||||||
if (!SetDSCP())
|
if (!SetDSCP())
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: connectionVTP.c,v 1.22 2009/07/02 06:03:51 schmirl Exp $
|
* $Id: connectionVTP.c,v 1.27.2.1 2010/06/11 06:06:03 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "server/connectionVTP.h"
|
#include "server/connectionVTP.h"
|
||||||
@ -40,6 +40,9 @@ private:
|
|||||||
#if defined(USE_PARENTALRATING) || defined(PARENTALRATINGCONTENTVERSNUM)
|
#if defined(USE_PARENTALRATING) || defined(PARENTALRATINGCONTENTVERSNUM)
|
||||||
enum eStates { Channel, Event, Title, Subtitle, Description, Vps, Content,
|
enum eStates { Channel, Event, Title, Subtitle, Description, Vps, Content,
|
||||||
EndEvent, EndChannel, EndEPG };
|
EndEvent, EndChannel, EndEPG };
|
||||||
|
#elif APIVERSNUM >= 10711
|
||||||
|
enum eStates { Channel, Event, Title, Subtitle, Description, Vps, Content, Rating,
|
||||||
|
EndEvent, EndChannel, EndEPG };
|
||||||
#else
|
#else
|
||||||
enum eStates { Channel, Event, Title, Subtitle, Description, Vps,
|
enum eStates { Channel, Event, Title, Subtitle, Description, Vps,
|
||||||
EndEvent, EndChannel, EndEPG };
|
EndEvent, EndChannel, EndEPG };
|
||||||
@ -50,7 +53,7 @@ private:
|
|||||||
const cSchedule *m_Schedule;
|
const cSchedule *m_Schedule;
|
||||||
const cEvent *m_Event;
|
const cEvent *m_Event;
|
||||||
int m_Errno;
|
int m_Errno;
|
||||||
char *m_Error;
|
cString m_Error;
|
||||||
eStates m_State;
|
eStates m_State;
|
||||||
bool m_Traverse;
|
bool m_Traverse;
|
||||||
time_t m_ToTime;
|
time_t m_ToTime;
|
||||||
@ -67,7 +70,6 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Schedule(NULL),
|
m_Schedule(NULL),
|
||||||
m_Event(NULL),
|
m_Event(NULL),
|
||||||
m_Errno(0),
|
m_Errno(0),
|
||||||
m_Error(NULL),
|
|
||||||
m_State(Channel),
|
m_State(Channel),
|
||||||
m_Traverse(false),
|
m_Traverse(false),
|
||||||
m_ToTime(0)
|
m_ToTime(0)
|
||||||
@ -94,12 +96,12 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
attime = strtol(p, NULL, 10);
|
attime = strtol(p, NULL, 10);
|
||||||
else {
|
else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
m_Error = strdup("Invalid time");
|
m_Error = "Invalid time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
m_Error = strdup("Missing time");
|
m_Error = "Missing time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,7 +112,7 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
fromtime = strtol(p, NULL, 10);
|
fromtime = strtol(p, NULL, 10);
|
||||||
else {
|
else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
m_Error = strdup("Invalid time");
|
m_Error = "Invalid time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
|
if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
|
||||||
@ -120,19 +122,19 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_ToTime = strtol(p, NULL, 10);
|
m_ToTime = strtol(p, NULL, 10);
|
||||||
else {
|
else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
m_Error = strdup("Invalid time");
|
m_Error = "Invalid time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
m_Error = strdup("Missing time");
|
m_Error = "Missing time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
m_Error = strdup("Missing time");
|
m_Error = "Missing time";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (!m_Schedule) {
|
} else if (!m_Schedule) {
|
||||||
@ -146,27 +148,27 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Schedule = m_Schedules->GetSchedule(Channel->GetChannelID());
|
m_Schedule = m_Schedules->GetSchedule(Channel->GetChannelID());
|
||||||
if (!m_Schedule) {
|
if (!m_Schedule) {
|
||||||
m_Errno = 550;
|
m_Errno = 550;
|
||||||
m_Error = strdup("No schedule found");
|
m_Error = "No schedule found";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 550;
|
m_Errno = 550;
|
||||||
asprintf(&m_Error, "Channel \"%s\" not defined", p);
|
m_Error = cString::sprintf("Channel \"%s\" not defined", p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Unknown option: \"%s\"", p);
|
m_Error = cString::sprintf("Unknown option: \"%s\"", p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p = strtok_r(NULL, delim, &strtok_next);
|
p = strtok_r(NULL, delim, &strtok_next);
|
||||||
}
|
}
|
||||||
} else if (m_Schedules == NULL) {
|
} else if (m_Schedules == NULL) {
|
||||||
m_Errno = 451;
|
m_Errno = 451;
|
||||||
m_Error = strdup("EPG data is being modified, try again");
|
m_Error = "EPG data is being modified, try again";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Error == NULL) {
|
if (*m_Error == NULL) {
|
||||||
if (m_Schedule != NULL)
|
if (m_Schedule != NULL)
|
||||||
m_Schedules = NULL;
|
m_Schedules = NULL;
|
||||||
else if (m_Schedules != NULL)
|
else if (m_Schedules != NULL)
|
||||||
@ -205,17 +207,15 @@ cLSTEHandler::cLSTEHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
cLSTEHandler::~cLSTEHandler()
|
cLSTEHandler::~cLSTEHandler()
|
||||||
{
|
{
|
||||||
delete m_SchedulesLock;
|
delete m_SchedulesLock;
|
||||||
if (m_Error != NULL)
|
|
||||||
free(m_Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cLSTEHandler::Next(bool &Last)
|
bool cLSTEHandler::Next(bool &Last)
|
||||||
{
|
{
|
||||||
if (m_Error != NULL) {
|
if (*m_Error != NULL) {
|
||||||
Last = true;
|
Last = true;
|
||||||
cString str(m_Error, true);
|
cString str(m_Error);
|
||||||
m_Error = NULL;
|
m_Error = NULL;
|
||||||
return m_Client->Respond(m_Errno, *str);
|
return m_Client->Respond(m_Errno, "%s", *str);
|
||||||
}
|
}
|
||||||
|
|
||||||
Last = false;
|
Last = false;
|
||||||
@ -285,7 +285,7 @@ bool cLSTEHandler::Next(bool &Last)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Vps:
|
case Vps:
|
||||||
#if defined(USE_PARENTALRATING) || defined(PARENTALRATINGCONTENTVERSNUM)
|
#if defined(USE_PARENTALRATING) || defined(PARENTALRATINGCONTENTVERSNUM) || APIVERSNUM >= 10711
|
||||||
m_State = Content;
|
m_State = Content;
|
||||||
#else
|
#else
|
||||||
m_State = EndEvent;
|
m_State = EndEvent;
|
||||||
@ -311,6 +311,25 @@ bool cLSTEHandler::Next(bool &Last)
|
|||||||
} else
|
} else
|
||||||
return Next(Last);
|
return Next(Last);
|
||||||
break;
|
break;
|
||||||
|
#elif APIVERSNUM >= 10711
|
||||||
|
case Content:
|
||||||
|
m_State = Rating;
|
||||||
|
if (!isempty(m_Event->ContentToString(m_Event->Contents()))) {
|
||||||
|
char *copy = strdup(m_Event->ContentToString(m_Event->Contents()));
|
||||||
|
cString cpy(copy, true);
|
||||||
|
strreplace(copy, '\n', '|');
|
||||||
|
return m_Client->Respond(-215, "G %i %i %s", m_Event->Contents() & 0xF0, m_Event->Contents() & 0x0F, copy);
|
||||||
|
} else
|
||||||
|
return Next(Last);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Rating:
|
||||||
|
m_State = EndEvent;
|
||||||
|
if (m_Event->ParentalRating())
|
||||||
|
return m_Client->Respond(-215, "R %d", m_Event->ParentalRating());
|
||||||
|
else
|
||||||
|
return Next(Last);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case EndEvent:
|
case EndEvent:
|
||||||
@ -361,7 +380,7 @@ private:
|
|||||||
const cChannel *m_Channel;
|
const cChannel *m_Channel;
|
||||||
char *m_Option;
|
char *m_Option;
|
||||||
int m_Errno;
|
int m_Errno;
|
||||||
char *m_Error;
|
cString m_Error;
|
||||||
bool m_Traverse;
|
bool m_Traverse;
|
||||||
public:
|
public:
|
||||||
cLSTCHandler(cConnectionVTP *Client, const char *Option);
|
cLSTCHandler(cConnectionVTP *Client, const char *Option);
|
||||||
@ -374,18 +393,17 @@ cLSTCHandler::cLSTCHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Channel(NULL),
|
m_Channel(NULL),
|
||||||
m_Option(NULL),
|
m_Option(NULL),
|
||||||
m_Errno(0),
|
m_Errno(0),
|
||||||
m_Error(NULL),
|
|
||||||
m_Traverse(false)
|
m_Traverse(false)
|
||||||
{
|
{
|
||||||
if (!Channels.Lock(false, 500)) {
|
if (!Channels.Lock(false, 500)) {
|
||||||
m_Errno = 451;
|
m_Errno = 451;
|
||||||
m_Error = strdup("Channels are being modified - try again");
|
m_Error = "Channels are being modified - try again";
|
||||||
} else if (*Option) {
|
} else if (*Option) {
|
||||||
if (isnumber(Option)) {
|
if (isnumber(Option)) {
|
||||||
m_Channel = Channels.GetByNumber(strtol(Option, NULL, 10));
|
m_Channel = Channels.GetByNumber(strtol(Option, NULL, 10));
|
||||||
if (m_Channel == NULL) {
|
if (m_Channel == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Channel \"%s\" not defined", Option);
|
m_Error = cString::sprintf("Channel \"%s\" not defined", Option);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -401,7 +419,7 @@ cLSTCHandler::cLSTCHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
|
|
||||||
if (i > Channels.MaxNumber()) {
|
if (i > Channels.MaxNumber()) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Channel \"%s\" not defined", Option);
|
m_Error = cString::sprintf("Channel \"%s\" not defined", Option);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,26 +428,24 @@ cLSTCHandler::cLSTCHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Traverse = true;
|
m_Traverse = true;
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 550;
|
m_Errno = 550;
|
||||||
m_Error = strdup("No channels defined");
|
m_Error = "No channels defined";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cLSTCHandler::~cLSTCHandler()
|
cLSTCHandler::~cLSTCHandler()
|
||||||
{
|
{
|
||||||
Channels.Unlock();
|
Channels.Unlock();
|
||||||
if (m_Error != NULL)
|
|
||||||
free(m_Error);
|
|
||||||
if (m_Option != NULL)
|
if (m_Option != NULL)
|
||||||
free(m_Option);
|
free(m_Option);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cLSTCHandler::Next(bool &Last)
|
bool cLSTCHandler::Next(bool &Last)
|
||||||
{
|
{
|
||||||
if (m_Error != NULL) {
|
if (*m_Error != NULL) {
|
||||||
Last = true;
|
Last = true;
|
||||||
cString str(m_Error, true);
|
cString str(m_Error);
|
||||||
m_Error = NULL;
|
m_Error = NULL;
|
||||||
return m_Client->Respond(m_Errno, *str);
|
return m_Client->Respond(m_Errno, "%s", *str);
|
||||||
}
|
}
|
||||||
|
|
||||||
int number;
|
int number;
|
||||||
@ -452,7 +468,7 @@ bool cLSTCHandler::Next(bool &Last)
|
|||||||
i = m_Channel->Number() + 1;
|
i = m_Channel->Number() + 1;
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Channel \"%d\" not found", i);
|
m_Error = cString::sprintf("Channel \"%d\" not found", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,7 +488,7 @@ private:
|
|||||||
cTimer *m_Timer;
|
cTimer *m_Timer;
|
||||||
int m_Index;
|
int m_Index;
|
||||||
int m_Errno;
|
int m_Errno;
|
||||||
char *m_Error;
|
cString m_Error;
|
||||||
bool m_Traverse;
|
bool m_Traverse;
|
||||||
public:
|
public:
|
||||||
cLSTTHandler(cConnectionVTP *Client, const char *Option);
|
cLSTTHandler(cConnectionVTP *Client, const char *Option);
|
||||||
@ -485,7 +501,6 @@ cLSTTHandler::cLSTTHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Timer(NULL),
|
m_Timer(NULL),
|
||||||
m_Index(0),
|
m_Index(0),
|
||||||
m_Errno(0),
|
m_Errno(0),
|
||||||
m_Error(NULL),
|
|
||||||
m_Traverse(false)
|
m_Traverse(false)
|
||||||
{
|
{
|
||||||
if (*Option) {
|
if (*Option) {
|
||||||
@ -493,11 +508,11 @@ cLSTTHandler::cLSTTHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Timer = Timers.Get(strtol(Option, NULL, 10) - 1);
|
m_Timer = Timers.Get(strtol(Option, NULL, 10) - 1);
|
||||||
if (m_Timer == NULL) {
|
if (m_Timer == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Timer \"%s\" not defined", Option);
|
m_Error = cString::sprintf("Timer \"%s\" not defined", Option);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Error in timer number \"%s\"", Option);
|
m_Error = cString::sprintf("Error in timer number \"%s\"", Option);
|
||||||
}
|
}
|
||||||
} else if (Timers.Count()) {
|
} else if (Timers.Count()) {
|
||||||
m_Traverse = true;
|
m_Traverse = true;
|
||||||
@ -505,27 +520,25 @@ cLSTTHandler::cLSTTHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Timer = Timers.Get(m_Index);
|
m_Timer = Timers.Get(m_Index);
|
||||||
if (m_Timer == NULL) {
|
if (m_Timer == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Timer \"%d\" not found", m_Index + 1);
|
m_Error = cString::sprintf("Timer \"%d\" not found", m_Index + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_Errno = 550;
|
m_Errno = 550;
|
||||||
m_Error = strdup("No timers defined");
|
m_Error = "No timers defined";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cLSTTHandler::~cLSTTHandler()
|
cLSTTHandler::~cLSTTHandler()
|
||||||
{
|
{
|
||||||
if (m_Error != NULL)
|
|
||||||
free(m_Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cLSTTHandler::Next(bool &Last)
|
bool cLSTTHandler::Next(bool &Last)
|
||||||
{
|
{
|
||||||
if (m_Error != NULL) {
|
if (*m_Error != NULL) {
|
||||||
Last = true;
|
Last = true;
|
||||||
cString str(m_Error, true);
|
cString str(m_Error);
|
||||||
m_Error = NULL;
|
m_Error = NULL;
|
||||||
return m_Client->Respond(m_Errno, *str);
|
return m_Client->Respond(m_Errno, "%s", *str);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result;
|
bool result;
|
||||||
@ -541,7 +554,7 @@ bool cLSTTHandler::Next(bool &Last)
|
|||||||
m_Timer = Timers.Get(++m_Index);
|
m_Timer = Timers.Get(++m_Index);
|
||||||
if (m_Timer == NULL) {
|
if (m_Timer == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Timer \"%d\" not found", m_Index + 1);
|
m_Error = cString::sprintf("Timer \"%d\" not found", m_Index + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -559,7 +572,7 @@ private:
|
|||||||
const cEvent *m_Event;
|
const cEvent *m_Event;
|
||||||
int m_Index;
|
int m_Index;
|
||||||
int m_Errno;
|
int m_Errno;
|
||||||
char *m_Error;
|
cString m_Error;
|
||||||
bool m_Traverse;
|
bool m_Traverse;
|
||||||
bool m_Info;
|
bool m_Info;
|
||||||
eStates m_State;
|
eStates m_State;
|
||||||
@ -576,7 +589,6 @@ cLSTRHandler::cLSTRHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Event(NULL),
|
m_Event(NULL),
|
||||||
m_Index(0),
|
m_Index(0),
|
||||||
m_Errno(0),
|
m_Errno(0),
|
||||||
m_Error(NULL),
|
|
||||||
m_Traverse(false),
|
m_Traverse(false),
|
||||||
m_Info(false),
|
m_Info(false),
|
||||||
m_State(Recording),
|
m_State(Recording),
|
||||||
@ -591,12 +603,12 @@ cLSTRHandler::cLSTRHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Info = true;
|
m_Info = true;
|
||||||
if (m_Recording == NULL) {
|
if (m_Recording == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Recording \"%s\" not found", Option);
|
m_Error = cString::sprintf("Recording \"%s\" not found", Option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Error in Recording number \"%s\"", Option);
|
m_Error = cString::sprintf("Error in Recording number \"%s\"", Option);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Recordings.Count()) {
|
else if (Recordings.Count()) {
|
||||||
@ -605,28 +617,26 @@ cLSTRHandler::cLSTRHandler(cConnectionVTP *Client, const char *Option):
|
|||||||
m_Recording = Recordings.Get(m_Index);
|
m_Recording = Recordings.Get(m_Index);
|
||||||
if (m_Recording == NULL) {
|
if (m_Recording == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Recording \"%d\" not found", m_Index + 1);
|
m_Error = cString::sprintf("Recording \"%d\" not found", m_Index + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_Errno = 550;
|
m_Errno = 550;
|
||||||
m_Error = strdup("No recordings available");
|
m_Error = "No recordings available";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cLSTRHandler::~cLSTRHandler()
|
cLSTRHandler::~cLSTRHandler()
|
||||||
{
|
{
|
||||||
if (m_Error != NULL)
|
|
||||||
free(m_Error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cLSTRHandler::Next(bool &Last)
|
bool cLSTRHandler::Next(bool &Last)
|
||||||
{
|
{
|
||||||
if (m_Error != NULL) {
|
if (*m_Error != NULL) {
|
||||||
Last = true;
|
Last = true;
|
||||||
cString str(m_Error, true);
|
cString str(m_Error);
|
||||||
m_Error = NULL;
|
m_Error = NULL;
|
||||||
return m_Client->Respond(m_Errno, *str);
|
return m_Client->Respond(m_Errno, "%s", *str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Info) {
|
if (m_Info) {
|
||||||
@ -714,7 +724,7 @@ bool cLSTRHandler::Next(bool &Last)
|
|||||||
m_Recording = Recordings.Get(++m_Index);
|
m_Recording = Recordings.Get(++m_Index);
|
||||||
if (m_Recording == NULL) {
|
if (m_Recording == NULL) {
|
||||||
m_Errno = 501;
|
m_Errno = 501;
|
||||||
asprintf(&m_Error, "Recording \"%d\" not found", m_Index + 1);
|
m_Error = cString::sprintf("Recording \"%d\" not found", m_Index + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -871,8 +881,8 @@ bool cConnectionVTP::CmdCAPS(char *Opts)
|
|||||||
return Respond(220, "Capability \"%s\" accepted", Opts);
|
return Respond(220, "Capability \"%s\" accepted", Opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcasecmp(Opts, "EXTERN") == 0) {
|
if (strcasecmp(Opts, "EXT") == 0) {
|
||||||
m_StreamType = stExtern;
|
m_StreamType = stEXT;
|
||||||
return Respond(220, "Capability \"%s\" accepted", Opts);
|
return Respond(220, "Capability \"%s\" accepted", Opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1068,7 +1078,7 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
|
|||||||
return Respond(560, "Channel not available");
|
return Respond(560, "Channel not available");
|
||||||
|
|
||||||
delete m_LiveStreamer;
|
delete m_LiveStreamer;
|
||||||
m_LiveStreamer = new cStreamdevLiveStreamer(1);
|
m_LiveStreamer = new cStreamdevLiveStreamer(1, this);
|
||||||
m_LiveStreamer->SetChannel(chan, m_StreamType);
|
m_LiveStreamer->SetChannel(chan, m_StreamType);
|
||||||
m_LiveStreamer->SetDevice(dev);
|
m_LiveStreamer->SetDevice(dev);
|
||||||
if(m_LiveSocket)
|
if(m_LiveSocket)
|
||||||
@ -1086,7 +1096,6 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
|
|||||||
|
|
||||||
bool cConnectionVTP::CmdPLAY(char *Opts)
|
bool cConnectionVTP::CmdPLAY(char *Opts)
|
||||||
{
|
{
|
||||||
Recordings.Update(true);
|
|
||||||
if (*Opts) {
|
if (*Opts) {
|
||||||
if (isnumber(Opts)) {
|
if (isnumber(Opts)) {
|
||||||
cRecording *recording = Recordings.Get(strtol(Opts, NULL, 10) - 1);
|
cRecording *recording = Recordings.Get(strtol(Opts, NULL, 10) - 1);
|
||||||
@ -1397,22 +1406,52 @@ bool cConnectionVTP::CmdDELT(const char *Option)
|
|||||||
{
|
{
|
||||||
INIT_WRAPPER();
|
INIT_WRAPPER();
|
||||||
if (*Option) {
|
if (*Option) {
|
||||||
if (isnumber(Option)) {
|
int number = 0;
|
||||||
cTimer *timer = Timers.Get(strtol(Option, NULL, 10) - 1);
|
bool force = false;
|
||||||
|
char buf[strlen(Option) + 1];
|
||||||
|
strcpy(buf, Option);
|
||||||
|
const char *delim = " \t";
|
||||||
|
char *strtok_next;
|
||||||
|
char *p = strtok_r(buf, delim, &strtok_next);
|
||||||
|
|
||||||
|
if (isnumber(p)) {
|
||||||
|
number = strtol(p, NULL, 10) - 1;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(p, "FORCE") == 0) {
|
||||||
|
force = true;
|
||||||
|
}
|
||||||
|
if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) {
|
||||||
|
if (isnumber(p)) {
|
||||||
|
number = strtol(p, NULL, 10) - 1;
|
||||||
|
}
|
||||||
|
else if (strcasecmp(p, "FORCE") == 0) {
|
||||||
|
force = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Reply(501, "Timer not found or wrong syntax");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cTimer *timer = Timers.Get(number);
|
||||||
if (timer) {
|
if (timer) {
|
||||||
if (!timer->Recording()) {
|
if (timer->Recording()) {
|
||||||
|
if (force) {
|
||||||
|
timer->Skip();
|
||||||
|
cRecordControls::Process(time(NULL));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Reply(550, "Timer \"%i\" is recording", number);
|
||||||
|
EXIT_WRAPPER();
|
||||||
|
}
|
||||||
|
}
|
||||||
isyslog("deleting timer %s", *timer->ToDescr());
|
isyslog("deleting timer %s", *timer->ToDescr());
|
||||||
Timers.Del(timer);
|
Timers.Del(timer);
|
||||||
Timers.SetModified();
|
Timers.SetModified();
|
||||||
Reply(250, "Timer \"%s\" deleted", Option);
|
Reply(250, "Timer \"%i\" deleted", number);
|
||||||
} else
|
} else
|
||||||
Reply(550, "Timer \"%s\" is recording", Option);
|
Reply(501, "Timer \"%i\" not defined", number);
|
||||||
} else
|
} else
|
||||||
Reply(501, "Timer \"%s\" not defined", Option);
|
Reply(501, "Missing timer option");
|
||||||
} else
|
|
||||||
Reply(501, "Error in timer number \"%s\"", Option);
|
|
||||||
} else
|
|
||||||
Reply(501, "Missing timer number");
|
|
||||||
EXIT_WRAPPER();
|
EXIT_WRAPPER();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1706,12 +1745,17 @@ bool cConnectionVTP::CmdRENR(const char *Option)
|
|||||||
|
|
||||||
bool cConnectionVTP::Respond(int Code, const char *Message, ...)
|
bool cConnectionVTP::Respond(int Code, const char *Message, ...)
|
||||||
{
|
{
|
||||||
char *buffer;
|
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, Message);
|
va_start(ap, Message);
|
||||||
vasprintf(&buffer, Message, ap);
|
#if APIVERSNUM < 10515
|
||||||
va_end(ap);
|
char *buffer;
|
||||||
|
if (vasprintf(&buffer, Message, ap) < 0)
|
||||||
|
buffer = strdup("???");
|
||||||
cString str(buffer, true);
|
cString str(buffer, true);
|
||||||
|
#else
|
||||||
|
cString str = cString::sprintf(Message, ap);
|
||||||
|
#endif
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
if (Code >= 0 && m_LastCommand != NULL) {
|
if (Code >= 0 && m_LastCommand != NULL) {
|
||||||
free(m_LastCommand);
|
free(m_LastCommand);
|
||||||
@ -1719,6 +1763,6 @@ bool cConnectionVTP::Respond(int Code, const char *Message, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return cServerConnection::Respond("%03d%c%s", Code >= 0,
|
return cServerConnection::Respond("%03d%c%s", Code >= 0,
|
||||||
Code < 0 ? -Code : Code,
|
Code < 0 ? -Code : Code,
|
||||||
Code < 0 ? '-' : ' ', buffer);
|
Code < 0 ? '-' : ' ', *str);
|
||||||
}
|
}
|
||||||
|
@ -172,16 +172,20 @@ int cStreamdevPatFilter::GetPid(SI::PMT::Stream& stream)
|
|||||||
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
|
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
|
||||||
switch (d->getDescriptorTag()) {
|
switch (d->getDescriptorTag()) {
|
||||||
case SI::AC3DescriptorTag:
|
case SI::AC3DescriptorTag:
|
||||||
|
case SI::EnhancedAC3DescriptorTag:
|
||||||
Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
|
Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
|
||||||
stream.getPid(), psStreamTypes[stream.getStreamType()], "AC3");
|
stream.getPid(), psStreamTypes[stream.getStreamType()], "AC3");
|
||||||
|
delete d;
|
||||||
return stream.getPid();
|
return stream.getPid();
|
||||||
case SI::TeletextDescriptorTag:
|
case SI::TeletextDescriptorTag:
|
||||||
Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
|
Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
|
||||||
stream.getPid(), psStreamTypes[stream.getStreamType()], "Teletext");
|
stream.getPid(), psStreamTypes[stream.getStreamType()], "Teletext");
|
||||||
|
delete d;
|
||||||
return stream.getPid();
|
return stream.getPid();
|
||||||
case SI::SubtitlingDescriptorTag:
|
case SI::SubtitlingDescriptorTag:
|
||||||
Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
|
Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
|
||||||
stream.getPid(), psStreamTypes[stream.getStreamType()], "DVBSUB");
|
stream.getPid(), psStreamTypes[stream.getStreamType()], "DVBSUB");
|
||||||
|
delete d;
|
||||||
return stream.getPid();
|
return stream.getPid();
|
||||||
default:
|
default:
|
||||||
Dprintf("cStreamdevPatFilter PMT scanner: NOT adding PID %d (%s) %s\n",
|
Dprintf("cStreamdevPatFilter PMT scanner: NOT adding PID %d (%s) %s\n",
|
||||||
@ -214,6 +218,7 @@ int cStreamdevPatFilter::GetPid(SI::PMT::Stream& stream)
|
|||||||
stream.getPid(), stream.getStreamType(),
|
stream.getPid(), stream.getStreamType(),
|
||||||
d->getLength(), rawdata[2], rawdata[3],
|
d->getLength(), rawdata[2], rawdata[3],
|
||||||
rawdata[4], rawdata[5]);
|
rawdata[4], rawdata[5]);
|
||||||
|
delete d;
|
||||||
return stream.getPid();
|
return stream.getPid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,10 +335,9 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
|
|||||||
|
|
||||||
// --- cStreamdevLiveStreamer -------------------------------------------------
|
// --- cStreamdevLiveStreamer -------------------------------------------------
|
||||||
|
|
||||||
cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority, std::string Parameter):
|
cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority, const cServerConnection *Connection):
|
||||||
cStreamdevStreamer("streamdev-livestreaming"),
|
cStreamdevStreamer("streamdev-livestreaming", Connection),
|
||||||
m_Priority(Priority),
|
m_Priority(Priority),
|
||||||
m_Parameter(Parameter),
|
|
||||||
m_NumPids(0),
|
m_NumPids(0),
|
||||||
m_StreamType(stTSPIDS),
|
m_StreamType(stTSPIDS),
|
||||||
m_Channel(NULL),
|
m_Channel(NULL),
|
||||||
@ -443,37 +447,39 @@ void cStreamdevLiveStreamer::StartReceiver(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
Dprintf("Initializing Remuxer for full channel transfer\n");
|
||||||
//printf("ca pid: %d\n", Channel->Ca());
|
//printf("ca pid: %d\n", Channel->Ca());
|
||||||
m_Channel = Channel;
|
m_Channel = Channel;
|
||||||
m_StreamType = StreamType;
|
m_StreamType = StreamType;
|
||||||
|
|
||||||
int apid[2] = { Apid, 0 };
|
const int *Apids = Apid ? Apid : m_Channel->Apids();
|
||||||
const int *Apids = Apid ? apid : m_Channel->Apids();
|
const int *Dpids = Dpid ? Dpid : m_Channel->Dpids();
|
||||||
const int *Dpids = Apid ? NULL : m_Channel->Dpids();
|
|
||||||
|
|
||||||
switch (m_StreamType) {
|
switch (m_StreamType) {
|
||||||
case stES:
|
case stES:
|
||||||
{
|
{
|
||||||
int pid = ISRADIO(m_Channel) ? m_Channel->Apid(0) : m_Channel->Vpid();
|
int pid = ISRADIO(m_Channel) ? m_Channel->Apid(0) : m_Channel->Vpid();
|
||||||
if (Apid != 0)
|
if (Apid && Apid[0])
|
||||||
pid = Apid;
|
pid = Apid[0];
|
||||||
|
else if (Dpid && Dpid[0])
|
||||||
|
pid = Dpid[0];
|
||||||
m_Remux = new cTS2ESRemux(pid);
|
m_Remux = new cTS2ESRemux(pid);
|
||||||
return SetPids(pid);
|
return SetPids(pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
case stPES:
|
case stPES:
|
||||||
m_Remux = new cTS2PESRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(),
|
m_Remux = new cTS2PESRemux(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
||||||
m_Channel->Spids());
|
|
||||||
return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
||||||
|
|
||||||
case stPS:
|
case stPS:
|
||||||
m_Remux = new cTS2PSRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(),
|
m_Remux = new cTS2PSRemux(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
||||||
m_Channel->Spids());
|
|
||||||
return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
||||||
|
|
||||||
|
case stEXT:
|
||||||
|
m_Remux = new cExternRemux(Connection(), m_Channel, Apids, Dpids);
|
||||||
|
// fall through
|
||||||
case stTS:
|
case stTS:
|
||||||
// This should never happen, but ...
|
// This should never happen, but ...
|
||||||
if (m_PatFilter) {
|
if (m_PatFilter) {
|
||||||
@ -488,16 +494,12 @@ bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType Str
|
|||||||
m_PatFilter = new cStreamdevPatFilter(this, m_Channel);
|
m_PatFilter = new cStreamdevPatFilter(this, m_Channel);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case stExtern:
|
|
||||||
m_Remux = new cExternRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(),
|
|
||||||
m_Channel->Spids(), m_Parameter);
|
|
||||||
return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
|
|
||||||
|
|
||||||
case stTSPIDS:
|
case stTSPIDS:
|
||||||
Dprintf("pid streaming mode\n");
|
Dprintf("pid streaming mode\n");
|
||||||
return true;
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cStreamdevLiveStreamer::Put(const uchar *Data, int Count)
|
int cStreamdevLiveStreamer::Put(const uchar *Data, int Count)
|
||||||
|
@ -18,7 +18,6 @@ class cStreamdevLiveReceiver;
|
|||||||
class cStreamdevLiveStreamer: public cStreamdevStreamer {
|
class cStreamdevLiveStreamer: public cStreamdevStreamer {
|
||||||
private:
|
private:
|
||||||
int m_Priority;
|
int m_Priority;
|
||||||
std::string m_Parameter;
|
|
||||||
int m_Pids[MAXRECEIVEPIDS + 1];
|
int m_Pids[MAXRECEIVEPIDS + 1];
|
||||||
int m_NumPids;
|
int m_NumPids;
|
||||||
eStreamType m_StreamType;
|
eStreamType m_StreamType;
|
||||||
@ -32,13 +31,13 @@ private:
|
|||||||
bool HasPid(int Pid);
|
bool HasPid(int Pid);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevLiveStreamer(int Priority, std::string Parameter = "");
|
cStreamdevLiveStreamer(int Priority, const cServerConnection *Connection);
|
||||||
virtual ~cStreamdevLiveStreamer();
|
virtual ~cStreamdevLiveStreamer();
|
||||||
|
|
||||||
void SetDevice(cDevice *Device) { m_Device = Device; }
|
void SetDevice(cDevice *Device) { m_Device = Device; }
|
||||||
bool SetPid(int Pid, bool On);
|
bool SetPid(int Pid, bool On);
|
||||||
bool SetPids(int Pid, const int *Pids1 = NULL, const int *Pids2 = NULL, const int *Pids3 = NULL);
|
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);
|
||||||
|
|
||||||
virtual int Put(const uchar *Data, int Count);
|
virtual int Put(const uchar *Data, int Count);
|
||||||
virtual uchar *Get(int &Count);
|
virtual uchar *Get(int &Count);
|
||||||
|
@ -205,8 +205,8 @@ std::string cHtmlChannelList::StreamTypeMenu()
|
|||||||
(std::string) "[<a href=\"/PES/" + self + "\">PES</a>] ");
|
(std::string) "[<a href=\"/PES/" + self + "\">PES</a>] ");
|
||||||
typeMenu += (streamType == stES ? (std::string) "[ES] " :
|
typeMenu += (streamType == stES ? (std::string) "[ES] " :
|
||||||
(std::string) "[<a href=\"/ES/" + self + "\">ES</a>] ");
|
(std::string) "[<a href=\"/ES/" + self + "\">ES</a>] ");
|
||||||
typeMenu += (streamType == stExtern ? (std::string) "[Extern] " :
|
typeMenu += (streamType == stEXT ? (std::string) "[EXT] " :
|
||||||
(std::string) "[<a href=\"/Extern/" + self + "\">Extern</a>] ");
|
(std::string) "[<a href=\"/EXT/" + self + "\">EXT</a>] ");
|
||||||
return typeMenu;
|
return typeMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,13 +415,13 @@ std::string cM3uChannelList::Next()
|
|||||||
|
|
||||||
if (channel->GroupSep())
|
if (channel->GroupSep())
|
||||||
{
|
{
|
||||||
return (std::string) "#EXTINF:0," + name + "\r\n" +
|
return (std::string) "#EXTINF:-1," + name + "\r\n" +
|
||||||
base + "group.m3u?group=" +
|
base + "group.m3u?group=" +
|
||||||
(const char*) itoa(cChannelList::GetGroupIndex(channel));
|
(const char*) itoa(cChannelList::GetGroupIndex(channel));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (std::string) "#EXTINF:0," +
|
return (std::string) "#EXTINF:-1," +
|
||||||
(const char*) itoa(channel->Number()) + " " + name + "\r\n" +
|
(const char*) itoa(channel->Number()) + " " + name + "\r\n" +
|
||||||
base + (std::string) channel->GetChannelID().ToString();
|
base + (std::string) channel->GetChannelID().ToString();
|
||||||
}
|
}
|
||||||
|
@ -113,7 +113,12 @@ class cHtmlChannelList: public cChannelList
|
|||||||
std::string ItemText();
|
std::string ItemText();
|
||||||
std::string PageBottom();
|
std::string PageBottom();
|
||||||
public:
|
public:
|
||||||
virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: text/html\r\n\r\n"; }
|
virtual std::string HttpHeader() {
|
||||||
|
return cChannelList::HttpHeader()
|
||||||
|
+ "Content-type: text/html; charset="
|
||||||
|
+ (cCharSetConv::SystemCharacterTable() ? cCharSetConv::SystemCharacterTable() : "UTF-8")
|
||||||
|
+ "\r\n";
|
||||||
|
}
|
||||||
virtual bool HasNext();
|
virtual bool HasNext();
|
||||||
virtual std::string Next();
|
virtual std::string Next();
|
||||||
cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *GroupTarget);
|
cHtmlChannelList(cChannelIterator *Iterator, eStreamType StreamType, const char *Self, const char *GroupTarget);
|
||||||
@ -128,7 +133,7 @@ class cM3uChannelList: public cChannelList
|
|||||||
eM3uState m3uState;
|
eM3uState m3uState;
|
||||||
cCharSetConv m_IConv;
|
cCharSetConv m_IConv;
|
||||||
public:
|
public:
|
||||||
virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: audio/x-mpegurl\r\n"; };
|
virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: audio/x-mpegurl; charset=UTF-8\r\n"; };
|
||||||
virtual bool HasNext();
|
virtual bool HasNext();
|
||||||
virtual std::string Next();
|
virtual std::string Next();
|
||||||
cM3uChannelList(cChannelIterator *Iterator, const char* Base);
|
cM3uChannelList(cChannelIterator *Iterator, const char* Base);
|
||||||
|
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: streamdev 0.5.0\n"
|
"Project-Id-Version: streamdev 0.5.0\n"
|
||||||
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
||||||
"POT-Creation-Date: 2009-02-13 11:53+0100\n"
|
"POT-Creation-Date: 2010-06-14 13:06+0200\n"
|
||||||
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
|
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
|
||||||
"Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n"
|
"Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n"
|
||||||
"Language-Team: <vdr@linuxtv.org>\n"
|
"Language-Team: <vdr@linuxtv.org>\n"
|
||||||
@ -15,42 +15,6 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "VTP Streaming Client"
|
|
||||||
msgstr "VTP Streaming Client"
|
|
||||||
|
|
||||||
msgid "Suspend Server"
|
|
||||||
msgstr "Server pausieren"
|
|
||||||
|
|
||||||
msgid "Server is suspended"
|
|
||||||
msgstr "Server ist pausiert"
|
|
||||||
|
|
||||||
msgid "Couldn't suspend Server!"
|
|
||||||
msgstr "Konnte Server nicht pausieren!"
|
|
||||||
|
|
||||||
msgid "Hide Mainmenu Entry"
|
|
||||||
msgstr "Hauptmenüeintrag verstecken"
|
|
||||||
|
|
||||||
msgid "Start Client"
|
|
||||||
msgstr "Client starten"
|
|
||||||
|
|
||||||
msgid "Remote IP"
|
|
||||||
msgstr "IP der Gegenseite"
|
|
||||||
|
|
||||||
msgid "Remote Port"
|
|
||||||
msgstr "Port der Gegenseite"
|
|
||||||
|
|
||||||
msgid "Filter Streaming"
|
|
||||||
msgstr "Filter-Daten streamen"
|
|
||||||
|
|
||||||
msgid "Synchronize EPG"
|
|
||||||
msgstr "EPG synchronisieren"
|
|
||||||
|
|
||||||
msgid "Minimum Priority"
|
|
||||||
msgstr "Minimale Priorität"
|
|
||||||
|
|
||||||
msgid "Maximum Priority"
|
|
||||||
msgstr "Maximale Priorität"
|
|
||||||
|
|
||||||
msgid "VDR Streaming Server"
|
msgid "VDR Streaming Server"
|
||||||
msgstr "VDR Streaming Server"
|
msgstr "VDR Streaming Server"
|
||||||
|
|
||||||
@ -60,6 +24,15 @@ msgstr "Streamen im Gange"
|
|||||||
msgid "Suspend Live TV"
|
msgid "Suspend Live TV"
|
||||||
msgstr "Live-TV pausieren"
|
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"
|
msgid "Common Settings"
|
||||||
msgstr "Allgemeines"
|
msgstr "Allgemeines"
|
||||||
|
|
||||||
@ -108,11 +81,3 @@ msgstr "Port des Multicast Clients"
|
|||||||
msgid "Multicast Streamtype"
|
msgid "Multicast Streamtype"
|
||||||
msgstr "Multicast Streamtyp"
|
msgstr "Multicast Streamtyp"
|
||||||
|
|
||||||
msgid "Offer suspend mode"
|
|
||||||
msgstr "Pausieren anbieten"
|
|
||||||
|
|
||||||
msgid "Always suspended"
|
|
||||||
msgstr "Immer pausiert"
|
|
||||||
|
|
||||||
msgid "Never suspended"
|
|
||||||
msgstr "Nie pausiert"
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: streamdev 0.5.0\n"
|
"Project-Id-Version: streamdev 0.5.0\n"
|
||||||
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
||||||
"POT-Creation-Date: 2009-02-13 11:53+0100\n"
|
"POT-Creation-Date: 2010-06-14 13:06+0200\n"
|
||||||
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
|
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
|
||||||
"Last-Translator: Rolf Ahrenberg <rahrenbe@cc.hut.fi>\n"
|
"Last-Translator: Rolf Ahrenberg <rahrenbe@cc.hut.fi>\n"
|
||||||
"Language-Team: <vdr@linuxtv.org>\n"
|
"Language-Team: <vdr@linuxtv.org>\n"
|
||||||
@ -15,42 +15,6 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "VTP Streaming Client"
|
|
||||||
msgstr "VTP-suoratoistoasiakas"
|
|
||||||
|
|
||||||
msgid "Suspend Server"
|
|
||||||
msgstr "Pysäytä palvelin"
|
|
||||||
|
|
||||||
msgid "Server is suspended"
|
|
||||||
msgstr "Palvelin on pysäytetty"
|
|
||||||
|
|
||||||
msgid "Couldn't suspend Server!"
|
|
||||||
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 "Remote IP"
|
|
||||||
msgstr "Etäkoneen IP-osoite"
|
|
||||||
|
|
||||||
msgid "Remote Port"
|
|
||||||
msgstr "Etäkoneen portti"
|
|
||||||
|
|
||||||
msgid "Filter Streaming"
|
|
||||||
msgstr "Suodatetun tiedon suoratoisto"
|
|
||||||
|
|
||||||
msgid "Synchronize EPG"
|
|
||||||
msgstr "Päivitä ohjelmaopas"
|
|
||||||
|
|
||||||
msgid "Minimum Priority"
|
|
||||||
msgstr "Pienin prioriteetti"
|
|
||||||
|
|
||||||
msgid "Maximum Priority"
|
|
||||||
msgstr "Suurin prioriteetti"
|
|
||||||
|
|
||||||
msgid "VDR Streaming Server"
|
msgid "VDR Streaming Server"
|
||||||
msgstr "VDR-suoratoistopalvelin"
|
msgstr "VDR-suoratoistopalvelin"
|
||||||
|
|
||||||
@ -60,6 +24,15 @@ msgstr "Suoratoistopalvelin aktiivinen"
|
|||||||
msgid "Suspend Live TV"
|
msgid "Suspend Live TV"
|
||||||
msgstr "Pysäytä suora TV-lähetys"
|
msgstr "Pysäytä suora TV-lähetys"
|
||||||
|
|
||||||
|
msgid "Offer suspend mode"
|
||||||
|
msgstr "tyrkytä"
|
||||||
|
|
||||||
|
msgid "Always suspended"
|
||||||
|
msgstr "aina"
|
||||||
|
|
||||||
|
msgid "Never suspended"
|
||||||
|
msgstr "ei koskaan"
|
||||||
|
|
||||||
msgid "Common Settings"
|
msgid "Common Settings"
|
||||||
msgstr "Yleiset asetukset"
|
msgstr "Yleiset asetukset"
|
||||||
|
|
||||||
@ -97,22 +70,14 @@ msgid "HTTP Streamtype"
|
|||||||
msgstr "HTTP-lähetysmuoto"
|
msgstr "HTTP-lähetysmuoto"
|
||||||
|
|
||||||
msgid "Multicast Streaming Server"
|
msgid "Multicast Streaming Server"
|
||||||
msgstr ""
|
msgstr "Multicast-suoratoistopalvelin"
|
||||||
|
|
||||||
msgid "Start IGMP Server"
|
msgid "Start IGMP Server"
|
||||||
msgstr ""
|
msgstr "Käynnistä IGMP-palvelin"
|
||||||
|
|
||||||
msgid "Multicast Client Port"
|
msgid "Multicast Client Port"
|
||||||
msgstr ""
|
msgstr "Multicast-portti"
|
||||||
|
|
||||||
msgid "Multicast Streamtype"
|
msgid "Multicast Streamtype"
|
||||||
msgstr ""
|
msgstr "Multicast-lähetysmuoto"
|
||||||
|
|
||||||
msgid "Offer suspend mode"
|
|
||||||
msgstr "tyrkytä"
|
|
||||||
|
|
||||||
msgid "Always suspended"
|
|
||||||
msgstr "aina"
|
|
||||||
|
|
||||||
msgid "Never suspended"
|
|
||||||
msgstr "ei koskaan"
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: streamdev 0.5.0\n"
|
"Project-Id-Version: streamdev 0.5.0\n"
|
||||||
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
||||||
"POT-Creation-Date: 2009-02-13 11:53+0100\n"
|
"POT-Creation-Date: 2010-06-14 13:06+0200\n"
|
||||||
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
|
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
|
||||||
"Last-Translator: micky979 <micky979@free.fr>\n"
|
"Last-Translator: micky979 <micky979@free.fr>\n"
|
||||||
"Language-Team: <vdr@linuxtv.org>\n"
|
"Language-Team: <vdr@linuxtv.org>\n"
|
||||||
@ -15,42 +15,6 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "VTP Streaming Client"
|
|
||||||
msgstr "Client de streaming VTP"
|
|
||||||
|
|
||||||
msgid "Suspend Server"
|
|
||||||
msgstr "Suspendre le serveur"
|
|
||||||
|
|
||||||
msgid "Server is suspended"
|
|
||||||
msgstr "Le serveur est suspendu"
|
|
||||||
|
|
||||||
msgid "Couldn't suspend Server!"
|
|
||||||
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 "Remote IP"
|
|
||||||
msgstr "Adresse IP du serveur"
|
|
||||||
|
|
||||||
msgid "Remote Port"
|
|
||||||
msgstr "Port du serveur"
|
|
||||||
|
|
||||||
msgid "Filter Streaming"
|
|
||||||
msgstr "Filtre streaming"
|
|
||||||
|
|
||||||
msgid "Synchronize EPG"
|
|
||||||
msgstr "Synchroniser l'EPG"
|
|
||||||
|
|
||||||
msgid "Minimum Priority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Maximum Priority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "VDR Streaming Server"
|
msgid "VDR Streaming Server"
|
||||||
msgstr "Serveur de streaming VDR"
|
msgstr "Serveur de streaming VDR"
|
||||||
|
|
||||||
@ -60,6 +24,15 @@ msgstr "Streaming actif"
|
|||||||
msgid "Suspend Live TV"
|
msgid "Suspend Live TV"
|
||||||
msgstr "Suspendre 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"
|
msgid "Common Settings"
|
||||||
msgstr "Paramètres communs"
|
msgstr "Paramètres communs"
|
||||||
|
|
||||||
@ -108,11 +81,3 @@ msgstr ""
|
|||||||
msgid "Multicast Streamtype"
|
msgid "Multicast Streamtype"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Offer suspend mode"
|
|
||||||
msgstr "Offrir le mode suspendre"
|
|
||||||
|
|
||||||
msgid "Always suspended"
|
|
||||||
msgstr "Toujours suspendre"
|
|
||||||
|
|
||||||
msgid "Never suspended"
|
|
||||||
msgstr "Jamais suspendre"
|
|
55
po/it_IT.po → server/po/it_IT.po
Executable file → Normal file
55
po/it_IT.po → server/po/it_IT.po
Executable file → Normal file
@ -9,7 +9,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: streamdev 0.5.0\n"
|
"Project-Id-Version: streamdev 0.5.0\n"
|
||||||
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
||||||
"POT-Creation-Date: 2009-02-13 11:53+0100\n"
|
"POT-Creation-Date: 2010-06-14 13:06+0200\n"
|
||||||
"PO-Revision-Date: 2008-04-13 23:42+0100\n"
|
"PO-Revision-Date: 2008-04-13 23:42+0100\n"
|
||||||
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
|
"Last-Translator: Diego Pierotto <vdr-italian@tiscali.it>\n"
|
||||||
"Language-Team: <vdr@linuxtv.org>\n"
|
"Language-Team: <vdr@linuxtv.org>\n"
|
||||||
@ -17,42 +17,6 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
"Content-Type: text/plain; charset=ISO-8859-15\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "VTP Streaming Client"
|
|
||||||
msgstr "Client trasmissione VTP"
|
|
||||||
|
|
||||||
msgid "Suspend Server"
|
|
||||||
msgstr "Sospendi Server"
|
|
||||||
|
|
||||||
msgid "Server is suspended"
|
|
||||||
msgstr "Server sospeso"
|
|
||||||
|
|
||||||
msgid "Couldn't suspend Server!"
|
|
||||||
msgstr "Impossibile sospendere il server!"
|
|
||||||
|
|
||||||
msgid "Hide Mainmenu Entry"
|
|
||||||
msgstr "Nascondi voce menu principale"
|
|
||||||
|
|
||||||
msgid "Start Client"
|
|
||||||
msgstr "Avvia Client"
|
|
||||||
|
|
||||||
msgid "Remote IP"
|
|
||||||
msgstr "Indirizzo IP del Server"
|
|
||||||
|
|
||||||
msgid "Remote Port"
|
|
||||||
msgstr "Porta Server Remoto"
|
|
||||||
|
|
||||||
msgid "Filter Streaming"
|
|
||||||
msgstr "Filtra trasmissione"
|
|
||||||
|
|
||||||
msgid "Synchronize EPG"
|
|
||||||
msgstr "Sincronizza EPG"
|
|
||||||
|
|
||||||
msgid "Minimum Priority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Maximum Priority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "VDR Streaming Server"
|
msgid "VDR Streaming Server"
|
||||||
msgstr "Server trasmissione VDR"
|
msgstr "Server trasmissione VDR"
|
||||||
|
|
||||||
@ -62,6 +26,15 @@ msgstr "Trasmissione attiva"
|
|||||||
msgid "Suspend Live TV"
|
msgid "Suspend Live TV"
|
||||||
msgstr "Sospendi TV dal vivo"
|
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"
|
msgid "Common Settings"
|
||||||
msgstr "Impostazioni comuni"
|
msgstr "Impostazioni comuni"
|
||||||
|
|
||||||
@ -110,11 +83,3 @@ msgstr ""
|
|||||||
msgid "Multicast Streamtype"
|
msgid "Multicast Streamtype"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Offer suspend mode"
|
|
||||||
msgstr "Offri mod. sospensione"
|
|
||||||
|
|
||||||
msgid "Always suspended"
|
|
||||||
msgstr "Sempre sospeso"
|
|
||||||
|
|
||||||
msgid "Never suspended"
|
|
||||||
msgstr "Mai sospeso"
|
|
83
server/po/lt_LT.po
Normal file
83
server/po/lt_LT.po
Normal file
@ -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"
|
||||||
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: streamdev 0.5.0\n"
|
"Project-Id-Version: streamdev 0.5.0\n"
|
||||||
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
"Report-Msgid-Bugs-To: <http://www.vdr-developer.org/mantisbt/>\n"
|
||||||
"POT-Creation-Date: 2009-02-13 11:53+0100\n"
|
"POT-Creation-Date: 2010-06-14 13:06+0200\n"
|
||||||
"PO-Revision-Date: 2008-06-26 15:36+0100\n"
|
"PO-Revision-Date: 2008-06-26 15:36+0100\n"
|
||||||
"Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"
|
"Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"
|
||||||
"Language-Team: <vdr@linuxtv.org>\n"
|
"Language-Team: <vdr@linuxtv.org>\n"
|
||||||
@ -15,42 +15,6 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=ISO-8859-5\n"
|
"Content-Type: text/plain; charset=ISO-8859-5\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
msgid "VTP Streaming Client"
|
|
||||||
msgstr "VTP Streaming ÚÛØÕÝâ"
|
|
||||||
|
|
||||||
msgid "Suspend Server"
|
|
||||||
msgstr "¾áâÐÝÞÒØâì áÕàÒÕà"
|
|
||||||
|
|
||||||
msgid "Server is suspended"
|
|
||||||
msgstr "ÁÕàÒÕà ÞáâÐÝÞÒÛÕÝ"
|
|
||||||
|
|
||||||
msgid "Couldn't suspend Server!"
|
|
||||||
msgstr "ÝÕ ÜÞÓã ÞáâÐÝÞÒØâì áÕàÒÕà"
|
|
||||||
|
|
||||||
msgid "Hide Mainmenu Entry"
|
|
||||||
msgstr "ÁßàïâÐâì Ò ÓÛÐÒÝÞÜ ÜÕÝî"
|
|
||||||
|
|
||||||
msgid "Start Client"
|
|
||||||
msgstr "ÁâÐàâ ÚÛØÕÝâÐ"
|
|
||||||
|
|
||||||
msgid "Remote IP"
|
|
||||||
msgstr "ÃÔÐÛÕÝÝëÙ IP"
|
|
||||||
|
|
||||||
msgid "Remote Port"
|
|
||||||
msgstr "ÃÔÐÛÕÝÝëÙ ßÞàâ"
|
|
||||||
|
|
||||||
msgid "Filter Streaming"
|
|
||||||
msgstr "ÄØÛìâà ßÞâÞÚÐ"
|
|
||||||
|
|
||||||
msgid "Synchronize EPG"
|
|
||||||
msgstr "ÁØÝåàÞÝØ×ÐæØï EPG"
|
|
||||||
|
|
||||||
msgid "Minimum Priority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Maximum Priority"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "VDR Streaming Server"
|
msgid "VDR Streaming Server"
|
||||||
msgstr "VDR Streaming áÕàÒÕà"
|
msgstr "VDR Streaming áÕàÒÕà"
|
||||||
|
|
||||||
@ -60,6 +24,15 @@ msgstr "
|
|||||||
msgid "Suspend Live TV"
|
msgid "Suspend Live TV"
|
||||||
msgstr "¾áâÐÝÞÒÚÐ Live TV"
|
msgstr "¾áâÐÝÞÒÚÐ Live TV"
|
||||||
|
|
||||||
|
msgid "Offer suspend mode"
|
||||||
|
msgstr "Предлагать остановку"
|
||||||
|
|
||||||
|
msgid "Always suspended"
|
||||||
|
msgstr "Всегда остановлен"
|
||||||
|
|
||||||
|
msgid "Never suspended"
|
||||||
|
msgstr "Никогда не остановлен"
|
||||||
|
|
||||||
msgid "Common Settings"
|
msgid "Common Settings"
|
||||||
msgstr "½ÐáâàÞÙÚØ"
|
msgstr "½ÐáâàÞÙÚØ"
|
||||||
|
|
||||||
@ -108,11 +81,3 @@ msgstr ""
|
|||||||
msgid "Multicast Streamtype"
|
msgid "Multicast Streamtype"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Offer suspend mode"
|
|
||||||
msgstr "¿àÕÔÛÐÓÐâì ÞáâÐÝÞÒÚã"
|
|
||||||
|
|
||||||
msgid "Always suspended"
|
|
||||||
msgstr "²áÕÓÔÐ ÞáâÐÝÞÒÛÕÝ"
|
|
||||||
|
|
||||||
msgid "Never suspended"
|
|
||||||
msgstr "½ØÚÞÓÔÐ ÝÕ ÞáâÐÝÞÒÛÕÝ"
|
|
85
server/po/sk_SK.po
Normal file
85
server/po/sk_SK.po
Normal file
@ -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 prúdový server"
|
||||||
|
|
||||||
|
msgid "Streaming active"
|
||||||
|
msgstr "streamovanie aktivne"
|
||||||
|
|
||||||
|
msgid "Suspend Live TV"
|
||||||
|
msgstr "Pozastavenie ¾ivého vysielania"
|
||||||
|
|
||||||
|
msgid "Offer suspend mode"
|
||||||
|
msgstr "Výber re¾ímu pozastavenia"
|
||||||
|
|
||||||
|
msgid "Always suspended"
|
||||||
|
msgstr "V¾dy pozastavi»"
|
||||||
|
|
||||||
|
msgid "Never suspended"
|
||||||
|
msgstr "Nikdy nepozastavi»"
|
||||||
|
|
||||||
|
msgid "Common Settings"
|
||||||
|
msgstr "V¹eobecné nastavenia"
|
||||||
|
|
||||||
|
msgid "Maximum Number of Clients"
|
||||||
|
msgstr "Maximály poèet klientov"
|
||||||
|
|
||||||
|
msgid "Suspend behaviour"
|
||||||
|
msgstr "Správanie preru¹enia"
|
||||||
|
|
||||||
|
msgid "Client may suspend"
|
||||||
|
msgstr "Klient mô¾e 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 prúdu HTTP"
|
||||||
|
|
||||||
|
msgid "Multicast Streaming Server"
|
||||||
|
msgstr "Multicast prúdový server"
|
||||||
|
|
||||||
|
msgid "Start IGMP Server"
|
||||||
|
msgstr "Spusti» IGMP Server"
|
||||||
|
|
||||||
|
msgid "Multicast Client Port"
|
||||||
|
msgstr "Port klienta Multicast"
|
||||||
|
|
||||||
|
msgid "Multicast Streamtype"
|
||||||
|
msgstr "Multicast typ streamu"
|
||||||
|
|
@ -21,6 +21,9 @@
|
|||||||
|
|
||||||
#include "recplayer.h"
|
#include "recplayer.h"
|
||||||
|
|
||||||
|
// for TSPLAY patch detection
|
||||||
|
#include "vdr/device.h"
|
||||||
|
|
||||||
#define _XOPEN_SOURCE 600
|
#define _XOPEN_SOURCE 600
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
@ -34,7 +37,7 @@ RecPlayer::RecPlayer(cRecording* rec)
|
|||||||
|
|
||||||
// FIXME find out max file path / name lengths
|
// FIXME find out max file path / name lengths
|
||||||
|
|
||||||
#if VDRVERSNUM >= 10703
|
#if VDRVERSNUM >= 10703 || defined(TSPLAY_PATCH_VERSION)
|
||||||
indexFile = new cIndexFile(recording->FileName(), false, rec->IsPesRecording());
|
indexFile = new cIndexFile(recording->FileName(), false, rec->IsPesRecording());
|
||||||
#else
|
#else
|
||||||
indexFile = new cIndexFile(recording->FileName(), false);
|
indexFile = new cIndexFile(recording->FileName(), false);
|
||||||
@ -58,7 +61,7 @@ void RecPlayer::scan()
|
|||||||
for(i = 1; i < 1000; i++)
|
for(i = 1; i < 1000; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if APIVERSNUM < 10703
|
#if APIVERSNUM < 10703 || !defined(TSPLAY_PATCH_VERSION)
|
||||||
snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
|
snprintf(fileName, 2047, "%s/%03i.vdr", recording->FileName(), i);
|
||||||
//log->log("RecPlayer", Log::DEBUG, "FILENAME: %s", fileName);
|
//log->log("RecPlayer", Log::DEBUG, "FILENAME: %s", fileName);
|
||||||
file = fopen(fileName, "r");
|
file = fopen(fileName, "r");
|
||||||
@ -99,7 +102,7 @@ int RecPlayer::openFile(int index)
|
|||||||
|
|
||||||
char fileName[2048];
|
char fileName[2048];
|
||||||
|
|
||||||
#if APIVERSNUM >= 10703
|
#if APIVERSNUM >= 10703 || defined(TSPLAY_PATCH_VERSION)
|
||||||
snprintf(fileName, 2047, "%s/%05i.ts", recording->FileName(), index);
|
snprintf(fileName, 2047, "%s/%05i.ts", recording->FileName(), index);
|
||||||
isyslog("openFile called for index %i string:%s", index, fileName);
|
isyslog("openFile called for index %i string:%s", index, fileName);
|
||||||
|
|
||||||
@ -222,7 +225,7 @@ uint64_t RecPlayer::positionFromFrameNumber(uint32_t frameNumber)
|
|||||||
{
|
{
|
||||||
if (!indexFile) return 0;
|
if (!indexFile) return 0;
|
||||||
|
|
||||||
#if VDRVERSNUM >= 10703
|
#if VDRVERSNUM >= 10703 || defined(TSPLAY_PATCH_VERSION)
|
||||||
uint16_t retFileNumber;
|
uint16_t retFileNumber;
|
||||||
off_t retFileOffset;
|
off_t retFileOffset;
|
||||||
#else
|
#else
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: setup.c,v 1.6 2009/02/13 10:39:22 schmirl Exp $
|
* $Id: setup.c,v 1.9.2.2 2010/06/18 19:07:32 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/menuitems.h>
|
#include <vdr/menuitems.h>
|
||||||
@ -45,35 +45,72 @@ bool cStreamdevServerSetup::SetupParse(const char *Name, const char *Value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* cStreamdevServerMenuSetupPage::StreamTypes[st_Count - 1] = {
|
||||||
|
"TS",
|
||||||
|
"PES",
|
||||||
|
"PS",
|
||||||
|
"ES",
|
||||||
|
"EXT"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* cStreamdevServerMenuSetupPage::SuspendModes[sm_Count] = {
|
||||||
|
trNOOP("Offer suspend mode"),
|
||||||
|
trNOOP("Always suspended"),
|
||||||
|
trNOOP("Never suspended")
|
||||||
|
};
|
||||||
|
|
||||||
cStreamdevServerMenuSetupPage::cStreamdevServerMenuSetupPage(void) {
|
cStreamdevServerMenuSetupPage::cStreamdevServerMenuSetupPage(void) {
|
||||||
m_NewSetup = StreamdevServerSetup;
|
m_NewSetup = StreamdevServerSetup;
|
||||||
|
|
||||||
AddCategory (tr("Common Settings"));
|
Set();
|
||||||
AddRangeEdit(tr("Maximum Number of Clients"), m_NewSetup.MaxClients, 0, 100);
|
|
||||||
AddSuspEdit (tr("Suspend behaviour"), m_NewSetup.SuspendMode);
|
|
||||||
AddBoolEdit (tr("Client may suspend"), m_NewSetup.AllowSuspend);
|
|
||||||
|
|
||||||
AddCategory (tr("VDR-to-VDR Server"));
|
|
||||||
AddBoolEdit (tr("Start VDR-to-VDR Server"), m_NewSetup.StartVTPServer);
|
|
||||||
AddShortEdit(tr("VDR-to-VDR Server Port"), m_NewSetup.VTPServerPort);
|
|
||||||
AddIpEdit (tr("Bind to IP"), m_NewSetup.VTPBindIP);
|
|
||||||
|
|
||||||
AddCategory (tr("HTTP Server"));
|
|
||||||
AddBoolEdit (tr("Start HTTP Server"), m_NewSetup.StartHTTPServer);
|
|
||||||
AddShortEdit(tr("HTTP Server Port"), m_NewSetup.HTTPServerPort);
|
|
||||||
AddTypeEdit (tr("HTTP Streamtype"), m_NewSetup.HTTPStreamType);
|
|
||||||
AddIpEdit (tr("Bind to IP"), m_NewSetup.HTTPBindIP);
|
|
||||||
AddCategory (tr("Multicast Streaming Server"));
|
|
||||||
AddBoolEdit (tr("Start IGMP Server"), m_NewSetup.StartIGMPServer);
|
|
||||||
AddShortEdit(tr("Multicast Client Port"), m_NewSetup.IGMPClientPort);
|
|
||||||
AddTypeEdit (tr("Multicast Streamtype"), m_NewSetup.IGMPStreamType);
|
|
||||||
AddIpEdit (tr("Bind to IP"), m_NewSetup.IGMPBindIP);
|
|
||||||
SetCurrent(Get(1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cStreamdevServerMenuSetupPage::~cStreamdevServerMenuSetupPage() {
|
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));
|
||||||
|
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));
|
||||||
|
Add(new cMenuEditIntItem (tr("VDR-to-VDR Server Port"), &m_NewSetup.VTPServerPort, 0, 65535));
|
||||||
|
Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.VTPBindIP));
|
||||||
|
|
||||||
|
AddCategory (tr("HTTP Server"));
|
||||||
|
Add(new cMenuEditBoolItem(tr("Start HTTP Server"), &m_NewSetup.StartHTTPServer));
|
||||||
|
Add(new cMenuEditIntItem (tr("HTTP Server Port"), &m_NewSetup.HTTPServerPort, 0, 65535));
|
||||||
|
Add(new cMenuEditStraItem(tr("HTTP Streamtype"), &m_NewSetup.HTTPStreamType, st_Count - 1, StreamTypes));
|
||||||
|
Add(new cMenuEditIpItem (tr("Bind to IP"), m_NewSetup.HTTPBindIP));
|
||||||
|
AddCategory (tr("Multicast Streaming Server"));
|
||||||
|
Add(new cMenuEditBoolItem(tr("Start IGMP Server"), &m_NewSetup.StartIGMPServer));
|
||||||
|
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(current));
|
||||||
|
Display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void cStreamdevServerMenuSetupPage::AddCategory(const char *Title) {
|
||||||
|
|
||||||
|
cString str = cString::sprintf("--- %s -------------------------------------------------"
|
||||||
|
"---------------", Title );
|
||||||
|
|
||||||
|
cOsdItem *item = new cOsdItem(*str);
|
||||||
|
item->SetSelectable(false);
|
||||||
|
Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
void cStreamdevServerMenuSetupPage::Store(void) {
|
void cStreamdevServerMenuSetupPage::Store(void) {
|
||||||
bool restart = false;
|
bool restart = false;
|
||||||
if (m_NewSetup.StartVTPServer != StreamdevServerSetup.StartVTPServer
|
if (m_NewSetup.StartVTPServer != StreamdevServerSetup.StartVTPServer
|
||||||
@ -110,3 +147,10 @@ void cStreamdevServerMenuSetupPage::Store(void) {
|
|||||||
cStreamdevServer::Initialize();
|
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;
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: setup.h,v 1.2 2009/02/13 10:39:22 schmirl Exp $
|
* $Id: setup.h,v 1.3.2.1 2010/06/18 19:07:32 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_SETUPSERVER_H
|
#ifndef VDR_STREAMDEV_SETUPSERVER_H
|
||||||
@ -30,12 +30,17 @@ struct cStreamdevServerSetup {
|
|||||||
|
|
||||||
extern cStreamdevServerSetup StreamdevServerSetup;
|
extern cStreamdevServerSetup StreamdevServerSetup;
|
||||||
|
|
||||||
class cStreamdevServerMenuSetupPage: public cStreamdevMenuSetupPage {
|
class cStreamdevServerMenuSetupPage: public cMenuSetupPage {
|
||||||
private:
|
private:
|
||||||
|
static const char* StreamTypes[];
|
||||||
|
static const char* SuspendModes[];
|
||||||
cStreamdevServerSetup m_NewSetup;
|
cStreamdevServerSetup m_NewSetup;
|
||||||
|
|
||||||
|
void AddCategory(const char *Title);
|
||||||
|
void Set();
|
||||||
protected:
|
protected:
|
||||||
virtual void Store(void);
|
virtual void Store(void);
|
||||||
|
virtual eOSState ProcessKey(eKeys Key);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevServerMenuSetupPage(void);
|
cStreamdevServerMenuSetupPage(void);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* See the README file for copyright information and how to reach the author.
|
* See the README file for copyright information and how to reach the author.
|
||||||
*
|
*
|
||||||
* $Id: streamdev-server.c,v 1.12 2009/06/19 06:32:38 schmirl Exp $
|
* $Id: streamdev-server.c,v 1.1.2.1 2010/06/14 10:40:20 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamdev-server.h,v 1.4 2007/02/19 12:08:16 schmirl Exp $
|
* $Id: streamdev-server.h,v 1.1.2.1 2010/06/14 10:40:20 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEVSERVER_H
|
#ifndef VDR_STREAMDEVSERVER_H
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamer.c,v 1.19 2009/06/19 06:32:45 schmirl Exp $
|
* $Id: streamer.c,v 1.19.2.1 2010/06/11 06:06:03 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vdr/ringbuffer.h>
|
#include <vdr/ringbuffer.h>
|
||||||
@ -100,8 +100,9 @@ void cStreamdevWriter::Action(void)
|
|||||||
|
|
||||||
// --- cStreamdevStreamer -----------------------------------------------------
|
// --- cStreamdevStreamer -----------------------------------------------------
|
||||||
|
|
||||||
cStreamdevStreamer::cStreamdevStreamer(const char *Name):
|
cStreamdevStreamer::cStreamdevStreamer(const char *Name, const cServerConnection *Connection):
|
||||||
cThread(Name),
|
cThread(Name),
|
||||||
|
m_Connection(Connection),
|
||||||
m_Writer(NULL),
|
m_Writer(NULL),
|
||||||
m_RingBuffer(new cStreamdevBuffer(STREAMERBUFSIZE, TS_SIZE * 2,
|
m_RingBuffer(new cStreamdevBuffer(STREAMERBUFSIZE, TS_SIZE * 2,
|
||||||
true, "streamdev-streamer")),
|
true, "streamdev-streamer")),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* $Id: streamer.h,v 1.11 2009/06/19 06:32:45 schmirl Exp $
|
* $Id: streamer.h,v 1.11.2.1 2010/06/11 06:06:03 schmirl Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VDR_STREAMDEV_STREAMER_H
|
#ifndef VDR_STREAMDEV_STREAMER_H
|
||||||
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
class cTBSocket;
|
class cTBSocket;
|
||||||
class cStreamdevStreamer;
|
class cStreamdevStreamer;
|
||||||
|
class cServerConnection;
|
||||||
|
|
||||||
#ifndef TS_SIZE
|
#ifndef TS_SIZE
|
||||||
#define TS_SIZE 188
|
#define TS_SIZE 188
|
||||||
@ -64,6 +65,7 @@ public:
|
|||||||
|
|
||||||
class cStreamdevStreamer: public cThread {
|
class cStreamdevStreamer: public cThread {
|
||||||
private:
|
private:
|
||||||
|
const cServerConnection *m_Connection;
|
||||||
cStreamdevWriter *m_Writer;
|
cStreamdevWriter *m_Writer;
|
||||||
cStreamdevBuffer *m_RingBuffer;
|
cStreamdevBuffer *m_RingBuffer;
|
||||||
cStreamdevBuffer *m_SendBuffer;
|
cStreamdevBuffer *m_SendBuffer;
|
||||||
@ -74,9 +76,11 @@ protected:
|
|||||||
bool IsRunning(void) const { return m_Writer; }
|
bool IsRunning(void) const { return m_Writer; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cStreamdevStreamer(const char *Name);
|
cStreamdevStreamer(const char *Name, const cServerConnection *Connection = NULL);
|
||||||
virtual ~cStreamdevStreamer();
|
virtual ~cStreamdevStreamer();
|
||||||
|
|
||||||
|
const cServerConnection* Connection(void) const { return m_Connection; }
|
||||||
|
|
||||||
virtual void Start(cTBSocket *Socket);
|
virtual void Start(cTBSocket *Socket);
|
||||||
virtual void Stop(void);
|
virtual void Stop(void);
|
||||||
bool Abort(void);
|
bool Abort(void);
|
||||||
|
268
streamdev-server/externremux.sh
Executable file
268
streamdev-server/externremux.sh
Executable file
@ -0,0 +1,268 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# externremux.sh - sample remux script using mencoder for remuxing.
|
||||||
|
#
|
||||||
|
# Install this script as VDRCONFDIR/plugins/streamdev-server/externremux.sh
|
||||||
|
#
|
||||||
|
# The parameter QUALITY selects the default remux parameters. Adjust
|
||||||
|
# to your needs and point your web browser to http://servername:3000/ext/
|
||||||
|
# To select different remux parameters on the fly, insert a semicolon
|
||||||
|
# followed by the name and value of the requested parameter, e.g:
|
||||||
|
# e.g. http://servername:3000/ext;QUALITY=WLAN11;VBR=512/
|
||||||
|
# The following parameters are recognized:
|
||||||
|
#
|
||||||
|
# PROG actual remux program
|
||||||
|
# VC video codec
|
||||||
|
# VBR video bitrate (kbit)
|
||||||
|
# VOPTS custom video options
|
||||||
|
# WIDTH scale video to width
|
||||||
|
# AC audio codec
|
||||||
|
# ABR audio bitrate (kbit)
|
||||||
|
# AOPTS custom audio options
|
||||||
|
#
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
### GENERAL CONFIG START
|
||||||
|
###
|
||||||
|
# Pick one of DSL1000/DSL2000/DSL3000/DSL6000/DSL16000/LAN10/WLAN11/WLAN54
|
||||||
|
QUALITY='DSL1000'
|
||||||
|
# Program used for logging (logging disabled if empty)
|
||||||
|
LOGGER=logger
|
||||||
|
# Path and name of FIFO
|
||||||
|
FIFO=/tmp/externremux-${RANDOM:-$$}
|
||||||
|
# Default remux program (cat/mencoder/ogg)
|
||||||
|
PROG=mencoder
|
||||||
|
# Use mono if $ABR is lower than this value
|
||||||
|
ABR_MONO=64
|
||||||
|
###
|
||||||
|
### GENERAL CONFIG END
|
||||||
|
|
||||||
|
### MENCODER CONFIG START
|
||||||
|
###
|
||||||
|
# mencoder binary
|
||||||
|
MENCODER=mencoder
|
||||||
|
# Default video codec (e.g. lavc/x264/copy)
|
||||||
|
MENCODER_VC=lavc
|
||||||
|
# Default audio codec (e.g. lavc/mp3lame/faac/copy)
|
||||||
|
MENCODER_AC=mp3lame
|
||||||
|
# Default video codec if lavc is used (-ovc lavc -lavcopts vcodec=)
|
||||||
|
MENCODER_LAVC_VC=mpeg4
|
||||||
|
# Default audio codec if lavc is used (-oac lavc -lavcopts acodec=)
|
||||||
|
MENCODER_LAVC_AC=mp2
|
||||||
|
###
|
||||||
|
### MENCODER CONFIG END
|
||||||
|
|
||||||
|
### OGG CONFIG START
|
||||||
|
###
|
||||||
|
# ffmpeg2theora binary
|
||||||
|
OGG=ffmpeg2theora
|
||||||
|
# speedlevel - lower value gives better quality but is slower (0..2)
|
||||||
|
OGG_SPEED=1
|
||||||
|
# videoquality - higher value gives better quality but is slower (0..10)
|
||||||
|
OGG_VQUALITY=0
|
||||||
|
# audioquality - higher value gives better quality but is slower (0..10)
|
||||||
|
OGG_AQUALITY=0
|
||||||
|
###
|
||||||
|
### OGG CONFIG END
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
function hasOpt { echo "$1" | grep -q "\b${2}\b"; }
|
||||||
|
|
||||||
|
function isNumeric() { echo "$@" | grep -q '^[0-9]\{1,\}$'; }
|
||||||
|
|
||||||
|
function remux_cat
|
||||||
|
{
|
||||||
|
startReply
|
||||||
|
exec 3<&0
|
||||||
|
cat 0<&3 >"$FIFO" &
|
||||||
|
}
|
||||||
|
|
||||||
|
function remux_mencoder
|
||||||
|
{
|
||||||
|
# lavc may be used for video and audio
|
||||||
|
LAVCOPTS=()
|
||||||
|
|
||||||
|
# Assemble video options
|
||||||
|
VC=${REMUX_PARAM_VC:-$MENCODER_VC}
|
||||||
|
VOPTS=${REMUX_PARAM_VOPTS}
|
||||||
|
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
||||||
|
case "$VC" in
|
||||||
|
lavc)
|
||||||
|
LAVCOPTS=(
|
||||||
|
${VOPTS}
|
||||||
|
$(hasOpt "$VOPTS" vcodec || echo "vcodec=$MENCODER_LAVC_VC")
|
||||||
|
${VBR:+vbitrate=$VBR}
|
||||||
|
)
|
||||||
|
[ ${#LAVCOPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -lavcopts "${LAVCOPTS[*]}")
|
||||||
|
;;
|
||||||
|
x264)
|
||||||
|
X264OPTS=(
|
||||||
|
${VOPTS}
|
||||||
|
$(hasOpt "$VOPTS" threads || echo "threads=auto")
|
||||||
|
${VBR:+bitrate=$ABR}
|
||||||
|
)
|
||||||
|
[ ${#X264OPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -x264encopts "${X264OPTS[*]}")
|
||||||
|
;;
|
||||||
|
copy)
|
||||||
|
VOPTS=
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unknown video codec '$VC'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Assemble audio options
|
||||||
|
AC=${REMUX_PARAM_AC:-$MENCODER_AC}
|
||||||
|
AOPTS=${REMUX_PARAM_AOPTS}
|
||||||
|
case "$AC" in
|
||||||
|
lavc)
|
||||||
|
LAVCOPTS=(
|
||||||
|
${LAVCOPTS[*]}
|
||||||
|
${AOPTS}
|
||||||
|
$(hasOpt "$AOPTS" acodec || echo "acodec=$MENCODER_LAVC_AC")
|
||||||
|
${ABR:+abitrate=$ABR}
|
||||||
|
)
|
||||||
|
|
||||||
|
[ ${#LAVCOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -lavcopts "${LAVCOPTS[*]}")
|
||||||
|
# lavc used for video and audio decoding - wipe out VOPTS as video options became part of AOPTS
|
||||||
|
[ "$VC" = lavc ] && VOPTS=
|
||||||
|
;;
|
||||||
|
mp3lame)
|
||||||
|
LAMEOPTS=(
|
||||||
|
${AOPTS}
|
||||||
|
$(isNumeric "${ABR}" && [ "${ABR}" -lt "$ABR_MONO" ] && ! hasOpt "${AOPTS}" mode ] && echo 'mode=3')
|
||||||
|
${ABR:+preset=$ABR}
|
||||||
|
)
|
||||||
|
[ ${#LAMEOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -lameopts "${LAMEOPTS[*]}")
|
||||||
|
;;
|
||||||
|
faac)
|
||||||
|
FAACOPTS=(
|
||||||
|
${AOPTS}
|
||||||
|
${ABR:+br=$ABR}
|
||||||
|
)
|
||||||
|
[ ${#FAACOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -faacopts "${FAACOPTS[*]}")
|
||||||
|
;;
|
||||||
|
copy)
|
||||||
|
AOPTS=
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unknown audio codec '$AC'"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
startReply
|
||||||
|
exec 3<&0
|
||||||
|
echo "$MENCODER" \
|
||||||
|
-ovc $VC $VOPTS \
|
||||||
|
-oac $AC $AOPTS \
|
||||||
|
${WIDTH:+-vf scale -zoom -xy $WIDTH} \
|
||||||
|
-o "$FIFO" -- - >&2
|
||||||
|
"$MENCODER" \
|
||||||
|
-ovc $VC $VOPTS \
|
||||||
|
-oac $AC $AOPTS \
|
||||||
|
${WIDTH:+-vf scale -zoom -xy $WIDTH} \
|
||||||
|
-o "$FIFO" -- - 0<&3 >/dev/null &
|
||||||
|
}
|
||||||
|
|
||||||
|
function remux_ogg
|
||||||
|
{
|
||||||
|
VOPTS=${REMUX_PARAM_VOPTS//[:=]/ }
|
||||||
|
AOPTS=${REMUX_PARAM_AOPTS//[:=]/ }
|
||||||
|
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
||||||
|
|
||||||
|
OGGOPTS=(
|
||||||
|
${VOPTS}
|
||||||
|
${VBR:+--videobitrate $VBR}
|
||||||
|
$(hasOpt "${VOPTS}" videoquality || echo "--videoquality $OGG_VQUALITY")
|
||||||
|
$(hasOpt "${VOPTS}" speedlevel || echo "--speedlevel $OGG_SPEED")
|
||||||
|
${AOPTS}
|
||||||
|
${ABR:+--audiobitrate $ABR}
|
||||||
|
$(isNumeric "${ABR}" && [ "${ABR}" -lt "$ABR_MONO" ] && ! hasOpt "${AOPTS}" channels ] && echo '--channels 1')
|
||||||
|
$(hasOpt "${AOPTS}" audioquality || echo "--audioquality $OGG_AQUALITY")
|
||||||
|
$(hasOpt "${AOPTS}" audiostream || echo '--audiostream 1')
|
||||||
|
)
|
||||||
|
|
||||||
|
startReply
|
||||||
|
exec 3<&0
|
||||||
|
echo "$OGG" --format ts \
|
||||||
|
${OGGOPTS[*]} \
|
||||||
|
${WIDTH:+--width $WIDTH --height $(($WIDTH * 3 / 4 / 8 * 8))} \
|
||||||
|
--title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \
|
||||||
|
--output "$FIFO" -- - 0<&3 >&2
|
||||||
|
"$OGG" --format ts \
|
||||||
|
${OGGOPTS[*]} \
|
||||||
|
${WIDTH:+--width $WIDTH --height $(($WIDTH * 3 / 4 / 8 * 8))} \
|
||||||
|
--title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \
|
||||||
|
--output "$FIFO" -- - 0<&3 >/dev/null &
|
||||||
|
}
|
||||||
|
|
||||||
|
function error
|
||||||
|
{
|
||||||
|
if [ "$SERVER_PROTOCOL" = HTTP ]; then
|
||||||
|
echo -ne "Content-type: text/plain\r\n"
|
||||||
|
echo -ne '\r\n'
|
||||||
|
echo "$*"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function startReply
|
||||||
|
{
|
||||||
|
if [ "$SERVER_PROTOCOL" = HTTP ]; then
|
||||||
|
# send content-type and custom headers
|
||||||
|
echo -ne "Content-type: ${CONTENTTYPE}\r\n"
|
||||||
|
for header in "${HEADER[@]}"; do echo -ne "$header\r\n"; done
|
||||||
|
echo -ne '\r\n'
|
||||||
|
|
||||||
|
# abort after headers
|
||||||
|
[ "$REQUEST_METHOD" = HEAD ] && exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create FIFO and read from it in the background
|
||||||
|
mkfifo "$FIFO"
|
||||||
|
trap "kill 0; sleep 1; rm '$FIFO'; trap - EXIT HUP INT TERM ABRT PIPE CHLD" EXIT HUP INT TERM ABRT PIPE CHLD
|
||||||
|
cat "$FIFO" <&- &
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADER=()
|
||||||
|
|
||||||
|
set > /tmp/env
|
||||||
|
[ "$LOGGER" ] && exec 2> >($LOGGER -t "vdr: [$$] streamdev EXT" 2>&-)
|
||||||
|
|
||||||
|
# set default content-types
|
||||||
|
case "$REMUX_VPID" in
|
||||||
|
''|0|1) CONTENTTYPE='audio/mpeg';;
|
||||||
|
*) CONTENTTYPE='video/mpeg';;
|
||||||
|
esac
|
||||||
|
|
||||||
|
QUALITY=${REMUX_PARAM_QUALITY:-$QUALITY}
|
||||||
|
case "$QUALITY" in
|
||||||
|
DSL1000) VBR=96; ABR=16; WIDTH=160;;
|
||||||
|
DSL2000) VBR=128; ABR=16; WIDTH=160;;
|
||||||
|
DSL3000) VBR=256; ABR=16; WIDTH=320;;
|
||||||
|
DSL6000) VBR=378; ABR=32; WIDTH=320;;
|
||||||
|
DSL16000) VBR=512; ABR=32; WIDTH=480;;
|
||||||
|
WLAN11) VBR=768; ABR=64; WIDTH=640;;
|
||||||
|
WLAN45) VBR=2048; ABR=128; WIDTH=;;
|
||||||
|
LAN10) VBR=4096; ABR=; WIDTH=;;
|
||||||
|
*) error "Unknown quality '$QUALITY'";;
|
||||||
|
esac
|
||||||
|
ABR=${REMUX_PARAM_ABR:-$ABR}
|
||||||
|
VBR=${REMUX_PARAM_VBR:-$VBR}
|
||||||
|
WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH}
|
||||||
|
PROG=${REMUX_PARAM_PROG:-$PROG}
|
||||||
|
|
||||||
|
case "$PROG" in
|
||||||
|
cat) remux_cat;;
|
||||||
|
mencoder) remux_mencoder;;
|
||||||
|
ogg) remux_ogg;;
|
||||||
|
*) error "Unknown remuxer '$PROG'";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
set -o monitor
|
||||||
|
wait
|
@ -11,4 +11,4 @@
|
|||||||
#192.168.100.0/24 # any host on the local net
|
#192.168.100.0/24 # any host on the local net
|
||||||
#204.152.189.113 # a specific host
|
#204.152.189.113 # a specific host
|
||||||
#239.255.0.0/16 # uncomment for IGMP multicast streaming
|
#239.255.0.0/16 # uncomment for IGMP multicast streaming
|
||||||
#0.0.0.0/0 # any host on any net (USE THIS WITH CARE!)
|
#0.0.0.0/0 # any host on any net (DON'T DO THAT! USE AUTHENTICATION)
|
@ -1,48 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# externremux.sh - sample remux script using mencoder for remuxing.
|
|
||||||
#
|
|
||||||
# Install this script as VDRCONFDIR/plugins/streamdev/externremux.sh
|
|
||||||
#
|
|
||||||
# The parameter STREAMQUALITY selects the default remux parameters. Adjust
|
|
||||||
# to your needs and point your web browser to http://servername:3000/extern/
|
|
||||||
# To select different remux parameters on the fly, insert a semicolon and
|
|
||||||
# the name of the requested quality: http://servername:3000/extern;WLAN11/
|
|
||||||
|
|
||||||
# CONFIG START
|
|
||||||
STREAMQUALITY="DSL6000" # DSL{1,2,3,6}000, LAN10, WLAN{11,54}, IPAQ
|
|
||||||
TMP=/tmp/externremux-${RANDOM:-$$}
|
|
||||||
MENCODER=mencoder
|
|
||||||
# CONFIG END
|
|
||||||
|
|
||||||
mkdir -p $TMP
|
|
||||||
mkfifo $TMP/out.avi
|
|
||||||
(trap "rm -rf $TMP" EXIT HUP INT TERM ABRT; cat $TMP/out.avi) &
|
|
||||||
|
|
||||||
case ${1:-$STREAMQUALITY} in
|
|
||||||
DSL1000) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=100 \
|
|
||||||
-oac mp3lame -lameopts preset=15:mode=3 -vf scale=160:104 \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
DSL2000) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=128 \
|
|
||||||
-oac mp3lame -lameopts preset=15:mode=3 -vf scale=160:104 \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
DSL3000) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=250 \
|
|
||||||
-oac mp3lame -lameopts preset=15:mode=3 -vf scale=320:208 \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
DSL6000) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=350 \
|
|
||||||
-oac mp3lame -lameopts preset=15:mode=3 -vf scale=320:208 \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
LAN10) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=4096 \
|
|
||||||
-oac mp3lame -lameopts preset=standard \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
WLAN11) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=768 \
|
|
||||||
-oac mp3lame -lameopts preset=standard -vf scale=640:408 \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
WLAN54) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=2048 \
|
|
||||||
-oac mp3lame -lameopts preset=standard \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
IPAQ) exec $MENCODER -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=350 \
|
|
||||||
-oac mp3lame -lameopts preset=15:mode=3 -vf scale=320:208 \
|
|
||||||
-o $TMP/out.avi -- - &>$TMP/out.log ;;
|
|
||||||
*) touch $TMP/out.avi ;;
|
|
||||||
esac
|
|
34
tools/Makefile
Normal file
34
tools/Makefile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#
|
||||||
|
# Makefile for a Video Disk Recorder plugin
|
||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1.2.1 2010/06/14 10:40:31 schmirl Exp $
|
||||||
|
|
||||||
|
### The object files (add further files here):
|
||||||
|
|
||||||
|
OBJS = select.o socket.o source.o tools.o
|
||||||
|
|
||||||
|
### The main target:
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
sockettools.a: $(OBJS)
|
||||||
|
ar -rcs sockettools.a $(OBJS)
|
||||||
|
|
||||||
|
### Implicit rules:
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
|
||||||
|
|
||||||
|
### Dependencies:
|
||||||
|
|
||||||
|
MAKEDEP = $(CXX) -MM -MG
|
||||||
|
DEPFILE = .dependencies
|
||||||
|
|
||||||
|
$(DEPFILE): Makefile
|
||||||
|
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
||||||
|
|
||||||
|
-include $(DEPFILE)
|
||||||
|
|
||||||
|
### Targets:
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@-rm -f $(OBJS) $(DEPFILE) *.a core* *~
|
@ -124,6 +124,10 @@ bool cTBSocket::Accept(const cTBSocket &Listener) {
|
|||||||
if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &addrlen) == -1)
|
if (::getsockname(socket, (struct sockaddr*)&m_LocalAddr, &addrlen) == -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int sol=1;
|
||||||
|
// Ignore possible errors here, proceed as usual
|
||||||
|
::setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &sol, sizeof(sol));
|
||||||
|
|
||||||
if (!cTBSource::Open(socket))
|
if (!cTBSource::Open(socket))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user