mirror of
				https://projects.vdr-developer.org/git/vdr-plugin-streamdev.git
				synced 2023-10-10 17:16:51 +00:00 
			
		
		
		
	Snapshot 2009-06-11
This commit is contained in:
		
							
								
								
									
										41
									
								
								CONTRIBUTORS
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								CONTRIBUTORS
									
									
									
									
									
								
							@@ -24,6 +24,12 @@ Rolf Ahrenberg
 | 
			
		||||
  for suggesting a fix of the Makefile's default target
 | 
			
		||||
  for a TS PAT repacker based on Petri Laine's VDR TS recording patch
 | 
			
		||||
  for making it possible to pass parameters to externremux.sh
 | 
			
		||||
  for removing pre VDR 1.4 legacy code
 | 
			
		||||
  for adding gettext support
 | 
			
		||||
  for fixing output format of some debug messages
 | 
			
		||||
  for replacing private members by cThread::Running()/Active()
 | 
			
		||||
  for improving externremux script termination
 | 
			
		||||
  for fixing PAT repacker version field
 | 
			
		||||
 | 
			
		||||
Rantanen Teemu
 | 
			
		||||
  for providing vdr-incompletesections.diff
 | 
			
		||||
@@ -42,6 +48,7 @@ Udo Richter
 | 
			
		||||
  for fixing streamdev-server shutdown
 | 
			
		||||
  for speeding up cPluginStreamdevServer::Active()
 | 
			
		||||
  for adapting to VDR 1.5.0 API
 | 
			
		||||
  for adapting to VDR 1.7.1
 | 
			
		||||
 | 
			
		||||
greenman
 | 
			
		||||
  for reporting that the log could get flooded on connection failures.
 | 
			
		||||
@@ -70,3 +77,37 @@ Olli Lammi
 | 
			
		||||
 | 
			
		||||
Joerg Pulz
 | 
			
		||||
  for his FreeBSD compatibility patch
 | 
			
		||||
 | 
			
		||||
tobi
 | 
			
		||||
  for pointing to unused files in the libdvbmpeg directory
 | 
			
		||||
 
 | 
			
		||||
Diego Pierotto
 | 
			
		||||
  for providing italian language texts
 | 
			
		||||
 
 | 
			
		||||
micky979
 | 
			
		||||
  for providing french language texts
 | 
			
		||||
 | 
			
		||||
Tiroler
 | 
			
		||||
  for reporting a problem when switching between encrypted channels
 | 
			
		||||
 | 
			
		||||
Pixelpeter
 | 
			
		||||
  for an initial fix to the "switching between ecncrypted channels" problem
 | 
			
		||||
 | 
			
		||||
Anssi Hannula
 | 
			
		||||
  for the vdr-1.6.0-ignore_missing_cam.diff patch
 | 
			
		||||
 | 
			
		||||
wirbel
 | 
			
		||||
  for pointing out that section filtering is optional for VDR devices
 | 
			
		||||
 | 
			
		||||
Jori Hamalainen
 | 
			
		||||
  for extensive testing while making stream compatible to Network Media Tank
 | 
			
		||||
  for adding Network Media Tank browser support to HTML pages
 | 
			
		||||
 | 
			
		||||
owagner
 | 
			
		||||
  for pointing out a problem with the encrypted channel switching fix
 | 
			
		||||
 | 
			
		||||
Joachim K<>nig-Baltes
 | 
			
		||||
  for fixing Min/MaxPriority parsing
 | 
			
		||||
 | 
			
		||||
Artem Makhutov
 | 
			
		||||
  for suggesting and heavy testing IGMP based multicast streaming
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								HISTORY
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								HISTORY
									
									
									
									
									
								
							@@ -1,6 +1,59 @@
 | 
			
		||||
VDR Plugin 'streamdev' Revision History
 | 
			
		||||
---------------------------------------
 | 
			
		||||
 | 
			
		||||
- added missing call to StopSectionHandler which could cause crashes when
 | 
			
		||||
  shutting down VDR
 | 
			
		||||
- added IGMP based multicast streaming
 | 
			
		||||
- ignore trailing blank lines in HTTP requests
 | 
			
		||||
- fixed parsing Min/MaxPriority from config (thanks to Joachim K<>nig-Baltes)
 | 
			
		||||
- updated Finnish translation (thanks to Rolf Ahrenberg)
 | 
			
		||||
- added Min/MaxPriority parameters. Can be used to keep client VDR from
 | 
			
		||||
  using streamdev e.g. when recording
 | 
			
		||||
- disabled PES for VDR 1.7.3+
 | 
			
		||||
- added Network Media Tank browser support to HTML pages (thanks to Jori
 | 
			
		||||
  Hamalainen)
 | 
			
		||||
- minor fixes of PAT repacker
 | 
			
		||||
- repack and send every PAT packet we receive
 | 
			
		||||
- fixed null pointer in server.c when cConnection::Accept() failes
 | 
			
		||||
- consider Pids from channels.conf when HTTP TS streaming. Section filtering
 | 
			
		||||
  is an optional feature for VDR devices, so we must not rely on the PMT
 | 
			
		||||
  alone (pointed out by wirbel@vdrportal)
 | 
			
		||||
- improved externremux script termination (thanks to Rolf Ahrenberg)
 | 
			
		||||
- use cThread::Running()/Active() instead of private members (thanks to
 | 
			
		||||
  Rolf Ahrenberg)
 | 
			
		||||
- fixed output format of some debug messages (thanks to Rolf Ahrenberg)
 | 
			
		||||
- added HTTP authentication
 | 
			
		||||
- compatibility for VDR 1.7.1 (thanks to Udo Richter)
 | 
			
		||||
- added vdr-1.6.0-intcamdevices.patch (thanks to Anssi Hannula)
 | 
			
		||||
- fixed problem when switching from one encrypted channel to an other
 | 
			
		||||
  (reported by Tiroler@vdrportal, initial bugfix by pixelpeter@vdrportal,
 | 
			
		||||
  another fix by owagner@vdrportal)
 | 
			
		||||
- added preprocessor directive for ancient gcc
 | 
			
		||||
- added Russian translation (thanks to Oleg Roitburd)
 | 
			
		||||
- fixed assignment of externremux.sh's default location (reported by plautze)
 | 
			
		||||
- added French translation (thanks to micky979)
 | 
			
		||||
- added Italian translation (thanks to Diego Pierotto)
 | 
			
		||||
- added gettext support (thanks to Rolf Ahrenberg)
 | 
			
		||||
- added vdr-1.6.0-ignore_missing_cam patch
 | 
			
		||||
- dropped obsolete respect_ca patch
 | 
			
		||||
- removed legacy code for < VDR 1.5.9 (thanks to Rolf Ahrenberg)
 | 
			
		||||
 | 
			
		||||
2008-04-07: Branched v0_4
 | 
			
		||||
 | 
			
		||||
- changed location of streamdevhosts.conf to VDRCONFDIR/plugins/streamdev
 | 
			
		||||
- changed externremux.sh's default location to VDRCONFDIR/plugins/streamdev
 | 
			
		||||
- added sample externremux.sh from http://www.vdr-wiki.de/
 | 
			
		||||
- stop providing channels after client has been disabled at runtime
 | 
			
		||||
- added logging of the client device's card index
 | 
			
		||||
- changed default suspend mode to "Always suspended"
 | 
			
		||||
- added "Hide Mainmenu Entry" setup option on client
 | 
			
		||||
- resurrected clients "Suspend Server" menu item as its mainmenu entry
 | 
			
		||||
- dropped unused code for remote timers/recordings on client side
 | 
			
		||||
- dropped unused files client/{assembler,menu,remote}.[hc]
 | 
			
		||||
- dropped unused files in libdvbmpeg (reported by tobi)
 | 
			
		||||
- dropped patches for pre VDR 1.4
 | 
			
		||||
- removed legacy code for pre VDR 1.4 (thanks to Rolf Ahrenberg)
 | 
			
		||||
 | 
			
		||||
2008-03-31: Version 0.3.4
 | 
			
		||||
 | 
			
		||||
- added possibility to pass parameter to externremux.sh (thanks to Rolf
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								Makefile
									
									
									
									
									
								
							@@ -1,7 +1,7 @@
 | 
			
		||||
#
 | 
			
		||||
# Makefile for a Video Disk Recorder plugin
 | 
			
		||||
#
 | 
			
		||||
# $Id: Makefile,v 1.12 2008/03/31 10:34:26 schmirl Exp $
 | 
			
		||||
# $Id: Makefile,v 1.17 2009/02/13 10:39:20 schmirl Exp $
 | 
			
		||||
 | 
			
		||||
# The official name of this plugin.
 | 
			
		||||
# This name will be used in the '-P...' option of VDR to load the plugin.
 | 
			
		||||
@@ -16,11 +16,10 @@ VERSION = $(shell grep 'const char \*VERSION *=' common.c | awk '{ print $$5 }'
 | 
			
		||||
### The C++ compiler and options:
 | 
			
		||||
 | 
			
		||||
CXX      ?= g++
 | 
			
		||||
CXXFLAGS ?= -fPIC -Wall -Woverloaded-virtual
 | 
			
		||||
CXXFLAGS ?= -fPIC -g -O2 -Wall -Woverloaded-virtual -Wno-parentheses
 | 
			
		||||
 | 
			
		||||
### The directory environment:
 | 
			
		||||
 | 
			
		||||
DVBDIR = ../../../../DVB
 | 
			
		||||
VDRDIR = ../../..
 | 
			
		||||
LIBDIR = ../../lib
 | 
			
		||||
TMPDIR = /tmp
 | 
			
		||||
@@ -40,55 +39,39 @@ PACKAGE = vdr-$(ARCHIVE)
 | 
			
		||||
 | 
			
		||||
### Includes and Defines (add further entries here):
 | 
			
		||||
 | 
			
		||||
INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include -I.
 | 
			
		||||
INCLUDES += -I$(VDRDIR)/include -I.
 | 
			
		||||
 | 
			
		||||
DEFINES += -D_GNU_SOURCE
 | 
			
		||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
 | 
			
		||||
 | 
			
		||||
### The object files (add further files here):
 | 
			
		||||
 | 
			
		||||
COMMONOBJS = common.o i18n.o \
 | 
			
		||||
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/remote.o client/assembler.o client/filter.o
 | 
			
		||||
	client/filter.o
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SERVEROBJS = $(PLUGIN)-server.o \
 | 
			
		||||
	\
 | 
			
		||||
	server/server.o server/connectionVTP.o server/connectionHTTP.o \
 | 
			
		||||
	server/componentHTTP.o server/componentVTP.o server/connection.o \
 | 
			
		||||
	server/component.o server/suspend.o server/setup.o server/streamer.o \
 | 
			
		||||
	server/livestreamer.o server/livefilter.o server/menuHTTP.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 \
 | 
			
		||||
	remux/tsremux.o remux/ts2ps.o remux/ts2es.o remux/extern.o
 | 
			
		||||
	
 | 
			
		||||
ifdef DEBUG
 | 
			
		||||
	DEFINES += -DDEBUG
 | 
			
		||||
	CXXFLAGS += -g
 | 
			
		||||
else
 | 
			
		||||
	CXXFLAGS += -O2
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(shell test -f $(VDRDIR)/fontsym.h ; echo $$?),0)
 | 
			
		||||
  DEFINES += -DHAVE_BEAUTYPATCH
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
ifeq ($(shell test -f $(VDRDIR)/fontsym.c ; echo $$?),0)
 | 
			
		||||
  DEFINES += -DHAVE_BEAUTYPATCH
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# HAVE_AUTOPID only applies if VDRVERSNUM < 10300
 | 
			
		||||
ifeq ($(shell test -f $(VDRDIR)/sections.c ; echo $$?),0)
 | 
			
		||||
  DEFINES += -DHAVE_AUTOPID
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
### The main target:
 | 
			
		||||
 | 
			
		||||
.PHONY: all dist clean
 | 
			
		||||
all: libvdr-$(PLUGIN)-client.so libvdr-$(PLUGIN)-server.so
 | 
			
		||||
.PHONY: all i18n dist clean
 | 
			
		||||
all: libvdr-$(PLUGIN)-client.so libvdr-$(PLUGIN)-server.so i18n
 | 
			
		||||
 | 
			
		||||
### Implicit rules:
 | 
			
		||||
 | 
			
		||||
@@ -97,7 +80,7 @@ all: libvdr-$(PLUGIN)-client.so libvdr-$(PLUGIN)-server.so
 | 
			
		||||
 | 
			
		||||
# Dependencies:
 | 
			
		||||
 | 
			
		||||
MAKEDEP = g++ -MM -MG
 | 
			
		||||
MAKEDEP = $(CXX) -MM -MG
 | 
			
		||||
DEPFILE = .dependencies
 | 
			
		||||
ifdef GCC3
 | 
			
		||||
$(DEPFILE): Makefile
 | 
			
		||||
@@ -113,12 +96,35 @@ 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:
 | 
			
		||||
 | 
			
		||||
libdvbmpeg/libdvbmpegtools.a: libdvbmpeg/*.c libdvbmpeg/*.cc libdvbmpeg/*.h libdvbmpeg/*.hh
 | 
			
		||||
libdvbmpeg/libdvbmpegtools.a: libdvbmpeg/*.c libdvbmpeg/*.h
 | 
			
		||||
	$(MAKE) -C ./libdvbmpeg libdvbmpegtools.a
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
libvdr-$(PLUGIN)-client.so: $(CLIENTOBJS) $(COMMONOBJS) libdvbmpeg/libdvbmpegtools.a
 | 
			
		||||
libvdr-$(PLUGIN)-server.so: $(SERVEROBJS) $(COMMONOBJS) libdvbmpeg/libdvbmpegtools.a
 | 
			
		||||
 | 
			
		||||
@@ -135,5 +141,5 @@ dist: clean
 | 
			
		||||
	@echo Distribution package created as $(PACKAGE).tgz
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	@-rm -f $(COMMONOBJS) $(CLIENTOBJS) $(SERVEROBJS) $(DEPFILE) *.so *.tgz core* *~
 | 
			
		||||
	@-rm -f $(COMMONOBJS) $(CLIENTOBJS) $(SERVEROBJS) $(DEPFILE) $(PODIR)/*.mo $(PODIR)/*.pot *.so *.tgz core* *~
 | 
			
		||||
	$(MAKE) -C ./libdvbmpeg clean
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										225
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										225
									
								
								README
									
									
									
									
									
								
							@@ -15,13 +15,18 @@ Contents:
 | 
			
		||||
 | 
			
		||||
1.   Description
 | 
			
		||||
2.   Installation
 | 
			
		||||
2.1  VDR 1.2.X
 | 
			
		||||
2.2  VDR 1.3.X and above
 | 
			
		||||
2.1  VDR 1.4.x and older
 | 
			
		||||
2.2  VDR 1.6.0 and above
 | 
			
		||||
2.3  Updating from streamdev 0.3.x
 | 
			
		||||
3.   Usage
 | 
			
		||||
3.1  Usage HTTP server
 | 
			
		||||
3.2  Usage VDR-to-VDR server
 | 
			
		||||
3.3  Usage VDR-to-VDR client
 | 
			
		||||
3.2  Usage IGMP multicast server
 | 
			
		||||
3.3  Usage VDR-to-VDR server
 | 
			
		||||
3.4  Usage VDR-to-VDR client
 | 
			
		||||
4.   Other useful Plugins
 | 
			
		||||
4.1  Plugins for VDR-to-VDR clients
 | 
			
		||||
4.2  Plugins for Server
 | 
			
		||||
4.3  Alternatives
 | 
			
		||||
5.   Known Problems
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -57,7 +62,7 @@ the PROTOCOL file.
 | 
			
		||||
2. Installation:
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
Let's say streamdev's version is 0.3.1 and vdr's version is 1.X.X. If you 
 | 
			
		||||
Let's say streamdev's version is 0.4.0 and vdr's version is 1.X.X. If you 
 | 
			
		||||
use anything else please exchange the version numbers appropriately (this
 | 
			
		||||
way I don't have to update this section all the times;) ).
 | 
			
		||||
 | 
			
		||||
@@ -68,48 +73,67 @@ command line.
 | 
			
		||||
What's important is that the client requests a channel using its Unique Channel
 | 
			
		||||
ID. So, in order to find the channel at the server, it must have the same ID
 | 
			
		||||
that is used on the client. You can achieve this by putting the server's 
 | 
			
		||||
channels.conf on the client, preferably after scanning (in case you use 1.2.X
 | 
			
		||||
with AutoPID or 1.3.X).
 | 
			
		||||
channels.conf on the client, preferably after scanning.
 | 
			
		||||
 | 
			
		||||
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 
 | 
			
		||||
device or the network device can receive the channels.
 | 
			
		||||
 | 
			
		||||
Last, but not least you have to put the provided streamdevhosts.conf.example
 | 
			
		||||
into the "plugins" subfolder of your config-directory (which is equal to your 
 | 
			
		||||
video-directory if not specified otherwise), rename it to streamdevhosts.conf
 | 
			
		||||
and adjust it 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. For example, if you didn't specify a separate config-directory,
 | 
			
		||||
and specified your video directory as "/video0", the file has to be put to
 | 
			
		||||
/video0/plugins/streamdevhosts.conf.
 | 
			
		||||
Last, but not least you have to copy the streamdev folder into the
 | 
			
		||||
"plugins/streamdev" subfolder of VDR's config-directory (which is equal to your
 | 
			
		||||
video-directory if not specified otherwise). For example, if you didn't specify
 | 
			
		||||
a separate config-directory, and specified your video directory as "/video0",
 | 
			
		||||
the directory has to be copied to /video0/plugins/streamdev.
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
streamdev's external remux feature. The sample script uses mencoder. Please
 | 
			
		||||
check the script for further information. You can specify a different 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,
 | 
			
		||||
as otherwise -r will be passed to VDR and not to streamdev.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
2.1 VDR 1.2.X:
 | 
			
		||||
--------------
 | 
			
		||||
2.1 VDR 1.4.x and older:
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
It is recommended that you apply a patch to VDR that improves thread 
 | 
			
		||||
cancellation. You can work without it, but you _might_ have delays in switching
 | 
			
		||||
(especially when using VDR-to-VDR streaming) that are around three seconds. 
 | 
			
		||||
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
 | 
			
		||||
VDRs you will probably need one of the streamdev-0.3.x releases.
 | 
			
		||||
 | 
			
		||||
cd vdr-1.X.X/PLUGINS/src
 | 
			
		||||
tar xvfz vdr-streamdev-0.3.1.tgz
 | 
			
		||||
ln -s streamdev-0.3.1 streamdev
 | 
			
		||||
cd ../..
 | 
			
		||||
patch -p1 <PLUGINS/src/streamdev/patches/thread.c.diff
 | 
			
		||||
make [options, if necessary] vdr
 | 
			
		||||
make [options, if necessary] plugins
 | 
			
		||||
 | 
			
		||||
2.2 VDR 1.3.X and above:
 | 
			
		||||
2.2 VDR 1.6.0 and above:
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
cd vdr-1.X.X/PLUGINS/src
 | 
			
		||||
tar xvfz vdr-streamdev-0.3.1.tgz
 | 
			
		||||
ln -s streamdev-0.3.1 streamdev
 | 
			
		||||
tar xvfz vdr-streamdev-0.4.0.tgz
 | 
			
		||||
ln -s streamdev-0.4.0 streamdev
 | 
			
		||||
cp -r streamdev/streamdev VDRCONFDIR/plugins/
 | 
			
		||||
cd ../..
 | 
			
		||||
make [options, if necessary] vdr
 | 
			
		||||
make [options, if necessary] plugins
 | 
			
		||||
 | 
			
		||||
2.3  Updating from streamdev 0.3.x
 | 
			
		||||
----------------------------------
 | 
			
		||||
 | 
			
		||||
Starting with streamdev 0.4.0, all additional files are kept in a directory
 | 
			
		||||
called "streamdev" 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:
 | 
			
		||||
 | 
			
		||||
mv VDRCONFDIR/plugins/streamdevhosts.conf VDRCONFDIR/plugins/streamdev/
 | 
			
		||||
 | 
			
		||||
(Directory VDRCONFDIR/plugins/streamdev already exists, as you copied the
 | 
			
		||||
whole folder from the sources directory as suggested above, right?)
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
*anyone* full access to streamdev, unless you took some other measures to
 | 
			
		||||
prevent this (e.g. firewall). You might want to remove this line and enable
 | 
			
		||||
HTTP authentication instead.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
3. Usage:
 | 
			
		||||
---------
 | 
			
		||||
@@ -120,12 +144,12 @@ can run in one VDR instance, if necessary.
 | 
			
		||||
 | 
			
		||||
The parameter "Suspend behaviour" allows you to specify how the server should 
 | 
			
		||||
react in case the client requests a channel that would require switching the
 | 
			
		||||
primary device (i.e. disrupt live-tv). If set to "Offer suspend mode" (the 
 | 
			
		||||
default), you will have a new entry in the main menu. Activating that will put
 | 
			
		||||
the server into "Suspend Mode" (a picture is displayed on TV). Then, a client
 | 
			
		||||
may switch the primary card to wherever it likes to. While watching TV (Suspend
 | 
			
		||||
deactivated), the client may not switch the transponder on the primary device.
 | 
			
		||||
If you set the behaviour to "Always suspended", there will be normal live-tv
 | 
			
		||||
primary device (i.e. disrupt live-tv). If set to "Offer suspend mode", you will
 | 
			
		||||
have a new entry in the main menu. Activating that will put the server into
 | 
			
		||||
"Suspend Mode" (a picture is displayed on TV). Then, a client may switch the
 | 
			
		||||
primary card to wherever it likes to. While watching TV (Suspend deactivated),
 | 
			
		||||
the client may not switch the transponder on the primary device.  If you set
 | 
			
		||||
the behaviour to "Always suspended" (the default), there will be normal live-tv
 | 
			
		||||
on the server, but whenever a client decides to switch the transponder, the 
 | 
			
		||||
server will lose it's live-tv. Set to "Never suspended", the server always 
 | 
			
		||||
prevents the client from switching transponders. If you set "Client may 
 | 
			
		||||
@@ -186,7 +210,78 @@ externremux script.
 | 
			
		||||
 | 
			
		||||
http://hostname:3000/EXTERN;some_parameter/3
 | 
			
		||||
 | 
			
		||||
3.2 Usage VDR-to-VDR server:
 | 
			
		||||
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
 | 
			
		||||
"-a" commandline option to streamdev-server. It takes a username and a password
 | 
			
		||||
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:
 | 
			
		||||
 | 
			
		||||
vdr ... -P 'streamdev-server -a vdr:secret' ...
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
as a system account.
 | 
			
		||||
 | 
			
		||||
3.2 Usage IGMP multicast server:
 | 
			
		||||
--------------------------------
 | 
			
		||||
 | 
			
		||||
IGMP based multicast streaming is often used by settop boxes to receive IP TV.
 | 
			
		||||
Streamdev's multicast server allows you to feed live TV from VDR to such a
 | 
			
		||||
settop box. VLC is known to work well if you look for a software client.
 | 
			
		||||
 | 
			
		||||
The advantage of multicasting is that the actual stream is sent out only once,
 | 
			
		||||
regardless of how many clients want to receive it. The downside is, that you
 | 
			
		||||
cannot simply multicast across network boundaries. You need multicast routers.
 | 
			
		||||
For multicast streaming over the public Internet you would even need to register
 | 
			
		||||
for your own IP range. So don't even think of multicasting via Internet with
 | 
			
		||||
streamdev! Streamdev will send the stream only to one local ethernet segment and
 | 
			
		||||
all clients must be connected to this same segment. There must not be a router
 | 
			
		||||
inbetween. Also note that the client must not run on the streamdev-server
 | 
			
		||||
machine.
 | 
			
		||||
 | 
			
		||||
Each channel is offered on a different multicast IP. Channel 1 is available from
 | 
			
		||||
multicast IP 239.255.0.1, channel 2 from 239.255.0.2 and so on. The upper limit
 | 
			
		||||
is 239.255.254.255 which corresponds to channel 65279 (239.255.255.0/24 is
 | 
			
		||||
reserved according to RFC-2365).
 | 
			
		||||
 | 
			
		||||
Before you can use streamdev's multicast server, you might need to patch VDR.
 | 
			
		||||
Binding an IGMP socket is a privileged operation, so you must start VDR as root.
 | 
			
		||||
If you pass the -u option to VDR, it will drop almost all priviledges before
 | 
			
		||||
streamdev is even loaded. Apply vdr-cap_net_raw.diff to keep VDR from dropping
 | 
			
		||||
the CAP_NET_RAW capability required to bind the IGMP socket. The patch is part
 | 
			
		||||
of streamdev's source distribution. Check the patches subdirectory. There's no
 | 
			
		||||
need to patch VDR if it is kept running as root (not recommended).
 | 
			
		||||
 | 
			
		||||
The multicast server is disabled by default. Enter the streamdev-server setup
 | 
			
		||||
menu to enable it and - IMPORTANT - bind the multicast server to the IP of your
 | 
			
		||||
VDR server's LAN ethernet card. The multicast server will refuse to start with
 | 
			
		||||
the default bind adresse "0.0.0.0".
 | 
			
		||||
 | 
			
		||||
Now edit your streamdevhosts.conf. To allow streaming of all channels, it must
 | 
			
		||||
contain "239.255.0.0/16". Note that you cannot limit connections by client IP
 | 
			
		||||
here. You can however restrict which channels are allowed to be multicasted.
 | 
			
		||||
Enter individual multicast IPs instead of "239.255.0.0/16".
 | 
			
		||||
 | 
			
		||||
By default, the linux kernel will refuse to join more than 20 multicast groups.
 | 
			
		||||
You might want to increase this up to "number_of_channels + 1". Note that it's
 | 
			
		||||
"number_of_channels", not "maximum_channel_number".
 | 
			
		||||
 | 
			
		||||
  #First 100 channels:
 | 
			
		||||
  bash# sysctl -w sys.net.ipv4.igmp_max_memberships=101
 | 
			
		||||
 | 
			
		||||
  #All channels:
 | 
			
		||||
  bash# COUNT=$(grep -c '^[^:]' PATH_TO_YOUR/channels.conf)
 | 
			
		||||
  bash# sysctl -w sys.net.ipv4.igmp_max_memberships=$COUNT
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
for other listeners before it can stop the stream. This may delay zapping from
 | 
			
		||||
one transponder to an other. The client will probably requests the new channel
 | 
			
		||||
before the previous stream has been stopped. If there's no free DVB card, VDR
 | 
			
		||||
won't be able to fulfill the request until a DVB card becomes available and the
 | 
			
		||||
client resends the request.
 | 
			
		||||
 | 
			
		||||
3.3 Usage VDR-to-VDR server:
 | 
			
		||||
----------------------------
 | 
			
		||||
 | 
			
		||||
You can activate the VDR-to-VDR server part in the PlugIn's Setup Menu. It is
 | 
			
		||||
@@ -195,9 +290,14 @@ port where you want the server to listen for incoming connections. The server
 | 
			
		||||
will be activated when you push the OK button inside the setup menu, so there's
 | 
			
		||||
no need to restart VDR.
 | 
			
		||||
 | 
			
		||||
3.3 Usage VDR-to-VDR client:
 | 
			
		||||
3.4 Usage VDR-to-VDR client:
 | 
			
		||||
----------------------------
 | 
			
		||||
 | 
			
		||||
Streamdev-client adds a "Suspend Server" item to VDR's mainmenu. With the
 | 
			
		||||
setup parameter "Hide Mainmenu Entry" you can hide this menu item if you don't
 | 
			
		||||
need it. "Suspend Server" is only useful if the server runs in "Offer suspend
 | 
			
		||||
mode" with "Client may suspend" enabled.
 | 
			
		||||
 | 
			
		||||
The parameter "Remote IP" uses an IP-Adress-Editor, where you can just enter
 | 
			
		||||
the IP number with the number keys on your remote. After three digits (or if 
 | 
			
		||||
the next digit would result in an invalid IP adress, or if the first digit is
 | 
			
		||||
@@ -214,8 +314,9 @@ setting "Start Client" to yes. It is disabled by default, because it wouldn't
 | 
			
		||||
make much sense to start the client without specifying a server anyway. The 
 | 
			
		||||
client is activated after you push the OK button, so there's no need to restart
 | 
			
		||||
VDR. Deactivation on-the-fly is not possible, so in order to deactivate the 
 | 
			
		||||
client, you will have to restart VDR. All other settings can be changed without
 | 
			
		||||
restarting VDR.
 | 
			
		||||
client, you will have to restart VDR. However requests to switch channels will
 | 
			
		||||
be refused by streamdev-client once it has been deactivated. All other settings
 | 
			
		||||
can be changed without restarting VDR.
 | 
			
		||||
 | 
			
		||||
The client will try to connect to the server (in case it isn't yet) whenever 
 | 
			
		||||
a remote channel is requested. Just activate the client and switch to a 
 | 
			
		||||
@@ -236,7 +337,7 @@ 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.
 | 
			
		||||
Link channels and even a client-side EPG scan have been reported to work.
 | 
			
		||||
 | 
			
		||||
The last parameter, "Synchronize EPG", will have the client synchronize it's 
 | 
			
		||||
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 
 | 
			
		||||
@@ -245,6 +346,16 @@ 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
 | 
			
		||||
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
 | 
			
		||||
what you want, you could set the maximum priority to 0. As recordings usually
 | 
			
		||||
have a much higher priority (default 50), streamdev is now no longer used for
 | 
			
		||||
recordings. The two parameters define the inclusive range of priorities for
 | 
			
		||||
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
 | 
			
		||||
and above".
 | 
			
		||||
 | 
			
		||||
4. Other useful Plugins:
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
@@ -295,3 +406,33 @@ priority than the actual channel switch. The later always uses priority 0.
 | 
			
		||||
Usually a channel switch for live TV has priority 0 anyway, so it is not a
 | 
			
		||||
problem here. However timers usually have a higher priority. Either avoid
 | 
			
		||||
client side recordings or set the priority of client side timers to 0.
 | 
			
		||||
 | 
			
		||||
* There have been reports that channel switching with VDR 1.5.x/1.6.x clients
 | 
			
		||||
sometimes fails. Current version includes a workaround which seems to work, but
 | 
			
		||||
YMMV ;)
 | 
			
		||||
 | 
			
		||||
* Viewing encrypted channels became an issue with VDR's new CAM handling code.
 | 
			
		||||
Streamdev doesn't provide a (dummy) CAM, so out of the box, VDR won't ever try
 | 
			
		||||
to receive encrypted channels from streamdev. Pick one of the following
 | 
			
		||||
solutions to work around the problem:
 | 
			
		||||
 | 
			
		||||
1. Force VDR to use streamdev. Open the channels menu on the client (or edit its
 | 
			
		||||
channels.conf if you know how to do this) and set the CA field of all channels
 | 
			
		||||
that only the server can decrypt to streamdev's device index. Usually streamdev
 | 
			
		||||
will get number 9 or 10. Streamdev logs the actual device number when starting
 | 
			
		||||
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
 | 
			
		||||
(number 10 becomes an "a", number 11 a "b", ...).
 | 
			
		||||
 | 
			
		||||
2. Turn encrypted channels into Free-to-Air channels on the client. Again,
 | 
			
		||||
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
 | 
			
		||||
is the clean solution. But as it modifies the VDR API, so you will need to
 | 
			
		||||
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
 | 
			
		||||
card of their own.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,125 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: assembler.c,v 1.2 2005/01/25 14:14:43 lordjaxom Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "client/assembler.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#include "tools/socket.h"
 | 
			
		||||
#include "tools/select.h"
 | 
			
		||||
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
#include <vdr/device.h>
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
cStreamdevAssembler::cStreamdevAssembler(cTBSocket *Socket)
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		:cThread("Streamdev: UDP-TS Assembler")
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
	m_Socket = Socket;
 | 
			
		||||
	if (pipe(m_Pipe) != 0) {
 | 
			
		||||
		esyslog("streamdev-client: Couldn't open assembler pipe: %m");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	fcntl(m_Pipe[0], F_SETFL, O_NONBLOCK);
 | 
			
		||||
	fcntl(m_Pipe[1], F_SETFL, O_NONBLOCK);
 | 
			
		||||
	m_Mutex.Lock();
 | 
			
		||||
	Start();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cStreamdevAssembler::~cStreamdevAssembler() {
 | 
			
		||||
	if (m_Active) {
 | 
			
		||||
		m_Active = false;
 | 
			
		||||
/*      WakeUp();*/
 | 
			
		||||
		Cancel(3);
 | 
			
		||||
	}
 | 
			
		||||
	close(m_Pipe[0]);
 | 
			
		||||
	close(m_Pipe[1]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cStreamdevAssembler::Action(void) {
 | 
			
		||||
	cTBSelect sel;
 | 
			
		||||
	uchar buffer[2048];
 | 
			
		||||
	bool fillup = true;
 | 
			
		||||
 | 
			
		||||
	const int rbsize = TS_SIZE * 5600;
 | 
			
		||||
	const int rbmargin = TS_SIZE * 2;
 | 
			
		||||
	const int rbminfill = rbmargin * 50;
 | 
			
		||||
	cRingBufferLinear ringbuf(rbsize, rbmargin, true);
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	isyslog("streamdev-client: UDP-TS Assembler thread started (pid=%d)", 
 | 
			
		||||
			getpid());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	m_Mutex.Lock();
 | 
			
		||||
 | 
			
		||||
	m_Active = true;
 | 
			
		||||
	while (m_Active) {
 | 
			
		||||
		sel.Clear();
 | 
			
		||||
 | 
			
		||||
		if (ringbuf.Available() < rbsize * 80 / 100)
 | 
			
		||||
			sel.Add(*m_Socket, false);
 | 
			
		||||
		if (ringbuf.Available() > rbminfill) {
 | 
			
		||||
			if (fillup) {
 | 
			
		||||
				Dprintf("giving signal\n");
 | 
			
		||||
				m_WaitFill.Broadcast();
 | 
			
		||||
				m_Mutex.Unlock();
 | 
			
		||||
				fillup = false;
 | 
			
		||||
			}
 | 
			
		||||
			sel.Add(m_Pipe[1], true);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (sel.Select(1500) < 0) {
 | 
			
		||||
			if (!m_Active) // Exit was requested
 | 
			
		||||
				break;
 | 
			
		||||
			esyslog("streamdev-client: Fatal error: %m");
 | 
			
		||||
			Dprintf("streamdev-client: select failed (%m)\n");
 | 
			
		||||
			m_Active = false;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (sel.CanRead(*m_Socket)) {
 | 
			
		||||
			int b;
 | 
			
		||||
			if ((b = m_Socket->Read(buffer, sizeof(buffer))) < 0) {
 | 
			
		||||
				esyslog("streamdev-client: Couldn't read from server: %m");
 | 
			
		||||
				Dprintf("streamdev-client: read failed (%m)\n");
 | 
			
		||||
				m_Active = false;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			if (b == 0)
 | 
			
		||||
				m_Active = false;
 | 
			
		||||
			else
 | 
			
		||||
				ringbuf.Put(buffer, b);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (sel.CanWrite(m_Pipe[1])) {
 | 
			
		||||
			int recvd;
 | 
			
		||||
			const uchar *block = ringbuf.Get(recvd);
 | 
			
		||||
			if (block && recvd > 0) {
 | 
			
		||||
				int result;
 | 
			
		||||
				if (recvd > ringbuf.Available() - rbminfill)
 | 
			
		||||
					recvd = ringbuf.Available() - rbminfill;
 | 
			
		||||
				if ((result = write(m_Pipe[1], block, recvd)) == -1) {
 | 
			
		||||
					esyslog("streamdev-client: Couldn't write to VDR: %m"); // TODO
 | 
			
		||||
					Dprintf("streamdev-client: write failed (%m)\n");
 | 
			
		||||
					m_Active = false;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				ringbuf.Del(result);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	isyslog("streamdev-client: UDP-TS Assembler thread stopped", getpid());
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cStreamdevAssembler::WaitForFill(void) {
 | 
			
		||||
	m_WaitFill.Wait(m_Mutex);
 | 
			
		||||
	m_Mutex.Unlock();
 | 
			
		||||
}
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: assembler.h,v 1.1.1.1 2004/12/30 22:44:04 lordjaxom Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef VDR_STREAMDEV_ASSEMBLER_H
 | 
			
		||||
#define VDR_STREAMDEV_ASSEMBLER_H
 | 
			
		||||
 | 
			
		||||
#include <vdr/config.h>
 | 
			
		||||
#include <vdr/thread.h>
 | 
			
		||||
 | 
			
		||||
class cTBSocket;
 | 
			
		||||
 | 
			
		||||
class cStreamdevAssembler: public cThread {
 | 
			
		||||
private:
 | 
			
		||||
	cTBSocket         *m_Socket;
 | 
			
		||||
	cMutex             m_Mutex;
 | 
			
		||||
	cCondVar           m_WaitFill;
 | 
			
		||||
	int                m_Pipe[2];
 | 
			
		||||
	bool               m_Active;
 | 
			
		||||
protected:
 | 
			
		||||
	virtual void Action(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevAssembler(cTBSocket *Socket);
 | 
			
		||||
	virtual ~cStreamdevAssembler();
 | 
			
		||||
 | 
			
		||||
	int ReadPipe(void) const { return m_Pipe[0]; }
 | 
			
		||||
	void WaitForFill(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_ASSEMBLER_H
 | 
			
		||||
 | 
			
		||||
@@ -1,10 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: device.c,v 1.15 2007/12/12 12:22:45 schmirl Exp $
 | 
			
		||||
 *  $Id: device.c,v 1.23 2009/04/06 06:48:59 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include "client/device.h"
 | 
			
		||||
#include "client/setup.h"
 | 
			
		||||
#include "client/assembler.h"
 | 
			
		||||
#include "client/filter.h"
 | 
			
		||||
 | 
			
		||||
#include "tools/select.h"
 | 
			
		||||
@@ -26,20 +25,10 @@ cStreamdevDevice *cStreamdevDevice::m_Device = NULL;
 | 
			
		||||
cStreamdevDevice::cStreamdevDevice(void) {
 | 
			
		||||
	m_Channel    = NULL;
 | 
			
		||||
	m_TSBuffer   = NULL;
 | 
			
		||||
	m_Assembler  = NULL;
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
#	if defined(HAVE_AUTOPID)
 | 
			
		||||
	(void)new cSIProcessor(new cSectionsScanner(""));
 | 
			
		||||
#	else
 | 
			
		||||
	(void)new cSIProcessor("");
 | 
			
		||||
# endif
 | 
			
		||||
	cSIProcessor::Read();
 | 
			
		||||
#else
 | 
			
		||||
	m_Filters    = new cStreamdevFilters;
 | 
			
		||||
	StartSectionHandler();
 | 
			
		||||
	cSchedules::Read();
 | 
			
		||||
#endif
 | 
			
		||||
	isyslog("streamdev-client: got device number %d", CardIndex() + 1);
 | 
			
		||||
 | 
			
		||||
	m_Device = this;
 | 
			
		||||
	m_Pids = 0;
 | 
			
		||||
@@ -61,11 +50,11 @@ cStreamdevDevice::~cStreamdevDevice() {
 | 
			
		||||
 | 
			
		||||
	Cancel(3);
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	DELETENULL(m_Filters);
 | 
			
		||||
#if APIVERSNUM >= 10515
 | 
			
		||||
	StopSectionHandler();
 | 
			
		||||
#endif
 | 
			
		||||
	DELETENULL(m_Filters);
 | 
			
		||||
	DELETENULL(m_TSBuffer);
 | 
			
		||||
	delete m_Assembler;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cStreamdevDevice::ProvidesSource(int Source) const {
 | 
			
		||||
@@ -93,8 +82,25 @@ bool cStreamdevDevice::ProvidesChannel(const cChannel *Channel, int Priority,
 | 
			
		||||
	bool res = false;
 | 
			
		||||
	bool prio = Priority < 0 || Priority > this->Priority();
 | 
			
		||||
	bool ndr = false;
 | 
			
		||||
 | 
			
		||||
	if (!StreamdevClientSetup.StartClient)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	Dprintf("ProvidesChannel, Channel=%s, Prio=%d\n", Channel->Name(), Priority);
 | 
			
		||||
 | 
			
		||||
	if (StreamdevClientSetup.MinPriority <= StreamdevClientSetup.MaxPriority)
 | 
			
		||||
	{
 | 
			
		||||
		if (Priority < StreamdevClientSetup.MinPriority ||
 | 
			
		||||
				Priority > StreamdevClientSetup.MaxPriority)
 | 
			
		||||
			return false;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		if (Priority < StreamdevClientSetup.MinPriority &&
 | 
			
		||||
				Priority > StreamdevClientSetup.MaxPriority)
 | 
			
		||||
			return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (ClientSocket.DataSocket(siLive) != NULL 
 | 
			
		||||
			&& TRANSPONDER(Channel, m_Channel))
 | 
			
		||||
		res = true;
 | 
			
		||||
@@ -117,23 +123,14 @@ bool cStreamdevDevice::SetChannelDevice(const cChannel *Channel,
 | 
			
		||||
	if (LiveView)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	if (ClientSocket.DataSocket(siLive) != NULL 
 | 
			
		||||
			&& TRANSPONDER(Channel, m_Channel))
 | 
			
		||||
			&& TRANSPONDER(Channel, m_Channel)
 | 
			
		||||
			&& Channel->Ca() < CA_ENCRYPTED_MIN)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10338
 | 
			
		||||
	DetachAll(pidHandles[ptAudio].pid);
 | 
			
		||||
	DetachAll(pidHandles[ptVideo].pid);
 | 
			
		||||
	DetachAll(pidHandles[ptPcr].pid);
 | 
			
		||||
	DetachAll(pidHandles[ptTeletext].pid);
 | 
			
		||||
	DelPid(pidHandles[ptAudio].pid);
 | 
			
		||||
	DelPid(pidHandles[ptVideo].pid);
 | 
			
		||||
	DelPid(pidHandles[ptPcr].pid, ptPcr);
 | 
			
		||||
	DelPid(pidHandles[ptTeletext].pid);
 | 
			
		||||
	DelPid(pidHandles[ptDolby].pid);
 | 
			
		||||
#else
 | 
			
		||||
	DetachAllReceivers();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	DetachAllReceivers();
 | 
			
		||||
	m_Channel = Channel;
 | 
			
		||||
	bool r = ClientSocket.SetChannelDevice(m_Channel);
 | 
			
		||||
	Dprintf("setchanneldevice r=%d\n", r);
 | 
			
		||||
@@ -212,16 +209,11 @@ void cStreamdevDevice::CloseDvrInt(void) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Dprintf("cStreamdevDevice::CloseDvrInt(): Closing DVR connection\n");
 | 
			
		||||
#if VDRVERSNUM < 10500
 | 
			
		||||
	DELETENULL(m_TSBuffer);
 | 
			
		||||
	ClientSocket.CloseDvr();
 | 
			
		||||
#else
 | 
			
		||||
	// Hack for VDR 1.5.x clients (sometimes sending ABRT after TUNE)
 | 
			
		||||
	// TODO: Find a clean solution to fix this
 | 
			
		||||
	ClientSocket.SetChannelDevice(m_Channel);
 | 
			
		||||
	ClientSocket.CloseDvr();
 | 
			
		||||
	DELETENULL(m_TSBuffer);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cStreamdevDevice::CloseDvr(void) {
 | 
			
		||||
@@ -268,7 +260,6 @@ esyslog("cStreamDevice::GetTSPacket: GetChecked: NOTHING (%d)", m_TSFails);
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
int cStreamdevDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) {
 | 
			
		||||
	Dprintf("OpenFilter\n");
 | 
			
		||||
 | 
			
		||||
@@ -290,7 +281,6 @@ int cStreamdevDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask) {
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool cStreamdevDevice::Init(void) {
 | 
			
		||||
	if (m_Device == NULL && StreamdevClientSetup.StartClient)
 | 
			
		||||
@@ -308,7 +298,6 @@ bool cStreamdevDevice::ReInit(void) {
 | 
			
		||||
	ClientSocket.Reset();
 | 
			
		||||
	if (m_Device != NULL) {
 | 
			
		||||
		//DELETENULL(m_Device->m_TSBuffer);
 | 
			
		||||
		DELETENULL(m_Device->m_Assembler);
 | 
			
		||||
		m_Device->Unlock();
 | 
			
		||||
	}
 | 
			
		||||
	return StreamdevClientSetup.StartClient ? Init() : true;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: device.h,v 1.5 2007/04/24 10:43:40 schmirl Exp $
 | 
			
		||||
 *  $Id: device.h,v 1.8 2008/10/02 07:14:47 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_DEVICE_H
 | 
			
		||||
@@ -8,7 +8,6 @@
 | 
			
		||||
#include <vdr/device.h>
 | 
			
		||||
 | 
			
		||||
#include "client/socket.h"
 | 
			
		||||
#include "client/assembler.h"
 | 
			
		||||
#include "client/filter.h"
 | 
			
		||||
 | 
			
		||||
class cTBString;
 | 
			
		||||
@@ -21,10 +20,7 @@ class cStreamdevDevice: public cDevice {
 | 
			
		||||
private:
 | 
			
		||||
	const cChannel      *m_Channel;
 | 
			
		||||
	cTSBuffer           *m_TSBuffer;
 | 
			
		||||
	cStreamdevAssembler *m_Assembler;
 | 
			
		||||
#if VDRVERSNUM >= 10307
 | 
			
		||||
	cStreamdevFilters   *m_Filters;
 | 
			
		||||
#endif
 | 
			
		||||
	int                  m_Pids;
 | 
			
		||||
	bool                 m_DvrClosed;
 | 
			
		||||
 | 
			
		||||
@@ -47,14 +43,13 @@ protected:
 | 
			
		||||
	virtual void CloseDvr(void);
 | 
			
		||||
	virtual bool GetTSPacket(uchar *&Data);
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevDevice(void);
 | 
			
		||||
	virtual ~cStreamdevDevice();
 | 
			
		||||
 | 
			
		||||
	virtual bool HasInternalCam(void) { return true; }
 | 
			
		||||
	virtual bool ProvidesSource(int Source) const;
 | 
			
		||||
	virtual bool ProvidesTransponder(const cChannel *Channel) const;
 | 
			
		||||
	virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: filter.c,v 1.11 2007/04/24 11:23:16 schmirl Exp $
 | 
			
		||||
 *  $Id: filter.c,v 1.14 2009/02/13 13:02:39 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "client/filter.h"
 | 
			
		||||
@@ -9,8 +9,7 @@
 | 
			
		||||
 | 
			
		||||
#include <vdr/device.h>
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
 | 
			
		||||
#define PID_MASK_HI 0x1F
 | 
			
		||||
// --- cStreamdevFilter ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevFilter: public cListObject {
 | 
			
		||||
@@ -228,6 +227,7 @@ void cStreamdevFilters::Action(void) {
 | 
			
		||||
			u_short pid = (((u_short)block[1] & PID_MASK_HI) << 8) | block[2];
 | 
			
		||||
			u_char tid = block[3];
 | 
			
		||||
			bool Pusi = block[1] & 0x40;
 | 
			
		||||
			// proprietary extension
 | 
			
		||||
			int len = block[4];
 | 
			
		||||
#if 0
 | 
			
		||||
			if (block[1] == 0xff &&
 | 
			
		||||
@@ -290,5 +290,3 @@ void cStreamdevFilters::Action(void) {
 | 
			
		||||
	DELETENULL(m_TSBuffer);
 | 
			
		||||
	dsyslog("StreamdevFilters::Action() ended");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // VDRVERSNUM >= 10300
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,11 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: filter.h,v 1.4 2007/04/24 11:23:16 schmirl Exp $
 | 
			
		||||
 *  $Id: filter.h,v 1.5 2008/04/07 14:27:28 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef VDR_STREAMDEV_FILTER_H
 | 
			
		||||
#define VDR_STREAMDEV_FILTER_H
 | 
			
		||||
 | 
			
		||||
#include <vdr/config.h>
 | 
			
		||||
 | 
			
		||||
#	if VDRVERSNUM >= 10300
 | 
			
		||||
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
#include <vdr/thread.h>
 | 
			
		||||
 | 
			
		||||
@@ -33,5 +30,4 @@ public:
 | 
			
		||||
	int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#	endif // VDRVERSNUM >= 10300
 | 
			
		||||
#endif // VDR_STREAMDEV_FILTER_H
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1045
									
								
								client/menu.c
									
									
									
									
									
								
							
							
						
						
									
										1045
									
								
								client/menu.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										144
									
								
								client/menu.h
									
									
									
									
									
								
							
							
						
						
									
										144
									
								
								client/menu.h
									
									
									
									
									
								
							@@ -1,144 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: menu.h,v 1.1.1.1 2004/12/30 22:44:02 lordjaxom Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_MENU_H
 | 
			
		||||
#define VDR_STREAMDEV_MENU_H
 | 
			
		||||
 | 
			
		||||
#include <vdr/osd.h>
 | 
			
		||||
 | 
			
		||||
#include "client/remote.h"
 | 
			
		||||
 | 
			
		||||
class cStreamdevMenuRecordingItem;
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevMenu --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevMenu: public cOsdMenu {
 | 
			
		||||
private:
 | 
			
		||||
	enum eSubmenus {
 | 
			
		||||
		sub_Start = os_User,
 | 
			
		||||
		subSchedule,
 | 
			
		||||
		subTimers,
 | 
			
		||||
		subRecordings,
 | 
			
		||||
		subSuspend,
 | 
			
		||||
		subSyncEPG
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	void SuspendServer(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevMenu(void);
 | 
			
		||||
	virtual ~cStreamdevMenu(void);
 | 
			
		||||
 | 
			
		||||
	virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevMenuSchedule ------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevMenuSchedule: public cOsdMenu {
 | 
			
		||||
private:
 | 
			
		||||
	bool              m_Now;
 | 
			
		||||
	bool              m_Next;
 | 
			
		||||
	int               m_OtherChannel;
 | 
			
		||||
	const cSchedules *m_Schedules;
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	cMutexLock        m_Lock;
 | 
			
		||||
#else
 | 
			
		||||
	cSchedulesLock    m_Lock;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	void PrepareSchedule(cChannel *Channel);
 | 
			
		||||
 | 
			
		||||
	eOSState Switch(void);
 | 
			
		||||
	eOSState Record(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevMenuSchedule(void);
 | 
			
		||||
	virtual ~cStreamdevMenuSchedule(void);
 | 
			
		||||
 | 
			
		||||
	virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevMenuWhatsOn -------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevMenuWhatsOn: public cOsdMenu {
 | 
			
		||||
private:
 | 
			
		||||
	static int               m_CurrentChannel;
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	static const cEventInfo *m_ScheduleEventInfo;
 | 
			
		||||
#else
 | 
			
		||||
	static const cEvent     *m_ScheduleEventInfo;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	eOSState Switch(void);
 | 
			
		||||
	eOSState Record(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevMenuWhatsOn(const cSchedules *Schedules, bool Now, 
 | 
			
		||||
			int CurrentChannel);
 | 
			
		||||
 | 
			
		||||
	static int CurrentChannel(void) { return m_CurrentChannel; }
 | 
			
		||||
	static void SetCurrentChannel(int Channel) { m_CurrentChannel = Channel; }
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	static const cEventInfo *ScheduleEventInfo(void);
 | 
			
		||||
#else
 | 
			
		||||
	static const cEvent *ScheduleEventInfo(void);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevMenuRecordings ----------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevMenuRecordings: public cOsdMenu {
 | 
			
		||||
private:
 | 
			
		||||
	char *m_Base;
 | 
			
		||||
	int   m_Level;
 | 
			
		||||
 | 
			
		||||
	static int               HelpKeys;
 | 
			
		||||
	static cRemoteRecordings Recordings;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	bool Open(bool OpenSubMenus = false);
 | 
			
		||||
	void SetHelpKeys();
 | 
			
		||||
	cRemoteRecording *cStreamdevMenuRecordings::GetRecording(
 | 
			
		||||
		cStreamdevMenuRecordingItem *Item);
 | 
			
		||||
 | 
			
		||||
	eOSState Select(void);
 | 
			
		||||
	eOSState Delete(void);
 | 
			
		||||
	eOSState Summary(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevMenuRecordings(const char *Base = NULL, int Level = 0, 
 | 
			
		||||
			bool OpenSubMenus = false);
 | 
			
		||||
	virtual ~cStreamdevMenuRecordings();
 | 
			
		||||
 | 
			
		||||
	virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevMenuTimers --------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevMenuTimers: public cOsdMenu {
 | 
			
		||||
protected:
 | 
			
		||||
	eOSState Edit(void);
 | 
			
		||||
  eOSState New(void);
 | 
			
		||||
  eOSState Delete(void);
 | 
			
		||||
  eOSState OnOff(void);
 | 
			
		||||
  eOSState Summary(void);
 | 
			
		||||
  
 | 
			
		||||
	cRemoteTimer *CurrentTimer(void);
 | 
			
		||||
 | 
			
		||||
	void Refresh(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevMenuTimers(void);
 | 
			
		||||
	virtual ~cStreamdevMenuTimers();
 | 
			
		||||
	
 | 
			
		||||
	virtual eOSState ProcessKey(eKeys Key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_MENU_H
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										476
									
								
								client/remote.c
									
									
									
									
									
								
							
							
						
						
									
										476
									
								
								client/remote.c
									
									
									
									
									
								
							@@ -1,476 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: remote.c,v 1.4 2005/04/24 16:26:14 lordjaxom Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 
 | 
			
		||||
#include "client/remote.h"
 | 
			
		||||
#include "client/device.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
cRemoteTimers RemoteTimers;
 | 
			
		||||
 | 
			
		||||
// --- cRemoteRecording ------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cRemoteRecording::cRemoteRecording(const char *Text) {
 | 
			
		||||
	m_IsValid     = false;
 | 
			
		||||
	m_Index       = -1;
 | 
			
		||||
	m_IsNew       = false;
 | 
			
		||||
	m_TitleBuffer = NULL;
 | 
			
		||||
 | 
			
		||||
	char *ptr;
 | 
			
		||||
	char *timestr;
 | 
			
		||||
	int idx;
 | 
			
		||||
 | 
			
		||||
	Dprintf("text: %s\n", Text);
 | 
			
		||||
 | 
			
		||||
	m_Index = strtoul(Text, &ptr, 10);
 | 
			
		||||
	Dprintf("index: %d\n", m_Index);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0' ) return;
 | 
			
		||||
	timestr = ptr;
 | 
			
		||||
	while (*ptr != '\0' && !isspace(*ptr)) ++ptr;
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
	while (*ptr != '\0' && *ptr != '*' && !isspace(*ptr)) ++ptr;
 | 
			
		||||
	if (*ptr == '*') m_IsNew = true;
 | 
			
		||||
	Dprintf("new: %d\n", m_IsNew);
 | 
			
		||||
	*(ptr++) = '\0';
 | 
			
		||||
	m_StartTime = timestr;
 | 
			
		||||
	idx = -1;
 | 
			
		||||
	while ((idx = m_StartTime.find(' ', idx + 1)) != -1) m_StartTime[idx] = '\t';
 | 
			
		||||
	Dprintf("m_Start: %s\n", m_StartTime.c_str());
 | 
			
		||||
	if (*ptr == 0) return;
 | 
			
		||||
	if (isspace(*ptr)) ++ptr;
 | 
			
		||||
	if (*ptr == 0) return;
 | 
			
		||||
	m_Name = ptr;
 | 
			
		||||
	Dprintf("file: %s\n", m_Name.c_str());
 | 
			
		||||
	m_IsValid = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cRemoteRecording::~cRemoteRecording(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cRemoteRecording::operator==(const cRemoteRecording &Recording) {
 | 
			
		||||
	return m_IsValid   == Recording.m_IsValid
 | 
			
		||||
			&& m_Index     == Recording.m_Index
 | 
			
		||||
			&& m_StartTime == Recording.m_StartTime
 | 
			
		||||
			&& m_Name      == Recording.m_Name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cRemoteRecording::ParseInfo(const char *Text) {
 | 
			
		||||
	m_Summary = strreplace(strdup(Text), '|', '\n');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cRemoteRecording::Title(char Delimiter, bool NewIndicator,
 | 
			
		||||
		int Level) {
 | 
			
		||||
  char New = NewIndicator && IsNew() ? '*' : ' ';
 | 
			
		||||
 | 
			
		||||
  if (m_TitleBuffer != NULL) {
 | 
			
		||||
		free(m_TitleBuffer);
 | 
			
		||||
		m_TitleBuffer = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  if (Level < 0 || Level == HierarchyLevels()) {
 | 
			
		||||
    char *s;
 | 
			
		||||
	const char *t;
 | 
			
		||||
    if (Level > 0 && (t = strrchr(m_Name.c_str(), '~')) != NULL)
 | 
			
		||||
      t++;
 | 
			
		||||
    else
 | 
			
		||||
      t = m_Name.c_str();
 | 
			
		||||
					
 | 
			
		||||
	asprintf(&m_TitleBuffer, "%s%c%c%s", m_StartTime.c_str(), New, Delimiter, t);
 | 
			
		||||
    // let's not display a trailing '~':
 | 
			
		||||
    stripspace(m_TitleBuffer);
 | 
			
		||||
    s = &m_TitleBuffer[strlen(m_TitleBuffer) - 1];
 | 
			
		||||
    if (*s == '~')
 | 
			
		||||
      *s = 0;
 | 
			
		||||
  } else if (Level < HierarchyLevels()) {
 | 
			
		||||
    const char *s = m_Name.c_str();
 | 
			
		||||
    const char *p = s;
 | 
			
		||||
    while (*++s) {
 | 
			
		||||
      if (*s == '~') {
 | 
			
		||||
        if (Level--)
 | 
			
		||||
          p = s + 1;
 | 
			
		||||
        else
 | 
			
		||||
          break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    m_TitleBuffer = MALLOC(char, s - p + 3);
 | 
			
		||||
    *m_TitleBuffer = Delimiter;
 | 
			
		||||
    *(m_TitleBuffer + 1) = Delimiter;
 | 
			
		||||
    strn0cpy(m_TitleBuffer + 2, p, s - p + 1);
 | 
			
		||||
  } else
 | 
			
		||||
    return "";
 | 
			
		||||
  return m_TitleBuffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cRemoteRecording::HierarchyLevels(void)
 | 
			
		||||
{
 | 
			
		||||
  const char *s = m_Name.c_str();
 | 
			
		||||
  int level = 0;
 | 
			
		||||
  while (*++s) {
 | 
			
		||||
    if (*s == '~') ++level;
 | 
			
		||||
  }
 | 
			
		||||
  return level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cRemoteRecordings -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
bool cRemoteRecordings::Load(void) {
 | 
			
		||||
	Clear();
 | 
			
		||||
	return ClientSocket.LoadRecordings(*this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cRemoteRecording *cRemoteRecordings::GetByName(const char *Name) {
 | 
			
		||||
	for (cRemoteRecording *r = First(); r; r = Next(r))
 | 
			
		||||
		if (strcmp(r->Name(), Name) == 0)
 | 
			
		||||
			return r;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cRemoteTimer ----------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
cRemoteTimer::cRemoteTimer(const char *Text) {
 | 
			
		||||
	m_IsValid   = false;
 | 
			
		||||
	m_Index     = -1;
 | 
			
		||||
	m_Active    = -1;
 | 
			
		||||
	m_Day       = -1;
 | 
			
		||||
	m_Start     = -1;
 | 
			
		||||
	m_Stop      = -1;
 | 
			
		||||
	m_StartTime = 0;
 | 
			
		||||
	m_StopTime  = 0;
 | 
			
		||||
	m_Priority  = -1;
 | 
			
		||||
	m_Lifetime  = -1;
 | 
			
		||||
	m_File[0]   = '\0';
 | 
			
		||||
	m_FirstDay  = 0;
 | 
			
		||||
	m_Buffer    = NULL;
 | 
			
		||||
	m_Channel   = NULL;
 | 
			
		||||
 | 
			
		||||
	char *tmpbuf;
 | 
			
		||||
	char *ptr;
 | 
			
		||||
 | 
			
		||||
	Dprintf("text: %s\n", Text);
 | 
			
		||||
 | 
			
		||||
	m_Index = strtoul(Text, &ptr, 10);
 | 
			
		||||
	Dprintf("index: %d\n", m_Index);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
	m_Active = strtoul(ptr, &ptr, 10);
 | 
			
		||||
	Dprintf("m_Active: %d\n", m_Active);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
 | 
			
		||||
	tmpbuf = ptr;
 | 
			
		||||
	while (*ptr != '\0' && *ptr != ':') ++ptr;
 | 
			
		||||
	if (*ptr == '\0') return;
 | 
			
		||||
	*(ptr++)= '\0';
 | 
			
		||||
	if (isnumber(tmpbuf))
 | 
			
		||||
		m_Channel = Channels.GetByNumber(strtoul(tmpbuf, NULL, 10));
 | 
			
		||||
	else
 | 
			
		||||
		m_Channel = Channels.GetByChannelID(tChannelID::FromString(tmpbuf));
 | 
			
		||||
	Dprintf("channel no.: %d\n", m_Channel->Number());
 | 
			
		||||
	
 | 
			
		||||
	tmpbuf = ptr;
 | 
			
		||||
	while (*ptr != '\0' && *ptr != ':') ++ptr;
 | 
			
		||||
	if (*ptr == '\0') return;
 | 
			
		||||
	*(ptr++) = '\0';
 | 
			
		||||
	m_Day = ParseDay(tmpbuf, &m_FirstDay);
 | 
			
		||||
	Dprintf("Day: %d\n", m_Day);
 | 
			
		||||
	m_Start = strtoul(ptr, &ptr, 10);
 | 
			
		||||
	Dprintf("Start: %d\n", m_Start);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
	m_Stop = strtoul(ptr, &ptr, 10);
 | 
			
		||||
	Dprintf("Stop: %d\n", m_Stop);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
	m_Priority = strtoul(ptr, &ptr, 10);
 | 
			
		||||
	Dprintf("Prio: %d\n", m_Priority);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
	m_Lifetime = strtoul(ptr, &ptr, 10);
 | 
			
		||||
	Dprintf("Lifetime: %d\n", m_Lifetime);
 | 
			
		||||
	if (*ptr == '\0' || *++ptr == '\0') return;
 | 
			
		||||
	tmpbuf = ptr;
 | 
			
		||||
	while (*ptr != '\0' && *ptr != ':') ++ptr;
 | 
			
		||||
	if (*ptr == '\0') return;
 | 
			
		||||
	*(ptr++) = '\0';
 | 
			
		||||
	strncpy(m_File, tmpbuf, MaxFileName);
 | 
			
		||||
	Dprintf("file: %s\n", m_File);
 | 
			
		||||
	if (*ptr != '\0') m_Summary = ptr;
 | 
			
		||||
	Dprintf("summary: %s\n", m_Summary.c_str());
 | 
			
		||||
	m_IsValid = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
cRemoteTimer::cRemoteTimer(const cEventInfo *EventInfo) {
 | 
			
		||||
	time_t tstart = EventInfo->GetTime();
 | 
			
		||||
	time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
 | 
			
		||||
	tstart -= Setup.MarginStart * 60;
 | 
			
		||||
	struct tm tm_r;
 | 
			
		||||
	struct tm *time = localtime_r(&tstart, &tm_r);
 | 
			
		||||
	const char *title = EventInfo->GetTitle();
 | 
			
		||||
	cChannel *channel = Channels.GetByChannelID(EventInfo->GetChannelID(), true);
 | 
			
		||||
#else
 | 
			
		||||
cRemoteTimer::cRemoteTimer(const cEvent *Event) {
 | 
			
		||||
	time_t tstart = Event->StartTime();
 | 
			
		||||
	time_t tstop = tstart + Event->Duration() + Setup.MarginStop * 60;
 | 
			
		||||
	tstart -= Setup.MarginStart * 60;
 | 
			
		||||
	struct tm tm_r;
 | 
			
		||||
	struct tm *time = localtime_r(&tstart, &tm_r);
 | 
			
		||||
	const char *title = Event->Title();
 | 
			
		||||
	cChannel *channel = Channels.GetByChannelID(Event->ChannelID(), true);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	m_IsValid   = true;
 | 
			
		||||
	m_Index     = -1;
 | 
			
		||||
	m_Active    = true;
 | 
			
		||||
	m_Day       = time->tm_mday;
 | 
			
		||||
	m_Start     = time->tm_hour * 100 + time->tm_min;
 | 
			
		||||
	time        = localtime_r(&tstop, &tm_r);
 | 
			
		||||
	m_Stop      = time->tm_hour * 100 + time->tm_min;
 | 
			
		||||
	m_StartTime = 0;
 | 
			
		||||
	m_StopTime  = 0;
 | 
			
		||||
	if (m_Stop >= 2400) m_Stop -= 2400;
 | 
			
		||||
	m_Priority  = Setup.DefaultPriority;
 | 
			
		||||
	m_Lifetime  = Setup.DefaultLifetime;
 | 
			
		||||
	m_File[0]   = '\0';
 | 
			
		||||
	if (!isempty(title))
 | 
			
		||||
		strn0cpy(m_File, title, sizeof(m_File));
 | 
			
		||||
	m_FirstDay  = 0;
 | 
			
		||||
	m_Channel   = channel;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cRemoteTimer::cRemoteTimer(void) {
 | 
			
		||||
	time_t t = time(NULL);
 | 
			
		||||
	struct tm tm_r;
 | 
			
		||||
	struct tm *now = localtime_r(&t, &tm_r);
 | 
			
		||||
 | 
			
		||||
	m_IsValid   = true;
 | 
			
		||||
	m_Index     = -1;
 | 
			
		||||
	m_Active    = -1;
 | 
			
		||||
	m_Day       = now->tm_mday;
 | 
			
		||||
	m_Start     = now->tm_hour * 100 + now->tm_min;
 | 
			
		||||
	m_Stop      = now->tm_hour * 60 + now->tm_min + Setup.InstantRecordTime;
 | 
			
		||||
	m_Stop      = (m_Stop / 60) * 100 + (m_Stop % 60);
 | 
			
		||||
	if (m_Stop >= 2400) m_Stop -= 2400;
 | 
			
		||||
	m_StartTime = 0;
 | 
			
		||||
	m_StopTime  = 0;
 | 
			
		||||
	m_Priority  = Setup.DefaultPriority;
 | 
			
		||||
	m_Lifetime  = Setup.DefaultLifetime;
 | 
			
		||||
	m_File[0]   = '\0';
 | 
			
		||||
	m_FirstDay  = 0;
 | 
			
		||||
	m_Buffer    = NULL;
 | 
			
		||||
	m_Channel   = Channels.GetByNumber(cDevice::CurrentChannel());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cRemoteTimer::~cRemoteTimer() {
 | 
			
		||||
	if (m_Buffer  != NULL) free(m_Buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cRemoteTimer &cRemoteTimer::operator=(const cRemoteTimer &Timer) {
 | 
			
		||||
	Dprintf("\n\n\n\nOP<EFBFBD>ERATHVBD<EFBFBD>LJVG\n\n\n");
 | 
			
		||||
	m_IsValid = Timer.m_IsValid;
 | 
			
		||||
	m_Index = Timer.m_Index;
 | 
			
		||||
	m_Active = Timer.m_Active;
 | 
			
		||||
	m_Day = Timer.m_Day;
 | 
			
		||||
	m_Start = Timer.m_Start;
 | 
			
		||||
	m_Stop = Timer.m_Stop;
 | 
			
		||||
	m_Priority = Timer.m_Priority;
 | 
			
		||||
	m_Lifetime = Timer.m_Lifetime;
 | 
			
		||||
	m_FirstDay = Timer.m_FirstDay;
 | 
			
		||||
	m_Channel = Timer.m_Channel;
 | 
			
		||||
	m_Summary = Timer.m_Summary;
 | 
			
		||||
	return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cRemoteTimer::operator==(const cRemoteTimer &Timer) {
 | 
			
		||||
	return m_IsValid   == Timer.m_IsValid
 | 
			
		||||
			&& m_Index     == Timer.m_Index
 | 
			
		||||
			&& m_Active    == Timer.m_Active
 | 
			
		||||
			&& m_Day       == Timer.m_Day
 | 
			
		||||
			&& m_Start     == Timer.m_Start
 | 
			
		||||
			&& m_Stop      == Timer.m_Stop
 | 
			
		||||
			&& m_Priority  == Timer.m_Priority
 | 
			
		||||
			&& m_Lifetime  == Timer.m_Lifetime
 | 
			
		||||
			&& m_FirstDay  == Timer.m_FirstDay
 | 
			
		||||
			&& m_Channel   == Timer.m_Channel
 | 
			
		||||
			&& strcmp(m_File, Timer.m_File) == 0
 | 
			
		||||
			&& m_Summary   == Timer.m_Summary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cRemoteTimer::ParseDay(const char *s, time_t *FirstDay) {
 | 
			
		||||
  char *tail;
 | 
			
		||||
  int d = strtol(s, &tail, 10);
 | 
			
		||||
  if (FirstDay)
 | 
			
		||||
     *FirstDay = 0;
 | 
			
		||||
  if (tail && *tail) {
 | 
			
		||||
     d = 0;
 | 
			
		||||
     if (tail == s) {
 | 
			
		||||
        const char *first = strchr(s, '@');
 | 
			
		||||
        int l = first ? first - s : strlen(s);
 | 
			
		||||
        if (l == 7) {
 | 
			
		||||
           for (const char *p = s + 6; p >= s; p--) {
 | 
			
		||||
               d <<= 1;
 | 
			
		||||
               d |= (*p != '-');
 | 
			
		||||
               }
 | 
			
		||||
           d |= 0x80000000;
 | 
			
		||||
           }
 | 
			
		||||
        if (FirstDay && first) {
 | 
			
		||||
           ++first;
 | 
			
		||||
           if (strlen(first) == 10) {
 | 
			
		||||
              struct tm tm_r;
 | 
			
		||||
              if (3 == sscanf(first, "%d-%d-%d", &tm_r.tm_year, &tm_r.tm_mon, &tm_r.tm_mday)) {
 | 
			
		||||
                 tm_r.tm_year -= 1900;
 | 
			
		||||
                 tm_r.tm_mon--;
 | 
			
		||||
                 tm_r.tm_hour = tm_r.tm_min = tm_r.tm_sec = 0;
 | 
			
		||||
                 tm_r.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
 | 
			
		||||
                 *FirstDay = mktime(&tm_r);
 | 
			
		||||
                 }
 | 
			
		||||
              }
 | 
			
		||||
           else
 | 
			
		||||
              d = 0;
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
     }
 | 
			
		||||
  else if (d < 1 || d > 31)
 | 
			
		||||
     d = 0;
 | 
			
		||||
  return d;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cRemoteTimer::PrintDay(int d, time_t FirstDay) {
 | 
			
		||||
#define DAYBUFFERSIZE 32
 | 
			
		||||
  static char buffer[DAYBUFFERSIZE];
 | 
			
		||||
  if ((d & 0x80000000) != 0) {
 | 
			
		||||
     char *b = buffer;
 | 
			
		||||
     const char *w = tr("MTWTFSS");
 | 
			
		||||
     while (*w) {
 | 
			
		||||
           *b++ = (d & 1) ? *w : '-';
 | 
			
		||||
           d >>= 1;
 | 
			
		||||
           w++;
 | 
			
		||||
           }
 | 
			
		||||
     if (FirstDay) {
 | 
			
		||||
        struct tm tm_r;
 | 
			
		||||
        localtime_r(&FirstDay, &tm_r);
 | 
			
		||||
        b += strftime(b, DAYBUFFERSIZE - (b - buffer), "@%Y-%m-%d", &tm_r);
 | 
			
		||||
        }
 | 
			
		||||
     *b = 0;
 | 
			
		||||
     }
 | 
			
		||||
  else
 | 
			
		||||
     sprintf(buffer, "%d", d);
 | 
			
		||||
  return buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cRemoteTimer::PrintFirstDay(void) const {
 | 
			
		||||
  if (m_FirstDay) {
 | 
			
		||||
     const char *s = PrintDay(m_Day, m_FirstDay);
 | 
			
		||||
     if (strlen(s) == 18)
 | 
			
		||||
        return s + 8;
 | 
			
		||||
     }
 | 
			
		||||
  return ""; // not NULL, so the caller can always use the result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cRemoteTimer::OnOff(void) {
 | 
			
		||||
  if (IsSingleEvent())
 | 
			
		||||
     m_Active = !m_Active;
 | 
			
		||||
  else if (m_FirstDay) {
 | 
			
		||||
     m_FirstDay = 0;
 | 
			
		||||
     m_Active = false;
 | 
			
		||||
     }
 | 
			
		||||
  else if (m_Active)
 | 
			
		||||
     Skip();
 | 
			
		||||
  else
 | 
			
		||||
     m_Active = true;
 | 
			
		||||
  Matches(); // refresh m_Start and end time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
time_t cRemoteTimer::SetTime(time_t t, int SecondsFromMidnight) {
 | 
			
		||||
  struct tm tm_r;
 | 
			
		||||
  tm tm = *localtime_r(&t, &tm_r);
 | 
			
		||||
  tm.tm_hour = SecondsFromMidnight / 3600;
 | 
			
		||||
  tm.tm_min = (SecondsFromMidnight % 3600) / 60;
 | 
			
		||||
  tm.tm_sec =  SecondsFromMidnight % 60;
 | 
			
		||||
  tm.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
 | 
			
		||||
  return mktime(&tm);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cRemoteTimer::Matches(time_t t) {
 | 
			
		||||
  m_StartTime = m_StopTime = 0;
 | 
			
		||||
  if (t == 0)
 | 
			
		||||
     t = time(NULL);
 | 
			
		||||
 | 
			
		||||
  int begin  = TimeToInt(m_Start); // seconds from midnight
 | 
			
		||||
  int length = TimeToInt(m_Stop) - begin;
 | 
			
		||||
  if (length < 0)
 | 
			
		||||
     length += SECSINDAY;
 | 
			
		||||
 | 
			
		||||
  int DaysToCheck = IsSingleEvent() ? 61 : 7; // 61 to handle months with 31/30/31
 | 
			
		||||
  for (int i = -1; i <= DaysToCheck; i++) {
 | 
			
		||||
      time_t t0 = IncDay(t, i);
 | 
			
		||||
      if (DayMatches(t0)) {
 | 
			
		||||
         time_t a = SetTime(t0, begin);
 | 
			
		||||
         time_t b = a + length;
 | 
			
		||||
         if ((!m_FirstDay || a >= m_FirstDay) && t <= b) {
 | 
			
		||||
            m_StartTime = a;
 | 
			
		||||
            m_StopTime = b;
 | 
			
		||||
            break;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
  if (!m_StartTime)
 | 
			
		||||
     m_StartTime = m_FirstDay; // just to have something that's more than a week in the future
 | 
			
		||||
  else if (t > m_StartTime || t > m_FirstDay + SECSINDAY + 3600) // +3600 in case of DST change
 | 
			
		||||
     m_FirstDay = 0;
 | 
			
		||||
  return m_Active && m_StartTime <= t && t < m_StopTime; // must m_Stop *before* m_StopTime to allow adjacent timers
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cRemoteTimer::DayMatches(time_t t) {
 | 
			
		||||
  return IsSingleEvent()
 | 
			
		||||
			? GetMDay(t) == m_Day
 | 
			
		||||
			: (m_Day & (1 << GetWDay(t))) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cRemoteTimer::GetMDay(time_t t)
 | 
			
		||||
{
 | 
			
		||||
  struct tm tm_r;
 | 
			
		||||
  return localtime_r(&t, &tm_r)->tm_mday;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cRemoteTimer::GetWDay(time_t t)
 | 
			
		||||
{
 | 
			
		||||
  struct tm tm_r;
 | 
			
		||||
  int weekday = localtime_r(&t, &tm_r)->tm_wday;
 | 
			
		||||
  return weekday == 0 ? 6 : weekday - 1; // we start with monday==0!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
time_t cRemoteTimer::IncDay(time_t t, int Days) {
 | 
			
		||||
  struct tm tm_r;
 | 
			
		||||
  tm tm = *localtime_r(&t, &tm_r);
 | 
			
		||||
  tm.tm_mday += Days; // now tm_mday may be out of its valid range
 | 
			
		||||
  int h = tm.tm_hour; // save original hour to compensate for DST change
 | 
			
		||||
  tm.tm_isdst = -1;   // makes sure mktime() will determine the correct DST setting
 | 
			
		||||
  t = mktime(&tm);    // normalize all values
 | 
			
		||||
  tm.tm_hour = h;     // compensate for DST change
 | 
			
		||||
  return mktime(&tm); // calculate final result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cRemoteTimer::ToText(void) {
 | 
			
		||||
	char *summary = NULL;
 | 
			
		||||
 | 
			
		||||
	if (m_Buffer != NULL) free(m_Buffer);
 | 
			
		||||
 | 
			
		||||
	strreplace(m_File, ':', '|');
 | 
			
		||||
	if (m_Summary != "")
 | 
			
		||||
		summary = strreplace(strdup(m_Summary.c_str()), ':', '|');
 | 
			
		||||
 | 
			
		||||
	asprintf(&m_Buffer, "%d:%s:%s:%04d:%04d:%d:%d:%s:%s", m_Active, 
 | 
			
		||||
			(const char*)Channel()->GetChannelID().ToString(), PrintDay(m_Day, m_FirstDay), 
 | 
			
		||||
			m_Start, m_Stop, m_Priority, m_Lifetime, m_File, summary ? summary : "");
 | 
			
		||||
 | 
			
		||||
	if (summary != NULL)
 | 
			
		||||
		free(summary);
 | 
			
		||||
	strreplace(m_File, '|', ':');
 | 
			
		||||
	return m_Buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// --- cRemoteTimers ---------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
bool cRemoteTimers::Load(void) {
 | 
			
		||||
	Clear();
 | 
			
		||||
	return ClientSocket.LoadTimers(*this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										131
									
								
								client/remote.h
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								client/remote.h
									
									
									
									
									
								
							@@ -1,131 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: remote.h,v 1.2 2005/02/08 17:22:35 lordjaxom Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_REMOTE_H
 | 
			
		||||
#define VDR_STREAMDEV_REMOTE_H
 | 
			
		||||
 | 
			
		||||
#include <vdr/config.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
class cEventInfo;
 | 
			
		||||
#else
 | 
			
		||||
class cEvent;
 | 
			
		||||
#endif
 | 
			
		||||
class cChannel;
 | 
			
		||||
 | 
			
		||||
class cRemoteRecording: public cListObject {
 | 
			
		||||
private:
 | 
			
		||||
	bool        m_IsValid;
 | 
			
		||||
	int         m_Index;
 | 
			
		||||
	bool        m_IsNew;
 | 
			
		||||
	char       *m_TitleBuffer;
 | 
			
		||||
	std::string m_StartTime;
 | 
			
		||||
	std::string m_Name;
 | 
			
		||||
	std::string m_Summary;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cRemoteRecording(const char *Text);
 | 
			
		||||
	~cRemoteRecording();
 | 
			
		||||
	
 | 
			
		||||
	bool operator==(const cRemoteRecording &Recording);
 | 
			
		||||
	bool operator!=(const cRemoteRecording &Recording);
 | 
			
		||||
 | 
			
		||||
	void ParseInfo(const char *Text);
 | 
			
		||||
 | 
			
		||||
	bool IsValid(void) const { return m_IsValid; }
 | 
			
		||||
	int Index(void) const { return m_Index; }
 | 
			
		||||
	const char *StartTime(void) const { return m_StartTime.c_str(); }
 | 
			
		||||
	bool IsNew(void) const { return m_IsNew; }
 | 
			
		||||
	const char *Name(void) const { return m_Name.c_str(); }
 | 
			
		||||
	const char *Summary(void) const { return m_Summary.c_str(); }
 | 
			
		||||
	const char *Title(char Delimiter, bool NewIndicator, int Level);
 | 
			
		||||
	int HierarchyLevels(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool cRemoteRecording::operator!=(const cRemoteRecording &Recording) { 
 | 
			
		||||
	return !operator==(Recording); 
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class cRemoteRecordings: public cList<cRemoteRecording> {
 | 
			
		||||
public:
 | 
			
		||||
	bool Load(void);
 | 
			
		||||
	cRemoteRecording *GetByName(const char *Name);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class cRemoteTimer: public cListObject {
 | 
			
		||||
	friend class cStreamdevMenuEditTimer;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	bool            m_IsValid;
 | 
			
		||||
	int             m_Index;
 | 
			
		||||
	int             m_Active;
 | 
			
		||||
	int             m_Day;
 | 
			
		||||
	int             m_Start;
 | 
			
		||||
	int             m_Stop;
 | 
			
		||||
	time_t          m_StartTime;
 | 
			
		||||
	time_t          m_StopTime;
 | 
			
		||||
	int             m_Priority;
 | 
			
		||||
	int             m_Lifetime;
 | 
			
		||||
	char            m_File[MaxFileName];
 | 
			
		||||
	time_t          m_FirstDay;
 | 
			
		||||
	std::string     m_Summary;
 | 
			
		||||
	char           *m_Buffer;
 | 
			
		||||
	const cChannel *m_Channel;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cRemoteTimer(const char *Text);
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	cRemoteTimer(const cEventInfo *EventInfo);
 | 
			
		||||
#else
 | 
			
		||||
	cRemoteTimer(const cEvent *Event);
 | 
			
		||||
#endif
 | 
			
		||||
	cRemoteTimer(void);
 | 
			
		||||
	~cRemoteTimer();
 | 
			
		||||
 | 
			
		||||
	cRemoteTimer &operator=(const cRemoteTimer &Timer);
 | 
			
		||||
	bool operator==(const cRemoteTimer &Timer);
 | 
			
		||||
	bool operator!=(const cRemoteTimer &Timer) { return !operator==(Timer); }
 | 
			
		||||
	
 | 
			
		||||
	static int ParseDay(const char *s, time_t *FirstDay);
 | 
			
		||||
	static const char *PrintDay(int d, time_t FirstDay = 0);
 | 
			
		||||
	static time_t SetTime(time_t t, int SecondsFromMidnight);
 | 
			
		||||
	static time_t IncDay(time_t t, int Days);
 | 
			
		||||
	static int TimeToInt(int t) { return (t / 100 * 60 + t % 100) * 60; }
 | 
			
		||||
 | 
			
		||||
	const char *PrintFirstDay(void) const;
 | 
			
		||||
	void OnOff(void);
 | 
			
		||||
	bool IsSingleEvent(void) const { return (m_Day & 0x80000000) == 0; }
 | 
			
		||||
	void Skip(void) { m_FirstDay = IncDay(SetTime(StartTime(), 0), 1); }
 | 
			
		||||
	bool Matches(time_t t = 0);
 | 
			
		||||
	bool DayMatches(time_t t = 0);
 | 
			
		||||
	int GetMDay(time_t t);
 | 
			
		||||
	int GetWDay(time_t t);
 | 
			
		||||
 | 
			
		||||
	bool IsValid(void) const { return m_IsValid; }
 | 
			
		||||
	int Index(void) const { return m_Index; }
 | 
			
		||||
	int Active(void) const { return m_Active; }
 | 
			
		||||
	int Day(void) const { return m_Day; }
 | 
			
		||||
	int Start(void) const { return m_Start; }
 | 
			
		||||
	int Stop(void) const { return m_Stop; }
 | 
			
		||||
	time_t StartTime(void) { if (!m_StartTime) Matches(); return m_StartTime; }
 | 
			
		||||
	time_t StopTime(void) { if (!m_StopTime) Matches(); return m_StopTime; }
 | 
			
		||||
	int Priority(void) const { return m_Priority; }
 | 
			
		||||
	int Lifetime(void) const { return m_Lifetime; }
 | 
			
		||||
	const char *File(void) const { return m_File; }
 | 
			
		||||
	time_t FirstDay(void) const { return m_FirstDay; }
 | 
			
		||||
	const std::string &Summary(void) const { return m_Summary; }
 | 
			
		||||
	const cChannel *Channel(void) const { return m_Channel; }
 | 
			
		||||
 | 
			
		||||
	const char *ToText(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class cRemoteTimers: public cList<cRemoteTimer> {
 | 
			
		||||
public:
 | 
			
		||||
	bool Load(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern cRemoteTimers RemoteTimers;
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_REMOTE_H
 | 
			
		||||
@@ -1,22 +1,22 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: setup.c,v 1.2 2005/02/08 15:34:38 lordjaxom Exp $
 | 
			
		||||
 *  $Id: setup.c,v 1.8 2009/02/03 10:26:21 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include <vdr/menuitems.h>
 | 
			
		||||
 | 
			
		||||
#include "client/setup.h"
 | 
			
		||||
#include "client/device.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
cStreamdevClientSetup StreamdevClientSetup;
 | 
			
		||||
 | 
			
		||||
cStreamdevClientSetup::cStreamdevClientSetup(void) {
 | 
			
		||||
	StartClient   = false;
 | 
			
		||||
	RemotePort    = 2004;
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	StreamFilters = false;
 | 
			
		||||
#endif
 | 
			
		||||
	SyncEPG       = false;
 | 
			
		||||
	HideMenuEntry = false;
 | 
			
		||||
	MinPriority   = -1;
 | 
			
		||||
	MaxPriority   = MAXPRIORITY;
 | 
			
		||||
	strcpy(RemoteIp, "");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -29,10 +29,11 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
 | 
			
		||||
			strcpy(RemoteIp, Value);
 | 
			
		||||
	}
 | 
			
		||||
	else if (strcmp(Name, "RemotePort") == 0)    RemotePort = atoi(Value);
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	else if (strcmp(Name, "StreamFilters") == 0) StreamFilters = atoi(Value);
 | 
			
		||||
#endif
 | 
			
		||||
	else if (strcmp(Name, "SyncEPG") == 0)       SyncEPG = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "HideMenuEntry") == 0) HideMenuEntry = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "MinPriority") == 0)   MinPriority = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "MaxPriority") == 0)   MaxPriority = atoi(Value);
 | 
			
		||||
	else return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -40,13 +41,14 @@ bool cStreamdevClientSetup::SetupParse(const char *Name, const char *Value) {
 | 
			
		||||
cStreamdevClientMenuSetupPage::cStreamdevClientMenuSetupPage(void) {
 | 
			
		||||
	m_NewSetup = StreamdevClientSetup;
 | 
			
		||||
 | 
			
		||||
	AddBoolEdit (tr("Hide Mainmenu Entry"),m_NewSetup.HideMenuEntry);
 | 
			
		||||
	AddBoolEdit (tr("Start Client"),       m_NewSetup.StartClient);
 | 
			
		||||
	AddIpEdit   (tr("Remote IP"),          m_NewSetup.RemoteIp);
 | 
			
		||||
	AddShortEdit(tr("Remote Port"),        m_NewSetup.RemotePort);
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	AddBoolEdit (tr("Filter Streaming"),   m_NewSetup.StreamFilters);
 | 
			
		||||
#endif
 | 
			
		||||
	AddBoolEdit (tr("Synchronize EPG"),    m_NewSetup.SyncEPG);
 | 
			
		||||
	AddRangeEdit (tr("Minimum Priority"),  m_NewSetup.MinPriority, -1, MAXPRIORITY);
 | 
			
		||||
	AddRangeEdit (tr("Maximum Priority"),  m_NewSetup.MaxPriority, -1, MAXPRIORITY);
 | 
			
		||||
	SetCurrent(Get(0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -57,8 +59,6 @@ void cStreamdevClientMenuSetupPage::Store(void) {
 | 
			
		||||
	if (m_NewSetup.StartClient != StreamdevClientSetup.StartClient) {
 | 
			
		||||
		if (m_NewSetup.StartClient)
 | 
			
		||||
			cStreamdevDevice::Init();
 | 
			
		||||
		else
 | 
			
		||||
			INFO(tr("Please restart VDR to activate changes"));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	SetupStore("StartClient", m_NewSetup.StartClient);
 | 
			
		||||
@@ -67,10 +67,11 @@ void cStreamdevClientMenuSetupPage::Store(void) {
 | 
			
		||||
	else
 | 
			
		||||
		SetupStore("RemoteIp",    m_NewSetup.RemoteIp);
 | 
			
		||||
	SetupStore("RemotePort",    m_NewSetup.RemotePort);
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	SetupStore("StreamFilters", m_NewSetup.StreamFilters);
 | 
			
		||||
#endif
 | 
			
		||||
	SetupStore("SyncEPG",       m_NewSetup.SyncEPG);
 | 
			
		||||
	SetupStore("HideMenuEntry", m_NewSetup.HideMenuEntry);
 | 
			
		||||
	SetupStore("MinPriority",   m_NewSetup.MinPriority);
 | 
			
		||||
	SetupStore("MaxPriority",   m_NewSetup.MaxPriority);
 | 
			
		||||
 | 
			
		||||
	StreamdevClientSetup = m_NewSetup;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: setup.h,v 1.2 2005/02/08 15:34:38 lordjaxom Exp $
 | 
			
		||||
 *  $Id: setup.h,v 1.5 2009/01/29 07:48:59 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SETUPCLIENT_H
 | 
			
		||||
@@ -15,10 +15,11 @@ struct cStreamdevClientSetup {
 | 
			
		||||
	int  StartClient;
 | 
			
		||||
	char RemoteIp[20];
 | 
			
		||||
	int  RemotePort;
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	int  StreamFilters;
 | 
			
		||||
#endif
 | 
			
		||||
	int  SyncEPG;
 | 
			
		||||
	int  HideMenuEntry;
 | 
			
		||||
	int  MinPriority;
 | 
			
		||||
	int  MaxPriority;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern cStreamdevClientSetup StreamdevClientSetup;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										239
									
								
								client/socket.c
									
									
									
									
									
								
							
							
						
						
									
										239
									
								
								client/socket.c
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: socket.c,v 1.9 2008/03/13 16:01:17 schmirl Exp $
 | 
			
		||||
 *  $Id: socket.c,v 1.12 2008/04/08 14:18:16 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include <tools/select.h>
 | 
			
		||||
@@ -13,9 +13,7 @@
 | 
			
		||||
 | 
			
		||||
#include "client/socket.h"
 | 
			
		||||
#include "client/setup.h"
 | 
			
		||||
#include "client/remote.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
cClientSocket ClientSocket;
 | 
			
		||||
 | 
			
		||||
@@ -141,10 +139,8 @@ bool cClientSocket::CheckConnection(void) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const char *Filters = "";
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	if(Command("CAPS FILTERS", 220))
 | 
			
		||||
		Filters = ",FILTERS";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	isyslog("Streamdev: Connected to server %s:%d using capabilities TSPIDS%s",
 | 
			
		||||
	        RemoteIp().c_str(), RemotePort(), Filters);
 | 
			
		||||
@@ -270,7 +266,6 @@ bool cClientSocket::SetPid(int Pid, bool On) {
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
 | 
			
		||||
@@ -286,7 +281,6 @@ bool cClientSocket::SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On) {
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::CloseDvr(void) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
@@ -342,11 +336,7 @@ bool cClientSocket::SynchronizeEPG(void) {
 | 
			
		||||
 | 
			
		||||
	rewind(epgfd);
 | 
			
		||||
	if (cSchedules::Read(epgfd))
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
		cSIProcessor::TriggerDump();
 | 
			
		||||
#else
 | 
			
		||||
		cSchedules::Cleanup(true);
 | 
			
		||||
#endif
 | 
			
		||||
	else {
 | 
			
		||||
		esyslog("ERROR: Streamdev: Parsing EPG data failed");
 | 
			
		||||
		fclose(epgfd);
 | 
			
		||||
@@ -370,128 +360,6 @@ bool cClientSocket::Quit(void) {
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
bool cClientSocket::LoadRecordings(cRemoteRecordings &Recordings) {
 | 
			
		||||
	bool res;
 | 
			
		||||
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
	
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (!Command("LSTR"))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	std::string buffer;
 | 
			
		||||
	while ((res = Expect(250, &buffer))) {
 | 
			
		||||
		cRemoteRecording *rec = new cRemoteRecording(buffer.c_str() + 4);
 | 
			
		||||
		Dprintf("recording valid: %d\n", rec->IsValid());
 | 
			
		||||
		if (rec->IsValid())
 | 
			
		||||
			Recordings.Add(rec);
 | 
			
		||||
		else
 | 
			
		||||
			delete rec;
 | 
			
		||||
		if (buffer[3] == ' ') break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!res && buffer.substr(0, 3) != "550") {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't fetch recordings from %s:%d",
 | 
			
		||||
					RemoteIp().c_str(), RemotePort());
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (cRemoteRecording *r = Recordings.First(); r; r = Recordings.Next(r)) {
 | 
			
		||||
		std::string command = (std::string)"LSTR " + (const char*)itoa(r->Index());
 | 
			
		||||
		if (!Command(command))
 | 
			
		||||
			return false;
 | 
			
		||||
			
 | 
			
		||||
		if (Expect(250, &buffer))
 | 
			
		||||
			r->ParseInfo(buffer.c_str() + 4);
 | 
			
		||||
		else if (buffer.substr(0, 3) != "550") {
 | 
			
		||||
			if (errno == 0)
 | 
			
		||||
				esyslog("ERROR: Streamdev: Couldn't fetch details for recording from %s:%d",
 | 
			
		||||
				        RemoteIp().c_str(), RemotePort());
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		Dprintf("recording complete: %d\n", r->Index());
 | 
			
		||||
	}
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::StartReplay(const char *Filename) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
	
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
	
 | 
			
		||||
	std::string command = (std::string)"PLAY " + Filename;
 | 
			
		||||
	if (!Command(command, 220)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't replay \"%s\" from %s:%d",
 | 
			
		||||
					Filename, RemoteIp().c_str(), RemotePort());
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::AbortReplay(void) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (m_DataSockets[siReplay] != NULL) {
 | 
			
		||||
		std::string command = (std::string)"ABRT " + (const char*)itoa(siReplay);
 | 
			
		||||
		if (!Command(command, 220)) {
 | 
			
		||||
			if (errno == 0)
 | 
			
		||||
				esyslog("ERROR: Streamdev: Couldn't cleanly close data connection");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		DELETENULL(m_DataSockets[siReplay]);
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::DeleteRecording(cRemoteRecording *Recording) {
 | 
			
		||||
	bool res;
 | 
			
		||||
	cRemoteRecording *rec = NULL;
 | 
			
		||||
 | 
			
		||||
	if (!CheckConnection())
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (!Command("LSTR"))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	std::string buffer;
 | 
			
		||||
	while ((res = Expect(250, &buffer))) {
 | 
			
		||||
		if (rec == NULL) {
 | 
			
		||||
			rec = new cRemoteRecording(buffer.c_str() + 4);
 | 
			
		||||
			if (!rec->IsValid() || rec->Index() != Recording->Index())
 | 
			
		||||
				DELETENULL(rec);
 | 
			
		||||
		}
 | 
			
		||||
		if (buffer[3] == ' ') break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!res && buffer.substr(0, 3) != "550") {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't fetch recordings from %s:%d",
 | 
			
		||||
					RemoteIp().c_str(), RemotePort());
 | 
			
		||||
		if (rec != NULL) delete rec;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (rec == NULL || *rec != *Recording) {
 | 
			
		||||
		ERROR(tr("Recordings not in sync! Try again..."));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string command = (std::string)"DELR " + (const char*)itoa(Recording->Index());
 | 
			
		||||
	if (!Command(command, 250)) {
 | 
			
		||||
		ERROR(tr("Couldn't delete recording! Try again..."));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::SuspendServer(void) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
 | 
			
		||||
@@ -504,108 +372,3 @@ bool cClientSocket::SuspendServer(void) {
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::LoadTimers(cRemoteTimers &Timers) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
	
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (!Command("LSTT"))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	bool res;
 | 
			
		||||
	std::string buffer;
 | 
			
		||||
	while ((res = Expect(250, &buffer))) {
 | 
			
		||||
		cRemoteTimer *timer = new cRemoteTimer(buffer.c_str() + 4);
 | 
			
		||||
		Dprintf("timer valid: %d\n", timer->IsValid());
 | 
			
		||||
		if (timer->IsValid())
 | 
			
		||||
			Timers.Add(timer);
 | 
			
		||||
		if (buffer[3] == ' ') break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!res && buffer.substr(0, 3) != "550") {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			esyslog("ERROR: Streamdev: Couldn't fetch recordings from %s:%d",
 | 
			
		||||
					RemoteIp().c_str(), RemotePort());
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::SaveTimer(cRemoteTimer *Old, cRemoteTimer &New) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
	
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	if (New.Index() == -1) { // New timer
 | 
			
		||||
		std::string command = (std::string)"NEWT " + (const char*)New.ToText();
 | 
			
		||||
		if (!Command(command, 250)) {
 | 
			
		||||
			ERROR(tr("Couldn't save timer! Try again..."));
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	} else { // Modified timer
 | 
			
		||||
		std::string command = (std::string)"LSTT " + (const char*)itoa(New.Index());
 | 
			
		||||
		if (!Command(command))
 | 
			
		||||
			return false;
 | 
			
		||||
		
 | 
			
		||||
		std::string buffer;
 | 
			
		||||
		if (!Expect(250, &buffer)) {
 | 
			
		||||
			if (errno == 0)
 | 
			
		||||
				ERROR(tr("Timers not in sync! Try again..."));
 | 
			
		||||
			else
 | 
			
		||||
				ERROR(tr("Server error! Try again..."));
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cRemoteTimer oldstate(buffer.c_str() + 4);
 | 
			
		||||
		if (oldstate != *Old) {
 | 
			
		||||
			/*Dprintf("old timer: %d,%d,%d,%d,%d,%d,%s,%d,%s,%d\n", oldstate.m_Index,
 | 
			
		||||
					oldstate.m_Active,oldstate.m_Day,oldstate.m_Start,oldstate.m_StartTime,oldstate.m_Priority,oldstate.m_File,oldstate.m_FirstDay,(const char*)oldstate.m_Summary,oldstate.m_Channel->Number());
 | 
			
		||||
			Dprintf("new timer: %d,%d,%d,%d,%d,%d,%s,%d,%s,%d\n", Old->m_Index,
 | 
			
		||||
					Old->m_Active,Old->m_Day,Old->m_Start,Old->m_StartTime,Old->m_Priority,Old->m_File,Old->m_FirstDay,(const char*)Old->m_Summary,Old->m_Channel->Number());*/
 | 
			
		||||
			ERROR(tr("Timers not in sync! Try again..."));
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		command = (std::string)"MODT " + (const char*)itoa(New.Index()) + " " 
 | 
			
		||||
		        + (const char*)New.ToText();
 | 
			
		||||
		if (!Command(command, 250)) {
 | 
			
		||||
			ERROR(tr("Couldn't save timer! Try again..."));
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cClientSocket::DeleteTimer(cRemoteTimer *Timer) {
 | 
			
		||||
	if (!CheckConnection()) return false;
 | 
			
		||||
 | 
			
		||||
	CMD_LOCK;
 | 
			
		||||
 | 
			
		||||
	std::string command = (std::string)"LSTT " + (const char*)itoa(Timer->Index());
 | 
			
		||||
	if (!Command(command))
 | 
			
		||||
		return false;
 | 
			
		||||
	
 | 
			
		||||
	std::string buffer;
 | 
			
		||||
	if (!Expect(250, &buffer)) {
 | 
			
		||||
		if (errno == 0)
 | 
			
		||||
			ERROR(tr("Timers not in sync! Try again..."));
 | 
			
		||||
		else
 | 
			
		||||
			ERROR(tr("Server error! Try again..."));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cRemoteTimer oldstate(buffer.c_str() + 4);
 | 
			
		||||
	if (oldstate != *Timer) {
 | 
			
		||||
		ERROR(tr("Timers not in sync! Try again..."));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	command = (std::string)"DELT " + (const char*)itoa(Timer->Index());
 | 
			
		||||
	if (!Command(command, 250)) {
 | 
			
		||||
		ERROR(tr("Couldn't delete timer! Try again..."));
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: socket.h,v 1.4 2007/04/24 10:57:34 schmirl Exp $
 | 
			
		||||
 *  $Id: socket.h,v 1.6 2008/04/07 14:40:40 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_CLIENT_CONNECTION_H
 | 
			
		||||
@@ -13,10 +13,6 @@
 | 
			
		||||
 | 
			
		||||
#define CMD_LOCK cMutexLock CmdLock((cMutex*)&m_Mutex)
 | 
			
		||||
 | 
			
		||||
class cRemoteRecordings;
 | 
			
		||||
class cRemoteRecording;
 | 
			
		||||
class cRemoteTimers;
 | 
			
		||||
class cRemoteTimer;
 | 
			
		||||
class cPES2TSRemux;
 | 
			
		||||
 | 
			
		||||
class cClientSocket: public cTBSocket {
 | 
			
		||||
@@ -50,18 +46,9 @@ public:
 | 
			
		||||
	bool CloseDataConnection(eSocketId Id);
 | 
			
		||||
	bool SetChannelDevice(const cChannel *Channel);
 | 
			
		||||
	bool SetPid(int Pid, bool On);
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	bool SetFilter(ushort Pid, uchar Tid, uchar Mask, bool On);
 | 
			
		||||
#endif
 | 
			
		||||
	bool CloseDvr(void);
 | 
			
		||||
	bool SynchronizeEPG(void);
 | 
			
		||||
	bool LoadRecordings(cRemoteRecordings &Recordings);
 | 
			
		||||
	bool StartReplay(const char *Filename);
 | 
			
		||||
	bool AbortReplay(void);
 | 
			
		||||
	bool DeleteRecording(cRemoteRecording *Recording);
 | 
			
		||||
	bool LoadTimers(cRemoteTimers &Timers);
 | 
			
		||||
	bool SaveTimer(cRemoteTimer *Old, cRemoteTimer &New);
 | 
			
		||||
	bool DeleteTimer(cRemoteTimer *Timer);
 | 
			
		||||
	bool SuspendServer(void);
 | 
			
		||||
	bool Quit(void);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								common.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								common.c
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: common.c,v 1.6 2008/03/31 10:34:26 schmirl Exp $
 | 
			
		||||
 *  $Id: common.c,v 1.9 2009/01/16 11:35:43 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include <vdr/channels.h>
 | 
			
		||||
@@ -7,15 +7,16 @@
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "tools/select.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
const char *VERSION = "0.3.4";
 | 
			
		||||
const char *VERSION = "0.5.0-pre-20090611";
 | 
			
		||||
 | 
			
		||||
const char *StreamTypes[st_Count] = {
 | 
			
		||||
	"TS",
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	"PES",
 | 
			
		||||
#endif
 | 
			
		||||
	"PS",
 | 
			
		||||
	"ES",
 | 
			
		||||
	"Extern",
 | 
			
		||||
@@ -23,9 +24,9 @@ const char *StreamTypes[st_Count] = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char *SuspendModes[sm_Count] = {
 | 
			
		||||
	"Offer suspend mode",
 | 
			
		||||
	"Always suspended",
 | 
			
		||||
	"Never suspended"
 | 
			
		||||
	trNOOP("Offer suspend mode"),
 | 
			
		||||
	trNOOP("Always suspended"),
 | 
			
		||||
	trNOOP("Never suspended")
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const char IpCharacters[] = "0123456789.";
 | 
			
		||||
@@ -113,16 +114,7 @@ void cStreamdevMenuSetupPage::AddCategory(const char *Title) {
 | 
			
		||||
 | 
			
		||||
  cOsdItem *item = new cOsdItem(buffer);
 | 
			
		||||
  free(buffer);
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10307
 | 
			
		||||
#	ifdef HAVE_BEAUTYPATCH
 | 
			
		||||
  item->SetColor(clrScrolLine, clrBackground);
 | 
			
		||||
#	else
 | 
			
		||||
  item->SetColor(clrCyan, clrBackground);
 | 
			
		||||
#	endif
 | 
			
		||||
#else
 | 
			
		||||
	item->SetSelectable(false);
 | 
			
		||||
#endif
 | 
			
		||||
  item->SetSelectable(false);
 | 
			
		||||
  Add(item);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										22
									
								
								common.h
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								common.h
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: common.h,v 1.9 2008/03/12 09:36:27 schmirl Exp $
 | 
			
		||||
 *  $Id: common.h,v 1.12 2009/01/16 11:35:43 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_COMMON_H
 | 
			
		||||
@@ -23,27 +23,9 @@
 | 
			
		||||
#	define Dprintf(x...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
#	define TRANSPONDER(c1, c2) (ISTRANSPONDER(c1->Frequency(), c2->Frequency()))
 | 
			
		||||
#else
 | 
			
		||||
#	define TRANSPONDER(c1, c2) (c1->Transponder() == c2->Transponder())
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10307
 | 
			
		||||
#	define INFO(s) Interface->Info(s)
 | 
			
		||||
#	define STATUS(s) Interface->Status(s)
 | 
			
		||||
#	define ERROR(s) Interface->Status(s)
 | 
			
		||||
#	define FLUSH() Interface->Flush()
 | 
			
		||||
#else
 | 
			
		||||
#	define INFO(s) Skins.Message(mtInfo, s)
 | 
			
		||||
#	define STATUS(s) Skins.Message(mtInfo, s)
 | 
			
		||||
#	define ERROR(s) Skins.Message(mtStatus, s)
 | 
			
		||||
#	define FLUSH() Skins.Flush()
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10336
 | 
			
		||||
#	define MAXPARSEBUFFER KILOBYTE(16)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Check if a channel is a radio station. */
 | 
			
		||||
#define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff)
 | 
			
		||||
@@ -69,7 +51,9 @@ const cChannel *ChannelFromString(const char *String, int *Apid = NULL);
 | 
			
		||||
 | 
			
		||||
enum eStreamType {
 | 
			
		||||
	stTS,
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	stPES,
 | 
			
		||||
#endif
 | 
			
		||||
	stPS,
 | 
			
		||||
	stES,
 | 
			
		||||
	stExtern,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										831
									
								
								i18n.c
									
									
									
									
									
								
							
							
						
						
									
										831
									
								
								i18n.c
									
									
									
									
									
								
							@@ -1,831 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: i18n.c,v 1.5 2006/08/17 09:26:00 thomas Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
const char *i18n_name = NULL;
 | 
			
		||||
 | 
			
		||||
const tI18nPhrase Phrases[] = {
 | 
			
		||||
	{	"VDR Streaming Server",	// English
 | 
			
		||||
		"VDR Streaming Server",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"VDR-suoratoistopalvelin",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika / Greek
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"VTP Streaming Client",	// English
 | 
			
		||||
		"VTP Streaming Client",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"VTP-suoratoistoasiakas ",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika / Greek
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Start VDR-to-VDR Server",// English
 | 
			
		||||
		"VDR-zu-VDR Server starten",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Avvia il Server VDR-toVDR",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"K<EFBFBD>ynnist<EFBFBD> VDR-palvelin",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika / Greek
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Start HTTP Server",		// English
 | 
			
		||||
		"HTTP Server starten",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Avvia il Server HTTP", // Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"K<EFBFBD>ynnist<EFBFBD> HTTP-palvelin",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"HTTP Streamtype",		  // English
 | 
			
		||||
		"HTTP Streamtyp",	      // Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Tipo di Stream HTTP",  // Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"HTTP-l<>hetysmuoto",									// Suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Start Client",					// English
 | 
			
		||||
		"Client starten",				// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Avvia il Client",			// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"K<EFBFBD>ynnist<EFBFBD> VDR-asiakas",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"VDR-to-VDR Server Port",// English
 | 
			
		||||
		"Port des VDR-zu-VDR Servers",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Porta del Server VDR-to-VDR",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"VDR-palvelimen portti",								// Suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"HTTP Server Port",			// English
 | 
			
		||||
		"Port des HTTP Servers",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Porta del Server HTTP",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"HTTP-palvelimen portti",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Maximum Number of Clients",// English
 | 
			
		||||
		"Maximalanzahl an Clients",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Numero Massimo di Client",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Suurin sallittu asiakkaiden m<><6D>r<EFBFBD>",							// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Remote IP",						// English
 | 
			
		||||
		"IP der Gegenseite",		// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Indirizzo IP del Server",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Et<EFBFBD>koneen IP-osoite",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Remote Port",					// English
 | 
			
		||||
		"Port der Gegenseite",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Porta del Server Remoto",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Et<EFBFBD>koneen portti",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Remote Streamtype",		// English
 | 
			
		||||
		"Streamtyp von Gegenseite",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Tipo di Stream",       // Italiano (oppure Flusso ?)
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Et<EFBFBD>koneen l<>hetysmuoto",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Common Settings",		  // English
 | 
			
		||||
		"Allgemeines",          // Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Settaggi Comuni",			// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Yleiset asetukset",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"VDR-to-VDR Server",		// English
 | 
			
		||||
		"VDR-zu-VDR Server",    // Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Server VDR-to-VDR",		// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"VDR-palvelin",										// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"HTTP Server",		      // English
 | 
			
		||||
		"HTTP Server",          // Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Server HTTP",					// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"HTTP-palvelin",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"VDR-to-VDR Client",		// English
 | 
			
		||||
		"VDR-zu-VDR Client",    // Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Client VDR-to-VDR",		// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"VDR-asiakas",										// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Please restart VDR to activate changes",// English
 | 
			
		||||
		"Bitte starten Sie f<>r die <20>nderungen VDR neu",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"Riavviare VDR per attivare i cambiamenti",// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Aktivoi muutokset k<>ynnist<73>m<EFBFBD>ll<6C> VDR uudelleen",					// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Synchronize EPG",			// English
 | 
			
		||||
		"EPG synchronisieren",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"P<EFBFBD>ivit<EFBFBD> ohjelmaopas",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Suspend Live TV",			// English
 | 
			
		||||
		"Live-TV pausieren",		// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Pys<EFBFBD>yt<EFBFBD> suora TV-l<>hetys",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Suspend behaviour",		// English
 | 
			
		||||
		"Pausierverhalten",			// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Pys<EFBFBD>ytystoiminto",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Offer suspend mode",		// English
 | 
			
		||||
		"Pausieren anbieten",		// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"tyrkyt<EFBFBD>",										// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Always suspended",			// English
 | 
			
		||||
		"Immer pausiert",				// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"aina",											// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Never suspended",			// English
 | 
			
		||||
		"Nie pausiert",					// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"ei koskaan",										// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Streaming Control",		// English
 | 
			
		||||
		"Streamkontrolle",			// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Suoratoiston hallinta",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Fetching recordings...",// English
 | 
			
		||||
		"Hole Aufnahmen...",		// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Haetaan tallenteita...",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Remote Recordings",		// English
 | 
			
		||||
		"Entfernte Aufnahmen",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Et<EFBFBD>tallenteet",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Remote Timers",				// English
 | 
			
		||||
		"Entfernte Timer",			// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Et<EFBFBD>ajastimet",										// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Suspend Server",				// English
 | 
			
		||||
		"Server pausieren",			// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Pys<EFBFBD>yt<EFBFBD> palvelin",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Server is suspended",	// English
 | 
			
		||||
		"Server ist pausiert",	// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Palvelin on pys<79>ytetty",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Couldn't suspend Server!",// English
 | 
			
		||||
		"Konnte Server nicht pausieren!",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Palvelinta ei onnistuttu pys<79>ytt<74>m<EFBFBD><6D>n!",						// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Edit remote timer",		// English
 | 
			
		||||
		"Entfernten Timer editieren",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Muokkaa et<65>ajastinta",									// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Timers not in sync! Try again...",// Englisch
 | 
			
		||||
		"Timer nicht synchron! Bitte wiederholen...",//Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Ajastimet eiv<69>t t<>sm<73><6D>! Yrit<69> uudelleen...",						// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Couldn't save timer! Try again...",// English
 | 
			
		||||
		"Konnte Timer nicht speichern! Bitte wiederholen...",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Ajastimen tallennus ep<65>onnistui! Yrit<69> uudelleen...",					// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Couldn't delete timer! Try again...",// English
 | 
			
		||||
		"Konnte Timer nicht l<>schen! Bitte wiederholen...",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Ajastimen poistaminen ep<65>onnistui! Yrit<69> uudelleen...",				// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Server error! Try again...",// English
 | 
			
		||||
		"Serverfehler! Bitte wiederholen...",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Palvelimessa virhe! Yrit<69> uudelleen...",						// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"MultiPID Streaming",		// English
 | 
			
		||||
		"Multiple PIDs streamen",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Usean PID:in suoratoisto",								// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
	{	"Client may suspend",		// English
 | 
			
		||||
		"Client darf pausieren",// Deutsch
 | 
			
		||||
		"",											// Slovenski
 | 
			
		||||
		"",											// Italiano
 | 
			
		||||
		"",											// Nederlands
 | 
			
		||||
		"",											// Portugu<67>s
 | 
			
		||||
		"",											// Fran<61>ais
 | 
			
		||||
		"",											// Norsk
 | 
			
		||||
		"Asiakas saa pys<79>ytt<74><74> palvelimen",							// suomi
 | 
			
		||||
		"",											// Polski
 | 
			
		||||
		"",											// Espa<70>ol
 | 
			
		||||
		"",											// Ellinika
 | 
			
		||||
		"",											// Svenska
 | 
			
		||||
		"",											// Romaneste
 | 
			
		||||
		"",											// Magyar
 | 
			
		||||
		"",											// Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
	},
 | 
			
		||||
        {       "Bind to IP",           // English
 | 
			
		||||
                "",// Deutsch
 | 
			
		||||
                "",                                                                                     // Slovenski
 | 
			
		||||
                "",                                                                                     // Italiano
 | 
			
		||||
                "",                                                                                     // Nederlands
 | 
			
		||||
                "",                                                                                     // Portugu<67>s
 | 
			
		||||
                "",                                                                                     // Fran<61>ais
 | 
			
		||||
                "",                                                                                     // Norsk
 | 
			
		||||
                "Sido osoitteeseen",                                                                    // suomi
 | 
			
		||||
                "",                                                                                     // Polski
 | 
			
		||||
                "",                                                                                     // Espa<70>ol
 | 
			
		||||
                "",                                                                                     // Ellinika
 | 
			
		||||
                "",                                                                                     // Svenska
 | 
			
		||||
                "",                                                                                     // Romaneste
 | 
			
		||||
                "",                                                                                     // Magyar
 | 
			
		||||
                "",                                                                                     // Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
                ""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
        },
 | 
			
		||||
        {       "Remote Schedule",      // English
 | 
			
		||||
                "",// Deutsch
 | 
			
		||||
                "",                                                                                     // Slovenski
 | 
			
		||||
                "",                                                                                     // Italiano
 | 
			
		||||
                "",                                                                                     // Nederlands
 | 
			
		||||
                "",                                                                                     // Portugu<67>s
 | 
			
		||||
                "",                                                                                     // Fran<61>ais
 | 
			
		||||
                "",                                                                                     // Norsk
 | 
			
		||||
                "Et<EFBFBD>koneen ohjelmaopas",                                                                // suomi
 | 
			
		||||
                "",                                                                                     // Polski
 | 
			
		||||
                "",                                                                                     // Espa<70>ol
 | 
			
		||||
                "",                                                                                     // Ellinika
 | 
			
		||||
                "",                                                                                     // Svenska
 | 
			
		||||
                "",                                                                                     // Romaneste
 | 
			
		||||
                "",                                                                                     // Magyar
 | 
			
		||||
                "",                                                                                     // Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
                ""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
        },
 | 
			
		||||
        {       "Filter Streaming",     // English
 | 
			
		||||
                "",// Deutsch
 | 
			
		||||
                "",                                                                                     // Slovenski
 | 
			
		||||
                "",                                                                                     // Italiano
 | 
			
		||||
                "",                                                                                     // Nederlands
 | 
			
		||||
                "",                                                                                     // Portugu<67>s
 | 
			
		||||
                "",                                                                                     // Fran<61>ais
 | 
			
		||||
                "",                                                                                     // Norsk
 | 
			
		||||
                "Suodatetun tiedon suoratoisto",                                                        // suomi
 | 
			
		||||
                "",                                                                                     // Polski
 | 
			
		||||
                "",                                                                                     // Espa<70>ol
 | 
			
		||||
                "",                                                                                     // Ellinika
 | 
			
		||||
                "",                                                                                     // Svenska
 | 
			
		||||
                "",                                                                                     // Romaneste
 | 
			
		||||
                "",                                                                                     // Magyar
 | 
			
		||||
                "",                                                                                     // Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
                ""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
        },
 | 
			
		||||
        {       "Streaming active",     // English
 | 
			
		||||
                "Streamen im Gange",// Deutsch
 | 
			
		||||
                "",                                                                                     // Slovenski
 | 
			
		||||
                "",                                                                                     // Italiano
 | 
			
		||||
                "",                                                                                     // Nederlands
 | 
			
		||||
                "",                                                                                     // Portugu<67>s
 | 
			
		||||
                "",                                                                                     // Fran<61>ais
 | 
			
		||||
                "",                                                                                     // Norsk
 | 
			
		||||
                "Suoratoistopalvelin aktiivinen", // suomi
 | 
			
		||||
                "",                                                                                     // Polski
 | 
			
		||||
                "",                                                                                     // Espa<70>ol
 | 
			
		||||
                "",                                                                                     // Ellinika
 | 
			
		||||
                "",                                                                                     // Svenska
 | 
			
		||||
                "",                                                                                     // Romaneste
 | 
			
		||||
                "",                                                                                     // Magyar
 | 
			
		||||
                "",                                                                                     // Catala
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
                ""                      // Russian
 | 
			
		||||
#endif
 | 
			
		||||
        },
 | 
			
		||||
	{ NULL }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										16
									
								
								i18n.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								i18n.h
									
									
									
									
									
								
							@@ -1,16 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: i18n.h,v 1.1.1.1 2004/12/30 22:43:58 lordjaxom Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_I18N_H
 | 
			
		||||
#define VDR_STREAMDEV_I18N_H
 | 
			
		||||
 | 
			
		||||
#include <vdr/i18n.h>
 | 
			
		||||
 | 
			
		||||
extern const char *i18n_name;
 | 
			
		||||
extern const tI18nPhrase Phrases[];
 | 
			
		||||
 | 
			
		||||
#undef tr
 | 
			
		||||
#define tr(s) I18nTranslate(s, i18n_name)
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_I18N_H
 | 
			
		||||
@@ -1,446 +0,0 @@
 | 
			
		||||
#ifndef _DVB_DEV_HH_
 | 
			
		||||
#define _DVB_DEV_HH_
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include <asm/errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <netdb.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <sys/ioctl.h>
 | 
			
		||||
#include <sys/poll.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#define NEWSTRUCT
 | 
			
		||||
#include <channel.h>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
#include <osd.hh>
 | 
			
		||||
#include <devices.hh>
 | 
			
		||||
 | 
			
		||||
#ifndef MAXNAM
 | 
			
		||||
#define MAXNAM 80
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define FRONT_DVBS 1
 | 
			
		||||
#define FRONT_DVBC 2
 | 
			
		||||
#define FRONT_DVBT 3
 | 
			
		||||
 | 
			
		||||
#define VTXDIR "/var/vtx"
 | 
			
		||||
 | 
			
		||||
#define DEC(N) dec << setw(N) << setfill('0') 
 | 
			
		||||
#define HEX(N) hex << setw(N) << setfill('0') 
 | 
			
		||||
 | 
			
		||||
#define MAXSECSIZE 4096
 | 
			
		||||
 | 
			
		||||
#define NK 10
 | 
			
		||||
enum {LNB=0,DIS,ROTOR,TRANS,CHAN,BOU,SAT,PICS,SWI,NTW};
 | 
			
		||||
static const int nums[]={LNB,DIS,ROTOR,TRANS,CHAN,BOU,SAT,PICS,SWI,NTW};
 | 
			
		||||
static const int maxs[]={ 32, 32,   32,  512,16384,512,100, 50, 10, 100};
 | 
			
		||||
 | 
			
		||||
#define MAX_TRANS_CHAN  1024
 | 
			
		||||
 | 
			
		||||
enum{DVB_ORIG=0, DVB_NOKIA, DVB_XML, DVB_SATCO};
 | 
			
		||||
 | 
			
		||||
typedef struct frontend_stat_s{
 | 
			
		||||
	fe_status_t status;
 | 
			
		||||
	uint16_t snr;
 | 
			
		||||
	uint16_t strength;
 | 
			
		||||
	uint32_t ber;
 | 
			
		||||
	uint32_t u_blocks;
 | 
			
		||||
} frontend_stat;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
extern uint8_t hamtab[256];
 | 
			
		||||
extern uint8_t invtab[256];
 | 
			
		||||
 | 
			
		||||
#define MAX_MAG 8
 | 
			
		||||
typedef struct mag_struct_ {
 | 
			
		||||
        int valid;
 | 
			
		||||
        int magn;
 | 
			
		||||
        uint8_t flags;
 | 
			
		||||
        uint8_t lang;
 | 
			
		||||
        int pnum,sub;
 | 
			
		||||
        uint8_t pagebuf[25*40];
 | 
			
		||||
} magazin_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class DVB {
 | 
			
		||||
public:
 | 
			
		||||
	int no_open;
 | 
			
		||||
	int fd_frontend;
 | 
			
		||||
	int fd_demuxa;
 | 
			
		||||
	int fd_demuxv;
 | 
			
		||||
	int fd_demuxpcr;
 | 
			
		||||
	int fd_demuxtt;
 | 
			
		||||
        int fdvb;
 | 
			
		||||
 | 
			
		||||
	int minor;
 | 
			
		||||
	int adapter;
 | 
			
		||||
	int max_tpid;
 | 
			
		||||
	int max_satid;
 | 
			
		||||
	int max_chanid;
 | 
			
		||||
	
 | 
			
		||||
	frontend_stat festat;
 | 
			
		||||
 | 
			
		||||
	struct dvb_diseqc_master_cmd dcmd;
 | 
			
		||||
	fe_sec_tone_mode_t tone;
 | 
			
		||||
	fe_sec_voltage_t voltage;
 | 
			
		||||
        int burst;
 | 
			
		||||
 	struct dmx_pes_filter_params pesFilterParamsV; 
 | 
			
		||||
	struct dmx_pes_filter_params pesFilterParamsA; 
 | 
			
		||||
	struct dmx_pes_filter_params pesFilterParamsP; 
 | 
			
		||||
	struct dmx_pes_filter_params pesFilterParamsTT; 
 | 
			
		||||
	struct dvb_frontend_parameters front_param;
 | 
			
		||||
        int front_type;
 | 
			
		||||
	int dvr_enabled;
 | 
			
		||||
        OSD osd;
 | 
			
		||||
	uint32_t transponder_freq;
 | 
			
		||||
	char transponder_pol;
 | 
			
		||||
	uint32_t transponder_srate;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	fe_status_t status;
 | 
			
		||||
	uint32_t ber, uncorrected_blocks;
 | 
			
		||||
	uint16_t snr, signal;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        struct Lnb *lnbs;
 | 
			
		||||
        struct DiSEqC *diseqcs;
 | 
			
		||||
        struct Rotor *rotors;
 | 
			
		||||
        struct Transponder *tps;
 | 
			
		||||
        struct Channel *chans;
 | 
			
		||||
        struct Bouquet *bouqs;
 | 
			
		||||
        struct Sat *sats;
 | 
			
		||||
        struct Picture *pics;
 | 
			
		||||
        struct Switch *swis;
 | 
			
		||||
        struct Network *ntws;
 | 
			
		||||
        int num[NK];
 | 
			
		||||
	int oldsec;
 | 
			
		||||
	int tryit;
 | 
			
		||||
	int oldpol;
 | 
			
		||||
 | 
			
		||||
	char *vtxdir;
 | 
			
		||||
	magazin_t magazin[MAX_MAG]; 
 | 
			
		||||
 | 
			
		||||
	DVB(){
 | 
			
		||||
		no_open = 0;
 | 
			
		||||
		max_tpid = 0;
 | 
			
		||||
		max_satid = 0;
 | 
			
		||||
		max_chanid = 0;
 | 
			
		||||
		minor = 0;
 | 
			
		||||
 | 
			
		||||
		fd_frontend = -1;
 | 
			
		||||
		fd_demuxa = -1;
 | 
			
		||||
		fd_demuxpcr = -1;
 | 
			
		||||
		fd_demuxv = -1;
 | 
			
		||||
		fd_demuxtt = -1;
 | 
			
		||||
		fdvb = -1;
 | 
			
		||||
		vtxdir = NULL;
 | 
			
		||||
		transponder_freq=0;
 | 
			
		||||
		transponder_pol=0;
 | 
			
		||||
		transponder_srate=0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	DVB(int i){
 | 
			
		||||
		if (i >= 0) 
 | 
			
		||||
			no_open = 0;
 | 
			
		||||
		else 
 | 
			
		||||
			no_open = 1;
 | 
			
		||||
		max_tpid = 0;
 | 
			
		||||
		max_satid = 0;
 | 
			
		||||
		max_chanid = 0;
 | 
			
		||||
	
 | 
			
		||||
		fd_frontend = -1;
 | 
			
		||||
		fd_demuxa = -1;
 | 
			
		||||
		fd_demuxpcr = -1;
 | 
			
		||||
		fd_demuxv = -1;
 | 
			
		||||
		fd_demuxtt = -1;
 | 
			
		||||
		fdvb = -1;
 | 
			
		||||
		vtxdir = NULL;
 | 
			
		||||
		transponder_freq=0;
 | 
			
		||||
		transponder_pol=0;
 | 
			
		||||
		transponder_srate=0;
 | 
			
		||||
 | 
			
		||||
	        init("","",i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        DVB(char *a, char *b) {
 | 
			
		||||
		max_tpid = 0;
 | 
			
		||||
		max_satid = 0;
 | 
			
		||||
		max_chanid = 0;
 | 
			
		||||
	
 | 
			
		||||
		fd_frontend = -1;
 | 
			
		||||
		fd_demuxa = -1;
 | 
			
		||||
		fd_demuxpcr = -1;
 | 
			
		||||
		fd_demuxv = -1;
 | 
			
		||||
		fd_demuxtt = -1;
 | 
			
		||||
 | 
			
		||||
		fdvb = -1;
 | 
			
		||||
		vtxdir = NULL;
 | 
			
		||||
	        init(a,b,0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~DVB();
 | 
			
		||||
  
 | 
			
		||||
	void use_osd(int fd = -1){
 | 
			
		||||
		char dvn[32];
 | 
			
		||||
		if (no_open) return;
 | 
			
		||||
		if (fd < 0) fd = 0;
 | 
			
		||||
		sprintf(dvn,OSD_DEV,adapter,fd);
 | 
			
		||||
		fdvb = open(dvn, O_RDWR);
 | 
			
		||||
		
 | 
			
		||||
		if (fdvb >= 0){
 | 
			
		||||
			cerr << dvn <<  " for OSD" << endl;
 | 
			
		||||
			osd.init(fdvb);
 | 
			
		||||
		} else perror("osd");
 | 
			
		||||
		osd.Open(80, 500, 640, 540, 2, 0, 2);
 | 
			
		||||
		osd.SetColor(0, 0, 0, 0, 255);
 | 
			
		||||
		osd.SetColor(1, 240, 240, 240, 255);
 | 
			
		||||
		osd.Show();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void set_vtxdir(char *newname){
 | 
			
		||||
		if (!newname) return;
 | 
			
		||||
		if (vtxdir) free(vtxdir);
 | 
			
		||||
		vtxdir = (char *) malloc(sizeof(char)*(strlen(newname)+1));
 | 
			
		||||
		if (vtxdir)
 | 
			
		||||
			strncpy(vtxdir, newname, strlen(newname));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void close_osd(){
 | 
			
		||||
		osd.Close(fdvb);
 | 
			
		||||
		close(fdvb);
 | 
			
		||||
	}
 | 
			
		||||
  
 | 
			
		||||
	int DVR_enabled(){
 | 
			
		||||
		if (no_open) return -1;
 | 
			
		||||
		return dvr_enabled;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void enable_DVR(){
 | 
			
		||||
		if (no_open) return;
 | 
			
		||||
		dvr_enabled = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void enable_DVR_other(){
 | 
			
		||||
		if (no_open) return;
 | 
			
		||||
		dvr_enabled = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void disable_DVR(){
 | 
			
		||||
		if (no_open) return;
 | 
			
		||||
		dvr_enabled = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        void init(char *a="/dev/video0", char *b="/dev/vbi0",int adapt=0,
 | 
			
		||||
		  int minor = 0); 
 | 
			
		||||
		  
 | 
			
		||||
 | 
			
		||||
	inline void init(char *a, char *b){
 | 
			
		||||
		if (no_open) return;
 | 
			
		||||
		init(a,b,0,0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int check_frontend();
 | 
			
		||||
 | 
			
		||||
	void set_apid(ushort apid);
 | 
			
		||||
	void set_vpid(ushort vpid); 
 | 
			
		||||
	void set_pcrpid(ushort vpid); 
 | 
			
		||||
	void set_ttpid(ushort ttpid); 
 | 
			
		||||
        int set_apid_fd(ushort apid, int fd);
 | 
			
		||||
        int set_vpid_fd(ushort vpid, int fd);
 | 
			
		||||
        int set_ttpid_fd(ushort ttpid, int fd);
 | 
			
		||||
        int set_pcrpid_fd(ushort pcrpid, int fd);
 | 
			
		||||
        int set_otherpid_fd(ushort otherpid, int fd);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        int set_lnb(int dis);
 | 
			
		||||
	void set_diseqc_nb(int nr); 
 | 
			
		||||
	int set_front(void); 
 | 
			
		||||
	void get_front(void); 
 | 
			
		||||
 | 
			
		||||
	void scan_pf_eit(int chnr,
 | 
			
		||||
			 int (*callback)(uint8_t *data, int l, int pnr, 
 | 
			
		||||
					  int c_n, uint8_t *t));
 | 
			
		||||
 | 
			
		||||
	void scan_pf_eit(Channel *chan, 
 | 
			
		||||
			 int (*callback)(uint8_t *data, int l, int pnr, 
 | 
			
		||||
					  int c_n, uint8_t *t));
 | 
			
		||||
	void scan_pf_eit(int chnr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	int search_in_TP(Transponder &tp, int show=1, int verbose=0);
 | 
			
		||||
	int search_in_TP(uint16_t tpid, uint16_t satid, int show=1,
 | 
			
		||||
			 int verbose=0);
 | 
			
		||||
	int scan_TP(uint16_t tpid, uint16_t satid, int timeout=-1, int verbose=0);
 | 
			
		||||
 | 
			
		||||
	int GetSection(uint8_t *buf, 
 | 
			
		||||
		       uint16_t PID, uint8_t TID, uint16_t TIDExt, 
 | 
			
		||||
		       uint16_t FilterTIDExt, 
 | 
			
		||||
		       uint8_t secnum, uint8_t &msecnum);
 | 
			
		||||
	int GetSection(uint8_t *buf, 
 | 
			
		||||
		       uint16_t PID, uint8_t *filter, uint8_t *mask,
 | 
			
		||||
		       uint8_t secnum, uint8_t &msecnum); 
 | 
			
		||||
	int GetSection(uint8_t *buf, ushort PID, uint8_t sec,
 | 
			
		||||
		       uint8_t secnum, uint8_t &msecnum); 
 | 
			
		||||
	int SetFilter(uint16_t pid, uint8_t *filter, 
 | 
			
		||||
		      uint8_t *mask,
 | 
			
		||||
		      uint32_t timeout, uint32_t flags); 
 | 
			
		||||
	uint16_t SetFilter(uint16_t pid, uint16_t section, uint16_t mode); 
 | 
			
		||||
	int CloseFilter(int h);
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	void bar2(int x, int y, int w, int h, int val, int col1, int col2);
 | 
			
		||||
 | 
			
		||||
        int SetTP(unsigned int, unsigned int);
 | 
			
		||||
        int scan(void);
 | 
			
		||||
        int scan_all_tps(void);
 | 
			
		||||
        int scan_lnb(struct Lnb &);
 | 
			
		||||
        int scan_cable(Sat &sat);
 | 
			
		||||
        int scan_sat(struct Sat &);
 | 
			
		||||
        int scan_tp(struct Transponder &);
 | 
			
		||||
 | 
			
		||||
        int AddLNB(int id, int t, uint l1, uint l2, uint sl,
 | 
			
		||||
		   int dnr, int dis, int sw);
 | 
			
		||||
	int AddSat(Sat &sat);
 | 
			
		||||
        int AddSat(int satid, unsigned int lnbid, char *name, uint fmin, uint fmax);
 | 
			
		||||
        int AddTP(Transponder &tp);
 | 
			
		||||
        int AddChannel(Channel &chan);
 | 
			
		||||
	int parse_descriptor(Channel *chan, uint8_t *data, int length);
 | 
			
		||||
	int parse_pmt(Channel *chan, uint8_t *data);
 | 
			
		||||
	int parse_pat(Channel *chan, uint8_t *data);
 | 
			
		||||
 | 
			
		||||
	int check_pids(Channel *chan);
 | 
			
		||||
	void check_all_pids();
 | 
			
		||||
	void scan_sdt(Channel *chan);
 | 
			
		||||
	int scan_sdts(int *chs, int n);
 | 
			
		||||
 | 
			
		||||
        int channel_num(void) {
 | 
			
		||||
	        return num[CHAN];
 | 
			
		||||
	};
 | 
			
		||||
	  
 | 
			
		||||
        int channel_change(int n) {
 | 
			
		||||
	        return 0;
 | 
			
		||||
	};
 | 
			
		||||
        int SetChannel(uint16_t, uint16_t, uint16_t, uint16_t);
 | 
			
		||||
	int SetChannel(Channel *chan,  char* apref=NULL, uint16_t *apidp=NULL, 
 | 
			
		||||
		       uint16_t *vpidp=NULL) ;
 | 
			
		||||
        int SetChannel(int chnr, char *apref=NULL, uint16_t *apidp=NULL, 
 | 
			
		||||
		       uint16_t *vpidp=NULL);
 | 
			
		||||
        int GetChannel(int chnr, struct channel *);
 | 
			
		||||
        int NumChannel(void) {
 | 
			
		||||
	        return num[CHAN];
 | 
			
		||||
	}
 | 
			
		||||
	int tune_it(struct dvb_frontend_parameters *qpsk);
 | 
			
		||||
	void find_satid(Channel &chan);
 | 
			
		||||
	int check_input_format(istream &ins);
 | 
			
		||||
	void read_original(istream &ins);
 | 
			
		||||
	int get_all_progs(uint16_t *progbuf, uint16_t *pnrbuf, int length);
 | 
			
		||||
	uint16_t find_pnr(uint16_t vpid, uint16_t apid);
 | 
			
		||||
	int get_pids(uint16_t prog_pid, uint16_t *vpid, uint16_t *apids, 
 | 
			
		||||
		     uint16_t *ttpid, uint8_t *apids_name=NULL);
 | 
			
		||||
	void AddECM(Channel *chan, uint8_t *data, int length);
 | 
			
		||||
	int check_ecm(Channel *chan);
 | 
			
		||||
	void add_vtx_line(magazin_t *mag, int line, uint8_t *data, int pnr);
 | 
			
		||||
	
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, DVB &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, DVB &x);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define NOKIA_MAX_SAT 4
 | 
			
		||||
class nokiaconv{
 | 
			
		||||
public:
 | 
			
		||||
	DVB *dvb;
 | 
			
		||||
	struct lnb_sat_l{
 | 
			
		||||
		int n;
 | 
			
		||||
		int diseqc[NOKIA_MAX_SAT];
 | 
			
		||||
		char sat_names[NOKIA_MAX_SAT][MAXNAM+1];
 | 
			
		||||
		int satid[NOKIA_MAX_SAT];
 | 
			
		||||
	} lnb_sat;
 | 
			
		||||
 | 
			
		||||
	nokiaconv(DVB *d){
 | 
			
		||||
		dvb = d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        friend istream &operator>>(istream &stream, nokiaconv &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define XML_MAX_SAT 4
 | 
			
		||||
class xmlconv{
 | 
			
		||||
public:
 | 
			
		||||
	DVB *dvb;
 | 
			
		||||
	struct lnb_sat_l{
 | 
			
		||||
		int n;
 | 
			
		||||
		int diseqc[XML_MAX_SAT];
 | 
			
		||||
		char sat_names[XML_MAX_SAT][MAXNAM+1];
 | 
			
		||||
		int satid[XML_MAX_SAT];
 | 
			
		||||
	} lnb_sat;
 | 
			
		||||
 | 
			
		||||
	xmlconv(DVB *d){
 | 
			
		||||
		dvb = d;
 | 
			
		||||
	}
 | 
			
		||||
	int read_stream(istream &ins, int nchan);
 | 
			
		||||
	int read_desc(istream &ins, int nchan);
 | 
			
		||||
	int read_serv(istream &ins, int ctp, int csat);
 | 
			
		||||
	int read_trans(istream &ins, int satid);
 | 
			
		||||
	int read_sat(istream &ins, int satid = -1);
 | 
			
		||||
	int skip_tag(istream &ins, char *tag);
 | 
			
		||||
	int read_iso639(istream &ins, int nchan, int apids);
 | 
			
		||||
 | 
			
		||||
        friend istream &operator>>(istream &stream, xmlconv &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define SATCO_MAX_SAT 10
 | 
			
		||||
class satcoconv{
 | 
			
		||||
public:
 | 
			
		||||
	DVB *dvb;
 | 
			
		||||
	int nlnb;
 | 
			
		||||
 | 
			
		||||
	satcoconv(DVB *d){
 | 
			
		||||
		dvb = d;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        friend istream &operator>>(istream &stream, satcoconv &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void hdump(uint8_t *buf, int n);
 | 
			
		||||
int get_dvbrc(char *path, DVB &dv, int dev, int len);
 | 
			
		||||
int set_dvbrc(char *path, DVB &dv, int dev, int len);
 | 
			
		||||
void dvb2txt(char *out, char *in, int len);
 | 
			
		||||
int set_sfront(int fdf, uint32_t freq, uint32_t pol, uint32_t sr , int snum, fe_code_rate_t fec);
 | 
			
		||||
void set_pes_filt(int fd,uint16_t pes_pid);
 | 
			
		||||
void set_diseqc(int fdf, int snum, fe_sec_voltage_t v, fe_sec_tone_mode_t t);
 | 
			
		||||
int tune(int fdf, uint32_t freq, uint32_t sr, fe_code_rate_t fec);
 | 
			
		||||
int set_sfront(int fdf, uint32_t freq, uint32_t pol, uint32_t sr , int snum, 
 | 
			
		||||
	       fe_code_rate_t fec);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct in_addr getaddress (const char *name);
 | 
			
		||||
int tcp_client_connect(const char *hostname, int sckt);
 | 
			
		||||
int udp_client_connect(const char *filename);
 | 
			
		||||
void client_send_msg(int fd, uint8_t *msg, int size);
 | 
			
		||||
int chck_frontend (int fefd, frontend_stat *festat);
 | 
			
		||||
 | 
			
		||||
uint8_t deham(uint8_t x, uint8_t y);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,14 +1,12 @@
 | 
			
		||||
INCS   = -I.
 | 
			
		||||
CFLAGS =  -g -Wall -O2 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -fPIC
 | 
			
		||||
MFLAG  = -M
 | 
			
		||||
OBJS = ctools.o ringbuffy.o remux.o transform.o cpptools.o
 | 
			
		||||
OBJS = ctools.o ringbuffy.o remux.o transform.o
 | 
			
		||||
SRC  = $(wildcard *.c)
 | 
			
		||||
CPPSRC = $(wildcard *.cpp)
 | 
			
		||||
CSRC = $(wildcard *.cc) 
 | 
			
		||||
 | 
			
		||||
DESTDIR = /usr/local
 | 
			
		||||
 | 
			
		||||
.PHONY: depend clean install uninstall
 | 
			
		||||
.PHONY: clean
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	- rm -f *.o  *~ *.a .depend
 | 
			
		||||
@@ -16,17 +14,11 @@ clean:
 | 
			
		||||
libdvbmpegtools.a: $(OBJS)
 | 
			
		||||
	ar -rcs libdvbmpegtools.a $(OBJS) 
 | 
			
		||||
 | 
			
		||||
%.o:    %.cc 
 | 
			
		||||
	$(CXX) -c $(CFLAGS) $(INCS) $(DEFINES) $<
 | 
			
		||||
 | 
			
		||||
%.o:    %.cpp
 | 
			
		||||
	$(CXX) -c $(CFLAGS) $(INCS) $(DEFINES) $<
 | 
			
		||||
 | 
			
		||||
%.o:    %.c 
 | 
			
		||||
	$(CC) -c $(CFLAGS) $(INCS) $(DEFINES) $<
 | 
			
		||||
 | 
			
		||||
.depend: 
 | 
			
		||||
	$(CXX) $(DEFINES) $(MFLAG) $(SRC) $(CSRC) $(CPPSRC) $(INCS)> .depend
 | 
			
		||||
	$(CXX) $(DEFINES) $(MFLAG) $(SRC) $(INCS)> .depend
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
#ifndef _OSD_H_
 | 
			
		||||
#define _OSD_H_
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif  /* __cplusplus */
 | 
			
		||||
int OSDClose(int dev);
 | 
			
		||||
int OSDOpen(int dev, int x0, int y0, int x1, int y1, int BitPerPixel, int mix);
 | 
			
		||||
int OSDShow(int dev);
 | 
			
		||||
int OSDHide(int dev); 
 | 
			
		||||
int OSDClear(int dev); 
 | 
			
		||||
int OSDFill(int dev, int color); 
 | 
			
		||||
int OSDSetColor(int dev, int color, int r, int g, int b, int op);
 | 
			
		||||
int OSDText(int dev, int x, int y, int size, int color, const char *text);
 | 
			
		||||
int OSDSetPalette(int dev, int first, int last, unsigned char *data);
 | 
			
		||||
int OSDSetTrans(int dev, int trans);
 | 
			
		||||
int OSDSetPixel(int dev, int x, int y, unsigned int color);
 | 
			
		||||
int OSDGetPixel(int dev, int x, int y);
 | 
			
		||||
int OSDSetRow(int dev, int x, int y, int x1, unsigned char *data);
 | 
			
		||||
int OSDSetBlock(int dev, int x, int y, int x1, int y1, int inc, unsigned char *data);
 | 
			
		||||
int OSDFillRow(int dev, int x, int y, int x1, int color);
 | 
			
		||||
int OSDFillBlock(int dev, int x, int y, int x1, int y1, int color);
 | 
			
		||||
int OSDLine(int dev, int x, int y, int x1, int y1, int color);
 | 
			
		||||
int OSDQuery(int dev);
 | 
			
		||||
int OSDSetWindow(int dev, int win);
 | 
			
		||||
int OSDMoveWindow(int dev, int x, int y);
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif  /* __cplusplus */
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,58 +0,0 @@
 | 
			
		||||
#ifndef _CHANNEL_H
 | 
			
		||||
#define _CHANNEL_H
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
 | 
			
		||||
struct channel {
 | 
			
		||||
        int id;
 | 
			
		||||
        char name[81];
 | 
			
		||||
        int type;
 | 
			
		||||
        ushort pnr;
 | 
			
		||||
        ushort vpid;
 | 
			
		||||
        ushort apids[8];
 | 
			
		||||
        ushort apidnum;
 | 
			
		||||
        ushort ac3pid;
 | 
			
		||||
        ushort pcrpid;
 | 
			
		||||
        
 | 
			
		||||
        uint freq;
 | 
			
		||||
        int pol;
 | 
			
		||||
        int qam;
 | 
			
		||||
        uint srate;
 | 
			
		||||
        int fec;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef NEWSTRUCT
 | 
			
		||||
 | 
			
		||||
#include <linux/dvb/dmx.h>
 | 
			
		||||
#include <linux/dvb/frontend.h>
 | 
			
		||||
#include <linux/dvb/video.h>
 | 
			
		||||
#include <linux/dvb/audio.h>
 | 
			
		||||
 | 
			
		||||
#define DVR_DEV   "/dev/dvb/adapter%d/dvr%d"     
 | 
			
		||||
#define VIDEO_DEV "/dev/dvb/adapter%d/video%d"
 | 
			
		||||
#define AUDIO_DEV "/dev/dvb/adapter%d/audio%d"
 | 
			
		||||
#define DEMUX_DEV "/dev/dvb/adapter%d/demux%d"
 | 
			
		||||
#define FRONT_DEV "/dev/dvb/adapter%d/frontend%d"
 | 
			
		||||
#define OSD_DEV   "/dev/dvb/adapter%d/osd%d"
 | 
			
		||||
#define CA_DEV    "/dev/dvb/adapter%d/ca%d"
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#include <ost/dmx.h>
 | 
			
		||||
#include <ost/frontend.h>
 | 
			
		||||
#include <ost/sec.h>
 | 
			
		||||
#include <ost/video.h>
 | 
			
		||||
#include <ost/audio.h>
 | 
			
		||||
 | 
			
		||||
#define DVR_DEV   "/dev/ost/dvr%d"
 | 
			
		||||
#define VIDEO_DEV "/dev/ost/video%d"
 | 
			
		||||
#define AUDIO_DEV "/dev/ost/audio%d"
 | 
			
		||||
#define DEMUX_DEV "/dev/ost/demux%d"
 | 
			
		||||
#define FRONT_DEV "/dev/ost/frontend%d"
 | 
			
		||||
#define OSD_DEV   "/dev/ost/osd%d"
 | 
			
		||||
#define CA_DEV   "/dev/ost/ca%d"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										167
									
								
								libdvbmpeg/ci.hh
									
									
									
									
									
								
							
							
						
						
									
										167
									
								
								libdvbmpeg/ci.hh
									
									
									
									
									
								
							@@ -1,167 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * ci.hh: Common Interface
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000 Klaus Schmidinger
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 | 
			
		||||
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 | 
			
		||||
 *
 | 
			
		||||
 * The author can be reached at kls@cadsoft.de
 | 
			
		||||
 *
 | 
			
		||||
 * The project's page is at http://www.cadsoft.de/people/kls/vdr
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __CI_H
 | 
			
		||||
#define __CI_H
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include <pthread.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/socket.h>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <sys/un.h>
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/uio.h>
 | 
			
		||||
 | 
			
		||||
#define MAXCASYSTEMIDS 16
 | 
			
		||||
 | 
			
		||||
class cMutex {
 | 
			
		||||
  friend class cCondVar;
 | 
			
		||||
private:
 | 
			
		||||
  pthread_mutex_t mutex;
 | 
			
		||||
  pid_t lockingPid;
 | 
			
		||||
  int locked;
 | 
			
		||||
public:
 | 
			
		||||
  cMutex(void);
 | 
			
		||||
  ~cMutex();
 | 
			
		||||
  void Lock(void);
 | 
			
		||||
  void Unlock(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cMutexLock {
 | 
			
		||||
private:
 | 
			
		||||
  cMutex *mutex;
 | 
			
		||||
  bool locked;
 | 
			
		||||
public:
 | 
			
		||||
  cMutexLock(cMutex *Mutex = NULL);
 | 
			
		||||
  ~cMutexLock();
 | 
			
		||||
  bool Lock(cMutex *Mutex);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class cCiMMI;
 | 
			
		||||
 | 
			
		||||
class cCiMenu {
 | 
			
		||||
  friend class cCiMMI;
 | 
			
		||||
private:
 | 
			
		||||
  enum { MAX_CIMENU_ENTRIES = 64 }; ///< XXX is there a specified maximum?
 | 
			
		||||
  cCiMMI *mmi;
 | 
			
		||||
  bool selectable;
 | 
			
		||||
  char *titleText;
 | 
			
		||||
  char *subTitleText;
 | 
			
		||||
  char *bottomText;
 | 
			
		||||
  char *entries[MAX_CIMENU_ENTRIES];
 | 
			
		||||
  int numEntries;
 | 
			
		||||
  bool AddEntry(char *s);
 | 
			
		||||
  cCiMenu(cCiMMI *MMI, bool Selectable);
 | 
			
		||||
public:
 | 
			
		||||
  ~cCiMenu();
 | 
			
		||||
  const char *TitleText(void) { return titleText; }
 | 
			
		||||
  const char *SubTitleText(void) { return subTitleText; }
 | 
			
		||||
  const char *BottomText(void) { return bottomText; }
 | 
			
		||||
  const char *Entry(int n) { return n < numEntries ? entries[n] : NULL; }
 | 
			
		||||
  int NumEntries(void) { return numEntries; }
 | 
			
		||||
  bool Selectable(void) { return selectable; }
 | 
			
		||||
  bool Select(int Index);
 | 
			
		||||
  bool Cancel(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cCiEnquiry {
 | 
			
		||||
  friend class cCiMMI;
 | 
			
		||||
private:
 | 
			
		||||
  cCiMMI *mmi;
 | 
			
		||||
  char *text;
 | 
			
		||||
  bool blind;
 | 
			
		||||
  int expectedLength;
 | 
			
		||||
  cCiEnquiry(cCiMMI *MMI);
 | 
			
		||||
public:
 | 
			
		||||
  ~cCiEnquiry();
 | 
			
		||||
  const char *Text(void) { return text; }
 | 
			
		||||
  bool Blind(void) { return blind; }
 | 
			
		||||
  int ExpectedLength(void) { return expectedLength; }
 | 
			
		||||
  bool Reply(const char *s);
 | 
			
		||||
  bool Cancel(void);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
class cCiCaPmt {
 | 
			
		||||
  friend class cCiConditionalAccessSupport;
 | 
			
		||||
private:
 | 
			
		||||
  int length;
 | 
			
		||||
  int esInfoLengthPos;
 | 
			
		||||
  uint8_t capmt[2048]; ///< XXX is there a specified maximum?
 | 
			
		||||
public:
 | 
			
		||||
  cCiCaPmt(int ProgramNumber);
 | 
			
		||||
  void AddPid(int Pid);
 | 
			
		||||
  void AddCaDescriptor(int Length, uint8_t *Data);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
#define MAX_CI_SESSION  16 //XXX
 | 
			
		||||
 | 
			
		||||
class cCiSession;
 | 
			
		||||
class cCiTransportLayer;
 | 
			
		||||
class cCiTransportConnection;
 | 
			
		||||
 | 
			
		||||
class cCiHandler {
 | 
			
		||||
private:
 | 
			
		||||
  cMutex mutex;
 | 
			
		||||
  int numSlots;
 | 
			
		||||
  bool newCaSupport;
 | 
			
		||||
  bool hasUserIO;
 | 
			
		||||
  cCiSession *sessions[MAX_CI_SESSION];
 | 
			
		||||
  cCiTransportLayer *tpl;
 | 
			
		||||
  cCiTransportConnection *tc;
 | 
			
		||||
  int ResourceIdToInt(const uint8_t *Data);
 | 
			
		||||
  bool Send(uint8_t Tag, int SessionId, int ResourceId = 0, int Status = -1);
 | 
			
		||||
  cCiSession *GetSessionBySessionId(int SessionId);
 | 
			
		||||
  cCiSession *GetSessionByResourceId(int ResourceId, int Slot);
 | 
			
		||||
  cCiSession *CreateSession(int ResourceId);
 | 
			
		||||
  bool OpenSession(int Length, const uint8_t *Data);
 | 
			
		||||
  bool CloseSession(int SessionId);
 | 
			
		||||
  int CloseAllSessions(int Slot);
 | 
			
		||||
  cCiHandler(int Fd, int NumSlots);
 | 
			
		||||
public:
 | 
			
		||||
  ~cCiHandler();
 | 
			
		||||
  static cCiHandler *CreateCiHandler(const char *FileName);
 | 
			
		||||
  int NumSlots(void) { return numSlots; }
 | 
			
		||||
  bool Process(void);
 | 
			
		||||
  bool HasUserIO(void) { return hasUserIO; }
 | 
			
		||||
  bool EnterMenu(int Slot);
 | 
			
		||||
  cCiMenu *GetMenu(void);
 | 
			
		||||
  cCiEnquiry *GetEnquiry(void);
 | 
			
		||||
  bool SetCaPmt(cCiCaPmt &CaPmt);
 | 
			
		||||
  const unsigned short *GetCaSystemIds(int Slot);
 | 
			
		||||
  bool SetCaPmt(cCiCaPmt &CaPmt, int Slot);
 | 
			
		||||
  bool Reset(int Slot);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
int tcp_listen(struct sockaddr_in *name,int sckt,unsigned long address=INADDR_ANY);
 | 
			
		||||
int accept_tcp(int ip_sock,struct sockaddr_in *ip_name);
 | 
			
		||||
int udp_listen(struct sockaddr_un *name,char const * const filename);
 | 
			
		||||
int accept_udp(int ip_sock,struct sockaddr_un *ip_name);
 | 
			
		||||
 | 
			
		||||
#endif //__CI_H
 | 
			
		||||
@@ -1,948 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000, 2001 Marcus Metzler 
 | 
			
		||||
 *            for convergence integrated media GmbH
 | 
			
		||||
 * Copyright (C) 2002  Marcus Metzler 
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 | 
			
		||||
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
 * The author can be reached at mocm@metzlerbros.de
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "cpptools.hh"
 | 
			
		||||
 | 
			
		||||
#define HEX(N) "0x" << hex << setw(2) << setfill('0') \
 | 
			
		||||
<< int(N) << " " << dec
 | 
			
		||||
#define HHEX(N,M) "0x" << hex << setw(M) << setfill('0') \
 | 
			
		||||
<< int(N) << " " << dec
 | 
			
		||||
#define LHEX(N,M) "0x" << hex << setw(M) << setfill('0') \
 | 
			
		||||
<< long(N) << " " << dec
 | 
			
		||||
 | 
			
		||||
#define MAX_SEARCH 1024 * 1024
 | 
			
		||||
 | 
			
		||||
ostream & operator << (ostream & stream, PES_Packet & x){
 | 
			
		||||
  
 | 
			
		||||
	if (x.info){
 | 
			
		||||
		cerr << "PES Packet: " ;
 | 
			
		||||
		switch ( x.p.stream_id ) {
 | 
			
		||||
				
 | 
			
		||||
		case PROG_STREAM_MAP:
 | 
			
		||||
			cerr << "Program Stream Map";
 | 
			
		||||
			break;
 | 
			
		||||
		case PRIVATE_STREAM2:
 | 
			
		||||
			cerr << "Private Stream 2";
 | 
			
		||||
			break;
 | 
			
		||||
		case PROG_STREAM_DIR:
 | 
			
		||||
			cerr << "Program Stream Directory";
 | 
			
		||||
			break;
 | 
			
		||||
		case ECM_STREAM     :
 | 
			
		||||
			cerr << "ECM Stream";
 | 
			
		||||
			break;
 | 
			
		||||
		case EMM_STREAM     :
 | 
			
		||||
			cerr << "EMM Stream";
 | 
			
		||||
			break;
 | 
			
		||||
		case PADDING_STREAM :
 | 
			
		||||
			cerr << "Padding Stream";
 | 
			
		||||
			break;
 | 
			
		||||
		case DSM_CC_STREAM  :
 | 
			
		||||
			cerr << "DSM Stream";
 | 
			
		||||
			break;
 | 
			
		||||
		case ISO13522_STREAM:
 | 
			
		||||
			cerr << "ISO13522 Stream";
 | 
			
		||||
			break;
 | 
			
		||||
		case PRIVATE_STREAM1:
 | 
			
		||||
			cerr << "Private Stream 1";
 | 
			
		||||
			break;
 | 
			
		||||
		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
 | 
			
		||||
			cerr << "Audio Stream " << HEX(x.p.stream_id);
 | 
			
		||||
			break;
 | 
			
		||||
		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
 | 
			
		||||
			cerr << "Video Stream " << HEX(x.p.stream_id);
 | 
			
		||||
			break;
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
		cerr << " MPEG" << x.p.mpeg << endl;
 | 
			
		||||
		if ( x.p.mpeg == 2 ){
 | 
			
		||||
			cerr << "    FLAGS: ";
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags1 & SCRAMBLE_FLAGS){
 | 
			
		||||
				cerr << " SCRAMBLE(";
 | 
			
		||||
				cerr << ((x.p.flags1 & SCRAMBLE_FLAGS)>>4);
 | 
			
		||||
				cerr << ")";
 | 
			
		||||
			}
 | 
			
		||||
			if (x.p.flags1 & PRIORITY_FLAG) 
 | 
			
		||||
				cerr << " PRIORITY";    
 | 
			
		||||
			if (x.p.flags1 & DATA_ALIGN_FLAG)
 | 
			
		||||
				cerr << " DATA_ALIGN";  
 | 
			
		||||
			if (x.p.flags1 & COPYRIGHT_FLAG) 
 | 
			
		||||
				cerr << " COPYRIGHT";   
 | 
			
		||||
			if (x.p.flags1 & ORIGINAL_FLAG) 
 | 
			
		||||
				cerr << " ORIGINAL";   
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & PTS_DTS_FLAGS){
 | 
			
		||||
				cerr << " PTS_DTS(";
 | 
			
		||||
				cerr << ((x.p.flags2 & PTS_DTS_FLAGS)>>6);
 | 
			
		||||
				cerr << ")";
 | 
			
		||||
			}
 | 
			
		||||
			if (x.p.flags2 & ESCR_FLAG) 
 | 
			
		||||
				cerr << " ESCR";
 | 
			
		||||
			if (x.p.flags2 & ES_RATE_FLAG)
 | 
			
		||||
				cerr << " ES_RATE";   
 | 
			
		||||
			if (x.p.flags2 & DSM_TRICK_FLAG)
 | 
			
		||||
				cerr << " DSM_TRICK";   
 | 
			
		||||
			if (x.p.flags2 & ADD_CPY_FLAG)
 | 
			
		||||
				cerr << " ADD_CPY";     
 | 
			
		||||
			if (x.p.flags2 & PES_CRC_FLAG) 
 | 
			
		||||
				cerr << " CRC";     
 | 
			
		||||
			if (x.p.flags2 & PES_EXT_FLAG)
 | 
			
		||||
				cerr << " EXT";     
 | 
			
		||||
 | 
			
		||||
			cerr << endl;
 | 
			
		||||
 | 
			
		||||
			if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
 | 
			
		||||
				cerr << "   PTS: " 
 | 
			
		||||
				     << LHEX(ntohl(x.WPTS()),8)
 | 
			
		||||
				     << "(h" << int(x.high_pts()) << ")"
 | 
			
		||||
				     << endl; 
 | 
			
		||||
			else if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
 | 
			
		||||
				cerr << "   PTS: " 
 | 
			
		||||
				     << LHEX(ntohl(x.WPTS()),8)
 | 
			
		||||
				     << "(h" << int(x.high_pts()) << ")";
 | 
			
		||||
				cerr << "   DTS: " 
 | 
			
		||||
				     << LHEX(ntohl(x.WDTS()),8)
 | 
			
		||||
				     << "(h" << int(x.high_dts()) << ")"
 | 
			
		||||
				     << endl; 
 | 
			
		||||
			}
 | 
			
		||||
/*			
 | 
			
		||||
			if (x.p.flags2 & ESCR_FLAG)
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			if (x.p.flags2 & ES_RATE_FLAG)
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			if (x.p.flags2 & DSM_TRICK_FLAG)
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			if (x.p.flags2 & ADD_CPY_FLAG)
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			if (x.p.flags2 & PES_CRC_FLAG)
 | 
			
		||||
 | 
			
		||||
			
 | 
			
		||||
			if (x.p.flags2 & PES_EXT_FLAG){
 | 
			
		||||
				
 | 
			
		||||
				if (x.p.priv_flags & PRIVATE_DATA)
 | 
			
		||||
					stream.write(x.p.pes_priv_data,16);
 | 
			
		||||
				
 | 
			
		||||
				if (x.p.priv_flags & HEADER_FIELD){
 | 
			
		||||
					stream.write(&x.p.pack_field_length,1);
 | 
			
		||||
					x.p.pack_header = new 
 | 
			
		||||
						uint8_t[x.p.pack_field_length];
 | 
			
		||||
					stream.write(x.p.pack_header,
 | 
			
		||||
						     x.p.pack_field_length);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if ( x.p.priv_flags & PACK_SEQ_CTR){
 | 
			
		||||
					stream.write(&x.p.pck_sqnc_cntr,1);
 | 
			
		||||
					stream.write(&x.p.org_stuff_length,1);
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if ( x.p.priv_flags & P_STD_BUFFER)
 | 
			
		||||
					stream.write(x.p.p_std,2);
 | 
			
		||||
				
 | 
			
		||||
				if ( x.p.priv_flags & PES_EXT_FLAG2){
 | 
			
		||||
					stream.write(&x.p.pes_ext_lngth,1);
 | 
			
		||||
					x.p.pes_ext = new 
 | 
			
		||||
						uint8_t[x.p.pes_ext_lngth];
 | 
			
		||||
					stream.write(x.p.pes_ext,
 | 
			
		||||
						     x.p.pes_ext_lngth);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY)
 | 
			
		||||
				stream.write(x.p.pts,5);
 | 
			
		||||
			else if ((x.p.flags2 & PTS_DTS_FLAGS) == 
 | 
			
		||||
				 PTS_DTS){
 | 
			
		||||
				stream.write(x.p.pts,5);
 | 
			
		||||
				stream.write(x.p.dts,5);
 | 
			
		||||
			}
 | 
			
		||||
*/	
 | 
			
		||||
		}			
 | 
			
		||||
		cerr << endl << endl;
 | 
			
		||||
		return stream;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int l = x.p.length+x.p.pes_hlength+9;
 | 
			
		||||
	uint8_t buf[l];
 | 
			
		||||
	int length = cwrite_pes(buf,&(x.p),l);
 | 
			
		||||
	stream.write((char *)buf,length);
 | 
			
		||||
	
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned int find_length(istream & stream){
 | 
			
		||||
	streampos p = 0;
 | 
			
		||||
	streampos start = 0;
 | 
			
		||||
	streampos q = 0;
 | 
			
		||||
	int found = 0;
 | 
			
		||||
	uint8_t sync4[4];
 | 
			
		||||
 | 
			
		||||
	start = stream.tellg();
 | 
			
		||||
	start -=2;
 | 
			
		||||
	stream.seekg(start);
 | 
			
		||||
	while ( !stream.eof() && !found ){
 | 
			
		||||
		p = stream.tellg();
 | 
			
		||||
		stream.read((char *)&sync4,4);
 | 
			
		||||
		if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
 | 
			
		||||
			switch ( sync4[3] ) {
 | 
			
		||||
				
 | 
			
		||||
			case PROG_STREAM_MAP:
 | 
			
		||||
			case PRIVATE_STREAM2:
 | 
			
		||||
			case PROG_STREAM_DIR:
 | 
			
		||||
			case ECM_STREAM     :
 | 
			
		||||
			case EMM_STREAM     :
 | 
			
		||||
			case PADDING_STREAM :
 | 
			
		||||
			case DSM_CC_STREAM  :
 | 
			
		||||
			case ISO13522_STREAM:
 | 
			
		||||
			case PRIVATE_STREAM1:
 | 
			
		||||
			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
 | 
			
		||||
			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
 | 
			
		||||
				found = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				q = stream.tellg();
 | 
			
		||||
				break;
 | 
			
		||||
			}	
 | 
			
		||||
		} 
 | 
			
		||||
	}
 | 
			
		||||
	q = stream.tellg();
 | 
			
		||||
	stream.seekg(streampos(2)+start);
 | 
			
		||||
	if (found) return (unsigned int)(q-start)-4-2;
 | 
			
		||||
	else return (unsigned int)(q-start)-2;
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
istream & operator >> (istream & stream, PES_Packet & x){
 | 
			
		||||
	
 | 
			
		||||
	uint8_t sync4[4];
 | 
			
		||||
	int found=0;
 | 
			
		||||
	int done=0;
 | 
			
		||||
	streampos p = 0;
 | 
			
		||||
	
 | 
			
		||||
	while (!stream.eof() && !found) {
 | 
			
		||||
	        p = stream.tellg();
 | 
			
		||||
		stream.read((char *)&sync4,4);
 | 
			
		||||
		if (sync4[0] == 0x00 && sync4[1] == 0x00 && sync4[2] == 0x01) {
 | 
			
		||||
			x.p.stream_id = sync4[3];
 | 
			
		||||
 | 
			
		||||
			switch ( sync4[3] ) {
 | 
			
		||||
				
 | 
			
		||||
			case PROG_STREAM_MAP:
 | 
			
		||||
			case PRIVATE_STREAM2:
 | 
			
		||||
			case PROG_STREAM_DIR:
 | 
			
		||||
			case ECM_STREAM     :
 | 
			
		||||
			case EMM_STREAM     :
 | 
			
		||||
				found = 1;
 | 
			
		||||
				stream.read((char *)x.p.llength,2);
 | 
			
		||||
				x.setlength();
 | 
			
		||||
				if (!x.p.length){ 
 | 
			
		||||
					x.p.length = find_length(stream);
 | 
			
		||||
					x.Nlength();
 | 
			
		||||
				}
 | 
			
		||||
				stream.read((char *)x.p.pes_pckt_data,x.p.length);
 | 
			
		||||
				done = 1;
 | 
			
		||||
				break;
 | 
			
		||||
			case PADDING_STREAM :
 | 
			
		||||
				found = 1;
 | 
			
		||||
				stream.read((char *)x.p.llength,2);
 | 
			
		||||
				x.setlength();
 | 
			
		||||
				if (!x.p.length){ 
 | 
			
		||||
					x.p.length = find_length(stream);
 | 
			
		||||
					x.Nlength();
 | 
			
		||||
				}
 | 
			
		||||
				x.p.padding = x.p.length;
 | 
			
		||||
				stream.read((char *)x.p.pes_pckt_data,x.p.length);
 | 
			
		||||
				done = 1;
 | 
			
		||||
				break;
 | 
			
		||||
				
 | 
			
		||||
			case DSM_CC_STREAM  :
 | 
			
		||||
			case ISO13522_STREAM:
 | 
			
		||||
			case PRIVATE_STREAM1:
 | 
			
		||||
			case AUDIO_STREAM_S ... AUDIO_STREAM_E:
 | 
			
		||||
			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
 | 
			
		||||
				stream.read((char *)x.p.llength,2);
 | 
			
		||||
				x.setlength();
 | 
			
		||||
				if (!x.p.length){ 
 | 
			
		||||
					x.p.length = find_length(stream);
 | 
			
		||||
					x.Nlength();
 | 
			
		||||
				}
 | 
			
		||||
				found = 1;
 | 
			
		||||
				break;
 | 
			
		||||
				
 | 
			
		||||
			default:
 | 
			
		||||
				stream.seekg(p+streampos(1));
 | 
			
		||||
			break;
 | 
			
		||||
			}	
 | 
			
		||||
		} else stream.seekg(p+streampos(1));
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if ( found && !done) {
 | 
			
		||||
		p = stream.tellg();
 | 
			
		||||
		stream.read((char *)&x.p.flags1,1);
 | 
			
		||||
		if ( (x.p.flags1 & 0xC0) == 0x80 )
 | 
			
		||||
			x.p.mpeg = 2;
 | 
			
		||||
		else
 | 
			
		||||
			x.p.mpeg = 1;
 | 
			
		||||
		if ( x.p.mpeg == 2 ){
 | 
			
		||||
			stream.read((char *)&x.p.flags2,1);
 | 
			
		||||
			stream.read((char *)&x.p.pes_hlength,1);
 | 
			
		||||
			
 | 
			
		||||
			if ((int)x.p.length > x.p.pes_hlength+3)
 | 
			
		||||
				x.p.length -=x.p.pes_hlength+3;
 | 
			
		||||
			else 
 | 
			
		||||
				return stream;
 | 
			
		||||
 | 
			
		||||
			uint8_t count = x.p.pes_hlength;
 | 
			
		||||
 | 
			
		||||
			if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
 | 
			
		||||
				stream.read((char *)x.p.pts,5);
 | 
			
		||||
				count -=5;
 | 
			
		||||
			} else 
 | 
			
		||||
				if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_DTS){
 | 
			
		||||
					stream.read((char *)x.p.pts,5);
 | 
			
		||||
					stream.read((char *)x.p.dts,5);
 | 
			
		||||
					count -= 10;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & ESCR_FLAG){
 | 
			
		||||
				stream.read((char *)x.p.escr,6);
 | 
			
		||||
				count -= 6;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & ES_RATE_FLAG){
 | 
			
		||||
				stream.read((char *)x.p.es_rate,3);
 | 
			
		||||
				count -= 6;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & DSM_TRICK_FLAG){
 | 
			
		||||
				stream.read((char *)&x.p.trick,1);
 | 
			
		||||
				count -= 1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & ADD_CPY_FLAG){
 | 
			
		||||
				stream.read((char *)&x.p.add_cpy,1);
 | 
			
		||||
				count -= 1;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & PES_CRC_FLAG){
 | 
			
		||||
				stream.read((char *)x.p.prev_pes_crc,2);
 | 
			
		||||
				count -= 2;
 | 
			
		||||
			}			
 | 
			
		||||
 | 
			
		||||
			if (x.p.flags2 & PES_EXT_FLAG){
 | 
			
		||||
				stream.read((char *)&x.p.priv_flags,1);
 | 
			
		||||
				count -= 1;
 | 
			
		||||
				
 | 
			
		||||
				if (x.p.priv_flags & PRIVATE_DATA){
 | 
			
		||||
					stream.read((char *)x.p.pes_priv_data,16);
 | 
			
		||||
					count -= 16;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (x.p.priv_flags & HEADER_FIELD){
 | 
			
		||||
					stream.read((char *)&x.p.pack_field_length,1);
 | 
			
		||||
					x.p.pack_header = new 
 | 
			
		||||
						uint8_t[x.p.pack_field_length];
 | 
			
		||||
					stream.read((char *)x.p.pack_header,
 | 
			
		||||
						    x.p.pack_field_length);
 | 
			
		||||
					count -= 1+x.p.pack_field_length;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if ( x.p.priv_flags & PACK_SEQ_CTR){
 | 
			
		||||
					stream.read((char *)&x.p.pck_sqnc_cntr,1);
 | 
			
		||||
					stream.read((char *)&x.p.org_stuff_length,1);
 | 
			
		||||
					count -= 2;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( x.p.priv_flags & P_STD_BUFFER){
 | 
			
		||||
					stream.read((char *)x.p.p_std,2);
 | 
			
		||||
					count -= 2;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if ( x.p.priv_flags & PES_EXT_FLAG2){
 | 
			
		||||
					stream.read((char *)&x.p.pes_ext_lngth,1);
 | 
			
		||||
					x.p.pes_ext = new 
 | 
			
		||||
						uint8_t[x.p.pes_ext_lngth];
 | 
			
		||||
					stream.read((char *)x.p.pes_ext,
 | 
			
		||||
						    x.p.pes_ext_lngth);
 | 
			
		||||
					count -= 1+x.p.pes_ext_lngth;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			x.p.stuffing = count;
 | 
			
		||||
			uint8_t dummy;
 | 
			
		||||
			for(int i = 0; i< count ;i++) 
 | 
			
		||||
				stream.read((char *)&dummy,1);
 | 
			
		||||
			
 | 
			
		||||
		} else {
 | 
			
		||||
			uint8_t check;
 | 
			
		||||
			x.p.mpeg1_pad = 1;
 | 
			
		||||
			check = x.p.flags1;
 | 
			
		||||
			while (check == 0xFF){
 | 
			
		||||
				stream.read((char *)&check,1);
 | 
			
		||||
				x.p.mpeg1_pad++;
 | 
			
		||||
			}
 | 
			
		||||
		    
 | 
			
		||||
			if ( (check & 0xC0) == 0x40){
 | 
			
		||||
				stream.read((char *)&check,1);
 | 
			
		||||
				x.p.mpeg1_pad++;
 | 
			
		||||
				stream.read((char *)&check,1);
 | 
			
		||||
				x.p.mpeg1_pad++;
 | 
			
		||||
			}
 | 
			
		||||
			x.p.flags2 = 0;
 | 
			
		||||
			x.p.length -= x.p.mpeg1_pad;
 | 
			
		||||
 | 
			
		||||
			stream.seekg(p);
 | 
			
		||||
			if ( (check & 0x30)){
 | 
			
		||||
				x.p.length ++;
 | 
			
		||||
				x.p.mpeg1_pad --;
 | 
			
		||||
 | 
			
		||||
				if (check == x.p.flags1){
 | 
			
		||||
					x.p.pes_hlength = 0;
 | 
			
		||||
				} else {
 | 
			
		||||
					x.p.mpeg1_headr = 
 | 
			
		||||
						new uint8_t[x.p.mpeg1_pad];
 | 
			
		||||
					x.p.pes_hlength = x.p.mpeg1_pad;
 | 
			
		||||
					stream.read((char *)x.p.mpeg1_headr,
 | 
			
		||||
						    x.p.mpeg1_pad);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				x.p.flags2 = (check & 0xF0) << 2;
 | 
			
		||||
				if ((x.p.flags2 & PTS_DTS_FLAGS) == PTS_ONLY){
 | 
			
		||||
					stream.read((char *)x.p.pts,5);
 | 
			
		||||
					x.p.length -= 5;
 | 
			
		||||
					x.p.pes_hlength += 5;
 | 
			
		||||
				}
 | 
			
		||||
				else if ((x.p.flags2 & PTS_DTS_FLAGS) == 
 | 
			
		||||
					 PTS_DTS){
 | 
			
		||||
					stream.read((char *)x.p.pts,5);
 | 
			
		||||
					stream.read((char *)x.p.dts,5);
 | 
			
		||||
					x.p.length -= 10;
 | 
			
		||||
					x.p.pes_hlength += 10;
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				x.p.mpeg1_headr = new uint8_t[x.p.mpeg1_pad];
 | 
			
		||||
				x.p.pes_hlength = x.p.mpeg1_pad;
 | 
			
		||||
				stream.read((char *)x.p.mpeg1_headr,x.p.mpeg1_pad);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		stream.read((char *)x.p.pes_pckt_data,x.p.length);
 | 
			
		||||
	}
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ostream & operator << (ostream & stream, TS_Packet & x){
 | 
			
		||||
 | 
			
		||||
	uint8_t buf[TS_SIZE];
 | 
			
		||||
	int length = cwrite_ts(buf,&(x.p),TS_SIZE);
 | 
			
		||||
	stream.write((char *)buf,length);
 | 
			
		||||
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
istream & operator >> (istream & stream, TS_Packet & x){
 | 
			
		||||
	uint8_t sync;
 | 
			
		||||
	int found=0;
 | 
			
		||||
	streampos p,q;
 | 
			
		||||
 | 
			
		||||
	sync=0;
 | 
			
		||||
	while (!stream.eof() && !found) {
 | 
			
		||||
		stream.read((char *)&sync,1);
 | 
			
		||||
		if (sync == 0x47) 
 | 
			
		||||
			found = 1;
 | 
			
		||||
	}
 | 
			
		||||
	stream.read((char *)x.p.pid,2);
 | 
			
		||||
	stream.read((char *)&x.p.flags,1);
 | 
			
		||||
	x.p.count = x.p.flags & COUNT_MASK;
 | 
			
		||||
	 
 | 
			
		||||
	if (!(x.p.flags & ADAPT_FIELD) && (x.p.flags & PAYLOAD)){
 | 
			
		||||
		//no adapt. field only payload
 | 
			
		||||
		stream.read((char *)x.p.data,184);
 | 
			
		||||
		x.p.rest = 184;
 | 
			
		||||
		return stream;
 | 
			
		||||
	} 
 | 
			
		||||
 | 
			
		||||
	if ( x.p.flags & ADAPT_FIELD ) {
 | 
			
		||||
		// adaption field
 | 
			
		||||
		stream.read((char *)&x.p.adapt_length,1);
 | 
			
		||||
		if (x.p.adapt_length){
 | 
			
		||||
			p = stream.tellg();
 | 
			
		||||
			stream.read((char *)&x.p.adapt_flags,1);
 | 
			
		||||
			
 | 
			
		||||
			if ( x.p.adapt_flags & PCR_FLAG )
 | 
			
		||||
				stream.read((char *) x.p.pcr,6);
 | 
			
		||||
 | 
			
		||||
			if ( x.p.adapt_flags & OPCR_FLAG )
 | 
			
		||||
				stream.read((char *) x.p.opcr,6);
 | 
			
		||||
 | 
			
		||||
			if ( x.p.adapt_flags & SPLICE_FLAG )
 | 
			
		||||
				stream.read((char *) &x.p.splice_count,1);
 | 
			
		||||
			
 | 
			
		||||
			if( x.p.adapt_flags & TRANS_PRIV){
 | 
			
		||||
				stream.read((char *)&x.p.priv_dat_len,1);
 | 
			
		||||
				x.p.priv_dat = new uint8_t[x.p.priv_dat_len];
 | 
			
		||||
				stream.read((char *)x.p.priv_dat,x.p.priv_dat_len);
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
			if( x.p.adapt_flags & ADAP_EXT_FLAG){
 | 
			
		||||
				stream.read((char *)&x.p.adapt_ext_len,1);
 | 
			
		||||
				stream.read((char *)&x.p.adapt_eflags,1);
 | 
			
		||||
				if( x.p.adapt_eflags & LTW_FLAG)
 | 
			
		||||
					stream.read((char *)x.p.ltw,2);
 | 
			
		||||
				
 | 
			
		||||
				if( x.p.adapt_eflags & PIECE_RATE)
 | 
			
		||||
					stream.read((char *)x.p.piece_rate,3);
 | 
			
		||||
				
 | 
			
		||||
				if( x.p.adapt_eflags & SEAM_SPLICE)
 | 
			
		||||
					stream.read((char *)x.p.dts,5);
 | 
			
		||||
			}
 | 
			
		||||
			q = stream.tellg();
 | 
			
		||||
			x.p.stuffing = x.p.adapt_length -(q-p);
 | 
			
		||||
			x.p.rest = 183-x.p.adapt_length;
 | 
			
		||||
			stream.seekg(q+streampos(x.p.stuffing));
 | 
			
		||||
			if (x.p.flags & PAYLOAD) // payload
 | 
			
		||||
				stream.read((char *)x.p.data,x.p.rest);
 | 
			
		||||
			else 
 | 
			
		||||
				stream.seekg(q+streampos(x.p.rest));
 | 
			
		||||
		} else {
 | 
			
		||||
			x.p.rest = 182;
 | 
			
		||||
			stream.read((char *)x.p.data, 183);
 | 
			
		||||
			return stream;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ostream & operator << (ostream & stream, PS_Packet & x){
 | 
			
		||||
 | 
			
		||||
	uint8_t buf[PS_MAX];
 | 
			
		||||
	int length = cwrite_ps(buf,&(x.p),PS_MAX);
 | 
			
		||||
	stream.write((char *)buf,length);
 | 
			
		||||
 | 
			
		||||
	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
istream & operator >> (istream & stream, PS_Packet & x){
 | 
			
		||||
	uint8_t headr[4];
 | 
			
		||||
	int found=0;
 | 
			
		||||
	streampos p = 0;
 | 
			
		||||
	streampos q = 0;
 | 
			
		||||
	int count = 0;
 | 
			
		||||
 | 
			
		||||
	p = stream.tellg();
 | 
			
		||||
	while (!stream.eof() && !found && count < MAX_SEARCH) {
 | 
			
		||||
		stream.read((char *)&headr,4);
 | 
			
		||||
		if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01) {
 | 
			
		||||
			if ( headr[3] == 0xBA ) 
 | 
			
		||||
				found = 1;
 | 
			
		||||
			else if ( headr[3] == 0xB9 ) break;
 | 
			
		||||
			else stream.seekg(p+streampos(1));
 | 
			
		||||
		}
 | 
			
		||||
		count++;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	if (found){
 | 
			
		||||
		stream.read((char *)x.p.scr,6);
 | 
			
		||||
		if (x.p.scr[0] & 0x40)
 | 
			
		||||
			x.p.mpeg = 2;
 | 
			
		||||
		else
 | 
			
		||||
			x.p.mpeg = 1;
 | 
			
		||||
 | 
			
		||||
		if (x.p.mpeg == 2){
 | 
			
		||||
			stream.read((char *)x.p.mux_rate,3);
 | 
			
		||||
			stream.read((char *)&x.p.stuff_length,1);
 | 
			
		||||
			p = stream.tellg();
 | 
			
		||||
			stream.seekg(p+streampos(x.p.stuff_length & 3));
 | 
			
		||||
		} else {
 | 
			
		||||
			x.p.mux_rate[0] = x.p.scr[5]; //mpeg1 scr is only 5 bytes
 | 
			
		||||
			stream.read((char *)x.p.mux_rate+1,2);
 | 
			
		||||
		}
 | 
			
		||||
			
 | 
			
		||||
		p=stream.tellg();
 | 
			
		||||
		stream.read((char *)headr,4);
 | 
			
		||||
		if (headr[0] == 0x00 && headr[1] == 0x00 && 
 | 
			
		||||
		    headr[2] == 0x01 && headr[3] == 0xBB ) {
 | 
			
		||||
			stream.read((char *)x.p.sheader_llength,2);
 | 
			
		||||
			x.setlength();
 | 
			
		||||
			if (x.p.mpeg == 2){
 | 
			
		||||
				stream.read((char *)x.p.rate_bound,3);
 | 
			
		||||
				stream.read((char *)&x.p.audio_bound,1);
 | 
			
		||||
				stream.read((char *)&x.p.video_bound,1);
 | 
			
		||||
				stream.read((char *)&x.p.reserved,1);
 | 
			
		||||
			}
 | 
			
		||||
			stream.read((char *)x.p.data,x.p.sheader_length);
 | 
			
		||||
		} else {
 | 
			
		||||
			stream.seekg(p);
 | 
			
		||||
			x.p.sheader_length = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		int i = 0;
 | 
			
		||||
		int done = 0;
 | 
			
		||||
		q = stream.tellg();
 | 
			
		||||
		PES_Packet pes;
 | 
			
		||||
		do {
 | 
			
		||||
			p=stream.tellg();
 | 
			
		||||
			stream.read((char *)headr,4);
 | 
			
		||||
			stream.seekg(p);
 | 
			
		||||
			if ( headr[0] == 0x00 && headr[1] == 0x00 
 | 
			
		||||
			     && headr[2] == 0x01 && headr[3] != 0xBA){
 | 
			
		||||
				pes.init();
 | 
			
		||||
				stream >> pes;
 | 
			
		||||
			        i++;
 | 
			
		||||
			} else done = 1;
 | 
			
		||||
		} while (!stream.eof() && !done);
 | 
			
		||||
		x.p.npes = i;
 | 
			
		||||
		stream.seekg(q);
 | 
			
		||||
	} 
 | 
			
		||||
 	return stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extract_audio_from_PES(istream &in, ostream &out){
 | 
			
		||||
	PES_Packet pes;
 | 
			
		||||
	
 | 
			
		||||
	while(!in.eof()){
 | 
			
		||||
		pes.init();
 | 
			
		||||
		in >> pes ;
 | 
			
		||||
		if (pes.Stream_ID() == 0xC0)
 | 
			
		||||
			out << pes;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extract_video_from_PES(istream &in, ostream &out){
 | 
			
		||||
	PES_Packet pes;
 | 
			
		||||
	
 | 
			
		||||
	while(!in.eof()){
 | 
			
		||||
		pes.init();
 | 
			
		||||
		in >> pes ;
 | 
			
		||||
		if (pes.Stream_ID() == 0xE0)
 | 
			
		||||
			out << pes;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extract_es_audio_from_PES(istream &in, ostream &out){
 | 
			
		||||
	PES_Packet pes;
 | 
			
		||||
	
 | 
			
		||||
	while(!in.eof()){
 | 
			
		||||
		pes.init();
 | 
			
		||||
		in >> pes ;
 | 
			
		||||
		if (pes.Stream_ID() == 0xC0)
 | 
			
		||||
		  out.write((char *)pes.Data(),pes.Length());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extract_es_video_from_PES(istream &in, ostream &out){
 | 
			
		||||
	PES_Packet pes;
 | 
			
		||||
	
 | 
			
		||||
	while(!in.eof()){
 | 
			
		||||
		pes.init();
 | 
			
		||||
		in >> pes ;
 | 
			
		||||
		if (pes.Stream_ID() == 0xE0)
 | 
			
		||||
		  out.write((char *)pes.Data(),pes.Length());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MAX_PID 20
 | 
			
		||||
int TS_PIDS(istream &in, ostream &out){
 | 
			
		||||
	int pid[MAX_PID];
 | 
			
		||||
	TS_Packet ts;
 | 
			
		||||
	int npid=0;
 | 
			
		||||
	
 | 
			
		||||
	for (int i=0 ; i<MAX_PID; i++)
 | 
			
		||||
		pid[i] = -1;
 | 
			
		||||
	while (!in.eof()) {
 | 
			
		||||
		ts.init();
 | 
			
		||||
		in >> ts;
 | 
			
		||||
		int j;
 | 
			
		||||
		int found = 0;
 | 
			
		||||
		for (j=0;j<npid;j++){
 | 
			
		||||
			if ( ts.PID() == pid[j] )
 | 
			
		||||
				found = 1;
 | 
			
		||||
		}
 | 
			
		||||
		if (! found){ 
 | 
			
		||||
			out << ts.PID() << " ";
 | 
			
		||||
			pid[npid] = ts.PID();
 | 
			
		||||
			npid++;
 | 
			
		||||
			if (npid == MAX_PID) return -1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	out << endl;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tv_norm(istream &stream){
 | 
			
		||||
	uint8_t headr[4];
 | 
			
		||||
	int found=0;
 | 
			
		||||
	streampos p = 0;
 | 
			
		||||
	streampos q = 0;
 | 
			
		||||
	int hsize,vsize;
 | 
			
		||||
	int form= 0;
 | 
			
		||||
 | 
			
		||||
	q = stream.tellg();
 | 
			
		||||
	while (!stream.eof() && !found) {
 | 
			
		||||
		p = stream.tellg();
 | 
			
		||||
		stream.read((char *)headr,4);
 | 
			
		||||
		if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01)
 | 
			
		||||
			if ( headr[3] == 0xB3 ){ 
 | 
			
		||||
				found = 1;
 | 
			
		||||
			}
 | 
			
		||||
		if (! found) stream.seekg(p+streampos(1));
 | 
			
		||||
	}
 | 
			
		||||
	stream.read((char *)headr,4);
 | 
			
		||||
 | 
			
		||||
	hsize = (headr[1] &0xF0) >> 4 | headr[0] << 4;
 | 
			
		||||
	vsize = (headr[1] &0x0F) << 8 | headr[2];
 | 
			
		||||
	cerr << "SIZE: " << hsize << "x" << vsize << endl;
 | 
			
		||||
	
 | 
			
		||||
	switch(((headr[3]&0xF0) >>4)){
 | 
			
		||||
	case 1:
 | 
			
		||||
		cerr << "ASPECT: 1:1" << endl;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		cerr << "ASPECT: 4:3" << endl;
 | 
			
		||||
		break;
 | 
			
		||||
	case 3:
 | 
			
		||||
		cerr << "ASPECT: 16:9" << endl;
 | 
			
		||||
		break;
 | 
			
		||||
	case 4:
 | 
			
		||||
		cerr << "ASPECT: 2.21:1" << endl;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (int(headr[3]&0x0F)){
 | 
			
		||||
	case 1:
 | 
			
		||||
		cerr << "FRAMERATE: 23.976" << endl;
 | 
			
		||||
		form = pDUNNO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		cerr << "FRAMERATE: 24" << endl;
 | 
			
		||||
		form = pDUNNO;
 | 
			
		||||
		break;
 | 
			
		||||
	case 3:
 | 
			
		||||
		cerr << "FRAMERATE: 25" << endl;
 | 
			
		||||
		form = pPAL;
 | 
			
		||||
		break;
 | 
			
		||||
	case 4:
 | 
			
		||||
		cerr << "FRAMERATE: 29.97" << endl;
 | 
			
		||||
		form = pNTSC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 5:
 | 
			
		||||
		cerr << "FRAMERATE: 30" << endl;
 | 
			
		||||
		form = pNTSC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 6:
 | 
			
		||||
		cerr << "FRAMERATE: 50" << endl;
 | 
			
		||||
		form = pPAL;
 | 
			
		||||
		break;
 | 
			
		||||
	case 7:
 | 
			
		||||
		cerr << "FRAMERATE: 59.94" << endl;
 | 
			
		||||
		form = pNTSC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 8:
 | 
			
		||||
		cerr << "FRAMERATE: 60" << endl;
 | 
			
		||||
		form = pNTSC;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	int mpeg = 0;
 | 
			
		||||
	found = 0;
 | 
			
		||||
	while (!stream.eof() && !found) {
 | 
			
		||||
		p = stream.tellg();
 | 
			
		||||
		stream.read((char *)headr,4);
 | 
			
		||||
		if (headr[0] == 0x00 && headr[1] == 0x00 && headr[2] == 0x01) {
 | 
			
		||||
			if ( headr[3] == 0xB5 ){ 
 | 
			
		||||
				const char *profile[] = {"reserved", "High", "Spatially Scalable",
 | 
			
		||||
						   "SNR Scalable", "Main", "Simple", "undef",
 | 
			
		||||
						   "undef"};
 | 
			
		||||
				const char *level[]   = {"res", "res", "res", "res",
 | 
			
		||||
						   "High","res", "High 1440", "res",
 | 
			
		||||
						   "Main","res", "Low", "res",
 | 
			
		||||
						   "res", "res", "res", "res"};
 | 
			
		||||
				const char *chroma[]  = {"res", "4:2:0", "4:2:2", "4:4:4:"};
 | 
			
		||||
				mpeg = 2;
 | 
			
		||||
				stream.read((char *)headr,4);
 | 
			
		||||
				cerr << "PROFILE: " << profile[headr[0] & 0x7] << endl;
 | 
			
		||||
				cerr << "LEVEL: " << level[headr[1]>>4 & 0xF] << endl;
 | 
			
		||||
				cerr << "CHROMA: " << chroma[headr[1]>>1 & 0x3] << endl;
 | 
			
		||||
				found = 1;
 | 
			
		||||
			} else {
 | 
			
		||||
				mpeg = 1;
 | 
			
		||||
				found = 1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (! found) stream.seekg(p+streampos(1));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stream.seekg(q);
 | 
			
		||||
	return (form | mpeg << 4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int stream_type(istream &fin){
 | 
			
		||||
	uint8_t headr[4];
 | 
			
		||||
	streampos p=fin.tellg();
 | 
			
		||||
	
 | 
			
		||||
	TS_Packet ts;
 | 
			
		||||
	fin >> ts;
 | 
			
		||||
	fin.read((char *)headr,1);
 | 
			
		||||
	fin.seekg(p);
 | 
			
		||||
	if(fin && headr[0] == 0x47){
 | 
			
		||||
		return TS_STREAM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	PS_Packet ps;
 | 
			
		||||
	fin >> ps;
 | 
			
		||||
	PES_Packet pes;
 | 
			
		||||
	for(int j=0;j < ps.NPES();j++){
 | 
			
		||||
		fin >> pes;
 | 
			
		||||
	}
 | 
			
		||||
	fin.read((char *)headr,4);
 | 
			
		||||
	fin.seekg(p);
 | 
			
		||||
	if (fin && headr[0] == 0x00 && headr[1] == 0x00
 | 
			
		||||
	    && headr[2] == 0x01 && headr[3] == 0xBA){
 | 
			
		||||
		return PS_STREAM;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	fin >> pes;
 | 
			
		||||
	fin.read((char *)NULL,4);
 | 
			
		||||
			fin.seekg(p);
 | 
			
		||||
	if (fin && headr[0] == 0x00 && headr[1] == 0x00
 | 
			
		||||
	    && headr[2] == 0x01 ){
 | 
			
		||||
		int found = 0;
 | 
			
		||||
		switch ( headr[3] ) {
 | 
			
		||||
			
 | 
			
		||||
		case PROG_STREAM_MAP:
 | 
			
		||||
		case PRIVATE_STREAM2:
 | 
			
		||||
		case PROG_STREAM_DIR:
 | 
			
		||||
		case ECM_STREAM     :
 | 
			
		||||
		case EMM_STREAM     :
 | 
			
		||||
		case PADDING_STREAM :
 | 
			
		||||
		case DSM_CC_STREAM  :
 | 
			
		||||
		case ISO13522_STREAM:
 | 
			
		||||
		case PRIVATE_STREAM1:
 | 
			
		||||
		case AUDIO_STREAM_S ... AUDIO_STREAM_E:
 | 
			
		||||
		case VIDEO_STREAM_S ... VIDEO_STREAM_E:
 | 
			
		||||
			found = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (found){
 | 
			
		||||
			return PES_STREAM;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
	return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void analyze(istream &fin)
 | 
			
		||||
{
 | 
			
		||||
	PS_Packet ps;
 | 
			
		||||
	PES_Packet pes;
 | 
			
		||||
	int fc = 0;
 | 
			
		||||
	const char *frames[3] = {"I-Frame","P-Frame","B-Frame"};
 | 
			
		||||
			
 | 
			
		||||
	while(fin){
 | 
			
		||||
		uint32_t pts;
 | 
			
		||||
		fin >> ps;
 | 
			
		||||
		cerr << "SCR base: " << hex << setw(5) 
 | 
			
		||||
		     << setfill('0') \
 | 
			
		||||
		     << ps.SCR_base() << " " << dec
 | 
			
		||||
		     << "ext : " << ps.SCR_ext();
 | 
			
		||||
 | 
			
		||||
		cerr << "   MUX rate: " << ps.MUX()*50*8/1000000.0
 | 
			
		||||
		     << " Mbit/s   ";
 | 
			
		||||
		cerr << "RATE bound: " << ps.Rate()*50*8/1000000.0
 | 
			
		||||
		     << " Mbit/s" << endl;
 | 
			
		||||
		cerr << "                             Audio bound: " 
 | 
			
		||||
		     << hex << "0x" 
 | 
			
		||||
		     << int(ps.P()->audio_bound);
 | 
			
		||||
		cerr << "         Video bound: " << hex << "0x" 
 | 
			
		||||
		     << int(ps.P()->video_bound)
 | 
			
		||||
		     << dec
 | 
			
		||||
		     << endl;
 | 
			
		||||
		cerr << endl;
 | 
			
		||||
 | 
			
		||||
		for (int i=0; i < ps.NPES(); i++){
 | 
			
		||||
			pes.init();
 | 
			
		||||
			fin >> pes;
 | 
			
		||||
			pts2pts((uint8_t *)&pts,pes.PTS());
 | 
			
		||||
			pes.Info() = 1;
 | 
			
		||||
			cerr  << pes;
 | 
			
		||||
 | 
			
		||||
			uint8_t *buf = pes.P()->pes_pckt_data;
 | 
			
		||||
			int c = 0;
 | 
			
		||||
			int l;
 | 
			
		||||
			switch (pes.P()->stream_id){
 | 
			
		||||
			case VIDEO_STREAM_S ... VIDEO_STREAM_E:
 | 
			
		||||
				l=pes.P()->length;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				l = 0;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			while ( c < l - 6){
 | 
			
		||||
				if (buf[c] == 0x00 && 
 | 
			
		||||
				    buf[c+1] == 0x00 &&
 | 
			
		||||
				    buf[c+2] == 0x01 && 
 | 
			
		||||
				    buf[c+3] == 0xB8) {
 | 
			
		||||
					c += 4;
 | 
			
		||||
					cerr << "TIME   hours: " 
 | 
			
		||||
					     << int((buf[c]>>2)& 0x1F)
 | 
			
		||||
					     << "  minutes: "
 | 
			
		||||
					     << int(((buf[c]<<4)& 0x30)|
 | 
			
		||||
						    ((buf[c+1]>>4)& 0x0F))
 | 
			
		||||
					     << " seconds: "
 | 
			
		||||
					     << int(((buf[c+1]<<3)& 0x38)|
 | 
			
		||||
						    ((buf[c+2]>>5)& 0x0F))
 | 
			
		||||
					     << endl;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
				if ( buf[c] == 0x00 && 
 | 
			
		||||
				     buf[c+1] == 0x00 &&
 | 
			
		||||
				     buf[c+2] == 0x01 && 
 | 
			
		||||
				     buf[c+3] == 0x00) {
 | 
			
		||||
					fc++;
 | 
			
		||||
					c += 4;
 | 
			
		||||
					cerr << "picture: " 
 | 
			
		||||
					     << fc 
 | 
			
		||||
					     << " ("
 | 
			
		||||
					     << frames[((buf[c+1]&0x38) >>3)-1]
 | 
			
		||||
					     << ")" << endl << endl;
 | 
			
		||||
				} else c++;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,330 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  dvb-mpegtools for the Siemens Fujitsu DVB PCI card
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2000, 2001 Marcus Metzler 
 | 
			
		||||
 *            for convergence integrated media GmbH
 | 
			
		||||
 * Copyright (C) 2002 Marcus Metzler 
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2
 | 
			
		||||
 * of the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 | 
			
		||||
 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
 | 
			
		||||
 * 
 | 
			
		||||
 | 
			
		||||
 * The author can be reached at mocm@metzlerbros.de, 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef _CPPTOOLS_HH_
 | 
			
		||||
#define _CPPTOOLS_HH_
 | 
			
		||||
 | 
			
		||||
#include "ctools.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PES_Packet{
 | 
			
		||||
	int info;
 | 
			
		||||
	pes_packet p;
 | 
			
		||||
public:
 | 
			
		||||
	PES_Packet(){
 | 
			
		||||
		info = 0;
 | 
			
		||||
		init_pes(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~PES_Packet(){
 | 
			
		||||
		if (p.pack_header)
 | 
			
		||||
			delete [] p.pack_header;
 | 
			
		||||
		if (p.pes_ext)
 | 
			
		||||
			delete [] p.pes_ext;
 | 
			
		||||
		if (p.pes_pckt_data)
 | 
			
		||||
			delete [] p.pes_pckt_data;
 | 
			
		||||
		if (p.mpeg1_headr)
 | 
			
		||||
			delete [] p.mpeg1_headr;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline void init(){
 | 
			
		||||
		if (p.pack_header)
 | 
			
		||||
			delete [] p.pack_header;
 | 
			
		||||
		if (p.pes_ext)
 | 
			
		||||
			delete [] p.pes_ext;
 | 
			
		||||
		if (p.pes_pckt_data)
 | 
			
		||||
			delete [] p.pes_pckt_data;
 | 
			
		||||
		if (p.mpeg1_headr)
 | 
			
		||||
			delete [] p.mpeg1_headr;
 | 
			
		||||
 | 
			
		||||
		info = 0;
 | 
			
		||||
		init_pes(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline pes_packet *P(){
 | 
			
		||||
		return &p;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void setlength(){
 | 
			
		||||
		setlength_pes(&p);
 | 
			
		||||
		if (p.length)
 | 
			
		||||
			p.pes_pckt_data = new uint8_t[p.length];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void Nlength(){
 | 
			
		||||
		nlength_pes(&p);
 | 
			
		||||
		p.pes_pckt_data = new uint8_t[p.length];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	inline uint8_t &Stream_ID(){
 | 
			
		||||
		return p.stream_id;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t &Flags1(){
 | 
			
		||||
		return p.flags1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t &Flags2(){
 | 
			
		||||
		return p.flags2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint32_t &Length(){
 | 
			
		||||
		return p.length;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline uint8_t &HLength(){
 | 
			
		||||
		return p.pes_hlength;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t &Stuffing(){
 | 
			
		||||
		return p.stuffing;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t *Data(){
 | 
			
		||||
		return p.pes_pckt_data;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline int has_pts(){
 | 
			
		||||
		return (p.flags2 & PTS_DTS);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int &MPEG(){
 | 
			
		||||
		return p.mpeg;
 | 
			
		||||
	}
 | 
			
		||||
	inline uint8_t *PTS(){
 | 
			
		||||
		return p.pts;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t *DTS(){
 | 
			
		||||
		return p.dts;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int &Info(){
 | 
			
		||||
		return info;
 | 
			
		||||
	}
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
	inline uint8_t high_pts(){
 | 
			
		||||
		if (has_pts())
 | 
			
		||||
			return ((p.pts[0] & 0x08)>>3);
 | 
			
		||||
		else
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t high_dts(){
 | 
			
		||||
		return ((p.dts[0] & 0x08)>>3);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int WDTS(){
 | 
			
		||||
		int w_dts;
 | 
			
		||||
		w_dts = (int)trans_pts_dts(p.dts);
 | 
			
		||||
		return w_dts;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int WPTS(){
 | 
			
		||||
		int w_dts;
 | 
			
		||||
		w_dts = (int)trans_pts_dts(p.pts);
 | 
			
		||||
		return w_dts;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	friend ostream & operator << (ostream & stream, PES_Packet & x);
 | 
			
		||||
	friend istream & operator >> (istream & stream, PES_Packet & x);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TS_Packet{
 | 
			
		||||
	ts_packet p;
 | 
			
		||||
	int info;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	TS_Packet(){
 | 
			
		||||
		init_ts(&p);
 | 
			
		||||
		info = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~TS_Packet(){
 | 
			
		||||
		if (p.priv_dat)
 | 
			
		||||
			delete [] p.priv_dat;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline void init(){
 | 
			
		||||
		if (p.priv_dat)
 | 
			
		||||
			delete [] p.priv_dat;
 | 
			
		||||
 | 
			
		||||
		init_ts(&p);
 | 
			
		||||
		info = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline ts_packet *P(){
 | 
			
		||||
		return &p;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
	inline int &Rest(){
 | 
			
		||||
		return p.rest;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t *Data(){
 | 
			
		||||
		return p.data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline short PID(){
 | 
			
		||||
		return pid_ts(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t FLAG1(){
 | 
			
		||||
		return (p.pid[0] & ~PID_MASK_HI);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int &Info(){
 | 
			
		||||
		return info;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	friend ostream & operator << (ostream & stream, TS_Packet & x);
 | 
			
		||||
	friend istream & operator >> (istream & stream, TS_Packet & x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class PS_Packet{
 | 
			
		||||
	int info;
 | 
			
		||||
	ps_packet p;
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
	PS_Packet(){
 | 
			
		||||
		init_ps(&p);
 | 
			
		||||
		info = 0;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	~PS_Packet(){
 | 
			
		||||
		if (p.data)
 | 
			
		||||
			delete [] p.data;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void init(){
 | 
			
		||||
		if (p.data)
 | 
			
		||||
			delete [] p.data;
 | 
			
		||||
 | 
			
		||||
		init_ps(&p);
 | 
			
		||||
		info = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline ps_packet *P(){
 | 
			
		||||
		return &p;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int MUX(){
 | 
			
		||||
		return mux_ps(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int Rate(){
 | 
			
		||||
		return rate_ps(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void setlength(){
 | 
			
		||||
		setlength_ps(&p);
 | 
			
		||||
		p.data = new uint8_t[p.sheader_length];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int Stuffing(){
 | 
			
		||||
		return p.stuff_length & PACK_STUFF_MASK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int NPES(){
 | 
			
		||||
		return p.npes;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int &MPEG(){
 | 
			
		||||
		return p.mpeg;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline uint8_t &operator()(int l){
 | 
			
		||||
		return p.data[l];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline char * Data() {
 | 
			
		||||
		return (char *)p.data+p.stuff_length;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline int &SLENGTH(){
 | 
			
		||||
		return p.sheader_length;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	inline int &Info(){
 | 
			
		||||
		return info;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	uint32_t SCR_base(){
 | 
			
		||||
		return scr_base_ps(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint16_t SCR_ext(){
 | 
			
		||||
		return scr_ext_ps(&p);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	friend ostream & operator << (ostream & stream, PS_Packet & x);
 | 
			
		||||
	friend istream & operator >> (istream & stream, PS_Packet & x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef void (* FILTER)(istream &in, ostream &out);
 | 
			
		||||
 | 
			
		||||
typedef struct thread_args_{
 | 
			
		||||
	FILTER function;
 | 
			
		||||
	int *fd;
 | 
			
		||||
	int in;
 | 
			
		||||
	int out;
 | 
			
		||||
} thread_args;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void extract_audio_from_PES(istream &in, ostream &out);
 | 
			
		||||
void extract_video_from_PES(istream &in, ostream &out);
 | 
			
		||||
void extract_es_audio_from_PES(istream &in, ostream &out);
 | 
			
		||||
void extract_es_video_from_PES(istream &in, ostream &out);
 | 
			
		||||
int TS_PIDS(istream &in, ostream &out);
 | 
			
		||||
int ifilter (istream &in, FILTER function);
 | 
			
		||||
int ofilter (istream &in, FILTER function);
 | 
			
		||||
int itfilter (int in, FILTER function);
 | 
			
		||||
int otfilter (istream &in, FILTER function);
 | 
			
		||||
int stream_type(int fd);
 | 
			
		||||
int stream_type(istream &stream);
 | 
			
		||||
int tv_norm(istream &fin);
 | 
			
		||||
 | 
			
		||||
void analyze(istream &fin);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //_CPPTOOLS_HH_
 | 
			
		||||
 | 
			
		||||
@@ -1,310 +0,0 @@
 | 
			
		||||
#ifndef _channel_hh
 | 
			
		||||
#define _channel_hh
 | 
			
		||||
 | 
			
		||||
using namespace std;
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
 | 
			
		||||
#include "DVB.hh"
 | 
			
		||||
 | 
			
		||||
#define MAXNAM 80
 | 
			
		||||
#define MAXKEY 15
 | 
			
		||||
 | 
			
		||||
const int maxname=80;
 | 
			
		||||
const int MAXAPIDS=32;
 | 
			
		||||
const uint32_t UNSET=0xffffffff;
 | 
			
		||||
const uint16_t NOID=0xffff;
 | 
			
		||||
const uint16_t NOPID=0xffff;
 | 
			
		||||
 | 
			
		||||
class Transponder {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        uint16_t onid;
 | 
			
		||||
        uint16_t satid;
 | 
			
		||||
        int type;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        uint32_t freq;
 | 
			
		||||
        int pol;
 | 
			
		||||
        int qam;
 | 
			
		||||
        uint32_t srate;
 | 
			
		||||
        int fec;
 | 
			
		||||
        int band;
 | 
			
		||||
        int hp_rate;         
 | 
			
		||||
	int lp_rate; 
 | 
			
		||||
        int mod;    
 | 
			
		||||
        int transmode;
 | 
			
		||||
        int guard;
 | 
			
		||||
        int hierarchy;
 | 
			
		||||
 | 
			
		||||
        struct Sat *sat;
 | 
			
		||||
        
 | 
			
		||||
        Transponder() {
 | 
			
		||||
		name[0]='\0';
 | 
			
		||||
		id = NOID;
 | 
			
		||||
		onid = NOID;
 | 
			
		||||
		satid = NOID;
 | 
			
		||||
		type = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Transponder &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Transponder &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Sat {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        unsigned int lnbid;
 | 
			
		||||
        struct Lnb *lnb;
 | 
			
		||||
        unsigned int rotorid;
 | 
			
		||||
        unsigned int fmin;
 | 
			
		||||
        unsigned int fmax;
 | 
			
		||||
 | 
			
		||||
        Sat() {
 | 
			
		||||
	        id=NOID;
 | 
			
		||||
		name[0]='\0';
 | 
			
		||||
		lnb=NULL;
 | 
			
		||||
	        rotorid=NOID;
 | 
			
		||||
	        lnbid=NOID;
 | 
			
		||||
		fmin=fmax=0;
 | 
			
		||||
	};
 | 
			
		||||
	int set(int sid, char *sname, int slnbid, int srotorid) {
 | 
			
		||||
	  return 0;
 | 
			
		||||
        }; 
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Sat &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Sat &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Lnb {
 | 
			
		||||
public:
 | 
			
		||||
        Sat *sat;
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        struct DVB *dvbd;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        int type;
 | 
			
		||||
        unsigned int lof1;
 | 
			
		||||
        unsigned int lof2;
 | 
			
		||||
        unsigned int slof;
 | 
			
		||||
        int diseqcnr;
 | 
			
		||||
        uint16_t diseqcid;
 | 
			
		||||
        uint16_t swiid;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        void cpy (const Lnb &olnb){
 | 
			
		||||
	  this->id=olnb.id;
 | 
			
		||||
	  this->type=olnb.type;
 | 
			
		||||
	  this->lof1=olnb.lof1;
 | 
			
		||||
	  this->lof2=olnb.lof2;
 | 
			
		||||
	  this->slof=olnb.slof;
 | 
			
		||||
	  this->diseqcnr=olnb.diseqcnr;
 | 
			
		||||
	  this->diseqcid=olnb.diseqcid;
 | 
			
		||||
	  this->swiid=olnb.swiid;
 | 
			
		||||
	  strncpy(this->name,olnb.name,maxname);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        void init(int t, uint l1, uint l2, uint sl,
 | 
			
		||||
		  int dnr, int disid, int sw) {
 | 
			
		||||
		type=t;
 | 
			
		||||
		lof1=l1;
 | 
			
		||||
		lof2=l2;
 | 
			
		||||
		slof=sl;
 | 
			
		||||
		diseqcnr=dnr;
 | 
			
		||||
		diseqcid=disid;
 | 
			
		||||
		swiid=sw;
 | 
			
		||||
		dvbd=0;
 | 
			
		||||
		name[0]='\0';
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        Lnb () {
 | 
			
		||||
	        lof1=lof2=slof=0;
 | 
			
		||||
	        swiid=NOID;
 | 
			
		||||
		diseqcid=NOID;
 | 
			
		||||
		diseqcnr=-1;
 | 
			
		||||
		name[0]='\0';
 | 
			
		||||
	}
 | 
			
		||||
  
 | 
			
		||||
        Lnb (const Lnb &olnb){
 | 
			
		||||
          cpy(olnb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Lnb &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Lnb &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct diseqcmsg {
 | 
			
		||||
        int burst;
 | 
			
		||||
        int len;
 | 
			
		||||
        unsigned char msg[8];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DiSEqC {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        diseqcmsg msgs[4];
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, DiSEqC &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, DiSEqC &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Rotor {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        diseqcmsg msgs[4];
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Rotor &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Rotor &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Switch {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        int switchid;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        diseqcmsg msg;
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Switch &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Switch &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Network {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Network &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Network &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Bouquet {
 | 
			
		||||
public:
 | 
			
		||||
        uint16_t id;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Bouquet &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Bouquet &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define MAX_ECM 16
 | 
			
		||||
#define MAX_ECM_DESC 256
 | 
			
		||||
typedef struct ecm_struct {
 | 
			
		||||
        int num;
 | 
			
		||||
        uint16_t sysid[MAX_ECM];
 | 
			
		||||
        uint16_t pid[MAX_ECM];
 | 
			
		||||
	uint16_t length[MAX_ECM];
 | 
			
		||||
	uint8_t data[MAX_ECM*MAX_ECM_DESC];
 | 
			
		||||
} ecm_t;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Channel{
 | 
			
		||||
public:
 | 
			
		||||
        Channel *next;
 | 
			
		||||
        uint32_t id;
 | 
			
		||||
        char name[maxname+1];
 | 
			
		||||
        int32_t type;
 | 
			
		||||
	int checked;
 | 
			
		||||
  
 | 
			
		||||
        uint16_t pnr;
 | 
			
		||||
        uint16_t vpid;
 | 
			
		||||
        uint16_t apids[MAXAPIDS];
 | 
			
		||||
        char apids_name[MAXAPIDS*4];
 | 
			
		||||
        int32_t  apidnum;
 | 
			
		||||
        int  last_apidn;
 | 
			
		||||
        uint16_t ac3pid;
 | 
			
		||||
        uint16_t ttpid;
 | 
			
		||||
        uint16_t pmtpid;
 | 
			
		||||
        uint16_t pcrpid;
 | 
			
		||||
        uint16_t casystem;
 | 
			
		||||
        uint16_t capid;
 | 
			
		||||
 | 
			
		||||
	ecm_t  ecm;
 | 
			
		||||
	int (*ecm_callback)(Channel *chan);
 | 
			
		||||
 | 
			
		||||
	int has_eit;
 | 
			
		||||
	int pres_follow;
 | 
			
		||||
 | 
			
		||||
        uint16_t satid;
 | 
			
		||||
        uint16_t tpid;
 | 
			
		||||
        uint16_t onid;
 | 
			
		||||
        uint16_t bid;
 | 
			
		||||
	int8_t eit_ver_n;
 | 
			
		||||
	int8_t eit_ver_c;
 | 
			
		||||
 | 
			
		||||
        void clearall(void) {
 | 
			
		||||
	        id=UNSET;
 | 
			
		||||
		name[0]='\0';
 | 
			
		||||
		type=0;
 | 
			
		||||
		checked = 0;
 | 
			
		||||
		has_eit = -1;
 | 
			
		||||
		pres_follow = -1;
 | 
			
		||||
		eit_ver_c = -1;
 | 
			
		||||
		eit_ver_n = -1;
 | 
			
		||||
		
 | 
			
		||||
		pnr=NOPID;
 | 
			
		||||
		vpid=NOPID;
 | 
			
		||||
		memset(apids, 0, sizeof(uint16_t)*MAXAPIDS);
 | 
			
		||||
		memset(apids_name, 0, sizeof(char)*MAXAPIDS*4);
 | 
			
		||||
		apidnum=0;
 | 
			
		||||
		last_apidn=-1;
 | 
			
		||||
		ac3pid=NOPID;
 | 
			
		||||
		ttpid=NOPID;
 | 
			
		||||
		pmtpid=NOPID;
 | 
			
		||||
		pcrpid=NOPID;
 | 
			
		||||
		capid=NOPID;
 | 
			
		||||
 | 
			
		||||
		satid=NOID;
 | 
			
		||||
		tpid=NOID;
 | 
			
		||||
		onid=NOID;
 | 
			
		||||
		bid=NOID;
 | 
			
		||||
		ecm_callback = NULL;
 | 
			
		||||
		memset(&ecm,0, sizeof(ecm_t));
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
        Channel() {
 | 
			
		||||
	        clearall();
 | 
			
		||||
	}
 | 
			
		||||
  
 | 
			
		||||
        Channel(int cid, char *nam, int ty, int prognr,
 | 
			
		||||
		int vid, int aid, int tid) {
 | 
			
		||||
	        int l=strlen(nam);
 | 
			
		||||
 | 
			
		||||
		clearall();
 | 
			
		||||
		if (l>maxname){
 | 
			
		||||
		  cerr << "" << endl; 
 | 
			
		||||
		  l=maxname;
 | 
			
		||||
		}
 | 
			
		||||
		strncpy(name, nam, l);
 | 
			
		||||
		name[l]='\0';
 | 
			
		||||
		type=ty;
 | 
			
		||||
		pnr=prognr;
 | 
			
		||||
		vpid=vid;
 | 
			
		||||
		apids[0]=aid;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
        ~Channel(){
 | 
			
		||||
	        cerr <<"Channel " << name << "  destroyed" << endl;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
        friend ostream &operator<<(ostream &stream, Channel &x);
 | 
			
		||||
        friend istream &operator>>(istream &stream, Channel &x);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int findkey(char *name, char *keys[]);
 | 
			
		||||
void getname(char *name,istream &ins);
 | 
			
		||||
#endif /*channel.h*/
 | 
			
		||||
@@ -1,84 +0,0 @@
 | 
			
		||||
#ifndef _OSD_HH_
 | 
			
		||||
#define _OSD_HH_
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
#include "OSD.h"
 | 
			
		||||
}
 | 
			
		||||
struct OSD {
 | 
			
		||||
        int dev;
 | 
			
		||||
        
 | 
			
		||||
        void init(int d) {
 | 
			
		||||
	        dev=d;
 | 
			
		||||
	}
 | 
			
		||||
        int Open(int x0, int y0, int x1, int y1, int BitPerPixel, int mix, int win) {
 | 
			
		||||
	        if (OSDSetWindow(dev, win))
 | 
			
		||||
		        return -1;
 | 
			
		||||
	        return OSDOpen(dev, x0, y0, x1, y1, BitPerPixel, mix);
 | 
			
		||||
	}
 | 
			
		||||
        int Open(int x0, int y0, int x1, int y1, int BitPerPixel, int mix) {
 | 
			
		||||
	        return OSDOpen(dev, x0, y0, x1, y1, BitPerPixel, mix);
 | 
			
		||||
	}
 | 
			
		||||
        int Close(int win) {
 | 
			
		||||
	        if (OSDSetWindow(dev, win))
 | 
			
		||||
		        return -1;
 | 
			
		||||
	        return OSDClose(dev);
 | 
			
		||||
	}
 | 
			
		||||
        int Close(void) {
 | 
			
		||||
	        return OSDClose(dev);
 | 
			
		||||
	}
 | 
			
		||||
        int Show(void) {
 | 
			
		||||
	        return OSDShow(dev);
 | 
			
		||||
	}
 | 
			
		||||
        int Hide(void) {
 | 
			
		||||
	        return OSDHide(dev);
 | 
			
		||||
	}
 | 
			
		||||
        int Clear(void) {
 | 
			
		||||
	        return OSDClear(dev);
 | 
			
		||||
	}
 | 
			
		||||
        int Fill(int color) {
 | 
			
		||||
	        return OSDFill(dev, color);
 | 
			
		||||
	}
 | 
			
		||||
        int SetColor(int color, int r, int g, int b, int op) {
 | 
			
		||||
	        return OSDSetColor(dev, color, r, g, b, op);
 | 
			
		||||
	}
 | 
			
		||||
        int Text(int x, int y, int size, int color, const char *text) {
 | 
			
		||||
	        return OSDText(dev, x, y, size, color, text); 
 | 
			
		||||
	}
 | 
			
		||||
        int SetPalette(int first, int last, unsigned char *data) {
 | 
			
		||||
	        return OSDSetPalette(dev, first, last, data);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
        int SetTrans(int trans) {
 | 
			
		||||
	        return OSDSetTrans(dev, trans);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
        int SetPixel(int dev, int x, int y, unsigned int color) {
 | 
			
		||||
	        return OSDSetPixel(dev, x, y, color); 
 | 
			
		||||
	}
 | 
			
		||||
        int GetPixel(int dev, int x, int y) {
 | 
			
		||||
	        return OSDGetPixel(dev, x, y); 
 | 
			
		||||
	}
 | 
			
		||||
        int SetRow(int x, int y, int x1, unsigned char *data) {
 | 
			
		||||
	        return OSDSetRow(dev, x, y, x1, data); 
 | 
			
		||||
	}
 | 
			
		||||
        int SetBlock(int x, int y, int x1, int y1, int inc, unsigned char *data) {
 | 
			
		||||
	        return OSDSetBlock(dev, x, y, x1, y1, inc, data); 
 | 
			
		||||
	}
 | 
			
		||||
        int FillRow(int x, int y, int x1, int color) {
 | 
			
		||||
	        return OSDFillRow(dev, x, y, x1, color); 
 | 
			
		||||
	}
 | 
			
		||||
        int FillBlock(int x, int y, int x1, int y1, int color) {
 | 
			
		||||
	        return OSDFillBlock(dev, x, y, x1, y1, color); 
 | 
			
		||||
	}
 | 
			
		||||
        int Line(int x, int y, int x1, int y1, int color) {
 | 
			
		||||
	        return OSDLine(dev, x, y, x1, y1, color); 
 | 
			
		||||
	}
 | 
			
		||||
        int Query() {
 | 
			
		||||
	        return OSDQuery(dev); 
 | 
			
		||||
	}
 | 
			
		||||
        int SetWindow(int win) {
 | 
			
		||||
	        return OSDSetWindow(dev, win); 
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
# The cannels.conf ca field can be used to bind a channel to a specific
 | 
			
		||||
# device. The streamdev-client does not consider this information, so
 | 
			
		||||
# there's no way to keep VDR from using streamdev for a specific
 | 
			
		||||
# channel. Apply this patch if you need this feature.
 | 
			
		||||
#
 | 
			
		||||
# This fix should probably become part of streamdev. However as it
 | 
			
		||||
# changes the behaviour of streamdev, I decided to keep it as a separate
 | 
			
		||||
# patch until there is something like a new official streamdev release.
 | 
			
		||||
#
 | 
			
		||||
--- client/device.h.bak	2006-11-09 12:25:21.000000000 +0100
 | 
			
		||||
+++ client/device.h	2006-11-09 12:26:57.000000000 +0100
 | 
			
		||||
@@ -50,6 +50,7 @@
 | 
			
		||||
 	cStreamdevDevice(void);
 | 
			
		||||
 	virtual ~cStreamdevDevice();
 | 
			
		||||
 
 | 
			
		||||
+	virtual int ProvidesCa(const cChannel *Channel) const;
 | 
			
		||||
 	virtual bool ProvidesSource(int Source) const;
 | 
			
		||||
   virtual bool ProvidesTransponder(const cChannel *Channel) const;
 | 
			
		||||
 	virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1,
 | 
			
		||||
--- client/device.c.bak	2006-11-09 12:23:24.000000000 +0100
 | 
			
		||||
+++ client/device.c	2006-11-09 12:35:48.000000000 +0100
 | 
			
		||||
@@ -57,6 +57,12 @@
 | 
			
		||||
 #endif
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+int cStreamdevDevice::ProvidesCa(const cChannel *Channel) const
 | 
			
		||||
+{
 | 
			
		||||
+	// Encrypted is acceptable for now. Will ask the server later.
 | 
			
		||||
+	return Channel->Ca() <= CA_DVB_MAX ? cDevice::ProvidesCa(Channel) : 1;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 bool cStreamdevDevice::ProvidesSource(int Source) const {
 | 
			
		||||
 	Dprintf("ProvidesSource, Source=%d\n", Source);
 | 
			
		||||
 	return false;
 | 
			
		||||
@@ -78,7 +84,7 @@
 | 
			
		||||
 	if (ClientSocket.DataSocket(siLive) != NULL 
 | 
			
		||||
 			&& TRANSPONDER(Channel, m_Channel))
 | 
			
		||||
 		res = true;
 | 
			
		||||
-	else {
 | 
			
		||||
+	else if (ProvidesCa(Channel)) {
 | 
			
		||||
 		res = prio && ClientSocket.ProvidesChannel(Channel, Priority);
 | 
			
		||||
 		ndr = true;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
--- vdr-vanilla/thread.c	2003-10-10 18:19:15.000000000 +0200
 | 
			
		||||
+++ vdr-vanilla-thread/thread.c	2003-10-10 18:43:36.000000000 +0200
 | 
			
		||||
@@ -158,12 +158,21 @@
 | 
			
		||||
 
 | 
			
		||||
 bool cThread::Active(void)
 | 
			
		||||
 {
 | 
			
		||||
-  if (threadPid) {
 | 
			
		||||
-     if (kill(threadPid, SIGIO) < 0) { // couldn't find another way of checking whether the thread is still running - any ideas?
 | 
			
		||||
-        if (errno == ESRCH)
 | 
			
		||||
-           threadPid = 0;
 | 
			
		||||
-        else
 | 
			
		||||
+  if (thread) {
 | 
			
		||||
+     /*
 | 
			
		||||
+      * Single UNIX Spec v2 says:
 | 
			
		||||
+      *
 | 
			
		||||
+      * The pthread_kill() function is used to request
 | 
			
		||||
+      * that a signal be delivered to the specified thread.
 | 
			
		||||
+      *
 | 
			
		||||
+      * As in kill(), if sig is zero, error checking is
 | 
			
		||||
+      * performed but no signal is actually sent.
 | 
			
		||||
+      */
 | 
			
		||||
+     int err;
 | 
			
		||||
+     if ((err = pthread_kill(thread, 0)) != 0) {
 | 
			
		||||
+        if (err != ESRCH)
 | 
			
		||||
            LOG_ERROR;
 | 
			
		||||
+        thread = 0;
 | 
			
		||||
         }
 | 
			
		||||
      else
 | 
			
		||||
         return true;
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
diff -u vdr-1.3.11/config.c vdr-1.3.11.LocalChannelProvide/config.c
 | 
			
		||||
--- vdr-1.3.11/config.c	2004-05-16 14:43:55.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.11.LocalChannelProvide/config.c	2004-08-29 17:55:59.000000000 +0200
 | 
			
		||||
@@ -297,6 +297,7 @@
 | 
			
		||||
   ResumeID = 0;
 | 
			
		||||
   CurrentChannel = -1;
 | 
			
		||||
   CurrentVolume = MAXVOLUME;
 | 
			
		||||
+  LocalChannelProvide = 1;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 cSetup& cSetup::operator= (const cSetup &s)
 | 
			
		||||
@@ -450,6 +451,7 @@
 | 
			
		||||
   else if (!strcasecmp(Name, "ResumeID"))            ResumeID           = atoi(Value);
 | 
			
		||||
   else if (!strcasecmp(Name, "CurrentChannel"))      CurrentChannel     = atoi(Value);
 | 
			
		||||
   else if (!strcasecmp(Name, "CurrentVolume"))       CurrentVolume      = atoi(Value);
 | 
			
		||||
+  else if (!strcasecmp(Name, "LocalChannelProvide")) LocalChannelProvide = atoi(Value);
 | 
			
		||||
   else
 | 
			
		||||
      return false;
 | 
			
		||||
   return true;
 | 
			
		||||
@@ -510,6 +512,7 @@
 | 
			
		||||
   Store("ResumeID",           ResumeID);
 | 
			
		||||
   Store("CurrentChannel",     CurrentChannel);
 | 
			
		||||
   Store("CurrentVolume",      CurrentVolume);
 | 
			
		||||
+  Store("LocalChannelProvide",LocalChannelProvide);
 | 
			
		||||
 
 | 
			
		||||
   Sort();
 | 
			
		||||
 
 | 
			
		||||
diff -u vdr-1.3.11/config.h vdr-1.3.11.LocalChannelProvide/config.h
 | 
			
		||||
--- vdr-1.3.11/config.h	2004-06-10 15:18:50.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.11.LocalChannelProvide/config.h	2004-08-29 17:47:32.000000000 +0200
 | 
			
		||||
@@ -251,6 +251,7 @@
 | 
			
		||||
   int ResumeID;
 | 
			
		||||
   int CurrentChannel;
 | 
			
		||||
   int CurrentVolume;
 | 
			
		||||
+  int LocalChannelProvide;
 | 
			
		||||
   int __EndData__;
 | 
			
		||||
   cSetup(void);
 | 
			
		||||
   cSetup& operator= (const cSetup &s);
 | 
			
		||||
diff -u vdr-1.3.11/dvbdevice.c vdr-1.3.11.LocalChannelProvide/dvbdevice.c
 | 
			
		||||
--- vdr-1.3.11/dvbdevice.c	2004-06-19 11:33:42.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.11.LocalChannelProvide/dvbdevice.c	2004-08-29 18:00:37.000000000 +0200
 | 
			
		||||
@@ -674,6 +674,8 @@
 | 
			
		||||
 
 | 
			
		||||
 bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
 | 
			
		||||
 {
 | 
			
		||||
+  if (Setup.LocalChannelProvide != 1)
 | 
			
		||||
+    return false;
 | 
			
		||||
   bool result = false;
 | 
			
		||||
   bool hasPriority = Priority < 0 || Priority > this->Priority();
 | 
			
		||||
   bool needsDetachReceivers = false;
 | 
			
		||||
diff -u vdr-1.3.11/menu.c vdr-1.3.11.LocalChannelProvide/menu.c
 | 
			
		||||
--- vdr-1.3.11/menu.c	2004-06-13 22:26:51.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.11.LocalChannelProvide/menu.c	2004-08-29 17:52:31.000000000 +0200
 | 
			
		||||
@@ -1878,6 +1878,7 @@
 | 
			
		||||
   Add(new cMenuEditIntItem( tr("Setup.DVB$Primary DVB interface"), &data.PrimaryDVB, 1, cDevice::NumDevices()));
 | 
			
		||||
   Add(new cMenuEditBoolItem(tr("Setup.DVB$Video format"),          &data.VideoFormat, "4:3", "16:9"));
 | 
			
		||||
   Add(new cMenuEditStraItem(tr("Setup.DVB$Update channels"),       &data.UpdateChannels, 5, updateChannelsTexts));
 | 
			
		||||
+  Add(new cMenuEditBoolItem(tr("Channels available locally"),      &data.LocalChannelProvide));
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 eOSState cMenuSetupDVB::ProcessKey(eKeys Key)
 | 
			
		||||
@@ -1,93 +0,0 @@
 | 
			
		||||
diff -Nu vdr-1.3.24/config.c vdr-1.3.24.LocalChannelProvide/config.c
 | 
			
		||||
--- vdr-1.3.24/config.c	2005-02-20 13:52:59.000000000 +0100
 | 
			
		||||
+++ vdr-1.3.24.LocalChannelProvide/config.c	2005-05-12 19:23:58.000000000 +0200
 | 
			
		||||
@@ -301,6 +301,7 @@
 | 
			
		||||
   CurrentChannel = -1;
 | 
			
		||||
   CurrentVolume = MAXVOLUME;
 | 
			
		||||
   CurrentDolby = 0;
 | 
			
		||||
+  LocalChannelProvide = 1;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 cSetup& cSetup::operator= (const cSetup &s)
 | 
			
		||||
@@ -458,6 +459,7 @@
 | 
			
		||||
   else if (!strcasecmp(Name, "CurrentChannel"))      CurrentChannel     = atoi(Value);
 | 
			
		||||
   else if (!strcasecmp(Name, "CurrentVolume"))       CurrentVolume      = atoi(Value);
 | 
			
		||||
   else if (!strcasecmp(Name, "CurrentDolby"))        CurrentDolby       = atoi(Value);
 | 
			
		||||
+  else if (!strcasecmp(Name, "LocalChannelProvide")) LocalChannelProvide = atoi(Value);
 | 
			
		||||
   else
 | 
			
		||||
      return false;
 | 
			
		||||
   return true;
 | 
			
		||||
@@ -522,6 +524,7 @@
 | 
			
		||||
   Store("CurrentChannel",     CurrentChannel);
 | 
			
		||||
   Store("CurrentVolume",      CurrentVolume);
 | 
			
		||||
   Store("CurrentDolby",       CurrentDolby);
 | 
			
		||||
+  Store("LocalChannelProvide",LocalChannelProvide);
 | 
			
		||||
 
 | 
			
		||||
   Sort();
 | 
			
		||||
 
 | 
			
		||||
diff -Nu vdr-1.3.24/config.h vdr-1.3.24.LocalChannelProvide/config.h
 | 
			
		||||
--- vdr-1.3.24/config.h	2005-05-05 13:04:18.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.24.LocalChannelProvide/config.h	2005-05-12 19:24:31.000000000 +0200
 | 
			
		||||
@@ -255,6 +255,7 @@
 | 
			
		||||
   int CurrentChannel;
 | 
			
		||||
   int CurrentVolume;
 | 
			
		||||
   int CurrentDolby;
 | 
			
		||||
+  int LocalChannelProvide;
 | 
			
		||||
   int __EndData__;
 | 
			
		||||
   cSetup(void);
 | 
			
		||||
   cSetup& operator= (const cSetup &s);
 | 
			
		||||
diff -Nu vdr-1.3.24/dvbdevice.c vdr-1.3.24.LocalChannelProvide/dvbdevice.c
 | 
			
		||||
--- vdr-1.3.24/dvbdevice.c	2005-03-20 11:10:38.000000000 +0100
 | 
			
		||||
+++ vdr-1.3.24.LocalChannelProvide/dvbdevice.c	2005-05-12 19:19:29.000000000 +0200
 | 
			
		||||
@@ -746,6 +746,8 @@
 | 
			
		||||
 
 | 
			
		||||
 bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
 | 
			
		||||
 {
 | 
			
		||||
+  if (Setup.LocalChannelProvide != 1)
 | 
			
		||||
+    return false;
 | 
			
		||||
   bool result = false;
 | 
			
		||||
   bool hasPriority = Priority < 0 || Priority > this->Priority();
 | 
			
		||||
   bool needsDetachReceivers = false;
 | 
			
		||||
diff -Nu vdr-1.3.24/i18n.c vdr-1.3.24.LocalChannelProvide/i18n.c
 | 
			
		||||
--- vdr-1.3.24/i18n.c	2005-05-05 15:12:54.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.24.LocalChannelProvide/i18n.c	2005-05-12 19:30:50.000000000 +0200
 | 
			
		||||
@@ -5325,6 +5325,27 @@
 | 
			
		||||
     "ST:TNG konsool",
 | 
			
		||||
     "ST:TNG konsol",
 | 
			
		||||
   },
 | 
			
		||||
+  { "Channels available locally",
 | 
			
		||||
+    "Kan<61>le lokal beziehen",
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",// TODO
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",
 | 
			
		||||
+    "",
 | 
			
		||||
+  },
 | 
			
		||||
   { NULL }
 | 
			
		||||
   };
 | 
			
		||||
 
 | 
			
		||||
diff -Nu vdr-1.3.24/menu.c vdr-1.3.24.LocalChannelProvide/menu.c
 | 
			
		||||
--- vdr-1.3.24/menu.c	2005-03-20 16:14:51.000000000 +0100
 | 
			
		||||
+++ vdr-1.3.24.LocalChannelProvide/menu.c	2005-05-12 19:26:57.000000000 +0200
 | 
			
		||||
@@ -1968,7 +1968,7 @@
 | 
			
		||||
   Add(new cMenuEditIntItem( tr("Setup.DVB$Audio languages"),       &numAudioLanguages, 0, I18nNumLanguages));
 | 
			
		||||
   for (int i = 0; i < numAudioLanguages; i++)
 | 
			
		||||
       Add(new cMenuEditStraItem(tr("Setup.DVB$Audio language"),    &data.AudioLanguages[i], I18nNumLanguages, I18nLanguages()));
 | 
			
		||||
-
 | 
			
		||||
+  Add(new cMenuEditBoolItem(tr("Channels available locally"),      &data.LocalChannelProvide));
 | 
			
		||||
   SetCurrent(Get(current));
 | 
			
		||||
   Display();
 | 
			
		||||
 }
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
--- vdr-1.3.6/sections.c	2004-02-07 17:51:57.000000000 +0200
 | 
			
		||||
+++ sections.c	2004-03-21 18:34:47.000000000 +0200
 | 
			
		||||
@@ -185,11 +185,17 @@
 | 
			
		||||
                   if (fh) {
 | 
			
		||||
                      // Read section data:
 | 
			
		||||
                      unsigned char buf[4096]; // max. allowed size for any EIT section
 | 
			
		||||
-                     int r = safe_read(fh->handle, buf, sizeof(buf));
 | 
			
		||||
+		     struct stat statbuf;
 | 
			
		||||
+		     int st = fstat(fh->handle, &statbuf);
 | 
			
		||||
+		     int ispipe = (st == 0 && !S_ISCHR(statbuf.st_mode));
 | 
			
		||||
+		     /*printf("ispipe %d\n", ispipe);*/
 | 
			
		||||
+                     int r = safe_read(fh->handle, buf, ispipe ? 3 : sizeof(buf));
 | 
			
		||||
                      if (!DeviceHasLock)
 | 
			
		||||
                         continue; // we do the read anyway, to flush any data that might have come from a different transponder
 | 
			
		||||
-                     if (r > 3) { // minimum number of bytes necessary to get section length
 | 
			
		||||
+                     if (r >= 3) { // minimum number of bytes necessary to get section length
 | 
			
		||||
                         int len = (((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF)) + 3;
 | 
			
		||||
+			if (ispipe)
 | 
			
		||||
+			    r += safe_read(fh->handle, buf+3, len-3);
 | 
			
		||||
                         if (len == r) {
 | 
			
		||||
                            // Distribute data to all attached filters:
 | 
			
		||||
                            int pid = fh->filterData.pid;
 | 
			
		||||
							
								
								
									
										13
									
								
								patches/vdr-1.6.0-ignore_missing_cam.diff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								patches/vdr-1.6.0-ignore_missing_cam.diff
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
--- device.c.orig	2008-03-28 11:47:25.000000000 +0100
 | 
			
		||||
+++ device.c	2008-03-28 11:47:09.000000000 +0100
 | 
			
		||||
@@ -375,8 +375,8 @@
 | 
			
		||||
                }
 | 
			
		||||
             }
 | 
			
		||||
          }
 | 
			
		||||
-     if (!NumUsableSlots)
 | 
			
		||||
-        return NULL; // no CAM is able to decrypt this channel
 | 
			
		||||
+//     if (!NumUsableSlots)
 | 
			
		||||
+//        return NULL; // no CAM is able to decrypt this channel
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
   bool NeedsDetachReceivers = false;
 | 
			
		||||
							
								
								
									
										78
									
								
								patches/vdr-1.6.0-intcamdevices.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								patches/vdr-1.6.0-intcamdevices.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
Index: vdr-1.6.0-nocamdevices/device.c
 | 
			
		||||
===================================================================
 | 
			
		||||
--- vdr-1.6.0-nocamdevices/device.c
 | 
			
		||||
+++ vdr-1.6.0-nocamdevices/device.c	2008-04-27 18:55:37.000000000 +0300
 | 
			
		||||
@@ -363,6 +363,7 @@
 | 
			
		||||
   int NumCamSlots = CamSlots.Count();
 | 
			
		||||
   int SlotPriority[NumCamSlots];
 | 
			
		||||
   int NumUsableSlots = 0;
 | 
			
		||||
+  bool InternalCamNeeded = false;
 | 
			
		||||
   if (Channel->Ca() >= CA_ENCRYPTED_MIN) {
 | 
			
		||||
      for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) {
 | 
			
		||||
          SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used
 | 
			
		||||
@@ -376,7 +377,7 @@
 | 
			
		||||
             }
 | 
			
		||||
          }
 | 
			
		||||
      if (!NumUsableSlots)
 | 
			
		||||
-        return NULL; // no CAM is able to decrypt this channel
 | 
			
		||||
+        InternalCamNeeded = true; // no CAM is able to decrypt this channel
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
   bool NeedsDetachReceivers = false;
 | 
			
		||||
@@ -392,11 +393,13 @@
 | 
			
		||||
              continue; // this device shall be temporarily avoided
 | 
			
		||||
           if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != device[i]->CardIndex() + 1)
 | 
			
		||||
              continue; // a specific card was requested, but not this one
 | 
			
		||||
-          if (NumUsableSlots && !CamSlots.Get(j)->Assign(device[i], true))
 | 
			
		||||
+          if (InternalCamNeeded && !device[i]->HasInternalCam())
 | 
			
		||||
+             continue; // no CAM is able to decrypt this channel and the device uses vdr handled CAMs
 | 
			
		||||
+          if (NumUsableSlots && !device[i]->HasInternalCam() && !CamSlots.Get(j)->Assign(device[i], true))
 | 
			
		||||
              continue; // CAM slot can't be used with this device
 | 
			
		||||
           bool ndr;
 | 
			
		||||
           if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
 | 
			
		||||
-             if (NumUsableSlots && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j))
 | 
			
		||||
+             if (NumUsableSlots && !device[i]->HasInternalCam() && device[i]->CamSlot() && device[i]->CamSlot() != CamSlots.Get(j))
 | 
			
		||||
                 ndr = true; // using a different CAM slot requires detaching receivers
 | 
			
		||||
              // Put together an integer number that reflects the "impact" using
 | 
			
		||||
              // this device would have on the overall system. Each condition is represented
 | 
			
		||||
@@ -410,18 +413,18 @@
 | 
			
		||||
              imp <<= 1; imp |= device[i]->Receiving();                                                               // avoid devices that are receiving
 | 
			
		||||
              imp <<= 1; imp |= device[i] == cTransferControl::ReceiverDevice();                                      // avoid the Transfer Mode receiver device
 | 
			
		||||
              imp <<= 8; imp |= min(max(device[i]->Priority() + MAXPRIORITY, 0), 0xFF);                               // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
 | 
			
		||||
-             imp <<= 8; imp |= min(max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF);              // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
 | 
			
		||||
+             imp <<= 8; imp |= min(max(((NumUsableSlots && !device[i]->HasInternalCam()) ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF);              // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used)
 | 
			
		||||
              imp <<= 1; imp |= ndr;                                                                                  // avoid devices if we need to detach existing receivers
 | 
			
		||||
              imp <<= 1; imp |= device[i]->IsPrimaryDevice();                                                         // avoid the primary device
 | 
			
		||||
-             imp <<= 1; imp |= NumUsableSlots ? 0 : device[i]->HasCi();                                              // avoid cards with Common Interface for FTA channels
 | 
			
		||||
+             imp <<= 1; imp |= (NumUsableSlots || InternalCamNeeded) ? 0 : device[i]->HasCi();                       // avoid cards with Common Interface for FTA channels
 | 
			
		||||
              imp <<= 1; imp |= device[i]->HasDecoder();                                                              // avoid full featured cards
 | 
			
		||||
-             imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
 | 
			
		||||
+             imp <<= 1; imp |= (NumUsableSlots && !device[i]->HasInternalCam()) ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; // prefer CAMs that are known to decrypt this channel
 | 
			
		||||
              if (imp < Impact) {
 | 
			
		||||
                 // This device has less impact than any previous one, so we take it.
 | 
			
		||||
                 Impact = imp;
 | 
			
		||||
                 d = device[i];
 | 
			
		||||
                 NeedsDetachReceivers = ndr;
 | 
			
		||||
-                if (NumUsableSlots)
 | 
			
		||||
+                if (NumUsableSlots && !device[i]->HasInternalCam())
 | 
			
		||||
                    s = CamSlots.Get(j);
 | 
			
		||||
                 }
 | 
			
		||||
              }
 | 
			
		||||
Index: vdr-1.6.0-nocamdevices/device.h
 | 
			
		||||
===================================================================
 | 
			
		||||
--- vdr-1.6.0-nocamdevices/device.h
 | 
			
		||||
+++ vdr-1.6.0-nocamdevices/device.h	2008-04-27 18:55:49.000000000 +0300
 | 
			
		||||
@@ -335,6 +335,12 @@
 | 
			
		||||
 public:
 | 
			
		||||
   virtual bool HasCi(void);
 | 
			
		||||
          ///< Returns true if this device has a Common Interface.
 | 
			
		||||
+  virtual bool HasInternalCam(void) { return false; }
 | 
			
		||||
+         ///< Returns true if this device handles encrypted channels itself
 | 
			
		||||
+         ///< without VDR assistance. This can be e.g. when the device is a
 | 
			
		||||
+         ///< client that gets the stream from another VDR instance that has
 | 
			
		||||
+         ///< already decrypted the stream. In this case ProvidesChannel()
 | 
			
		||||
+         ///< shall check whether the channel can be decrypted.
 | 
			
		||||
   void SetCamSlot(cCamSlot *CamSlot);
 | 
			
		||||
          ///< Sets the given CamSlot to be used with this device.
 | 
			
		||||
   cCamSlot *CamSlot(void) const { return camSlot; }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								patches/vdr-cap_net_raw.diff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								patches/vdr-cap_net_raw.diff
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
--- vdr.c.orig	2009-02-13 09:45:55.000000000 +0100
 | 
			
		||||
+++ vdr.c	2009-02-13 09:46:24.000000000 +0100
 | 
			
		||||
@@ -115,7 +115,7 @@
 | 
			
		||||
 static bool SetCapSysTime(void)
 | 
			
		||||
 {
 | 
			
		||||
   // drop all capabilities except cap_sys_time
 | 
			
		||||
-  cap_t caps = cap_from_text("= cap_sys_time=ep");
 | 
			
		||||
+  cap_t caps = cap_from_text("= cap_sys_time,cap_net_raw=ep");
 | 
			
		||||
   if (!caps) {
 | 
			
		||||
      fprintf(stderr, "vdr: cap_from_text failed: %s\n", strerror(errno));
 | 
			
		||||
      return false;
 | 
			
		||||
@@ -1,113 +0,0 @@
 | 
			
		||||
diff -Nru -x PLUGINS vdr-1.3.12-orig/i18n.c vdr-1.3.12/i18n.c
 | 
			
		||||
--- vdr-1.3.12-orig/i18n.c	2004-05-28 15:19:29.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.12/i18n.c	2004-08-17 16:01:07.000000000 +0200
 | 
			
		||||
@@ -1033,8 +1033,8 @@
 | 
			
		||||
     "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?",
 | 
			
		||||
     "Zaista ponovo pokrenuti?",
 | 
			
		||||
   },
 | 
			
		||||
-  { "Recording - restart anyway?",
 | 
			
		||||
-    "Aufnahme l<>uft - trotzdem neu starten?",
 | 
			
		||||
+  { "Busy - restart anyway?",
 | 
			
		||||
+    "Besch<63>ftigt - trotzdem neu starten?",
 | 
			
		||||
     "Snemanje - zares ponoven zagon?",
 | 
			
		||||
     "In registrazione - restart comunque?",
 | 
			
		||||
     "Opname loopt - toch opnieuw starten?",
 | 
			
		||||
@@ -1052,8 +1052,8 @@
 | 
			
		||||
     "<22><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?",
 | 
			
		||||
     "Snimanje traje - svejedno restart sistema?",
 | 
			
		||||
   },
 | 
			
		||||
-  { "Recording - shut down anyway?",
 | 
			
		||||
-    "Aufnahme l<>uft - trotzdem ausschalten?",
 | 
			
		||||
+  { "Busy - shut down anyway?",
 | 
			
		||||
+    "Besch<63>ftigt - trotzdem ausschalten?",
 | 
			
		||||
     "Snemanje - zares izklopi?",
 | 
			
		||||
     "In registrazione - spengo comunque?",
 | 
			
		||||
     "Opname loopt - toch uitschakelen?",
 | 
			
		||||
diff -Nru -x PLUGINS vdr-1.3.12-orig/menu.c vdr-1.3.12/menu.c
 | 
			
		||||
--- vdr-1.3.12-orig/menu.c	2004-06-13 22:26:51.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.12/menu.c	2004-08-17 16:00:07.000000000 +0200
 | 
			
		||||
@@ -2201,7 +2201,7 @@
 | 
			
		||||
 
 | 
			
		||||
 eOSState cMenuSetup::Restart(void)
 | 
			
		||||
 {
 | 
			
		||||
-  if (Interface->Confirm(cRecordControls::Active() ? tr("Recording - restart anyway?") : tr("Really restart?"))) {
 | 
			
		||||
+  if (Interface->Confirm((cRecordControls::Active() || cPluginManager::Active()) ? tr("Busy - restart anyway?") : tr("Really restart?"))) {
 | 
			
		||||
      cThread::EmergencyExit(true);
 | 
			
		||||
      return osEnd;
 | 
			
		||||
      }
 | 
			
		||||
diff -Nru -x PLUGINS vdr-1.3.12-orig/plugin.c vdr-1.3.12/plugin.c
 | 
			
		||||
--- vdr-1.3.12-orig/plugin.c	2004-05-22 13:25:22.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.12/plugin.c	2004-08-17 15:57:52.000000000 +0200
 | 
			
		||||
@@ -64,6 +64,11 @@
 | 
			
		||||
 {
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+bool cPlugin::Active(void)
 | 
			
		||||
+{
 | 
			
		||||
+  return false;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 const char *cPlugin::MainMenuEntry(void)
 | 
			
		||||
 {
 | 
			
		||||
   return NULL;
 | 
			
		||||
@@ -369,6 +374,18 @@
 | 
			
		||||
   return NULL;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+bool cPluginManager::Active(void)
 | 
			
		||||
+{
 | 
			
		||||
+  if (pluginManager) {
 | 
			
		||||
+     for (cDll *dll = pluginManager->dlls.First(); dll; dll = pluginManager->dlls.Next(dll)) {
 | 
			
		||||
+         cPlugin *p = dll->Plugin();
 | 
			
		||||
+         if (p && p->Active())
 | 
			
		||||
+            return true;
 | 
			
		||||
+         }
 | 
			
		||||
+     }
 | 
			
		||||
+  return false;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 void cPluginManager::Shutdown(bool Log)
 | 
			
		||||
 {
 | 
			
		||||
   cDll *dll;
 | 
			
		||||
diff -Nru -x PLUGINS vdr-1.3.12-orig/plugin.h vdr-1.3.12/plugin.h
 | 
			
		||||
--- vdr-1.3.12-orig/plugin.h	2004-04-30 15:46:21.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.12/plugin.h	2004-08-17 15:56:51.000000000 +0200
 | 
			
		||||
@@ -36,6 +36,7 @@
 | 
			
		||||
   virtual bool Initialize(void);
 | 
			
		||||
   virtual bool Start(void);
 | 
			
		||||
   virtual void Housekeeping(void);
 | 
			
		||||
+	virtual bool Active(void);
 | 
			
		||||
 
 | 
			
		||||
   virtual const char *MainMenuEntry(void);
 | 
			
		||||
   virtual cOsdObject *MainMenuAction(void);
 | 
			
		||||
@@ -85,6 +86,7 @@
 | 
			
		||||
   static bool HasPlugins(void);
 | 
			
		||||
   static cPlugin *GetPlugin(int Index);
 | 
			
		||||
   static cPlugin *GetPlugin(const char *Name);
 | 
			
		||||
+	static bool Active(void);
 | 
			
		||||
   void Shutdown(bool Log = false);
 | 
			
		||||
   };
 | 
			
		||||
 
 | 
			
		||||
diff -Nru -x PLUGINS vdr-1.3.12-orig/vdr.c vdr-1.3.12/vdr.c
 | 
			
		||||
--- vdr-1.3.12-orig/vdr.c	2004-06-13 15:52:09.000000000 +0200
 | 
			
		||||
+++ vdr-1.3.12/vdr.c	2004-08-17 15:59:18.000000000 +0200
 | 
			
		||||
@@ -707,8 +707,8 @@
 | 
			
		||||
                           Skins.Message(mtError, tr("Can't shutdown - option '-s' not given!"));
 | 
			
		||||
                           break;
 | 
			
		||||
                           }
 | 
			
		||||
-                       if (cRecordControls::Active()) {
 | 
			
		||||
-                          if (Interface->Confirm(tr("Recording - shut down anyway?")))
 | 
			
		||||
+                       if (cRecordControls::Active() || cPluginManager::Active()) {
 | 
			
		||||
+                          if (Interface->Confirm(tr("Busy - shut down anyway?")))
 | 
			
		||||
                              ForceShutdown = true;
 | 
			
		||||
                           }
 | 
			
		||||
                        LastActivity = 1; // not 0, see below!
 | 
			
		||||
@@ -821,7 +821,7 @@
 | 
			
		||||
                  Skins.Message(mtInfo, tr("Editing process finished"));
 | 
			
		||||
               }
 | 
			
		||||
            }
 | 
			
		||||
-        if (!Interact && ((!cRecordControls::Active() && !cCutter::Active() && (!Interface->HasSVDRPConnection() || UserShutdown)) || ForceShutdown)) {
 | 
			
		||||
+        if (!Interact && ((!cRecordControls::Active() && !cCutter::Active() && !cPluginManager::Active() && (!Interface->HasSVDRPConnection() || UserShutdown)) || ForceShutdown)) {
 | 
			
		||||
            time_t Now = time(NULL);
 | 
			
		||||
            if (Now - LastActivity > ACTIVITYTIMEOUT) {
 | 
			
		||||
               // Shutdown:
 | 
			
		||||
							
								
								
									
										118
									
								
								po/de_DE.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								po/de_DE.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
# 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: 2009-02-13 11:53+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
 | 
			
		||||
"Last-Translator: Frank Schmirler <vdrdev@schmirler.de>\n"
 | 
			
		||||
"Language-Team: <vdr@linuxtv.org>\n"
 | 
			
		||||
"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<65>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<69>t"
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Priority"
 | 
			
		||||
msgstr "Maximale Priorit<69>t"
 | 
			
		||||
 | 
			
		||||
msgid "VDR Streaming Server"
 | 
			
		||||
msgstr "VDR Streaming Server"
 | 
			
		||||
 | 
			
		||||
msgid "Streaming active"
 | 
			
		||||
msgstr "Streamen im Gange"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend Live TV"
 | 
			
		||||
msgstr "Live-TV pausieren"
 | 
			
		||||
 | 
			
		||||
msgid "Common Settings"
 | 
			
		||||
msgstr "Allgemeines"
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Number of Clients"
 | 
			
		||||
msgstr "Maximalanzahl an Clients"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend behaviour"
 | 
			
		||||
msgstr "Pausierverhalten"
 | 
			
		||||
 | 
			
		||||
msgid "Client may suspend"
 | 
			
		||||
msgstr "Client darf pausieren"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server"
 | 
			
		||||
msgstr "VDR-zu-VDR Server"
 | 
			
		||||
 | 
			
		||||
msgid "Start VDR-to-VDR Server"
 | 
			
		||||
msgstr "VDR-zu-VDR Server starten"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server Port"
 | 
			
		||||
msgstr "Port des VDR-zu-VDR Servers"
 | 
			
		||||
 | 
			
		||||
msgid "Bind to IP"
 | 
			
		||||
msgstr "Binde an IP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server"
 | 
			
		||||
msgstr "HTTP Server"
 | 
			
		||||
 | 
			
		||||
msgid "Start HTTP Server"
 | 
			
		||||
msgstr "HTTP Server starten"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server Port"
 | 
			
		||||
msgstr "Port des HTTP Servers"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Streamtype"
 | 
			
		||||
msgstr "HTTP Streamtyp"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streaming Server"
 | 
			
		||||
msgstr "Multicast Streaming Server"
 | 
			
		||||
 | 
			
		||||
msgid "Start IGMP Server"
 | 
			
		||||
msgstr "IGMP Server starten"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Client Port"
 | 
			
		||||
msgstr "Port des Multicast Clients"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streamtype"
 | 
			
		||||
msgstr "Multicast Streamtyp"
 | 
			
		||||
 | 
			
		||||
msgid "Offer suspend mode"
 | 
			
		||||
msgstr "Pausieren anbieten"
 | 
			
		||||
 | 
			
		||||
msgid "Always suspended"
 | 
			
		||||
msgstr "Immer pausiert"
 | 
			
		||||
 | 
			
		||||
msgid "Never suspended"
 | 
			
		||||
msgstr "Nie pausiert"
 | 
			
		||||
							
								
								
									
										118
									
								
								po/fi_FI.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								po/fi_FI.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
# 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-02-13 11:53+0100\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<79>yt<79> palvelin"
 | 
			
		||||
 | 
			
		||||
msgid "Server is suspended"
 | 
			
		||||
msgstr "Palvelin on pys<79>ytetty"
 | 
			
		||||
 | 
			
		||||
msgid "Couldn't suspend Server!"
 | 
			
		||||
msgstr "Palvelinta ei onnistuttu pys<79>ytt<74>m<EFBFBD><6D>n!"
 | 
			
		||||
 | 
			
		||||
msgid "Hide Mainmenu Entry"
 | 
			
		||||
msgstr "Piilota valinta p<><70>valikosta"
 | 
			
		||||
 | 
			
		||||
msgid "Start Client"
 | 
			
		||||
msgstr "K<>ynnist<73> VDR-asiakas"
 | 
			
		||||
 | 
			
		||||
msgid "Remote IP"
 | 
			
		||||
msgstr "Et<45>koneen IP-osoite"
 | 
			
		||||
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "Et<45>koneen portti"
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "Suodatetun tiedon suoratoisto"
 | 
			
		||||
 | 
			
		||||
msgid "Synchronize EPG"
 | 
			
		||||
msgstr "P<>ivit<69> 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<79>yt<79> suora TV-l<>hetys"
 | 
			
		||||
 | 
			
		||||
msgid "Common Settings"
 | 
			
		||||
msgstr "Yleiset asetukset"
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Number of Clients"
 | 
			
		||||
msgstr "Suurin sallittu asiakkaiden m<><6D>r<EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend behaviour"
 | 
			
		||||
msgstr "Pys<79>ytystoiminto"
 | 
			
		||||
 | 
			
		||||
msgid "Client may suspend"
 | 
			
		||||
msgstr "Asiakas saa pys<79>ytt<74><74> palvelimen"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server"
 | 
			
		||||
msgstr "VDR-palvelin"
 | 
			
		||||
 | 
			
		||||
msgid "Start VDR-to-VDR Server"
 | 
			
		||||
msgstr "K<>ynnist<73> 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<73> HTTP-palvelin"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server Port"
 | 
			
		||||
msgstr "HTTP-palvelimen portti"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Streamtype"
 | 
			
		||||
msgstr "HTTP-l<>hetysmuoto"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streaming Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Start IGMP Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Client Port"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streamtype"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Offer suspend mode"
 | 
			
		||||
msgstr "tyrkyt<79>"
 | 
			
		||||
 | 
			
		||||
msgid "Always suspended"
 | 
			
		||||
msgstr "aina"
 | 
			
		||||
 | 
			
		||||
msgid "Never suspended"
 | 
			
		||||
msgstr "ei koskaan"
 | 
			
		||||
							
								
								
									
										106
									
								
								po/fi_FI.po.bak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								po/fi_FI.po.bak
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
# 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"
 | 
			
		||||
							
								
								
									
										118
									
								
								po/fr_FR.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								po/fr_FR.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
# 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: 2009-02-13 11:53+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2008-03-30 02:11+0200\n"
 | 
			
		||||
"Last-Translator: micky979 <micky979@free.fr>\n"
 | 
			
		||||
"Language-Team: <vdr@linuxtv.org>\n"
 | 
			
		||||
"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 "Synchronize EPG"
 | 
			
		||||
msgstr "Synchroniser l'EPG"
 | 
			
		||||
 | 
			
		||||
msgid "Minimum Priority"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Priority"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "VDR Streaming Server"
 | 
			
		||||
msgstr "Serveur de streaming VDR"
 | 
			
		||||
 | 
			
		||||
msgid "Streaming active"
 | 
			
		||||
msgstr "Streaming actif"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend Live TV"
 | 
			
		||||
msgstr "Suspendre Live TV"
 | 
			
		||||
 | 
			
		||||
msgid "Common Settings"
 | 
			
		||||
msgstr "Param<61>tres communs"
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Number of Clients"
 | 
			
		||||
msgstr "Nombre maximun de clients"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend behaviour"
 | 
			
		||||
msgstr "Suspendre"
 | 
			
		||||
 | 
			
		||||
msgid "Client may suspend"
 | 
			
		||||
msgstr "Le client peut suspendre"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server"
 | 
			
		||||
msgstr "VDR-to-VDR Serveur"
 | 
			
		||||
 | 
			
		||||
msgid "Start VDR-to-VDR Server"
 | 
			
		||||
msgstr "D<>marrer le serveur VDR-to-VDR"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server Port"
 | 
			
		||||
msgstr "Port du serveur VDR-to-VDR"
 | 
			
		||||
 | 
			
		||||
msgid "Bind to IP"
 | 
			
		||||
msgstr "Attacher aux IP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server"
 | 
			
		||||
msgstr "Serveur HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "Start HTTP Server"
 | 
			
		||||
msgstr "D<>marrer le serveur HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server Port"
 | 
			
		||||
msgstr "Port du serveur HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Streamtype"
 | 
			
		||||
msgstr "Type de Streaming HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streaming Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Start IGMP Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Client Port"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streamtype"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Offer suspend mode"
 | 
			
		||||
msgstr "Offrir le mode suspendre"
 | 
			
		||||
 | 
			
		||||
msgid "Always suspended"
 | 
			
		||||
msgstr "Toujours suspendre"
 | 
			
		||||
 | 
			
		||||
msgid "Never suspended"
 | 
			
		||||
msgstr "Jamais suspendre"
 | 
			
		||||
							
								
								
									
										120
									
								
								po/it_IT.po
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										120
									
								
								po/it_IT.po
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
# 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: 2009-02-13 11:53+0100\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 "Synchronize EPG"
 | 
			
		||||
msgstr "Sincronizza EPG"
 | 
			
		||||
 | 
			
		||||
msgid "Minimum Priority"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Priority"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "VDR Streaming Server"
 | 
			
		||||
msgstr "Server trasmissione VDR"
 | 
			
		||||
 | 
			
		||||
msgid "Streaming active"
 | 
			
		||||
msgstr "Trasmissione attiva"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend Live TV"
 | 
			
		||||
msgstr "Sospendi TV dal vivo"
 | 
			
		||||
 | 
			
		||||
msgid "Common Settings"
 | 
			
		||||
msgstr "Impostazioni comuni"
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Number of Clients"
 | 
			
		||||
msgstr "Numero massimo di Client"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend behaviour"
 | 
			
		||||
msgstr "Tipo sospensione"
 | 
			
		||||
 | 
			
		||||
msgid "Client may suspend"
 | 
			
		||||
msgstr "Permetti sospensione al Client"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server"
 | 
			
		||||
msgstr "Server VDR-a-VDR"
 | 
			
		||||
 | 
			
		||||
msgid "Start VDR-to-VDR Server"
 | 
			
		||||
msgstr "Avvia Server VDR-a-VDR"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server Port"
 | 
			
		||||
msgstr "Porta Server VDR-a-VDR"
 | 
			
		||||
 | 
			
		||||
msgid "Bind to IP"
 | 
			
		||||
msgstr "IP associati"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server"
 | 
			
		||||
msgstr "Server HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "Start HTTP Server"
 | 
			
		||||
msgstr "Avvia Server HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server Port"
 | 
			
		||||
msgstr "Porta Server HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Streamtype"
 | 
			
		||||
msgstr "Tipo flusso HTTP"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streaming Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Start IGMP Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Client Port"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streamtype"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Offer suspend mode"
 | 
			
		||||
msgstr "Offri mod. sospensione"
 | 
			
		||||
 | 
			
		||||
msgid "Always suspended"
 | 
			
		||||
msgstr "Sempre sospeso"
 | 
			
		||||
 | 
			
		||||
msgid "Never suspended"
 | 
			
		||||
msgstr "Mai sospeso"
 | 
			
		||||
							
								
								
									
										118
									
								
								po/ru_RU.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								po/ru_RU.po
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
# 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: 2009-02-13 11:53+0100\n"
 | 
			
		||||
"PO-Revision-Date: 2008-06-26 15:36+0100\n"
 | 
			
		||||
"Last-Translator: Oleg Roitburd <oleg@roitburd.de>\n"
 | 
			
		||||
"Language-Team: <vdr@linuxtv.org>\n"
 | 
			
		||||
"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 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend Server"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Server is suspended"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Couldn't suspend Server!"
 | 
			
		||||
msgstr "<22><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Hide Mainmenu Entry"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Start Client"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Remote IP"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> IP"
 | 
			
		||||
 | 
			
		||||
msgid "Remote Port"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Filter Streaming"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Synchronize EPG"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> EPG"
 | 
			
		||||
 | 
			
		||||
msgid "Minimum Priority"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Priority"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "VDR Streaming Server"
 | 
			
		||||
msgstr "VDR Streaming <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Streaming active"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend Live TV"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Live TV"
 | 
			
		||||
 | 
			
		||||
msgid "Common Settings"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Maximum Number of Clients"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Suspend behaviour"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Client may suspend"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server"
 | 
			
		||||
msgstr "VDR-to-VDR <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Start VDR-to-VDR Server"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD> VDR-to-VDR <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "VDR-to-VDR Server Port"
 | 
			
		||||
msgstr "VDR-to-VDR <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Bind to IP"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> IP"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server"
 | 
			
		||||
msgstr "HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Start HTTP Server"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD> HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Server Port"
 | 
			
		||||
msgstr "HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "HTTP Streamtype"
 | 
			
		||||
msgstr "<22><><EFBFBD> HTTP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streaming Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Start IGMP Server"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Client Port"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Multicast Streamtype"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
msgid "Offer suspend mode"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Always suspended"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
 | 
			
		||||
msgid "Never suspended"
 | 
			
		||||
msgstr "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
#include "remux/extern.h"
 | 
			
		||||
#include "server/server.h"
 | 
			
		||||
#include "server/streamer.h"
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
@@ -6,8 +7,6 @@
 | 
			
		||||
#include <signal.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
const char *g_ExternRemux = "/root/externremux.sh";
 | 
			
		||||
 | 
			
		||||
class cTSExt: public cThread {
 | 
			
		||||
private:
 | 
			
		||||
	cRingBufferLinear *m_ResultBuffer;
 | 
			
		||||
@@ -28,7 +27,7 @@ public:
 | 
			
		||||
cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, std::string Parameter):
 | 
			
		||||
		m_ResultBuffer(ResultBuffer),
 | 
			
		||||
		m_Active(false),
 | 
			
		||||
		m_Process(0),
 | 
			
		||||
		m_Process(-1),
 | 
			
		||||
		m_Inpipe(0),
 | 
			
		||||
		m_Outpipe(0)
 | 
			
		||||
{
 | 
			
		||||
@@ -67,9 +66,13 @@ cTSExt::cTSExt(cRingBufferLinear *ResultBuffer, std::string Parameter):
 | 
			
		||||
		for (int i = STDERR_FILENO + 1; i < MaxPossibleFileDescriptors; i++)
 | 
			
		||||
			close(i); //close all dup'ed filedescriptors
 | 
			
		||||
 | 
			
		||||
		std::string cmd = std::string(g_ExternRemux) + " " + Parameter;
 | 
			
		||||
		execl("/bin/sh", "sh", "-c", cmd.c_str(), NULL);
 | 
			
		||||
		_exit(-1);
 | 
			
		||||
		std::string cmd = std::string(opt_remux) + " " + Parameter;
 | 
			
		||||
		if (execl("/bin/sh", "sh", "-c", cmd.c_str(), NULL) == -1) {
 | 
			
		||||
			esyslog("streamdev-server: externremux script '%s' execution failed: %m", cmd.c_str());
 | 
			
		||||
			_exit(-1);
 | 
			
		||||
		}
 | 
			
		||||
		// should never be reached
 | 
			
		||||
		_exit(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	close(inpipe[0]);
 | 
			
		||||
@@ -84,16 +87,31 @@ cTSExt::~cTSExt()
 | 
			
		||||
	m_Active = false;
 | 
			
		||||
	Cancel(3);
 | 
			
		||||
	if (m_Process > 0) {
 | 
			
		||||
		// close pipes
 | 
			
		||||
		close(m_Outpipe);
 | 
			
		||||
		close(m_Inpipe);
 | 
			
		||||
		kill(m_Process, SIGTERM);
 | 
			
		||||
		for (int i = 0; waitpid(m_Process, NULL, WNOHANG) == 0; i++) {
 | 
			
		||||
			if (i == 20) {
 | 
			
		||||
				esyslog("streamdev-server: externremux process won't stop - killing it");
 | 
			
		||||
				kill(m_Process, SIGKILL);
 | 
			
		||||
			}
 | 
			
		||||
			cCondWait::SleepMs(100);
 | 
			
		||||
		// signal and wait for termination
 | 
			
		||||
		if (kill(m_Process, SIGINT) < 0) {
 | 
			
		||||
			esyslog("streamdev-server: externremux SIGINT failed: %m");
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			int i = 0;
 | 
			
		||||
			int retval;
 | 
			
		||||
			while ((retval = waitpid(m_Process, NULL, WNOHANG)) == 0) {
 | 
			
		||||
 | 
			
		||||
				if ((++i % 20) == 0) {
 | 
			
		||||
					esyslog("streamdev-server: externremux process won't stop - killing it");
 | 
			
		||||
					kill(m_Process, SIGKILL);
 | 
			
		||||
				}
 | 
			
		||||
				cCondWait::SleepMs(100);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (retval < 0)
 | 
			
		||||
				esyslog("streamdev-server: externremux process waitpid failed: %m");
 | 
			
		||||
			else
 | 
			
		||||
				Dprintf("streamdev-server: externremux child (%d) exited as expected\n", m_Process);
 | 
			
		||||
		}
 | 
			
		||||
		m_Process = -1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,6 @@
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
extern const char *g_ExternRemux;
 | 
			
		||||
 | 
			
		||||
class cTSExt;
 | 
			
		||||
 | 
			
		||||
class cExternRemux: public cTSRemux {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@
 | 
			
		||||
#include <vdr/remux.h>
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
#ifndef MAXTRACKS
 | 
			
		||||
#define MAXTRACKS 64
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class cTS2PS;
 | 
			
		||||
 | 
			
		||||
class cTS2PSRemux: public cTSRemux {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#include "remux/tsremux.h"
 | 
			
		||||
 | 
			
		||||
#define SC_PICTURE 0x00  // "picture header"
 | 
			
		||||
#define SC_PICTURE  0x00  // "picture header"
 | 
			
		||||
#define PID_MASK_HI 0x1F
 | 
			
		||||
 | 
			
		||||
void cTSRemux::SetBrokenLink(uchar *Data, int Length)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,10 @@
 | 
			
		||||
#include "libdvbmpeg/transform.h"
 | 
			
		||||
#include <vdr/remux.h>
 | 
			
		||||
 | 
			
		||||
#ifndef NO_PICTURE
 | 
			
		||||
#define NO_PICTURE 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define RESULTBUFFERSIZE KILOBYTE(256)
 | 
			
		||||
 | 
			
		||||
class cTSRemux {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,14 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: component.c,v 1.3 2005/05/09 20:22:29 lordjaxom Exp $
 | 
			
		||||
 *  $Id: component.c,v 1.4 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include "server/component.h"
 | 
			
		||||
#include "server/connection.h"
 | 
			
		||||
 | 
			
		||||
cServerComponent::cServerComponent(const char *Protocol, const char *ListenIp,
 | 
			
		||||
                                   uint ListenPort):
 | 
			
		||||
                                   uint ListenPort, int Type, int IpProto):
 | 
			
		||||
		m_Protocol(Protocol),
 | 
			
		||||
		m_Listen(Type, IpProto),
 | 
			
		||||
		m_ListenIp(ListenIp),
 | 
			
		||||
		m_ListenPort(ListenPort)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: component.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
 | 
			
		||||
 *  $Id: component.h,v 1.3 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SERVERS_COMPONENT_H
 | 
			
		||||
@@ -17,8 +17,8 @@ class cServerConnection;
 | 
			
		||||
 | 
			
		||||
class cServerComponent: public cListObject {
 | 
			
		||||
private:
 | 
			
		||||
	cTBSocket m_Listen;
 | 
			
		||||
	const char *m_Protocol;
 | 
			
		||||
	cTBSocket m_Listen;
 | 
			
		||||
	const char *m_ListenIp;
 | 
			
		||||
	uint m_ListenPort;
 | 
			
		||||
 | 
			
		||||
@@ -27,7 +27,7 @@ protected:
 | 
			
		||||
	virtual cServerConnection *NewClient(void) = 0;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cServerComponent(const char *Protocol, const char *ListenIp, uint ListenPort);
 | 
			
		||||
	cServerComponent(const char *Protocol, const char *ListenIp, uint ListenPort, int Type = SOCK_STREAM, int IpProto = 0);
 | 
			
		||||
	virtual ~cServerComponent();
 | 
			
		||||
 | 
			
		||||
	/* Starts listening on the specified Port, override if you want to do things
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										447
									
								
								server/componentIGMP.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								server/componentIGMP.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,447 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: componentIGMP.c,v 1.1 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
#include <netinet/ip.h>
 | 
			
		||||
#include <netinet/igmp.h>
 | 
			
		||||
 
 | 
			
		||||
#include "server/componentIGMP.h"
 | 
			
		||||
#include "server/connectionIGMP.h"
 | 
			
		||||
#include "server/setup.h"
 | 
			
		||||
 | 
			
		||||
#ifndef IGMP_ALL_HOSTS
 | 
			
		||||
#define IGMP_ALL_HOSTS htonl(0xE0000001L)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef IGMP_ALL_ROUTER
 | 
			
		||||
#define IGMP_ALL_ROUTER htonl(0xE0000002L)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// IGMP parameters according to RFC2236. All time values in seconds.
 | 
			
		||||
#define IGMP_ROBUSTNESS 2
 | 
			
		||||
#define IGMP_QUERY_INTERVAL 125
 | 
			
		||||
#define IGMP_QUERY_RESPONSE_INTERVAL 10
 | 
			
		||||
#define IGMP_GROUP_MEMBERSHIP_INTERVAL (2 * IGMP_QUERY_INTERVAL + IGMP_QUERY_RESPONSE_INTERVAL)
 | 
			
		||||
#define IGMP_OTHER_QUERIER_PRESENT_INTERVAL (2 * IGMP_QUERY_INTERVAL + IGMP_QUERY_RESPONSE_INTERVAL / 2)
 | 
			
		||||
#define IGMP_STARTUP_QUERY_INTERVAL (IGMP_QUERY_INTERVAL / 4)
 | 
			
		||||
#define IGMP_STARTUP_QUERY_COUNT IGMP_ROBUSTNESS
 | 
			
		||||
// This value is 1/10 sec. RFC default is 10. Reduced to minimum to free unused channels ASAP
 | 
			
		||||
#define IGMP_LAST_MEMBER_QUERY_INTERVAL_TS 1
 | 
			
		||||
#define IGMP_LAST_MEMBER_QUERY_COUNT IGMP_ROBUSTNESS
 | 
			
		||||
 | 
			
		||||
// operations on struct timeval
 | 
			
		||||
#define TV_CMP(a, cmp, b) (a.tv_sec == b.tv_sec ? a.tv_usec cmp b.tv_usec : a.tv_sec cmp b.tv_sec)
 | 
			
		||||
#define TV_SET(tv) (tv.tv_sec || tv.tv_usec)
 | 
			
		||||
#define TV_CLR(tv) memset(&tv, 0, sizeof(tv))
 | 
			
		||||
#define TV_CPY(dst, src) memcpy(&dst, &src, sizeof(dst))
 | 
			
		||||
#define TV_ADD(dst, ts) dst.tv_sec += ts / 10; dst.tv_usec += (ts % 10) * 100000; if (dst.tv_usec >= 1000000) { dst.tv_usec -= 1000000; dst.tv_sec++; }
 | 
			
		||||
 | 
			
		||||
class cMulticastGroup: public cListObject
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	cConnectionIGMP *connection;
 | 
			
		||||
	in_addr_t group;
 | 
			
		||||
	in_addr_t reporter;
 | 
			
		||||
	struct timeval timeout;
 | 
			
		||||
	struct timeval v1timer;
 | 
			
		||||
	struct timeval retransmit;
 | 
			
		||||
 | 
			
		||||
	cMulticastGroup(in_addr_t Group);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
cMulticastGroup::cMulticastGroup(in_addr_t Group) :
 | 
			
		||||
		connection(NULL),
 | 
			
		||||
		group(Group),
 | 
			
		||||
		reporter(0)
 | 
			
		||||
{
 | 
			
		||||
	TV_CLR(timeout);
 | 
			
		||||
	TV_CLR(v1timer);
 | 
			
		||||
	TV_CLR(retransmit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void logIGMP(uint8_t type, struct in_addr Src, struct in_addr Dst, struct in_addr Grp)
 | 
			
		||||
{
 | 
			
		||||
	const char* msg;
 | 
			
		||||
	switch (type) {
 | 
			
		||||
		case IGMP_MEMBERSHIP_QUERY:	msg = "membership query"; break;
 | 
			
		||||
		case IGMP_V1_MEMBERSHIP_REPORT:	msg = "V1 membership report"; break;
 | 
			
		||||
		case IGMP_V2_MEMBERSHIP_REPORT:	msg = "V2 membership report"; break;
 | 
			
		||||
		case IGMP_V2_LEAVE_GROUP:	msg = "leave group"; break;
 | 
			
		||||
		default:			msg = "unknown"; break;
 | 
			
		||||
	}
 | 
			
		||||
	char* s = strdup(inet_ntoa(Src));
 | 
			
		||||
	char* d = strdup(inet_ntoa(Dst));
 | 
			
		||||
	dsyslog("streamdev-server IGMP: Received %s from %s (dst %s) for %s", msg, s, d, inet_ntoa(Grp));
 | 
			
		||||
	free(s);
 | 
			
		||||
	free(d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Taken from http://tools.ietf.org/html/rfc1071 */
 | 
			
		||||
uint16_t inetChecksum(uint16_t *addr, int count)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t sum = 0;
 | 
			
		||||
	while (count > 1) {
 | 
			
		||||
		sum += *addr++;
 | 
			
		||||
		count -= 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        if( count > 0 )
 | 
			
		||||
		sum += * (uint8_t *) addr;
 | 
			
		||||
 | 
			
		||||
	while (sum>>16)
 | 
			
		||||
		sum = (sum & 0xffff) + (sum >> 16);
 | 
			
		||||
 | 
			
		||||
	return ~sum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cComponentIGMP::cComponentIGMP(void):
 | 
			
		||||
		cServerComponent("IGMP", "0.0.0.0", 0, SOCK_RAW, IPPROTO_IGMP),
 | 
			
		||||
		cThread("IGMP timeout handler"),
 | 
			
		||||
		m_BindIp(inet_addr(StreamdevServerSetup.IGMPBindIP)),
 | 
			
		||||
		m_MaxChannelNumber(0),
 | 
			
		||||
		m_StartupQueryCount(IGMP_STARTUP_QUERY_COUNT),
 | 
			
		||||
		m_Querier(true)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cComponentIGMP::~cComponentIGMP(void)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMulticastGroup* cComponentIGMP::FindGroup(in_addr_t Group) const
 | 
			
		||||
{
 | 
			
		||||
	cMulticastGroup *group = m_Groups.First();
 | 
			
		||||
	while (group && group->group != Group)
 | 
			
		||||
		group = m_Groups.Next(group);
 | 
			
		||||
	return group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cComponentIGMP::Initialize(void)
 | 
			
		||||
{
 | 
			
		||||
	if (cServerComponent::Initialize() && IGMPMembership(IGMP_ALL_ROUTER))
 | 
			
		||||
	{
 | 
			
		||||
		for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
 | 
			
		||||
		{
 | 
			
		||||
			if (channel->GroupSep())
 | 
			
		||||
				continue;
 | 
			
		||||
			int num = channel->Number();
 | 
			
		||||
			if (!IGMPMembership(htonl(MULTICAST_PRIV_MIN + num)))
 | 
			
		||||
				break;
 | 
			
		||||
			m_MaxChannelNumber = num;
 | 
			
		||||
		}
 | 
			
		||||
		if (m_MaxChannelNumber == 0)
 | 
			
		||||
		{
 | 
			
		||||
			IGMPMembership(IGMP_ALL_ROUTER, false);
 | 
			
		||||
			esyslog("streamdev-server IGMP: no multicast group joined");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			Start();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return m_MaxChannelNumber > 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::Destruct(void)
 | 
			
		||||
{
 | 
			
		||||
	if (m_MaxChannelNumber > 0)
 | 
			
		||||
	{
 | 
			
		||||
		Cancel(3);
 | 
			
		||||
		for (cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel))
 | 
			
		||||
		{
 | 
			
		||||
			if (channel->GroupSep())
 | 
			
		||||
				continue;
 | 
			
		||||
			int num = channel->Number();
 | 
			
		||||
			if (num > m_MaxChannelNumber)
 | 
			
		||||
				break;
 | 
			
		||||
			IGMPMembership(htonl(MULTICAST_PRIV_MIN + num), false);
 | 
			
		||||
		}
 | 
			
		||||
		IGMPMembership(IGMP_ALL_ROUTER, false);
 | 
			
		||||
	}
 | 
			
		||||
	m_MaxChannelNumber = 0;
 | 
			
		||||
	cServerComponent::Destruct();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cServerConnection *cComponentIGMP::NewClient(void)
 | 
			
		||||
{
 | 
			
		||||
	return new cConnectionIGMP("IGMP", StreamdevServerSetup.IGMPClientPort, (eStreamType) StreamdevServerSetup.IGMPStreamType);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cServerConnection* cComponentIGMP::Accept(void)
 | 
			
		||||
{
 | 
			
		||||
	ssize_t recv_len;
 | 
			
		||||
	int ip_hdrlen, ip_datalen;
 | 
			
		||||
	struct ip *ip;
 | 
			
		||||
	struct igmp *igmp;
 | 
			
		||||
 | 
			
		||||
	while ((recv_len = ::recvfrom(Socket(), m_ReadBuffer, sizeof(m_ReadBuffer), 0, NULL, NULL)) < 0 && errno == EINTR)
 | 
			
		||||
		errno = 0;
 | 
			
		||||
 | 
			
		||||
	if (recv_len < 0) {
 | 
			
		||||
		esyslog("streamdev-server IGMP: read failed: %m");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	else if (recv_len < (ssize_t) sizeof(struct ip)) {
 | 
			
		||||
		esyslog("streamdev-server IGMP: IP packet too short");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ip = (struct ip*) m_ReadBuffer;
 | 
			
		||||
 | 
			
		||||
	// filter out my own packets
 | 
			
		||||
	if (ip->ip_src.s_addr == m_BindIp)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	ip_hdrlen = ip->ip_hl << 2;
 | 
			
		||||
#ifdef __FreeBSD__
 | 
			
		||||
	ip_datalen = ip->ip_len;
 | 
			
		||||
#else
 | 
			
		||||
	ip_datalen = ntohs(ip->ip_len) - ip_hdrlen;
 | 
			
		||||
#endif
 | 
			
		||||
	if (ip->ip_p != IPPROTO_IGMP) {
 | 
			
		||||
		esyslog("streamdev-server IGMP: Unexpected protocol %hhu", ip->ip_p);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	if (recv_len < ip_hdrlen + IGMP_MINLEN) {
 | 
			
		||||
		esyslog("streamdev-server IGMP: packet too short");
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	igmp = (struct igmp*) (m_ReadBuffer + ip_hdrlen);
 | 
			
		||||
	uint16_t chksum = igmp->igmp_cksum;
 | 
			
		||||
	igmp->igmp_cksum = 0;
 | 
			
		||||
	if (chksum != inetChecksum((uint16_t *)igmp, ip_datalen))
 | 
			
		||||
	{
 | 
			
		||||
		esyslog("INVALID CHECKSUM %d %d %d %d 0x%x 0x%x", ntohs(ip->ip_len), ip_hdrlen, ip_datalen, recv_len, chksum, inetChecksum((uint16_t *)igmp, ip_datalen));
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	logIGMP(igmp->igmp_type, ip->ip_src, ip->ip_dst, igmp->igmp_group);
 | 
			
		||||
	return ProcessMessage(igmp, igmp->igmp_group.s_addr, ip->ip_src.s_addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cServerConnection* cComponentIGMP::ProcessMessage(struct igmp *Igmp, in_addr_t Group, in_addr_t Sender)
 | 
			
		||||
{
 | 
			
		||||
	cServerConnection* conn = NULL;
 | 
			
		||||
	cMulticastGroup* group;
 | 
			
		||||
	LOCK_THREAD;
 | 
			
		||||
	switch (Igmp->igmp_type) {
 | 
			
		||||
		case IGMP_MEMBERSHIP_QUERY:
 | 
			
		||||
			if (ntohl(Sender) < ntohl(m_BindIp))
 | 
			
		||||
				IGMPStartOtherQuerierPresentTimer();
 | 
			
		||||
			break;
 | 
			
		||||
		case IGMP_V1_MEMBERSHIP_REPORT:
 | 
			
		||||
		case IGMP_V2_MEMBERSHIP_REPORT:
 | 
			
		||||
			group = FindGroup(Group);
 | 
			
		||||
			if (!group) {
 | 
			
		||||
				group = new cMulticastGroup(Group);
 | 
			
		||||
				m_Groups.Add(group);
 | 
			
		||||
			}
 | 
			
		||||
			if (!group->connection) {
 | 
			
		||||
				IGMPStartMulticast(group);
 | 
			
		||||
				conn = group->connection;
 | 
			
		||||
			}
 | 
			
		||||
			IGMPStartTimer(group, Sender);
 | 
			
		||||
			if (Igmp->igmp_type == IGMP_V1_MEMBERSHIP_REPORT)
 | 
			
		||||
				IGMPStartV1HostTimer(group);
 | 
			
		||||
			break;
 | 
			
		||||
		case IGMP_V2_LEAVE_GROUP:
 | 
			
		||||
			group = FindGroup(Group);
 | 
			
		||||
			if (group && !TV_SET(group->v1timer)) {
 | 
			
		||||
				if (group->reporter == Sender) {
 | 
			
		||||
					IGMPStartTimerAfterLeave(group, m_Querier ? IGMP_LAST_MEMBER_QUERY_INTERVAL_TS : Igmp->igmp_code);
 | 
			
		||||
					if (m_Querier)
 | 
			
		||||
						IGMPSendGroupQuery(group);
 | 
			
		||||
					IGMPStartRetransmitTimer(group);
 | 
			
		||||
				}
 | 
			
		||||
				m_CondWait.Signal();
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			break;
 | 
			
		||||
	}
 | 
			
		||||
	return conn;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::Action()
 | 
			
		||||
{
 | 
			
		||||
	while (Running()) {
 | 
			
		||||
		struct timeval now;
 | 
			
		||||
		struct timeval next;
 | 
			
		||||
 | 
			
		||||
		gettimeofday(&now, NULL);
 | 
			
		||||
		TV_CPY(next, now);
 | 
			
		||||
		next.tv_sec += IGMP_QUERY_INTERVAL;
 | 
			
		||||
 | 
			
		||||
		cMulticastGroup *del = NULL;
 | 
			
		||||
		{
 | 
			
		||||
			LOCK_THREAD;
 | 
			
		||||
			if (TV_CMP(m_GeneralQueryTimer, <, now)) {
 | 
			
		||||
				dsyslog("General Query");
 | 
			
		||||
				IGMPSendGeneralQuery();
 | 
			
		||||
				IGMPStartGeneralQueryTimer();
 | 
			
		||||
			}
 | 
			
		||||
			if (TV_CMP(next, >, m_GeneralQueryTimer))
 | 
			
		||||
				TV_CPY(next, m_GeneralQueryTimer);
 | 
			
		||||
 | 
			
		||||
			for (cMulticastGroup *group = m_Groups.First(); group; group = m_Groups.Next(group)) {
 | 
			
		||||
				if (TV_CMP(group->timeout, <, now)) {
 | 
			
		||||
					IGMPStopMulticast(group);
 | 
			
		||||
					IGMPClearRetransmitTimer(group);
 | 
			
		||||
					if (del)
 | 
			
		||||
						m_Groups.Del(del);
 | 
			
		||||
					del = group;
 | 
			
		||||
				}
 | 
			
		||||
				else if (m_Querier && TV_SET(group->retransmit) && TV_CMP(group->retransmit, <, now)) {
 | 
			
		||||
					IGMPSendGroupQuery(group);
 | 
			
		||||
					IGMPStartRetransmitTimer(group);
 | 
			
		||||
					if (TV_CMP(next, >, group->retransmit))
 | 
			
		||||
						TV_CPY(next, group->retransmit);
 | 
			
		||||
				}
 | 
			
		||||
				else if (TV_SET(group->v1timer) && TV_CMP(group->v1timer, <, now)) {
 | 
			
		||||
					TV_CLR(group->v1timer);
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					if (TV_CMP(next, >, group->timeout))
 | 
			
		||||
						TV_CPY(next, group->timeout);
 | 
			
		||||
					if (TV_SET(group->retransmit) && TV_CMP(next, >, group->retransmit))
 | 
			
		||||
						TV_CPY(next, group->retransmit);
 | 
			
		||||
					if (TV_SET(group->v1timer) && TV_CMP(next, >, group->v1timer))
 | 
			
		||||
						TV_CPY(next, group->v1timer);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (del)
 | 
			
		||||
				m_Groups.Del(del);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		int sleep = (next.tv_sec - now.tv_sec) * 1000;
 | 
			
		||||
		sleep += (next.tv_usec - now.tv_usec) / 1000;
 | 
			
		||||
		if (next.tv_usec < now.tv_usec)
 | 
			
		||||
			sleep += 1000;
 | 
			
		||||
		dsyslog("Sleeping %d ms", sleep);
 | 
			
		||||
		m_CondWait.Wait(sleep);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cComponentIGMP::IGMPMembership(in_addr_t Group, bool Add)
 | 
			
		||||
{
 | 
			
		||||
	struct ip_mreqn mreq;
 | 
			
		||||
	mreq.imr_multiaddr.s_addr = Group;
 | 
			
		||||
	mreq.imr_address.s_addr = INADDR_ANY;
 | 
			
		||||
	mreq.imr_ifindex = 0;
 | 
			
		||||
	if (setsockopt(Socket(), IPPROTO_IP, Add ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
 | 
			
		||||
	{
 | 
			
		||||
		esyslog("streamdev-server IGMP: unable to %s %s: %m", Add ? "join" : "leave", inet_ntoa(mreq.imr_multiaddr));
 | 
			
		||||
		if (errno == ENOBUFS)
 | 
			
		||||
			esyslog("consider increasing sys.net.ipv4.igmp_max_memberships");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPSendQuery(in_addr_t Group, int Timeout)
 | 
			
		||||
{
 | 
			
		||||
	struct sockaddr_in dst;
 | 
			
		||||
	struct igmp query;
 | 
			
		||||
 | 
			
		||||
	dst.sin_family = AF_INET;
 | 
			
		||||
	dst.sin_port = IPPROTO_IGMP;
 | 
			
		||||
	dst.sin_addr.s_addr = Group;
 | 
			
		||||
	query.igmp_type = IGMP_MEMBERSHIP_QUERY;
 | 
			
		||||
	query.igmp_code = Timeout * 10;
 | 
			
		||||
	query.igmp_cksum = 0;
 | 
			
		||||
	query.igmp_group.s_addr = (Group == IGMP_ALL_HOSTS) ? 0 : Group;
 | 
			
		||||
	query.igmp_cksum = inetChecksum((uint16_t *) &query, sizeof(query));
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < 5 && ::sendto(Socket(), &query, sizeof(query), 0, (sockaddr*)&dst, sizeof(dst)) == -1; i++) {
 | 
			
		||||
		if (errno != EAGAIN && errno != EWOULDBLOCK) {
 | 
			
		||||
			esyslog("streamdev-server IGMP: unable to query group %s: %m", inet_ntoa(dst.sin_addr));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		cCondWait::SleepMs(10);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Querier state actions
 | 
			
		||||
void cComponentIGMP::IGMPStartGeneralQueryTimer()
 | 
			
		||||
{
 | 
			
		||||
	m_Querier = true;
 | 
			
		||||
	if (m_StartupQueryCount) {
 | 
			
		||||
		gettimeofday(&m_GeneralQueryTimer, NULL);
 | 
			
		||||
		m_GeneralQueryTimer.tv_sec += IGMP_STARTUP_QUERY_INTERVAL;
 | 
			
		||||
		m_StartupQueryCount--;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		gettimeofday(&m_GeneralQueryTimer, NULL);
 | 
			
		||||
		m_GeneralQueryTimer.tv_sec += IGMP_QUERY_INTERVAL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPStartOtherQuerierPresentTimer()
 | 
			
		||||
{
 | 
			
		||||
	m_Querier = false;
 | 
			
		||||
	m_StartupQueryCount = 0;
 | 
			
		||||
	gettimeofday(&m_GeneralQueryTimer, NULL);
 | 
			
		||||
	m_GeneralQueryTimer.tv_sec += IGMP_OTHER_QUERIER_PRESENT_INTERVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPSendGeneralQuery()
 | 
			
		||||
{
 | 
			
		||||
	IGMPSendQuery(IGMP_ALL_HOSTS, IGMP_QUERY_RESPONSE_INTERVAL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Group state actions
 | 
			
		||||
void cComponentIGMP::IGMPStartTimer(cMulticastGroup* Group, in_addr_t Member)
 | 
			
		||||
{
 | 
			
		||||
	gettimeofday(&Group->timeout, NULL);
 | 
			
		||||
	Group->timeout.tv_sec += IGMP_GROUP_MEMBERSHIP_INTERVAL;
 | 
			
		||||
	TV_CLR(Group->retransmit);
 | 
			
		||||
	Group->reporter = Member;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPStartV1HostTimer(cMulticastGroup* Group)
 | 
			
		||||
{
 | 
			
		||||
	gettimeofday(&Group->v1timer, NULL);
 | 
			
		||||
	Group->v1timer.tv_sec += IGMP_GROUP_MEMBERSHIP_INTERVAL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPStartTimerAfterLeave(cMulticastGroup* Group, unsigned int MaxResponseTimeTs)
 | 
			
		||||
{
 | 
			
		||||
	//Group->Update(time(NULL) + MaxResponseTime * IGMP_LAST_MEMBER_QUERY_COUNT / 10);
 | 
			
		||||
	MaxResponseTimeTs *= IGMP_LAST_MEMBER_QUERY_COUNT;
 | 
			
		||||
	gettimeofday(&Group->timeout, NULL);
 | 
			
		||||
	TV_ADD(Group->timeout, MaxResponseTimeTs);
 | 
			
		||||
	TV_CLR(Group->retransmit);
 | 
			
		||||
	Group->reporter = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPStartRetransmitTimer(cMulticastGroup* Group)
 | 
			
		||||
{
 | 
			
		||||
	gettimeofday(&Group->retransmit, NULL);
 | 
			
		||||
	TV_ADD(Group->retransmit, IGMP_LAST_MEMBER_QUERY_INTERVAL_TS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPClearRetransmitTimer(cMulticastGroup* Group)
 | 
			
		||||
{
 | 
			
		||||
	TV_CLR(Group->retransmit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPSendGroupQuery(cMulticastGroup* Group)
 | 
			
		||||
{
 | 
			
		||||
	IGMPSendQuery(Group->group, IGMP_LAST_MEMBER_QUERY_INTERVAL_TS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPStartMulticast(cMulticastGroup* Group)
 | 
			
		||||
{
 | 
			
		||||
	in_addr_t g = ntohl(Group->group);
 | 
			
		||||
	if (g > MULTICAST_PRIV_MIN && g <= MULTICAST_PRIV_MAX) {
 | 
			
		||||
		cChannel *channel = Channels.GetByNumber(g - MULTICAST_PRIV_MIN);
 | 
			
		||||
		Group->connection = (cConnectionIGMP*) NewClient();
 | 
			
		||||
		if (!Group->connection->Start(channel, Group->group)) {
 | 
			
		||||
			DELETENULL(Group->connection);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cComponentIGMP::IGMPStopMulticast(cMulticastGroup* Group)
 | 
			
		||||
{
 | 
			
		||||
	if (Group->connection)
 | 
			
		||||
		Group->connection->Stop();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								server/componentIGMP.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								server/componentIGMP.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: componentIGMP.h,v 1.1 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_IGMPSERVER_H
 | 
			
		||||
#define VDR_STREAMDEV_IGMPSERVER_H
 | 
			
		||||
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <time.h>
 | 
			
		||||
#include <vdr/thread.h>
 | 
			
		||||
#include "server/component.h"
 | 
			
		||||
 | 
			
		||||
class cConnectionIGMP;
 | 
			
		||||
class cMulticastGroup;
 | 
			
		||||
 | 
			
		||||
class cComponentIGMP: public cServerComponent, public cThread {
 | 
			
		||||
private:
 | 
			
		||||
	char m_ReadBuffer[2048];
 | 
			
		||||
	cList<cMulticastGroup> m_Groups;
 | 
			
		||||
	in_addr_t m_BindIp;
 | 
			
		||||
	int m_MaxChannelNumber;
 | 
			
		||||
	struct timeval m_GeneralQueryTimer;
 | 
			
		||||
	int m_StartupQueryCount;
 | 
			
		||||
	bool m_Querier;
 | 
			
		||||
	cCondWait m_CondWait;
 | 
			
		||||
 | 
			
		||||
	cMulticastGroup* FindGroup(in_addr_t Group) const;
 | 
			
		||||
 | 
			
		||||
	/* Add or remove local host to multicast group */
 | 
			
		||||
	bool IGMPMembership(in_addr_t Group, bool Add = true);
 | 
			
		||||
	void IGMPSendQuery(in_addr_t Group, int Timeout);
 | 
			
		||||
 | 
			
		||||
	cServerConnection* ProcessMessage(struct igmp *Igmp, in_addr_t Group, in_addr_t Sender);
 | 
			
		||||
 | 
			
		||||
	void IGMPStartGeneralQueryTimer();
 | 
			
		||||
	void IGMPStartOtherQuerierPresentTimer();
 | 
			
		||||
	void IGMPSendGeneralQuery();
 | 
			
		||||
 | 
			
		||||
	void IGMPStartTimer(cMulticastGroup* Group, in_addr_t Member);
 | 
			
		||||
	void IGMPStartV1HostTimer(cMulticastGroup* Group);
 | 
			
		||||
	void IGMPStartTimerAfterLeave(cMulticastGroup* Group, unsigned int MaxResponseTime);
 | 
			
		||||
	void IGMPStartRetransmitTimer(cMulticastGroup* Group);
 | 
			
		||||
	void IGMPClearRetransmitTimer(cMulticastGroup* Group);
 | 
			
		||||
	void IGMPSendGroupQuery(cMulticastGroup* Group);
 | 
			
		||||
	void IGMPStartMulticast(cMulticastGroup* Group);
 | 
			
		||||
	void IGMPStopMulticast(cMulticastGroup* Group);
 | 
			
		||||
 | 
			
		||||
	virtual void Action();
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	virtual cServerConnection *NewClient(void);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	virtual bool Initialize(void);
 | 
			
		||||
	virtual void Destruct(void);
 | 
			
		||||
	virtual cServerConnection* Accept(void);
 | 
			
		||||
 | 
			
		||||
	cComponentIGMP(void);
 | 
			
		||||
	~cComponentIGMP(void);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_IGMPSERVER_H
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connection.c,v 1.10 2007/05/07 12:25:11 schmirl Exp $
 | 
			
		||||
 *  $Id: connection.c,v 1.12 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include "server/connection.h"
 | 
			
		||||
@@ -12,7 +12,8 @@
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
cServerConnection::cServerConnection(const char *Protocol):
 | 
			
		||||
cServerConnection::cServerConnection(const char *Protocol, int Type):
 | 
			
		||||
		cTBSocket(Type),
 | 
			
		||||
		m_Protocol(Protocol),
 | 
			
		||||
		m_DeferClose(false),
 | 
			
		||||
		m_Pending(false),
 | 
			
		||||
@@ -139,11 +140,7 @@ cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
 | 
			
		||||
	Dprintf(" * GetDevice(const cChannel*, int)\n");
 | 
			
		||||
	Dprintf(" * -------------------------------\n");
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10500
 | 
			
		||||
	device = cDevice::GetDevice(Channel, Priority);
 | 
			
		||||
#else
 | 
			
		||||
	device = cDevice::GetDevice(Channel, Priority, false);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	Dprintf(" * Found following device: %p (%d)\n", device, 
 | 
			
		||||
			device ? device->CardIndex() + 1 : 0);
 | 
			
		||||
@@ -161,11 +158,7 @@ cDevice *cServerConnection::GetDevice(const cChannel *Channel, int Priority)
 | 
			
		||||
		const cChannel *current = Channels.GetByNumber(cDevice::CurrentChannel());
 | 
			
		||||
		isyslog("streamdev-server: Detaching current receiver");
 | 
			
		||||
		Detach();
 | 
			
		||||
#if VDRVERSNUM < 10500
 | 
			
		||||
		device = cDevice::GetDevice(Channel, Priority);
 | 
			
		||||
#else
 | 
			
		||||
		device = cDevice::GetDevice(Channel, Priority, false);
 | 
			
		||||
#endif
 | 
			
		||||
		Attach();
 | 
			
		||||
		Dprintf(" * Found following device: %p (%d)\n", device, 
 | 
			
		||||
				device ? device->CardIndex() + 1 : 0);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connection.h,v 1.5 2007/04/16 11:01:02 schmirl Exp $
 | 
			
		||||
 *  $Id: connection.h,v 1.7 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SERVER_CONNECTION_H
 | 
			
		||||
@@ -44,9 +44,12 @@ protected:
 | 
			
		||||
public:
 | 
			
		||||
	/* If you derive, specify a short string such as HTTP for Protocol, which
 | 
			
		||||
	   will be displayed in error messages */
 | 
			
		||||
	cServerConnection(const char *Protocol);
 | 
			
		||||
	cServerConnection(const char *Protocol, int Type = SOCK_STREAM);
 | 
			
		||||
	virtual ~cServerConnection();
 | 
			
		||||
 | 
			
		||||
	/* If true, any client IP will be accepted */
 | 
			
		||||
	virtual bool CanAuthenticate(void) { return false; }
 | 
			
		||||
 | 
			
		||||
	/* Gets called if the client has been accepted by the core */
 | 
			
		||||
	virtual void Welcome(void) { }
 | 
			
		||||
	
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,12 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connectionHTTP.c,v 1.13 2008/03/28 15:11:40 schmirl Exp $
 | 
			
		||||
 *  $Id: connectionHTTP.c,v 1.16 2009/02/13 07:02:19 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 
 | 
			
		||||
#include "server/connectionHTTP.h"
 | 
			
		||||
#include "server/menuHTTP.h"
 | 
			
		||||
#include "server/server.h"
 | 
			
		||||
#include "server/setup.h"
 | 
			
		||||
 | 
			
		||||
cConnectionHTTP::cConnectionHTTP(void): 
 | 
			
		||||
@@ -26,6 +27,11 @@ cConnectionHTTP::~cConnectionHTTP()
 | 
			
		||||
	delete m_LiveStreamer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cConnectionHTTP::CanAuthenticate(void)
 | 
			
		||||
{
 | 
			
		||||
	return opt_auth != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cConnectionHTTP::Command(char *Cmd) 
 | 
			
		||||
{
 | 
			
		||||
	Dprintf("command %s\n", Cmd);
 | 
			
		||||
@@ -44,10 +50,22 @@ bool cConnectionHTTP::Command(char *Cmd)
 | 
			
		||||
		if (strncasecmp(Cmd, "Host:", 5) == 0) {
 | 
			
		||||
			Dprintf("Host-Header\n");
 | 
			
		||||
			m_Host = (std::string) skipspace(Cmd + 5);
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		else if (strncasecmp(Cmd, "Authorization:", 14) == 0) {
 | 
			
		||||
			Cmd = skipspace(Cmd + 14);
 | 
			
		||||
			if (strncasecmp(Cmd, "Basic", 5) == 0) {
 | 
			
		||||
				Dprintf("'Authorization Basic'-Header\n");
 | 
			
		||||
				m_Authorization = (std::string) skipspace(Cmd + 5);
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		Dprintf("header\n");
 | 
			
		||||
		return true;
 | 
			
		||||
	default:
 | 
			
		||||
		// skip additional blank lines
 | 
			
		||||
		if (*Cmd == '\0')
 | 
			
		||||
			return true;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return false; // ??? shouldn't happen
 | 
			
		||||
@@ -56,6 +74,16 @@ bool cConnectionHTTP::Command(char *Cmd)
 | 
			
		||||
bool cConnectionHTTP::ProcessRequest(void) 
 | 
			
		||||
{
 | 
			
		||||
	Dprintf("process\n");
 | 
			
		||||
	if (!StreamdevHosts.Acceptable(RemoteIpAddr()))
 | 
			
		||||
	{
 | 
			
		||||
		if (!opt_auth || m_Authorization.empty() || m_Authorization.compare(opt_auth) != 0) {
 | 
			
		||||
			isyslog("streamdev-server: HTTP authorization required");
 | 
			
		||||
			DeferClose();
 | 
			
		||||
			return Respond("HTTP/1.0 401 Authorization Required")
 | 
			
		||||
				&& Respond("WWW-authenticate: basic Realm=\"Streamdev-Server\")")
 | 
			
		||||
				&& Respond("");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (m_Request.substr(0, 4) == "GET " && CmdGET(m_Request.substr(4))) {
 | 
			
		||||
		switch (m_Job) {
 | 
			
		||||
		case hjListing:
 | 
			
		||||
@@ -183,8 +211,10 @@ bool cConnectionHTTP::CmdGET(const std::string &Opts)
 | 
			
		||||
	const char* pType = type.c_str();
 | 
			
		||||
	if (strcasecmp(pType, "PS") == 0) {
 | 
			
		||||
		m_StreamType = stPS;
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	} else if (strcasecmp(pType, "PES") == 0) {
 | 
			
		||||
		m_StreamType = stPES;
 | 
			
		||||
#endif
 | 
			
		||||
	} else if (strcasecmp(pType, "TS") == 0) {
 | 
			
		||||
		m_StreamType = stTS;
 | 
			
		||||
	} else if (strcasecmp(pType, "ES") == 0) {
 | 
			
		||||
@@ -236,7 +266,9 @@ bool cConnectionHTTP::CmdGET(const std::string &Opts)
 | 
			
		||||
				{
 | 
			
		||||
					case stTS:	base += "TS/"; break;
 | 
			
		||||
					case stPS:	base += "PS/"; break;
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
					case stPES:	base += "PES/"; break;
 | 
			
		||||
#endif
 | 
			
		||||
					case stES:	base += "ES/"; break;
 | 
			
		||||
					case stExtern:	base += "Extern/"; break;
 | 
			
		||||
					default:	break;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connectionHTTP.h,v 1.5 2008/03/28 15:11:40 schmirl Exp $
 | 
			
		||||
 *  $Id: connectionHTTP.h,v 1.6 2008/10/14 11:05:48 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONHTTP_H
 | 
			
		||||
@@ -30,6 +30,7 @@ private:
 | 
			
		||||
 | 
			
		||||
	std::string                       m_Request;
 | 
			
		||||
	std::string                       m_Host;
 | 
			
		||||
	std::string                       m_Authorization;
 | 
			
		||||
	//std::map<std::string,std::string> m_Headers; TODO: later?
 | 
			
		||||
	eHTTPStatus                       m_Status;
 | 
			
		||||
	eHTTPJob                          m_Job;
 | 
			
		||||
@@ -52,6 +53,8 @@ public:
 | 
			
		||||
	virtual void Attach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Attach(); }
 | 
			
		||||
	virtual void Detach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Detach(); }
 | 
			
		||||
 | 
			
		||||
	virtual bool CanAuthenticate(void);
 | 
			
		||||
 | 
			
		||||
	virtual bool Command(char *Cmd);
 | 
			
		||||
	bool CmdGET(const std::string &Opts);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										64
									
								
								server/connectionIGMP.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								server/connectionIGMP.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connectionIGMP.c,v 1.1 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
 
 | 
			
		||||
#include "server/connectionIGMP.h"
 | 
			
		||||
#include "server/server.h"
 | 
			
		||||
#include "server/setup.h"
 | 
			
		||||
#include <vdr/channels.h>
 | 
			
		||||
 | 
			
		||||
cConnectionIGMP::cConnectionIGMP(const char* Name, int ClientPort, eStreamType StreamType) :
 | 
			
		||||
		cServerConnection(Name, SOCK_DGRAM),
 | 
			
		||||
		m_LiveStreamer(NULL),
 | 
			
		||||
		m_ClientPort(ClientPort),
 | 
			
		||||
		m_StreamType(StreamType)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cConnectionIGMP::~cConnectionIGMP() 
 | 
			
		||||
{
 | 
			
		||||
	delete m_LiveStreamer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cConnectionIGMP::Start(cChannel *Channel, in_addr_t Dst)
 | 
			
		||||
{
 | 
			
		||||
	if (Channel != NULL) {
 | 
			
		||||
		cDevice *device = GetDevice(Channel, 0);
 | 
			
		||||
		if (device != NULL) {
 | 
			
		||||
			device->SwitchChannel(Channel, false);
 | 
			
		||||
			struct in_addr ip;
 | 
			
		||||
			ip.s_addr = Dst;
 | 
			
		||||
			if (Connect(inet_ntoa(ip), m_ClientPort)) {
 | 
			
		||||
				m_LiveStreamer = new cStreamdevLiveStreamer(0);
 | 
			
		||||
				if (m_LiveStreamer->SetChannel(Channel, m_StreamType)) {
 | 
			
		||||
					m_LiveStreamer->SetDevice(device);
 | 
			
		||||
					if (!SetDSCP())
 | 
			
		||||
						LOG_ERROR_STR("unable to set DSCP sockopt");
 | 
			
		||||
					Dprintf("streamer start\n");
 | 
			
		||||
					m_LiveStreamer->Start(this);
 | 
			
		||||
					return true;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					esyslog("streamdev-server IGMP: SetDevice failed");
 | 
			
		||||
				DELETENULL(m_LiveStreamer);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				esyslog("streamdev-server IGMP: Connect failed: %m");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			esyslog("streamdev-server IGMP: GetDevice failed");
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		esyslog("streamdev-server IGMP: Channel not found");
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cConnectionIGMP::Stop()
 | 
			
		||||
{
 | 
			
		||||
	if (m_LiveStreamer) {
 | 
			
		||||
		m_LiveStreamer->Stop();
 | 
			
		||||
		DELETENULL(m_LiveStreamer);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								server/connectionIGMP.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								server/connectionIGMP.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connectionIGMP.h,v 1.1 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SERVERS_CONNECTIONIGMP_H
 | 
			
		||||
#define VDR_STREAMDEV_SERVERS_CONNECTIONIGMP_H
 | 
			
		||||
 | 
			
		||||
#include "connection.h"
 | 
			
		||||
#include "server/livestreamer.h"
 | 
			
		||||
 | 
			
		||||
#include <tools/select.h>
 | 
			
		||||
 | 
			
		||||
#define MULTICAST_PRIV_MIN ((uint32_t) 0xefff0000)
 | 
			
		||||
#define MULTICAST_PRIV_MAX ((uint32_t) 0xeffffeff)
 | 
			
		||||
 | 
			
		||||
class cStreamdevLiveStreamer;
 | 
			
		||||
 | 
			
		||||
class cConnectionIGMP: public cServerConnection {
 | 
			
		||||
private:
 | 
			
		||||
	cStreamdevLiveStreamer           *m_LiveStreamer;
 | 
			
		||||
	int                               m_ClientPort;
 | 
			
		||||
	eStreamType                       m_StreamType;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cConnectionIGMP(const char* Name, int ClientPort, eStreamType StreamType);
 | 
			
		||||
	virtual ~cConnectionIGMP();
 | 
			
		||||
 | 
			
		||||
	bool Start(cChannel *Channel, in_addr_t Dst);
 | 
			
		||||
	void Stop();
 | 
			
		||||
 | 
			
		||||
	/* Not used here */
 | 
			
		||||
	virtual bool Command(char *Cmd) { return false; }
 | 
			
		||||
 | 
			
		||||
	virtual void Attach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Attach(); }
 | 
			
		||||
	virtual void Detach(void) { if (m_LiveStreamer != NULL) m_LiveStreamer->Detach(); }
 | 
			
		||||
 | 
			
		||||
	virtual bool Abort(void) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool cConnectionIGMP::Abort(void) const
 | 
			
		||||
{
 | 
			
		||||
	return !m_LiveStreamer || m_LiveStreamer->Abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_SERVERS_CONNECTIONIGMP_H
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: connectionVTP.c,v 1.17 2008/03/13 16:01:18 schmirl Exp $
 | 
			
		||||
 *  $Id: connectionVTP.c,v 1.19 2009/01/16 11:35:44 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include "server/connectionVTP.h"
 | 
			
		||||
@@ -595,17 +595,18 @@ bool cConnectionVTP::CmdCAPS(char *Opts)
 | 
			
		||||
		return Respond(220, "Capability \"%s\" accepted", Opts);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	if (strcasecmp(Opts, "PES") == 0) {
 | 
			
		||||
		m_StreamType = stPES;
 | 
			
		||||
		return Respond(220, "Capability \"%s\" accepted", Opts);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (strcasecmp(Opts, "EXTERN") == 0) {
 | 
			
		||||
		m_StreamType = stExtern;
 | 
			
		||||
		return Respond(220, "Capability \"%s\" accepted", Opts);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	//
 | 
			
		||||
	// Deliver section filters data in separate, channel-independent data stream
 | 
			
		||||
	//
 | 
			
		||||
@@ -613,7 +614,6 @@ bool cConnectionVTP::CmdCAPS(char *Opts)
 | 
			
		||||
		m_FiltersSupport = true;
 | 
			
		||||
		return Respond(220, "Capability \"%s\" accepted", Opts);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return Respond(561, "Capability \"%s\" not known", Opts);
 | 
			
		||||
}
 | 
			
		||||
@@ -648,13 +648,8 @@ bool cConnectionVTP::CmdPORT(char *Opts)
 | 
			
		||||
	if (ep == Opts || !isspace(*ep))
 | 
			
		||||
		return Respond(500, "Use: PORT Id Destination");
 | 
			
		||||
	
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	if (id != siLive && id != siLiveFilter)
 | 
			
		||||
		return Respond(501, "Wrong connection id %d", id);
 | 
			
		||||
#else
 | 
			
		||||
	if (id != siLive)
 | 
			
		||||
		return Respond(501, "Wrong connection id %d", id);
 | 
			
		||||
#endif
 | 
			
		||||
	
 | 
			
		||||
	Opts = skipspace(ep);
 | 
			
		||||
	n = 0;
 | 
			
		||||
@@ -681,7 +676,6 @@ bool cConnectionVTP::CmdPORT(char *Opts)
 | 
			
		||||
 | 
			
		||||
	isyslog("Streamdev: Setting data connection to %s:%d", dataip, dataport);
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	if (id == siLiveFilter) {
 | 
			
		||||
		m_FiltersSupport = true;
 | 
			
		||||
		if(m_FilterStreamer)
 | 
			
		||||
@@ -703,7 +697,6 @@ bool cConnectionVTP::CmdPORT(char *Opts)
 | 
			
		||||
 | 
			
		||||
		return Respond(220, "Port command ok, data connection opened");
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if(m_LiveSocket && m_LiveStreamer)
 | 
			
		||||
		m_LiveStreamer->Stop();
 | 
			
		||||
@@ -746,14 +739,12 @@ bool cConnectionVTP::CmdTUNE(char *Opts)
 | 
			
		||||
	if(m_LiveSocket)
 | 
			
		||||
		m_LiveStreamer->Start(m_LiveSocket);
 | 
			
		||||
	
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	if(m_FiltersSupport) {
 | 
			
		||||
		if(!m_FilterStreamer)
 | 
			
		||||
			m_FilterStreamer = new cStreamdevFilterStreamer;
 | 
			
		||||
		m_FilterStreamer->SetDevice(dev);
 | 
			
		||||
		//m_FilterStreamer->SetChannel(chan);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	return Respond(220, "Channel tuned");
 | 
			
		||||
}
 | 
			
		||||
@@ -788,7 +779,6 @@ bool cConnectionVTP::CmdDELP(char *Opts)
 | 
			
		||||
 | 
			
		||||
bool cConnectionVTP::CmdADDF(char *Opts) 
 | 
			
		||||
{
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	int pid, tid, mask;
 | 
			
		||||
	char *ep;
 | 
			
		||||
 | 
			
		||||
@@ -810,14 +800,10 @@ bool cConnectionVTP::CmdADDF(char *Opts)
 | 
			
		||||
	return m_FilterStreamer->SetFilter(pid, tid, mask, true)
 | 
			
		||||
			? Respond(220, "Filter %d transferring", pid)
 | 
			
		||||
			: Respond(560, "Filter %d not available", pid);
 | 
			
		||||
#else
 | 
			
		||||
	return Respond(500, "ADDF known but unimplemented with VDR < 1.3.0");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cConnectionVTP::CmdDELF(char *Opts) 
 | 
			
		||||
{
 | 
			
		||||
#if VDRVERSNUM >= 10307
 | 
			
		||||
	int pid, tid, mask;
 | 
			
		||||
	char *ep;
 | 
			
		||||
	
 | 
			
		||||
@@ -838,9 +824,6 @@ bool cConnectionVTP::CmdDELF(char *Opts)
 | 
			
		||||
 | 
			
		||||
	m_FilterStreamer->SetFilter(pid, tid, mask, false);
 | 
			
		||||
	return Respond(220, "Filter %d stopped", pid);
 | 
			
		||||
#else
 | 
			
		||||
	return Respond(500, "DELF known but unimplemented with VDR < 1.3.0");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cConnectionVTP::CmdABRT(char *Opts) 
 | 
			
		||||
@@ -857,12 +840,10 @@ bool cConnectionVTP::CmdABRT(char *Opts)
 | 
			
		||||
		DELETENULL(m_LiveStreamer); 
 | 
			
		||||
		DELETENULL(m_LiveSocket);
 | 
			
		||||
		break;
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
	case siLiveFilter:
 | 
			
		||||
		DELETENULL(m_FilterStreamer);
 | 
			
		||||
		DELETENULL(m_FilterSocket);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	default:
 | 
			
		||||
		return Respond(501, "Wrong connection id %d", id);
 | 
			
		||||
		break;
 | 
			
		||||
 
 | 
			
		||||
@@ -12,9 +12,9 @@ class cLSTTHandler;
 | 
			
		||||
 | 
			
		||||
class cConnectionVTP: public cServerConnection {
 | 
			
		||||
	friend class cLSTEHandler;
 | 
			
		||||
	// if your compiler doesn't understand the following statement
 | 
			
		||||
	// (e.g. gcc 2.x), simply remove it and try again ;-)
 | 
			
		||||
#if !defined __GNUC__ || __GNUC__ >= 3
 | 
			
		||||
	using cServerConnection::Respond;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	cTBSocket                *m_LiveSocket;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,15 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: livefilter.c,v 1.4 2007/04/24 11:06:12 schmirl Exp $
 | 
			
		||||
 *  $Id: livefilter.c,v 1.7 2009/02/13 13:02:40 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "server/livefilter.h"
 | 
			
		||||
#include "server/streamer.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#ifndef TS_SIZE
 | 
			
		||||
#    define TS_SIZE          188
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef TS_SYNC_BYTE
 | 
			
		||||
#    define TS_SYNC_BYTE     0x47
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
 | 
			
		||||
cStreamdevLiveFilter::cStreamdevLiveFilter(cStreamdevStreamer *Streamer) {
 | 
			
		||||
	m_Streamer = Streamer;
 | 
			
		||||
}
 | 
			
		||||
@@ -31,6 +26,7 @@ void cStreamdevLiveFilter::Process(u_short Pid, u_char Tid, const u_char *Data,
 | 
			
		||||
		buffer[1] = ((Pid >> 8) & 0x3f) | (pos==0 ? 0x40 : 0); /* bit 6: payload unit start indicator (PUSI) */
 | 
			
		||||
		buffer[2] = Pid & 0xff;
 | 
			
		||||
		buffer[3] = Tid;
 | 
			
		||||
		// this makes it a proprietary stream
 | 
			
		||||
		buffer[4] = (uchar)chunk;
 | 
			
		||||
		memcpy(buffer + 5, Data + pos, chunk);
 | 
			
		||||
		length -= chunk;
 | 
			
		||||
@@ -41,5 +37,3 @@ void cStreamdevLiveFilter::Process(u_short Pid, u_char Tid, const u_char *Data,
 | 
			
		||||
			m_Streamer->ReportOverflow(TS_SIZE - p);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // VDRVERSNUM >= 10300
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: livefilter.h,v 1.4 2007/04/24 11:29:29 schmirl Exp $
 | 
			
		||||
 *  $Id: livefilter.h,v 1.5 2008/04/07 14:27:31 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef VDR_STREAMEV_LIVEFILTER_H
 | 
			
		||||
@@ -7,8 +7,6 @@
 | 
			
		||||
 | 
			
		||||
#include <vdr/config.h>
 | 
			
		||||
 | 
			
		||||
#	if VDRVERSNUM >= 10300
 | 
			
		||||
 | 
			
		||||
#include <vdr/filter.h>
 | 
			
		||||
 | 
			
		||||
class cStreamdevStreamer;
 | 
			
		||||
@@ -31,5 +29,4 @@ public:
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#	endif // VDRVERSNUM >= 10300
 | 
			
		||||
#endif // VDR_STREAMEV_LIVEFILTER_H
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,14 @@
 | 
			
		||||
#include <libsi/section.h>
 | 
			
		||||
#include <libsi/descriptor.h>
 | 
			
		||||
 | 
			
		||||
#include "remux/ts2ps.h"
 | 
			
		||||
#include "remux/ts2es.h"
 | 
			
		||||
#include "remux/extern.h"
 | 
			
		||||
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
 | 
			
		||||
#include "server/livestreamer.h"
 | 
			
		||||
#include "server/livefilter.h"
 | 
			
		||||
#include "remux/ts2ps.h"
 | 
			
		||||
#include "remux/ts2es.h"
 | 
			
		||||
#include "remux/extern.h"
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
#define TSPATREPACKER
 | 
			
		||||
@@ -27,23 +28,13 @@ protected:
 | 
			
		||||
	virtual void Receive(uchar *Data, int Length);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
#if VDRVERSNUM < 10500
 | 
			
		||||
	cStreamdevLiveReceiver(cStreamdevStreamer *Streamer, int Ca, int Priority, const int *Pids);
 | 
			
		||||
#else
 | 
			
		||||
	cStreamdevLiveReceiver(cStreamdevStreamer *Streamer, tChannelID ChannelID, int Priority, const int *Pids);
 | 
			
		||||
#endif
 | 
			
		||||
	virtual ~cStreamdevLiveReceiver();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10500
 | 
			
		||||
cStreamdevLiveReceiver::cStreamdevLiveReceiver(cStreamdevStreamer *Streamer, int Ca, 
 | 
			
		||||
                                               int Priority, const int *Pids):
 | 
			
		||||
		cReceiver(Ca, Priority, 0, Pids),
 | 
			
		||||
#else
 | 
			
		||||
cStreamdevLiveReceiver::cStreamdevLiveReceiver(cStreamdevStreamer *Streamer, tChannelID ChannelID, 
 | 
			
		||||
                                               int Priority, const int *Pids):
 | 
			
		||||
		cReceiver(ChannelID, Priority, 0, Pids),
 | 
			
		||||
#endif
 | 
			
		||||
		m_Streamer(Streamer)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@@ -86,7 +77,7 @@ public:
 | 
			
		||||
 | 
			
		||||
cStreamdevPatFilter::cStreamdevPatFilter(cStreamdevLiveStreamer *Streamer, const cChannel *Channel)
 | 
			
		||||
{
 | 
			
		||||
	Dprintf("cStreamdevPatFilter(\"%s\")", Channel->Name());
 | 
			
		||||
	Dprintf("cStreamdevPatFilter(\"%s\")\n", Channel->Name());
 | 
			
		||||
	assert(Streamer);
 | 
			
		||||
	m_Channel = Channel;
 | 
			
		||||
	m_Streamer = Streamer;
 | 
			
		||||
@@ -145,7 +136,7 @@ int cStreamdevPatFilter::GetPid(SI::PMT::Stream& stream)
 | 
			
		||||
	case 0x10: // ISO/IEC 14496-2 Visual (MPEG-4)
 | 
			
		||||
	case 0x11: // ISO/IEC 14496-3 Audio with LATM transport syntax
 | 
			
		||||
	case 0x1b: // ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264)
 | 
			
		||||
		Dprintf("cStreamdevPatFilter PMT scanner adding PID %d (%s)",
 | 
			
		||||
		Dprintf("cStreamdevPatFilter PMT scanner adding PID %d (%s)\n",
 | 
			
		||||
			stream.getPid(), psStreamTypes[stream.getStreamType()]);
 | 
			
		||||
		return stream.getPid();
 | 
			
		||||
	case 0x05: // ISO/IEC 13818-1 private sections
 | 
			
		||||
@@ -153,19 +144,19 @@ int cStreamdevPatFilter::GetPid(SI::PMT::Stream& stream)
 | 
			
		||||
		for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
 | 
			
		||||
			switch (d->getDescriptorTag()) {
 | 
			
		||||
			case SI::AC3DescriptorTag:
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s", 
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
 | 
			
		||||
					stream.getPid(), psStreamTypes[stream.getStreamType()], "AC3");
 | 
			
		||||
				return stream.getPid();
 | 
			
		||||
			case SI::TeletextDescriptorTag:
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s", 
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
 | 
			
		||||
					stream.getPid(), psStreamTypes[stream.getStreamType()], "Teletext");
 | 
			
		||||
				return stream.getPid();
 | 
			
		||||
			case SI::SubtitlingDescriptorTag:
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s", 
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: adding PID %d (%s) %s\n",
 | 
			
		||||
					stream.getPid(), psStreamTypes[stream.getStreamType()], "DVBSUB");
 | 
			
		||||
				return stream.getPid();
 | 
			
		||||
			default:
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: NOT adding PID %d (%s) %s", 
 | 
			
		||||
				Dprintf("cStreamdevPatFilter PMT scanner: NOT adding PID %d (%s) %s\n",
 | 
			
		||||
					stream.getPid(), psStreamTypes[stream.getStreamType()], "UNKNOWN");
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
@@ -210,7 +201,7 @@ int cStreamdevPatFilter::GetPid(SI::PMT::Stream& stream)
 | 
			
		||||
				return stream.getPid();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		Dprintf("cStreamdevPatFilter PMT scanner: NOT adding PID %d (%s) %s",
 | 
			
		||||
		Dprintf("cStreamdevPatFilter PMT scanner: NOT adding PID %d (%s) %s\n",
 | 
			
		||||
			stream.getPid(), psStreamTypes[stream.getStreamType()<0x1c?stream.getStreamType():0], "UNKNOWN");
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
@@ -220,7 +211,7 @@ int cStreamdevPatFilter::GetPid(SI::PMT::Stream& stream)
 | 
			
		||||
void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
 | 
			
		||||
{
 | 
			
		||||
	if (Pid == 0x00) {
 | 
			
		||||
		if (Tid == 0x00 && !pmtPid) {
 | 
			
		||||
		if (Tid == 0x00) {
 | 
			
		||||
			SI::PAT pat(Data, false);
 | 
			
		||||
			if (!pat.CheckCRCAndParse())
 | 
			
		||||
				return;
 | 
			
		||||
@@ -229,8 +220,9 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
 | 
			
		||||
				if (!assoc.isNITPid()) {
 | 
			
		||||
					const cChannel *Channel =  Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId());
 | 
			
		||||
					if (Channel && (Channel == m_Channel)) {
 | 
			
		||||
						int prevPmtPid = pmtPid;
 | 
			
		||||
						if (0 != (pmtPid = assoc.getPid())) {
 | 
			
		||||
							Dprintf("cStreamdevPatFilter: PMT pid for channel %s: %d", Channel->Name(), pmtPid);
 | 
			
		||||
							Dprintf("cStreamdevPatFilter: PMT pid for channel %s: %d\n", Channel->Name(), pmtPid);
 | 
			
		||||
							pmtSid = assoc.getServiceId();
 | 
			
		||||
							if (Length < TS_SIZE-5) {
 | 
			
		||||
								// repack PAT to TS frame and send to client
 | 
			
		||||
@@ -242,25 +234,27 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
 | 
			
		||||
								int ts_id;
 | 
			
		||||
								unsigned int crc, i, len;
 | 
			
		||||
								uint8_t *tmp, tspat_buf[TS_SIZE];
 | 
			
		||||
								static uint8_t ccounter = 0;
 | 
			
		||||
								ccounter = (ccounter + 1) % 16;
 | 
			
		||||
								memset(tspat_buf, 0xff, TS_SIZE);
 | 
			
		||||
								memset(tspat_buf, 0x0, 4 + 12 + 5);   // TS_HDR_LEN + PAT_TABLE_LEN + 5
 | 
			
		||||
								ts_id = Channel->Tid();               // Get transport stream id of the channel
 | 
			
		||||
								tspat_buf[0] = TS_SYNC_BYTE;          // Transport packet header sunchronization byte (1000011 = 0x47h)
 | 
			
		||||
								tspat_buf[1] = 0x40;                  // Set payload unit start indicator bit
 | 
			
		||||
								tspat_buf[2] = 0x0;                   // PID
 | 
			
		||||
								tspat_buf[3] = 0x10;                  // Set payload flag to indicate precence of payload data
 | 
			
		||||
								tspat_buf[4] = 0x0;                   // PSI
 | 
			
		||||
								tspat_buf[3] = 0x10 | ccounter;       // Set payload flag, Continuity counter
 | 
			
		||||
								tspat_buf[4] = 0x0;                   // SI pointer field
 | 
			
		||||
								tspat_buf[5] = 0x0;                   // PAT table id
 | 
			
		||||
								tspat_buf[6] = 0xb0;                  // Section syntax indicator bit and reserved bits set
 | 
			
		||||
								tspat_buf[7] = 12 + 1;                // Section length (12 bit): PAT_TABLE_LEN + 1
 | 
			
		||||
								tspat_buf[8] = (ts_id >> 8) & 0xff;   // Transport stream ID (bits 8-15)
 | 
			
		||||
								tspat_buf[8] = (ts_id >> 8);          // Transport stream ID (bits 8-15)
 | 
			
		||||
								tspat_buf[9] = (ts_id & 0xff);        // Transport stream ID (bits 0-7)
 | 
			
		||||
								tspat_buf[10] = 0x01;                 // Version number 0, Current next indicator bit set  
 | 
			
		||||
								tspat_buf[10] = 0xc0 | ((pat.getVersionNumber() << 1) & 0x3e) |
 | 
			
		||||
									pat.getCurrentNextIndicator();// Version number, Current next indicator
 | 
			
		||||
								tspat_buf[11] = 0x0;                  // Section number
 | 
			
		||||
								tspat_buf[12] = 0x0;                  // Last section number
 | 
			
		||||
								tspat_buf[13] = (pmtSid >> 8) & 0xff; // Program number (bits 8-15)
 | 
			
		||||
								tspat_buf[13] = (pmtSid >> 8);        // Program number (bits 8-15)
 | 
			
		||||
								tspat_buf[14] = (pmtSid & 0xff);      // Program number (bits 0-7)
 | 
			
		||||
								tspat_buf[15] = (pmtPid >> 8) & 0xff; // Network ID (bits 8-12)
 | 
			
		||||
								tspat_buf[15] = 0xe0 | (pmtPid >> 8); // Network ID (bits 8-12)
 | 
			
		||||
								tspat_buf[16] = (pmtPid & 0xff);      // Network ID (bits 0-7)
 | 
			
		||||
								crc = 0xffffffff;
 | 
			
		||||
								len = 12;                             // PAT_TABLE_LEN
 | 
			
		||||
@@ -278,9 +272,11 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
 | 
			
		||||
#endif
 | 
			
		||||
							} else 
 | 
			
		||||
								isyslog("cStreamdevPatFilter: PAT size %d too large to fit in one TS", Length);
 | 
			
		||||
							m_Streamer->SetPids(pmtPid);
 | 
			
		||||
							Add(pmtPid, 0x02);
 | 
			
		||||
							pmtVersion = -1;
 | 
			
		||||
							if (pmtPid != prevPmtPid) {
 | 
			
		||||
								m_Streamer->SetPids(pmtPid);
 | 
			
		||||
								Add(pmtPid, 0x02);
 | 
			
		||||
								pmtVersion = -1;
 | 
			
		||||
							}
 | 
			
		||||
							return;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
@@ -295,7 +291,7 @@ void cStreamdevPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, i
 | 
			
		||||
			return; // skip broken PMT records
 | 
			
		||||
		if (pmtVersion != -1) {
 | 
			
		||||
			if (pmtVersion != pmt.getVersionNumber()) {
 | 
			
		||||
				Dprintf("cStreamdevPatFilter: PMT version changed, detaching all pids");
 | 
			
		||||
				Dprintf("cStreamdevPatFilter: PMT version changed, detaching all pids\n");
 | 
			
		||||
				Del(pmtPid, 0x02);
 | 
			
		||||
				pmtPid = 0; // this triggers PAT scan
 | 
			
		||||
			}
 | 
			
		||||
@@ -333,7 +329,9 @@ cStreamdevLiveStreamer::cStreamdevLiveStreamer(int Priority, std::string Paramet
 | 
			
		||||
		m_Device(NULL),
 | 
			
		||||
		m_Receiver(NULL),
 | 
			
		||||
		m_PatFilter(NULL),
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
		m_PESRemux(NULL),
 | 
			
		||||
#endif
 | 
			
		||||
		m_ESRemux(NULL),
 | 
			
		||||
		m_PSRemux(NULL),
 | 
			
		||||
		m_ExtRemux(NULL)
 | 
			
		||||
@@ -349,7 +347,9 @@ cStreamdevLiveStreamer::~cStreamdevLiveStreamer()
 | 
			
		||||
		DELETENULL(m_PatFilter);
 | 
			
		||||
	}
 | 
			
		||||
	DELETENULL(m_Receiver);
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	delete m_PESRemux;
 | 
			
		||||
#endif
 | 
			
		||||
	delete m_ESRemux;
 | 
			
		||||
	delete m_PSRemux;
 | 
			
		||||
	delete m_ExtRemux;
 | 
			
		||||
@@ -434,11 +434,7 @@ void cStreamdevLiveStreamer::StartReceiver(void)
 | 
			
		||||
	DELETENULL(m_Receiver);
 | 
			
		||||
	if (m_NumPids > 0) {
 | 
			
		||||
		Dprintf("Creating Receiver to respect changed pids\n");
 | 
			
		||||
#if VDRVERSNUM < 10500
 | 
			
		||||
		m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->Ca(), m_Priority, m_Pids);
 | 
			
		||||
#else
 | 
			
		||||
		m_Receiver = new cStreamdevLiveReceiver(this, m_Channel->GetChannelID(), m_Priority, m_Pids);
 | 
			
		||||
#endif
 | 
			
		||||
		if (IsRunning() && m_Device != NULL) {
 | 
			
		||||
			Dprintf("Attaching new receiver\n");
 | 
			
		||||
			Attach();
 | 
			
		||||
@@ -467,10 +463,12 @@ bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType Str
 | 
			
		||||
			return SetPids(pid);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	case stPES: 
 | 
			
		||||
		m_PESRemux = new cRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(), 
 | 
			
		||||
								m_Channel->Spids(), false);
 | 
			
		||||
		return SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	case stPS:  
 | 
			
		||||
		m_PSRemux = new cTS2PSRemux(m_Channel->Vpid(), m_Channel->Apids(), m_Channel->Dpids(),
 | 
			
		||||
@@ -483,6 +481,10 @@ bool cStreamdevLiveStreamer::SetChannel(const cChannel *Channel, eStreamType Str
 | 
			
		||||
			Detach();
 | 
			
		||||
			DELETENULL(m_PatFilter);
 | 
			
		||||
		}
 | 
			
		||||
		// Set pids from cChannel
 | 
			
		||||
		SetPids(m_Channel->Vpid(), Apids, Dpids, m_Channel->Spids());
 | 
			
		||||
		if (m_Channel->Vpid() != m_Channel->Ppid())
 | 
			
		||||
			SetPid(m_Channel->Ppid(), true);
 | 
			
		||||
		// Set pids from PMT
 | 
			
		||||
		m_PatFilter = new cStreamdevPatFilter(this, m_Channel);
 | 
			
		||||
		return true;
 | 
			
		||||
@@ -506,8 +508,10 @@ int cStreamdevLiveStreamer::Put(const uchar *Data, int Count)
 | 
			
		||||
	case stTSPIDS:
 | 
			
		||||
		return cStreamdevStreamer::Put(Data, Count);
 | 
			
		||||
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	case stPES:
 | 
			
		||||
		return m_PESRemux->Put(Data, Count);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	case stES:
 | 
			
		||||
		return m_ESRemux->Put(Data, Count);
 | 
			
		||||
@@ -530,8 +534,10 @@ uchar *cStreamdevLiveStreamer::Get(int &Count)
 | 
			
		||||
	case stTSPIDS:
 | 
			
		||||
		return cStreamdevStreamer::Get(Count);
 | 
			
		||||
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	case stPES:
 | 
			
		||||
		return m_PESRemux->Get(Count);
 | 
			
		||||
#endif
 | 
			
		||||
	
 | 
			
		||||
	case stES:
 | 
			
		||||
		return m_ESRemux->Get(Count);
 | 
			
		||||
@@ -555,9 +561,11 @@ void cStreamdevLiveStreamer::Del(int Count)
 | 
			
		||||
		cStreamdevStreamer::Del(Count);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	case stPES:
 | 
			
		||||
		m_PESRemux->Del(Count);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
	
 | 
			
		||||
	case stES:
 | 
			
		||||
		m_ESRemux->Del(Count);
 | 
			
		||||
@@ -618,7 +626,6 @@ std::string cStreamdevLiveStreamer::Report(void)
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevFilterStreamer -------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
cStreamdevFilterStreamer::cStreamdevFilterStreamer():
 | 
			
		||||
		cStreamdevStreamer("streamdev-filterstreaming"),
 | 
			
		||||
		m_Device(NULL),
 | 
			
		||||
@@ -720,5 +727,3 @@ void cStreamdevFilterStreamer::ChannelSwitch(const cDevice *Device, int ChannelN
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // if VDRVERSNUM >= 10300
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,9 @@
 | 
			
		||||
class cTS2PSRemux;
 | 
			
		||||
class cTS2ESRemux;
 | 
			
		||||
class cExternRemux;
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
class cRemux;
 | 
			
		||||
#endif
 | 
			
		||||
class cStreamdevPatFilter;
 | 
			
		||||
class cStreamdevLiveReceiver;
 | 
			
		||||
 | 
			
		||||
@@ -27,7 +29,9 @@ private:
 | 
			
		||||
	cDevice                *m_Device;
 | 
			
		||||
	cStreamdevLiveReceiver *m_Receiver;
 | 
			
		||||
	cStreamdevPatFilter    *m_PatFilter;
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	cRemux                 *m_PESRemux;
 | 
			
		||||
#endif
 | 
			
		||||
	cTS2ESRemux            *m_ESRemux;
 | 
			
		||||
	cTS2PSRemux            *m_PSRemux;
 | 
			
		||||
	cExternRemux           *m_ExtRemux;
 | 
			
		||||
@@ -58,8 +62,6 @@ public:
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevFilterStreamer -------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#  if VDRVERSNUM >= 10300
 | 
			
		||||
 | 
			
		||||
//#include <vdr/status.h>
 | 
			
		||||
 | 
			
		||||
class cStreamdevLiveFilter;
 | 
			
		||||
@@ -85,6 +87,4 @@ public:
 | 
			
		||||
	//virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#  endif // if VDRVERSNUM >= 10300
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_LIVESTREAMER_H
 | 
			
		||||
 
 | 
			
		||||
@@ -112,10 +112,10 @@ const cChannel* cChannelList::GetGroup(int Index)
 | 
			
		||||
 | 
			
		||||
// ******************** cHtmlChannelList ******************
 | 
			
		||||
const char* cHtmlChannelList::menu =
 | 
			
		||||
	"[<a href=\"/\">Home</a> (<a href=\"all.html\">no script</a>)] "
 | 
			
		||||
	"[<a href=\"tree.html\">Tree View</a>] "
 | 
			
		||||
	"[<a href=\"groups.html\">Groups</a> (<a href=\"groups.m3u\">Playlist</a>)] "
 | 
			
		||||
	"[<a href=\"channels.html\">Channels</a> (<a href=\"channels.m3u\">Playlist</a>)] ";
 | 
			
		||||
	"[<a href=\"/\">Home</a> (<a href=\"all.html\" tvid=\"RED\">no script</a>)] "
 | 
			
		||||
	"[<a href=\"tree.html\" tvid=\"GREEN\">Tree View</a>] "
 | 
			
		||||
	"[<a href=\"groups.html\" tvid=\"YELLOW\">Groups</a> (<a href=\"groups.m3u\">Playlist</a>)] "
 | 
			
		||||
	"[<a href=\"channels.html\" tvid=\"BLUE\">Channels</a> (<a href=\"channels.m3u\">Playlist</a>)] ";
 | 
			
		||||
 | 
			
		||||
const char* cHtmlChannelList::css =
 | 
			
		||||
	"<style type=\"text/css\">\n"
 | 
			
		||||
@@ -201,8 +201,10 @@ std::string cHtmlChannelList::StreamTypeMenu()
 | 
			
		||||
			(std::string) "[<a href=\"/TS/" + self + "\">TS</a>] ");
 | 
			
		||||
	typeMenu += (streamType == stPS ? (std::string) "[PS] " :
 | 
			
		||||
			(std::string) "[<a href=\"/PS/" + self + "\">PS</a>] ");
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
	typeMenu += (streamType == stPES ? (std::string) "[PES] " :
 | 
			
		||||
			(std::string) "[<a href=\"/PES/" + self + "\">PES</a>] ");
 | 
			
		||||
#endif
 | 
			
		||||
	typeMenu += (streamType == stES ? (std::string) "[ES] " :
 | 
			
		||||
			(std::string) "[<a href=\"/ES/" + self + "\">ES</a>] ");
 | 
			
		||||
	typeMenu += (streamType == stExtern ? (std::string) "[Extern] " :
 | 
			
		||||
@@ -336,9 +338,26 @@ std::string cHtmlChannelList::GroupTitle()
 | 
			
		||||
std::string cHtmlChannelList::ItemText()
 | 
			
		||||
{
 | 
			
		||||
	std::string line;
 | 
			
		||||
	std::string suffix;
 | 
			
		||||
 | 
			
		||||
	switch (streamType) {
 | 
			
		||||
		case stTS: suffix = (std::string) ".ts"; break;
 | 
			
		||||
		case stPS: suffix = (std::string) ".vob"; break;
 | 
			
		||||
#if APIVERSNUM < 10703
 | 
			
		||||
		// for Network Media Tank
 | 
			
		||||
		case stPES: suffix = (std::string) ".vdr"; break; 
 | 
			
		||||
#endif
 | 
			
		||||
		default: suffix = "";
 | 
			
		||||
	}
 | 
			
		||||
	line += (std::string) "<li value=\"" + (const char*) itoa(current->Number()) + "\">";
 | 
			
		||||
	line += (std::string) "<a href=\"" + (std::string) current->GetChannelID().ToString() + "\">" +
 | 
			
		||||
		current->Name() + "</a>";
 | 
			
		||||
	line += (std::string) "<a href=\"" + (std::string) current->GetChannelID().ToString() + suffix + "\"";
 | 
			
		||||
 | 
			
		||||
	// for Network Media Tank
 | 
			
		||||
	line += (std::string) " vod ";
 | 
			
		||||
	if (current->Number() < 1000)
 | 
			
		||||
	    line += (std::string) " tvid=\"" + (const char*) itoa(current->Number()) + "\""; 
 | 
			
		||||
 | 
			
		||||
	line += (std::string) ">" + current->Name() + "</a>";
 | 
			
		||||
 | 
			
		||||
	int count = 0;
 | 
			
		||||
	for (int i = 0; current->Apid(i) != 0; ++i, ++count)
 | 
			
		||||
@@ -351,11 +370,11 @@ std::string cHtmlChannelList::ItemText()
 | 
			
		||||
		int index = 1;
 | 
			
		||||
		for (int i = 0; current->Apid(i) != 0; ++i, ++index) {
 | 
			
		||||
			line += (std::string) " <a href=\"" + (std::string) current->GetChannelID().ToString() +
 | 
			
		||||
					"+" + (const char*)itoa(index) + "\" class=\"apid\">" + current->Alang(i) + "</a>";
 | 
			
		||||
					"+" + (const char*)itoa(index) + suffix + "\" class=\"apid\" vod>" + current->Alang(i) + "</a>";
 | 
			
		||||
			}
 | 
			
		||||
		for (int i = 0; current->Dpid(i) != 0; ++i, ++index) {
 | 
			
		||||
			line += (std::string) " <a href=\"" + (std::string) current->GetChannelID().ToString() +
 | 
			
		||||
					"+" + (const char*)itoa(index) + "\" class=\"dpid\">" + current->Dlang(i) + "</a>";
 | 
			
		||||
					"+" + (const char*)itoa(index) + suffix + "\" class=\"dpid\" vod>" + current->Dlang(i) + "</a>";
 | 
			
		||||
			}
 | 
			
		||||
	}
 | 
			
		||||
	line += "</li>";
 | 
			
		||||
@@ -364,10 +383,8 @@ std::string cHtmlChannelList::ItemText()
 | 
			
		||||
 | 
			
		||||
// ******************** cM3uChannelList ******************
 | 
			
		||||
cM3uChannelList::cM3uChannelList(cChannelIterator *Iterator, const char* Base)
 | 
			
		||||
: cChannelList(Iterator)
 | 
			
		||||
#if defined(APIVERSNUM) && APIVERSNUM >= 10503
 | 
			
		||||
  , m_IConv(cCharSetConv::SystemCharacterTable(), "UTF-8")
 | 
			
		||||
#endif
 | 
			
		||||
: cChannelList(Iterator),
 | 
			
		||||
  m_IConv(cCharSetConv::SystemCharacterTable(), "UTF-8")
 | 
			
		||||
{
 | 
			
		||||
	base = strdup(Base);
 | 
			
		||||
	m3uState = msFirst;
 | 
			
		||||
@@ -398,11 +415,7 @@ std::string cM3uChannelList::Next()
 | 
			
		||||
		return "";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if defined(APIVERSNUM) && APIVERSNUM >= 10503
 | 
			
		||||
	std::string name = (std::string) m_IConv.Convert(channel->Name());
 | 
			
		||||
#else
 | 
			
		||||
	std::string name = channel->Name();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (channel->GroupSep())
 | 
			
		||||
	{
 | 
			
		||||
 
 | 
			
		||||
@@ -126,9 +126,7 @@ class cM3uChannelList: public cChannelList
 | 
			
		||||
		char *base;
 | 
			
		||||
		enum eM3uState { msFirst, msContinue, msLast };
 | 
			
		||||
		eM3uState m3uState;
 | 
			
		||||
#if defined(APIVERSNUM) && APIVERSNUM >= 10503
 | 
			
		||||
		cCharSetConv m_IConv;
 | 
			
		||||
#endif
 | 
			
		||||
	public:
 | 
			
		||||
		virtual std::string HttpHeader() { return cChannelList::HttpHeader() + "Content-type: audio/x-mpegurl\r\n"; };
 | 
			
		||||
		virtual bool HasNext();
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,11 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: server.c,v 1.5 2007/04/02 10:32:34 schmirl Exp $
 | 
			
		||||
 *  $Id: server.c,v 1.10 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "server/server.h"
 | 
			
		||||
#include "server/componentVTP.h"
 | 
			
		||||
#include "server/componentHTTP.h"
 | 
			
		||||
#include "server/componentIGMP.h"
 | 
			
		||||
#include "server/setup.h"
 | 
			
		||||
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
@@ -13,14 +14,15 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
cSVDRPhosts StreamdevHosts;
 | 
			
		||||
char *opt_auth = NULL;
 | 
			
		||||
char *opt_remux = NULL;
 | 
			
		||||
 | 
			
		||||
cStreamdevServer         *cStreamdevServer::m_Instance = NULL;
 | 
			
		||||
cList<cServerComponent>   cStreamdevServer::m_Servers;
 | 
			
		||||
cList<cServerConnection>  cStreamdevServer::m_Clients;
 | 
			
		||||
 | 
			
		||||
cStreamdevServer::cStreamdevServer(void):
 | 
			
		||||
		cThread("streamdev server"),
 | 
			
		||||
		m_Active(false)
 | 
			
		||||
		cThread("streamdev server")
 | 
			
		||||
{
 | 
			
		||||
	Start();
 | 
			
		||||
}
 | 
			
		||||
@@ -35,6 +37,12 @@ void cStreamdevServer::Initialize(void)
 | 
			
		||||
	if (m_Instance == NULL) {
 | 
			
		||||
		if (StreamdevServerSetup.StartVTPServer)  Register(new cComponentVTP);
 | 
			
		||||
		if (StreamdevServerSetup.StartHTTPServer) Register(new cComponentHTTP);
 | 
			
		||||
		if (StreamdevServerSetup.StartIGMPServer) {
 | 
			
		||||
			if (strcmp(StreamdevServerSetup.IGMPBindIP, "0.0.0.0") == 0)
 | 
			
		||||
				esyslog("streamdev-server: Not starting IGMP. IGMP must be bound to a local IP");
 | 
			
		||||
			else
 | 
			
		||||
				Register(new cComponentIGMP);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_Instance = new cStreamdevServer;
 | 
			
		||||
	}
 | 
			
		||||
@@ -47,10 +55,8 @@ void cStreamdevServer::Destruct(void)
 | 
			
		||||
 | 
			
		||||
void cStreamdevServer::Stop(void) 
 | 
			
		||||
{
 | 
			
		||||
	if (m_Active) {
 | 
			
		||||
		m_Active = false;
 | 
			
		||||
	if (Running())
 | 
			
		||||
		Cancel(3);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cStreamdevServer::Register(cServerComponent *Server) 
 | 
			
		||||
@@ -60,8 +66,6 @@ void cStreamdevServer::Register(cServerComponent *Server)
 | 
			
		||||
 | 
			
		||||
void cStreamdevServer::Action(void) 
 | 
			
		||||
{
 | 
			
		||||
	m_Active = true;
 | 
			
		||||
 | 
			
		||||
	/* Initialize Server components, deleting those that failed */
 | 
			
		||||
	for (cServerComponent *c = m_Servers.First(); c;) {
 | 
			
		||||
		cServerComponent *next = m_Servers.Next(c);
 | 
			
		||||
@@ -72,11 +76,11 @@ void cStreamdevServer::Action(void)
 | 
			
		||||
			
 | 
			
		||||
	if (m_Servers.Count() == 0) {
 | 
			
		||||
		esyslog("ERROR: no streamdev server activated, exiting");
 | 
			
		||||
		m_Active = false;
 | 
			
		||||
		Cancel(-1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cTBSelect select;
 | 
			
		||||
	while (m_Active) {
 | 
			
		||||
	while (Running()) {
 | 
			
		||||
		select.Clear();
 | 
			
		||||
 | 
			
		||||
		/* Ask all Server components to register to the selector */
 | 
			
		||||
@@ -102,9 +106,9 @@ void cStreamdevServer::Action(void)
 | 
			
		||||
						sel = 0;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} while (sel < 0 && errno == ETIMEDOUT && m_Active);
 | 
			
		||||
		} while (sel < 0 && errno == ETIMEDOUT && Running());
 | 
			
		||||
 | 
			
		||||
		if (!m_Active)
 | 
			
		||||
		if (!Running())
 | 
			
		||||
			break;
 | 
			
		||||
		if (sel < 0) {
 | 
			
		||||
			esyslog("fatal error, server exiting: %m");
 | 
			
		||||
@@ -115,13 +119,15 @@ void cStreamdevServer::Action(void)
 | 
			
		||||
		for (cServerComponent *c = m_Servers.First(); c; c = m_Servers.Next(c)){
 | 
			
		||||
			if (sel && select.CanRead(c->Socket())) {
 | 
			
		||||
				cServerConnection *client = c->Accept();
 | 
			
		||||
				if (!client)
 | 
			
		||||
					continue;
 | 
			
		||||
				m_Clients.Add(client);
 | 
			
		||||
 | 
			
		||||
				if (m_Clients.Count() > StreamdevServerSetup.MaxClients) {
 | 
			
		||||
					esyslog("streamdev: too many clients, rejecting %s:%d",
 | 
			
		||||
					        client->RemoteIp().c_str(), client->RemotePort());
 | 
			
		||||
					client->Reject();
 | 
			
		||||
				} else if (!StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
 | 
			
		||||
				} else if (!client->CanAuthenticate() && !StreamdevHosts.Acceptable(client->RemoteIpAddr())) {
 | 
			
		||||
					esyslog("streamdev: client %s:%d not allowed to connect",
 | 
			
		||||
					        client->RemoteIp().c_str(), client->RemotePort());
 | 
			
		||||
					client->Reject();
 | 
			
		||||
@@ -164,6 +170,4 @@ void cStreamdevServer::Action(void)
 | 
			
		||||
		c->Destruct();
 | 
			
		||||
		m_Servers.Del(c);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_Active = false;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: server.h,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
 | 
			
		||||
 *  $Id: server.h,v 1.6 2008/10/22 11:59:32 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SERVER_H
 | 
			
		||||
@@ -10,12 +10,14 @@
 | 
			
		||||
#include "server/component.h"
 | 
			
		||||
#include "server/connection.h"
 | 
			
		||||
 | 
			
		||||
#define STREAMDEVHOSTSPATH (*AddDirectory(cPlugin::ConfigDirectory(), "streamdevhosts.conf"))
 | 
			
		||||
#define DEFAULT_EXTERNREMUX (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "externremux.sh"))
 | 
			
		||||
#define STREAMDEVHOSTSPATH (*AddDirectory(cPlugin::ConfigDirectory(PLUGIN_NAME_I18N), "streamdevhosts.conf"))
 | 
			
		||||
 | 
			
		||||
extern char *opt_auth;
 | 
			
		||||
extern char *opt_remux;
 | 
			
		||||
 | 
			
		||||
class cStreamdevServer: public cThread {
 | 
			
		||||
private:
 | 
			
		||||
	bool m_Active;
 | 
			
		||||
 | 
			
		||||
	static cStreamdevServer         *m_Instance;
 | 
			
		||||
	static cList<cServerComponent>   m_Servers;
 | 
			
		||||
	static cList<cServerConnection>  m_Clients;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,11 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: setup.c,v 1.2 2005/05/09 20:22:29 lordjaxom Exp $
 | 
			
		||||
 *  $Id: setup.c,v 1.6 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include <vdr/menuitems.h>
 | 
			
		||||
 | 
			
		||||
#include "server/setup.h"
 | 
			
		||||
#include "server/server.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
cStreamdevServerSetup StreamdevServerSetup;
 | 
			
		||||
 | 
			
		||||
@@ -16,11 +15,15 @@ cStreamdevServerSetup::cStreamdevServerSetup(void) {
 | 
			
		||||
	VTPServerPort   = 2004;
 | 
			
		||||
	StartHTTPServer = true;
 | 
			
		||||
	HTTPServerPort  = 3000;
 | 
			
		||||
	HTTPStreamType  = stPES;
 | 
			
		||||
	SuspendMode     = smOffer;
 | 
			
		||||
	HTTPStreamType  = stTS;
 | 
			
		||||
	StartIGMPServer = false;
 | 
			
		||||
	IGMPClientPort  = 1234;
 | 
			
		||||
	IGMPStreamType  = stTS;
 | 
			
		||||
	SuspendMode     = smAlways;
 | 
			
		||||
	AllowSuspend    = false;
 | 
			
		||||
	strcpy(VTPBindIP, "0.0.0.0");
 | 
			
		||||
	strcpy(HTTPBindIP, "0.0.0.0");
 | 
			
		||||
	strcpy(IGMPBindIP, "0.0.0.0");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cStreamdevServerSetup::SetupParse(const char *Name, const char *Value) {
 | 
			
		||||
@@ -32,6 +35,10 @@ bool cStreamdevServerSetup::SetupParse(const char *Name, const char *Value) {
 | 
			
		||||
	else if (strcmp(Name, "HTTPServerPort") == 0)  HTTPServerPort  = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "HTTPStreamType") == 0)  HTTPStreamType  = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "HTTPBindIP") == 0)      strcpy(HTTPBindIP, Value);
 | 
			
		||||
	else if (strcmp(Name, "StartIGMPServer") == 0) StartIGMPServer = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "IGMPClientPort") == 0)  IGMPClientPort  = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "IGMPStreamType") == 0)  IGMPStreamType  = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "IGMPBindIP") == 0)      strcpy(IGMPBindIP, Value);
 | 
			
		||||
	else if (strcmp(Name, "SuspendMode") == 0)     SuspendMode     = atoi(Value);
 | 
			
		||||
	else if (strcmp(Name, "AllowSuspend") == 0)    AllowSuspend    = atoi(Value);
 | 
			
		||||
	else return false;
 | 
			
		||||
@@ -56,7 +63,11 @@ cStreamdevServerMenuSetupPage::cStreamdevServerMenuSetupPage(void) {
 | 
			
		||||
	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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -70,7 +81,10 @@ void cStreamdevServerMenuSetupPage::Store(void) {
 | 
			
		||||
			|| strcmp(m_NewSetup.VTPBindIP, StreamdevServerSetup.VTPBindIP) != 0
 | 
			
		||||
			|| m_NewSetup.StartHTTPServer != StreamdevServerSetup.StartHTTPServer
 | 
			
		||||
			|| m_NewSetup.HTTPServerPort != StreamdevServerSetup.HTTPServerPort
 | 
			
		||||
			|| strcmp(m_NewSetup.HTTPBindIP, StreamdevServerSetup.HTTPBindIP) != 0) {
 | 
			
		||||
			|| strcmp(m_NewSetup.HTTPBindIP, StreamdevServerSetup.HTTPBindIP) != 0
 | 
			
		||||
			|| m_NewSetup.StartIGMPServer != StreamdevServerSetup.StartIGMPServer
 | 
			
		||||
			|| m_NewSetup.IGMPClientPort != StreamdevServerSetup.IGMPClientPort
 | 
			
		||||
			|| strcmp(m_NewSetup.IGMPBindIP, StreamdevServerSetup.IGMPBindIP) != 0) {
 | 
			
		||||
		restart = true;
 | 
			
		||||
		cStreamdevServer::Destruct();
 | 
			
		||||
	}
 | 
			
		||||
@@ -83,6 +97,10 @@ void cStreamdevServerMenuSetupPage::Store(void) {
 | 
			
		||||
	SetupStore("HTTPServerPort",  m_NewSetup.HTTPServerPort);
 | 
			
		||||
	SetupStore("HTTPStreamType",  m_NewSetup.HTTPStreamType);
 | 
			
		||||
	SetupStore("HTTPBindIP",      m_NewSetup.HTTPBindIP);
 | 
			
		||||
	SetupStore("StartIGMPServer", m_NewSetup.StartIGMPServer);
 | 
			
		||||
	SetupStore("IGMPClientPort",  m_NewSetup.IGMPClientPort);
 | 
			
		||||
	SetupStore("IGMPStreamType",  m_NewSetup.IGMPStreamType);
 | 
			
		||||
	SetupStore("IGMPBindIP",      m_NewSetup.IGMPBindIP);
 | 
			
		||||
	SetupStore("SuspendMode",     m_NewSetup.SuspendMode);
 | 
			
		||||
	SetupStore("AllowSuspend",    m_NewSetup.AllowSuspend);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: setup.h,v 1.1.1.1 2004/12/30 22:44:21 lordjaxom Exp $
 | 
			
		||||
 *  $Id: setup.h,v 1.2 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SETUPSERVER_H
 | 
			
		||||
@@ -20,6 +20,10 @@ struct cStreamdevServerSetup {
 | 
			
		||||
	int HTTPServerPort;
 | 
			
		||||
	int HTTPStreamType;
 | 
			
		||||
	char HTTPBindIP[20];
 | 
			
		||||
	int StartIGMPServer;
 | 
			
		||||
	int IGMPClientPort;
 | 
			
		||||
	int IGMPStreamType;
 | 
			
		||||
	char IGMPBindIP[20];
 | 
			
		||||
	int SuspendMode;
 | 
			
		||||
	int AllowSuspend;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: streamer.c,v 1.16 2007/09/21 11:45:53 schmirl Exp $
 | 
			
		||||
 *  $Id: streamer.c,v 1.18 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include <vdr/ringbuffer.h>
 | 
			
		||||
@@ -20,16 +20,15 @@ cStreamdevWriter::cStreamdevWriter(cTBSocket *Socket,
 | 
			
		||||
                                   cStreamdevStreamer *Streamer):
 | 
			
		||||
		cThread("streamdev-writer"),
 | 
			
		||||
		m_Streamer(Streamer),
 | 
			
		||||
		m_Socket(Socket),
 | 
			
		||||
		m_Active(false)
 | 
			
		||||
		m_Socket(Socket)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cStreamdevWriter::~cStreamdevWriter()
 | 
			
		||||
{
 | 
			
		||||
	Dprintf("destructing writer\n");
 | 
			
		||||
	m_Active = false;
 | 
			
		||||
	Cancel(3);
 | 
			
		||||
	if (Running())
 | 
			
		||||
		Cancel(3);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cStreamdevWriter::Action(void)
 | 
			
		||||
@@ -39,11 +38,10 @@ void cStreamdevWriter::Action(void)
 | 
			
		||||
	int max = 0;
 | 
			
		||||
	uchar *block = NULL;
 | 
			
		||||
	int count, offset = 0;
 | 
			
		||||
	m_Active = true;
 | 
			
		||||
 | 
			
		||||
	sel.Clear();
 | 
			
		||||
	sel.Add(*m_Socket, true);
 | 
			
		||||
	while (m_Active) {
 | 
			
		||||
	while (Running()) {
 | 
			
		||||
		if (block == NULL) {
 | 
			
		||||
			block = m_Streamer->Get(count);
 | 
			
		||||
			offset = 0;
 | 
			
		||||
@@ -57,23 +55,39 @@ void cStreamdevWriter::Action(void)
 | 
			
		||||
 | 
			
		||||
			if (sel.CanWrite(*m_Socket)) {
 | 
			
		||||
				int written;
 | 
			
		||||
				if ((written = m_Socket->Write(block + offset, count)) == -1) {
 | 
			
		||||
					esyslog("ERROR: streamdev-server: couldn't send data: %m");
 | 
			
		||||
				int pkgsize = count;
 | 
			
		||||
				// SOCK_DGRAM indicates multicast
 | 
			
		||||
				if (m_Socket->Type() == SOCK_DGRAM) {
 | 
			
		||||
					// don't fragment multicast packets
 | 
			
		||||
					// max. payload on standard local ethernet is 1416 to 1456 bytes
 | 
			
		||||
					// and some STBs expect complete TS packets
 | 
			
		||||
					// so let's always limit to 7 * TS_SIZE = 1316
 | 
			
		||||
					if (pkgsize > 7 * TS_SIZE)
 | 
			
		||||
						pkgsize = 7 * TS_SIZE;
 | 
			
		||||
					else
 | 
			
		||||
						pkgsize -= pkgsize % TS_SIZE;
 | 
			
		||||
				}
 | 
			
		||||
				if ((written = m_Socket->Write(block + offset, pkgsize)) == -1) {
 | 
			
		||||
					esyslog("ERROR: streamdev-server: couldn't send %d bytes: %m", pkgsize);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				// statistics
 | 
			
		||||
				if (count > max)
 | 
			
		||||
					max = count;
 | 
			
		||||
 | 
			
		||||
				offset += written;
 | 
			
		||||
				count -= written;
 | 
			
		||||
				if (count == 0) {
 | 
			
		||||
 | 
			
		||||
				// less than one TS packet left:
 | 
			
		||||
				// delete what we've written so far and get next chunk
 | 
			
		||||
				if (count < TS_SIZE) {
 | 
			
		||||
					m_Streamer->Del(offset);
 | 
			
		||||
					block = NULL;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	m_Active = false;
 | 
			
		||||
	Dprintf("Max. Transmit Blocksize was: %d\n", max);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -81,7 +95,6 @@ void cStreamdevWriter::Action(void)
 | 
			
		||||
 | 
			
		||||
cStreamdevStreamer::cStreamdevStreamer(const char *Name):
 | 
			
		||||
		cThread(Name),
 | 
			
		||||
		m_Active(false),
 | 
			
		||||
		m_Running(false),
 | 
			
		||||
		m_Writer(NULL),
 | 
			
		||||
		m_RingBuffer(new cRingBufferLinear(STREAMERBUFSIZE, TS_SIZE * 2,
 | 
			
		||||
@@ -109,7 +122,7 @@ void cStreamdevStreamer::Start(cTBSocket *Socket)
 | 
			
		||||
 | 
			
		||||
void cStreamdevStreamer::Activate(bool On) 
 | 
			
		||||
{
 | 
			
		||||
	if (On && !m_Active) {
 | 
			
		||||
	if (On && !Active()) {
 | 
			
		||||
		Dprintf("activate streamer\n");
 | 
			
		||||
		m_Writer->Start();
 | 
			
		||||
		cThread::Start();
 | 
			
		||||
@@ -118,9 +131,8 @@ void cStreamdevStreamer::Activate(bool On)
 | 
			
		||||
 | 
			
		||||
void cStreamdevStreamer::Stop(void) 
 | 
			
		||||
{
 | 
			
		||||
	if (m_Active) {
 | 
			
		||||
	if (Running()) {
 | 
			
		||||
		Dprintf("stopping streamer\n");
 | 
			
		||||
		m_Active = false;
 | 
			
		||||
		Cancel(3);
 | 
			
		||||
	}
 | 
			
		||||
	if (m_Running) {
 | 
			
		||||
@@ -132,8 +144,7 @@ void cStreamdevStreamer::Stop(void)
 | 
			
		||||
 | 
			
		||||
void cStreamdevStreamer::Action(void) 
 | 
			
		||||
{
 | 
			
		||||
	m_Active = true;
 | 
			
		||||
	while (m_Active) {
 | 
			
		||||
	while (Running()) {
 | 
			
		||||
		int got;
 | 
			
		||||
		uchar *block = m_RingBuffer->Get(got);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: streamer.h,v 1.8 2007/04/02 10:32:34 schmirl Exp $
 | 
			
		||||
 *  $Id: streamer.h,v 1.10 2009/02/13 10:39:22 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_STREAMER_H
 | 
			
		||||
@@ -12,6 +12,10 @@
 | 
			
		||||
class cTBSocket;
 | 
			
		||||
class cStreamdevStreamer;
 | 
			
		||||
 | 
			
		||||
#ifndef TS_SIZE
 | 
			
		||||
#define TS_SIZE 188
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define STREAMERBUFSIZE MEGABYTE(4)
 | 
			
		||||
#define WRITERBUFSIZE KILOBYTE(256)
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +25,6 @@ class cStreamdevWriter: public cThread {
 | 
			
		||||
private:
 | 
			
		||||
	cStreamdevStreamer *m_Streamer;
 | 
			
		||||
	cTBSocket          *m_Socket;
 | 
			
		||||
	bool                m_Active;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
	virtual void Action(void);
 | 
			
		||||
@@ -29,15 +32,12 @@ protected:
 | 
			
		||||
public:
 | 
			
		||||
	cStreamdevWriter(cTBSocket *Socket, cStreamdevStreamer *Streamer);
 | 
			
		||||
	virtual ~cStreamdevWriter();
 | 
			
		||||
 | 
			
		||||
	bool IsActive(void) const { return m_Active; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// --- cStreamdevStreamer -----------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class cStreamdevStreamer: public cThread {
 | 
			
		||||
private:
 | 
			
		||||
	bool               m_Active;
 | 
			
		||||
	bool               m_Running;
 | 
			
		||||
	cStreamdevWriter  *m_Writer;
 | 
			
		||||
	cRingBufferLinear *m_RingBuffer;
 | 
			
		||||
@@ -54,7 +54,7 @@ public:
 | 
			
		||||
 | 
			
		||||
	virtual void Start(cTBSocket *Socket);
 | 
			
		||||
	virtual void Stop(void);
 | 
			
		||||
	bool Abort(void) const;
 | 
			
		||||
	bool Abort(void);
 | 
			
		||||
 | 
			
		||||
	void Activate(bool On);
 | 
			
		||||
	int Receive(uchar *Data, int Length) { return m_RingBuffer->Put(Data, Length); }
 | 
			
		||||
@@ -68,9 +68,9 @@ public:
 | 
			
		||||
	virtual void Attach(void) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline bool cStreamdevStreamer::Abort(void) const
 | 
			
		||||
inline bool cStreamdevStreamer::Abort(void)
 | 
			
		||||
{
 | 
			
		||||
	return m_Active && !m_Writer->IsActive();
 | 
			
		||||
	return Active() && !m_Writer->Active();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // VDR_STREAMDEV_STREAMER_H
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: suspend.c,v 1.1.1.1 2004/12/30 22:44:21 lordjaxom Exp $
 | 
			
		||||
 *  $Id: suspend.c,v 1.3 2008/10/22 11:59:32 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#include "server/suspend.h"
 | 
			
		||||
@@ -7,13 +7,12 @@
 | 
			
		||||
#include "common.h"
 | 
			
		||||
 | 
			
		||||
cSuspendLive::cSuspendLive(void)
 | 
			
		||||
#if VDRVERSNUM >= 10300
 | 
			
		||||
		: cThread("Streamdev: server suspend")
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cSuspendLive::~cSuspendLive() {
 | 
			
		||||
	Stop();
 | 
			
		||||
	Detach();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -26,26 +25,15 @@ void cSuspendLive::Activate(bool On) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cSuspendLive::Stop(void) {
 | 
			
		||||
	if (m_Active) {
 | 
			
		||||
		m_Active = false;
 | 
			
		||||
	if (Running())
 | 
			
		||||
		Cancel(3);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cSuspendLive::Action(void) {
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	isyslog("Streamdev: Suspend Live thread started (pid = %d)", getpid());
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	m_Active = true;
 | 
			
		||||
	while (m_Active) {
 | 
			
		||||
	while (Running()) {
 | 
			
		||||
		DeviceStillPicture(suspend_mpg, sizeof(suspend_mpg));
 | 
			
		||||
		usleep(100000);
 | 
			
		||||
		cCondWait::SleepMs(100);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#if VDRVERSNUM < 10300
 | 
			
		||||
	isyslog("Streamdev: Suspend Live thread stopped");
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cSuspendCtl::m_Active = false;
 | 
			
		||||
@@ -61,7 +49,7 @@ cSuspendCtl::~cSuspendCtl() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
eOSState cSuspendCtl::ProcessKey(eKeys Key) {
 | 
			
		||||
	if (!m_Suspend->IsActive() || Key == kBack) {
 | 
			
		||||
	if (!m_Suspend->Active() || Key == kBack) {
 | 
			
		||||
		DELETENULL(m_Suspend);
 | 
			
		||||
		return osEnd;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  $Id: suspend.h,v 1.1.1.1 2004/12/30 22:44:26 lordjaxom Exp $
 | 
			
		||||
 *  $Id: suspend.h,v 1.2 2008/10/22 11:59:32 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 
 | 
			
		||||
#ifndef VDR_STREAMDEV_SUSPEND_H
 | 
			
		||||
@@ -7,10 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <vdr/player.h>
 | 
			
		||||
 | 
			
		||||
class cSuspendLive: public cPlayer, cThread {
 | 
			
		||||
private:
 | 
			
		||||
	bool m_Active;
 | 
			
		||||
 | 
			
		||||
class cSuspendLive: public cPlayer, public cThread {
 | 
			
		||||
protected:
 | 
			
		||||
	virtual void Activate(bool On);
 | 
			
		||||
	virtual void Action(void);
 | 
			
		||||
@@ -20,8 +17,6 @@ protected:
 | 
			
		||||
public:
 | 
			
		||||
	cSuspendLive(void);
 | 
			
		||||
	virtual ~cSuspendLive();
 | 
			
		||||
 | 
			
		||||
	bool IsActive(void) const { return m_Active; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class cSuspendCtl: public cControl {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,16 +3,18 @@
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: streamdev-client.c,v 1.2 2005/04/24 16:19:44 lordjaxom Exp $
 | 
			
		||||
 * $Id: streamdev-client.c,v 1.6 2008/04/08 14:18:15 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "streamdev-client.h"
 | 
			
		||||
#include "client/device.h"
 | 
			
		||||
#include "client/setup.h"
 | 
			
		||||
//#include "client/menu.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
const char *cPluginStreamdevClient::DESCRIPTION = "VTP Streaming Client";
 | 
			
		||||
#if !defined(APIVERSNUM) || APIVERSNUM < 10509
 | 
			
		||||
#error "VDR-1.5.9 API version or greater is required!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const char *cPluginStreamdevClient::DESCRIPTION = trNOOP("VTP Streaming Client");
 | 
			
		||||
 | 
			
		||||
cPluginStreamdevClient::cPluginStreamdevClient(void) {
 | 
			
		||||
}
 | 
			
		||||
@@ -25,12 +27,9 @@ const char *cPluginStreamdevClient::Description(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPluginStreamdevClient::Start(void) {
 | 
			
		||||
	i18n_name = Name();
 | 
			
		||||
	RegisterI18n(Phrases);
 | 
			
		||||
 | 
			
		||||
	I18nRegister(PLUGIN_NAME_I18N);
 | 
			
		||||
	cStreamdevDevice::Init();
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cPluginStreamdevClient::Housekeeping(void) {
 | 
			
		||||
@@ -39,13 +38,15 @@ void cPluginStreamdevClient::Housekeeping(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cPluginStreamdevClient::MainMenuEntry(void) {
 | 
			
		||||
	return NULL;
 | 
			
		||||
	//return StreamdevClientSetup.StartClient ? tr("Streaming Control") : NULL;
 | 
			
		||||
	return StreamdevClientSetup.StartClient && !StreamdevClientSetup.HideMenuEntry ? tr("Suspend Server") : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cOsdObject *cPluginStreamdevClient::MainMenuAction(void) {
 | 
			
		||||
	if (ClientSocket.SuspendServer())
 | 
			
		||||
		Skins.Message(mtInfo, tr("Server is suspended"));
 | 
			
		||||
	else
 | 
			
		||||
		Skins.Message(mtError, tr("Couldn't suspend Server!"));
 | 
			
		||||
	return NULL;
 | 
			
		||||
	//return StreamdevClientSetup.StartClient ? new cStreamdevMenu : NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cMenuSetupPage *cPluginStreamdevClient::SetupMenu(void) {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,18 +3,22 @@
 | 
			
		||||
 *
 | 
			
		||||
 * See the README file for copyright information and how to reach the author.
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: streamdev-server.c,v 1.6 2007/04/16 11:01:02 schmirl Exp $
 | 
			
		||||
 * $Id: streamdev-server.c,v 1.11 2008/10/14 11:05:47 schmirl Exp $
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <getopt.h>
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
#include "remux/extern.h"
 | 
			
		||||
#include "streamdev-server.h"
 | 
			
		||||
#include "server/setup.h"
 | 
			
		||||
#include "server/server.h"
 | 
			
		||||
#include "server/suspend.h"
 | 
			
		||||
#include "remux/extern.h"
 | 
			
		||||
#include "i18n.h"
 | 
			
		||||
 | 
			
		||||
const char *cPluginStreamdevServer::DESCRIPTION = "VDR Streaming Server";
 | 
			
		||||
#if !defined(APIVERSNUM) || APIVERSNUM < 10509
 | 
			
		||||
#error "VDR-1.5.9 API version or greater is required!"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
const char *cPluginStreamdevServer::DESCRIPTION = trNOOP("VDR Streaming Server");
 | 
			
		||||
 | 
			
		||||
cPluginStreamdevServer::cPluginStreamdevServer(void) 
 | 
			
		||||
{
 | 
			
		||||
@@ -22,6 +26,8 @@ cPluginStreamdevServer::cPluginStreamdevServer(void)
 | 
			
		||||
 | 
			
		||||
cPluginStreamdevServer::~cPluginStreamdevServer() 
 | 
			
		||||
{
 | 
			
		||||
	free(opt_auth);
 | 
			
		||||
	free(opt_remux);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *cPluginStreamdevServer::Description(void) 
 | 
			
		||||
@@ -32,22 +38,39 @@ const char *cPluginStreamdevServer::Description(void)
 | 
			
		||||
const char *cPluginStreamdevServer::CommandLineHelp(void)
 | 
			
		||||
{
 | 
			
		||||
	// return a string that describes all known command line options.
 | 
			
		||||
	return "  -r <CMD>, --remux=<CMD>  Define an external command for remuxing.\n";
 | 
			
		||||
	return
 | 
			
		||||
		"  -a <LOGIN:PASSWORD>, --auth=<LOGIN:PASSWORD>  Credentials for HTTP authentication.\n"
 | 
			
		||||
		"  -r <CMD>, --remux=<CMD>  Define an external command for remuxing.\n"
 | 
			
		||||
		;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cPluginStreamdevServer::ProcessArgs(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
	// implement command line argument processing here if applicable.
 | 
			
		||||
	static const struct option long_options[] = {
 | 
			
		||||
		{ "auth", required_argument, NULL, 'a' },
 | 
			
		||||
		{ "remux", required_argument, NULL, 'r' },
 | 
			
		||||
		{ NULL, 0, NULL, 0 }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	int c;
 | 
			
		||||
	while((c = getopt_long(argc, argv, "r:", long_options, NULL)) != -1) {
 | 
			
		||||
	while((c = getopt_long(argc, argv, "a:r:", long_options, NULL)) != -1) {
 | 
			
		||||
		switch (c) {
 | 
			
		||||
			case 'a':
 | 
			
		||||
				{
 | 
			
		||||
					if (opt_auth)
 | 
			
		||||
						free(opt_auth);
 | 
			
		||||
					int l = strlen(optarg);
 | 
			
		||||
					cBase64Encoder Base64((uchar*) optarg, l,  l * 4 / 3 + 3);
 | 
			
		||||
					const char *s = Base64.NextLine();
 | 
			
		||||
					if (s)
 | 
			
		||||
						opt_auth = strdup(s);
 | 
			
		||||
				}
 | 
			
		||||
				break;
 | 
			
		||||
			case 'r':
 | 
			
		||||
				g_ExternRemux = optarg;
 | 
			
		||||
				if (opt_remux)
 | 
			
		||||
				    free(opt_remux);
 | 
			
		||||
				opt_remux = strdup(optarg);
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				return false;
 | 
			
		||||
@@ -58,9 +81,7 @@ bool cPluginStreamdevServer::ProcessArgs(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
bool cPluginStreamdevServer::Start(void) 
 | 
			
		||||
{
 | 
			
		||||
	i18n_name = Name();
 | 
			
		||||
	RegisterI18n(Phrases);
 | 
			
		||||
 | 
			
		||||
	I18nRegister(PLUGIN_NAME_I18N);
 | 
			
		||||
	if (!StreamdevHosts.Load(STREAMDEVHOSTSPATH, true, true)) {
 | 
			
		||||
		esyslog("streamdev-server: error while loading %s", STREAMDEVHOSTSPATH);
 | 
			
		||||
		fprintf(stderr, "streamdev-server: error while loading %s\n", STREAMDEVHOSTSPATH);
 | 
			
		||||
@@ -73,6 +94,8 @@ bool cPluginStreamdevServer::Start(void)
 | 
			
		||||
		}
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	if (!opt_remux)
 | 
			
		||||
		opt_remux = strdup(DEFAULT_EXTERNREMUX);
 | 
			
		||||
 | 
			
		||||
	cStreamdevServer::Initialize();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										48
									
								
								streamdev/externremux.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										48
									
								
								streamdev/externremux.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
#!/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
 | 
			
		||||
@@ -10,4 +10,5 @@
 | 
			
		||||
127.0.0.1             # always accept localhost
 | 
			
		||||
#192.168.100.0/24     # any host on the local net
 | 
			
		||||
#204.152.189.113      # a specific host
 | 
			
		||||
#239.255.0.0/16       # uncomment for IGMP multicast streaming
 | 
			
		||||
#0.0.0.0/0            # any host on any net (USE THIS WITH CARE!)
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
#include "tools/socket.h"
 | 
			
		||||
 | 
			
		||||
#include <vdr/tools.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
@@ -15,10 +16,11 @@
 | 
			
		||||
// actual DSCP value used
 | 
			
		||||
#define STREAMDEV_DSCP DSCP_AF41
 | 
			
		||||
 | 
			
		||||
cTBSocket::cTBSocket(int Type) {
 | 
			
		||||
cTBSocket::cTBSocket(int Type, int Protocol) {
 | 
			
		||||
	memset(&m_LocalAddr, 0, sizeof(m_LocalAddr));
 | 
			
		||||
	memset(&m_RemoteAddr, 0, sizeof(m_RemoteAddr));
 | 
			
		||||
	m_Type = Type;
 | 
			
		||||
	m_Protocol = Protocol;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cTBSocket::~cTBSocket() {
 | 
			
		||||
@@ -31,7 +33,7 @@ bool cTBSocket::Connect(const std::string &Host, unsigned int Port) {
 | 
			
		||||
 | 
			
		||||
	if (IsOpen()) Close();
 | 
			
		||||
		
 | 
			
		||||
	if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1)
 | 
			
		||||
	if ((socket = ::socket(PF_INET, m_Type, m_Protocol)) == -1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	m_LocalAddr.sin_family = AF_INET;
 | 
			
		||||
@@ -52,10 +54,12 @@ bool cTBSocket::Connect(const std::string &Host, unsigned int Port) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	len = sizeof(struct sockaddr_in);
 | 
			
		||||
	if (::getpeername(socket, (struct sockaddr*)&m_RemoteAddr, &len) == -1) {
 | 
			
		||||
		::close(socket);
 | 
			
		||||
		return false;
 | 
			
		||||
	if (m_Type == SOCK_STREAM) {
 | 
			
		||||
		len = sizeof(struct sockaddr_in);
 | 
			
		||||
		if (::getpeername(socket, (struct sockaddr*)&m_RemoteAddr, &len) == -1) {
 | 
			
		||||
			::close(socket);
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	len = sizeof(struct sockaddr_in);
 | 
			
		||||
@@ -64,7 +68,11 @@ bool cTBSocket::Connect(const std::string &Host, unsigned int Port) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cTBSource::Open(socket);
 | 
			
		||||
	if (!cTBSource::Open(socket)) {
 | 
			
		||||
		::close(socket);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool cTBSocket::Listen(const std::string &Ip, unsigned int Port, int BackLog) {
 | 
			
		||||
@@ -74,7 +82,7 @@ bool cTBSocket::Listen(const std::string &Ip, unsigned int Port, int BackLog) {
 | 
			
		||||
 | 
			
		||||
	if (IsOpen()) Close();
 | 
			
		||||
	
 | 
			
		||||
	if ((socket = ::socket(PF_INET, m_Type, IPPROTO_IP)) == -1)
 | 
			
		||||
	if ((socket = ::socket(PF_INET, m_Type, m_Protocol)) == -1)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	val = 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,10 @@ private:
 | 
			
		||||
	struct sockaddr_in m_RemoteAddr;
 | 
			
		||||
 | 
			
		||||
	int m_Type;
 | 
			
		||||
	int m_Protocol;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
	cTBSocket(int Type = SOCK_STREAM);
 | 
			
		||||
	cTBSocket(int Type = SOCK_STREAM, int Protocol = 0);
 | 
			
		||||
	virtual ~cTBSocket();
 | 
			
		||||
	
 | 
			
		||||
	/* See cTBSource::SysRead() 
 | 
			
		||||
@@ -97,15 +98,22 @@ public:
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline ssize_t cTBSocket::SysRead(void *Buffer, size_t Length) const {
 | 
			
		||||
	if (m_Type == SOCK_DGRAM) {
 | 
			
		||||
	if (m_Type == SOCK_STREAM)
 | 
			
		||||
		return ::recv(*this, Buffer, Length, 0);
 | 
			
		||||
	else {
 | 
			
		||||
		socklen_t len = sizeof(m_RemoteAddr);
 | 
			
		||||
		return ::recvfrom(*this, Buffer, Length, 0, (sockaddr*)&m_RemoteAddr, &len);
 | 
			
		||||
	} else
 | 
			
		||||
		return ::recv(*this, Buffer, Length, 0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline ssize_t cTBSocket::SysWrite(const void *Buffer, size_t Length) const {
 | 
			
		||||
	return ::send(*this, Buffer, Length, 0);
 | 
			
		||||
	if (m_Type == SOCK_STREAM)
 | 
			
		||||
		return ::send(*this, Buffer, Length, 0);
 | 
			
		||||
	else {
 | 
			
		||||
		socklen_t len = sizeof(m_RemoteAddr);
 | 
			
		||||
		return ::sendto(*this, Buffer, Length, 0, (sockaddr*)&m_RemoteAddr, len);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // TOOLBOX_SOCKET_H
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user