mirror of
https://github.com/vdr-projects/vdr.git
synced 2025-03-01 10:50:46 +00:00
Version 1.3.0
- Changed thread handling to make it work with NPTL ("Native Posix Thread Library"). Thanks to Jon Burgess, Andreas Schultz, Werner Fink and Stefan Huelswitt. - The cThread class now accepts a 'Description' parameter, which is used to log the beginning and end of the thread, together with its process and thread id. For descriptions that need additional parameters you can use the function cThread::SetDescription(), which accepts 'printf()' like arguments. Existing plugins that use threads should be changed to use this functionality instead of explicit 'dsyslog()' calls inside their Action() function in order to support logging the thread ids. - Added "Slovak Link" and "Czech Link" to 'ca.conf' (thanks to Emil Petersky). However, 'ca.conf' is now pretty much obsolete due to the automatic CA handling. - Mutexes are now created with PTHREAD_MUTEX_ERRORCHECK_NP, which makes the 'lockingTid' stuff obsolete (thanks to Stefan Huelswitt). - Changed font handling to allow language specific character sets. - Adopted the small font character set from the "Elchi" patch (originally provided by Alessio Sangalli). - Greek language texts now use iso8859-7 character set (thanks to Dimitrios Dimitrakos). - Rearranged section data handling, so that the actual data handling can be done separately, even from within plugins. - The EPG data structures have been moved from eit.[hc] to epg.[hc] and have been adapted to the general VDR coding style. Plugins that use these data structures may need to change some function names (which should be obvious). The name 'subtitle' has been changed to 'shortText' to avoid clashes with actual subtitles that are part of a movie. The name 'extendedDescription' has been shortened to 'description'. - Replaced 'libdtv' with 'libsi' (thanks to Marcel Wiesweg), which is thread safe and can be used by multiple section filters simultaneously. - Added 'cRwLock' to 'thread.[hc]'. Note that all plugin Makefiles need to define _GNU_SOURCE for this to work (see the example plugin Makefiles and 'newplugin'). - Fixed a problem with crc32 in SI handling on 64bit systems (thanks to Pedro Miguel Sequeira de Justo Teixeira for reporting this one). - Fixed an alignment problem in CAM access on 64bit systems (thanks to Pedro Miguel Sequeira de Justo Teixeira for reporting this one). - Added 'StreamType' setting to CAM communication, which is important for Aston/SECA CAMs (thanks to Antonino Sergi). - Now the CA descriptors are sent to the CAM in the 'program' or 'ES level' sections, depending on where they are found in the PMT (thanks to Hans-Peter Raschke for reporting this one). This should make SkyCrypt CAMs work. - Now using the 'version number' of EPG events to avoid unnecessary work. - Channel data is now automatically derived from the DVB data stream (inspired by the 'autopid' patch from Andreas Schultz). - The current channel is now automatically re-tuned if the PIDs or other settings change. If a recording is going on on a channel that has a change in its settings, the recording will be stopped and immediately restarted to use the new channel settings. - EPG events now use the complete channel ID with NID, TID and SID. - Channel names in 'channels.conf' can now have a short form, as provided by some tv stations (see man vdr(5)). Currently channels that provide short names in addition to long ones are listed in the OSD as "short,long name", as in "RTL,RTL Television". The short names will be used explicitly later. - The Ca parameter in 'channels.conf' has been extended and now contains all the CA system ids for the given channel. When switching to a channel VDR now tests for a device that provides one of these CA system ids. The devices automatically get their supported ids from the CI handler. - The values in 'ca.conf' are currently without any real meaning. Whether or not a channel with conditional access can be received is now determined automatically by evaluating its CA descriptors and comparing them to the CA system ids provided by the installed CAM. Only the special values 1-16 are used to assign a channel to a particular device. - Increased the maximum number of possible OSD colors to 256. - Limited the line length in the EPG bugfix report, which appears to fix a buffer overflow that caused a crash when cleaning up the EPG data (at 05:00 in the morning).
This commit is contained in:
parent
c432905dd6
commit
93a94b18b5
25
CONTRIBUTORS
25
CONTRIBUTORS
@ -83,6 +83,8 @@ Dave Chapman <dave@dchapman.com>
|
||||
Hans-Peter Raschke <Hans-Peter.Raschke@Wintermann-DatenService.de>
|
||||
for his support in adapting VDR to DVB-C
|
||||
for adding the 'statdvb2vdr' tool (see Tools/statdvb2vdr)
|
||||
for reporting that the CA descriptors need to be sent to the CAM in the 'program'
|
||||
or 'ES level' sections to make SkyCrypt CAMs work
|
||||
|
||||
Peter Hofmann <software@pxh.de>
|
||||
for his support in adapting VDR to DVB-C
|
||||
@ -177,6 +179,9 @@ Stefan Huelswitt <huels@iname.com>
|
||||
for fixing an uninitialized variable in cDisplayChannel
|
||||
for fixing a possible access of invalid file handles in cSIProcessor::Action()
|
||||
for fixing extracting the ES data in cDvbDevice::StillPicture()
|
||||
for changing thread handling to make it work with NPTL ("Native Posix Thread Library")
|
||||
for creating mutexes with PTHREAD_MUTEX_ERRORCHECK_NP, which made the 'lockingTid'
|
||||
stuff obsolete
|
||||
|
||||
Ulrich Röder <roeder@efr-net.de>
|
||||
for pointing out that there are channels that have a symbol rate higher than
|
||||
@ -210,6 +215,9 @@ Andreas Schultz <aschultz@warp10.net>
|
||||
for changing C++ style comments in libdtv into C style to avoid warnings in gcc 3.x
|
||||
for implementing the TerrestrialDeliverySystemDescriptor in libdtv
|
||||
for fixing setting the locking pid after a timed wait
|
||||
for changing thread handling to make it work with NPTL ("Native Posix Thread Library")
|
||||
for his 'autopid' patch which was helpful when implementing automatic
|
||||
channel data gathering
|
||||
|
||||
Aaron Holtzman
|
||||
for writing 'ac3dec'
|
||||
@ -243,6 +251,7 @@ Werner Fink <werner@suse.de>
|
||||
for replacing the 'for' loops in StripAudioPackets() with memset() calls
|
||||
for modifying handling of audio packets in cDvbPlayer for better sync with external
|
||||
AC3 replay
|
||||
for changing thread handling to make it work with NPTL ("Native Posix Thread Library")
|
||||
|
||||
Rolf Hakenes <hakenes@hippomi.de>
|
||||
for providing 'libdtv' and adapting the EIT mechanisms to it
|
||||
@ -403,6 +412,7 @@ Simon Dean <linux-dvb@sickhack.com>
|
||||
Dimitrios Dimitrakos <mail@dimitrios.de>
|
||||
for translating OSD texts to the Greek language
|
||||
for fixing handling the LOG_LOCALn parameters in the -l option
|
||||
for providing the iso8859-7 fonts
|
||||
|
||||
Marcus Kuba <marcus@kuba4u.de>
|
||||
for reporting a bug in the unit of the "SVDRP timeout" setup parameter
|
||||
@ -636,6 +646,7 @@ Marcel Wiesweg <marcel.wiesweg@gmx.de>
|
||||
for reporting a problem with cReceivers that want to receive from PIDs that are
|
||||
currently not transmitting
|
||||
for fixing volume display in case a plugin has its own OSD open
|
||||
for providing 'libsi' and adapting the EIT mechanisms to it
|
||||
|
||||
Torsten Herz <torsten.herz@web.de>
|
||||
for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu
|
||||
@ -762,6 +773,7 @@ Karim Afifi <karim.afifi@free.fr>
|
||||
|
||||
Jon Burgess <mplayer@jburgess.uklinux.net>
|
||||
for pointing out a problem with NPTL ("Native Posix Thread Library")
|
||||
for changing thread handling to make it work with NPTL ("Native Posix Thread Library")
|
||||
|
||||
Thomas Schmidt <thomas.schmidt@in.stud.tu-ilmenau.de>
|
||||
for reporting a crash when cancelling a newly created timer
|
||||
@ -862,3 +874,16 @@ Luke Jenkins <a@xmission.com>
|
||||
Dirk Mueller <dmuell@gmx.net>
|
||||
for fixing getting the list of recordings in case VDR is started from a directory
|
||||
where it doesn't have access to
|
||||
|
||||
Emil Petersky <petersky@isr.uni-stuttgart.de>
|
||||
for adding "Slovak Link" and "Czech Link" to 'ca.conf'
|
||||
|
||||
Alessio Sangalli <alesan@manoweb.com>
|
||||
for providing the iso8859-1 small font
|
||||
|
||||
Pedro Miguel Sequeira de Justo Teixeira <pedro.miguel.teixeira@bigfoot.com>
|
||||
for reporting a problem with crc32 in SI handling on 64bit systems
|
||||
for reporting an alignment problem in CAM access on 64bit systems
|
||||
|
||||
Antonino Sergi <voyaser@tiscalinet.it>
|
||||
for adding 'StreamType' setting to CAM communication
|
||||
|
70
HISTORY
70
HISTORY
@ -2393,7 +2393,7 @@ Video Disk Recorder Revision History
|
||||
not loaded (suggested by Alexander Wetzel).
|
||||
- Fixed checking for VIDEO_STREAM_S in cRemux::SetBrokenLink() (thanks to Oliver
|
||||
Endriss).
|
||||
- Added 'repeat' function keys '7' and '9' ("jump to mark") in replay mode
|
||||
- Added 'repeat' function to keys '7' and '9' ("jump to mark") in replay mode
|
||||
(suggested by Oliver Endriss).
|
||||
- Made cOsdMenu::Display() virtual, which allows plugins to do some additional
|
||||
processing after calling the base class function (suggested by Jan Rieger).
|
||||
@ -2469,3 +2469,71 @@ Video Disk Recorder Revision History
|
||||
2003-11-14: Version 1.2.6
|
||||
|
||||
- Final release of version 1.2.6.
|
||||
|
||||
2004-01-04: Version 1.3.0
|
||||
|
||||
- Changed thread handling to make it work with NPTL ("Native Posix Thread Library").
|
||||
Thanks to Jon Burgess, Andreas Schultz, Werner Fink and Stefan Huelswitt.
|
||||
- The cThread class now accepts a 'Description' parameter, which is used to log
|
||||
the beginning and end of the thread, together with its process and thread id.
|
||||
For descriptions that need additional parameters you can use the function
|
||||
cThread::SetDescription(), which accepts 'printf()' like arguments.
|
||||
Existing plugins that use threads should be changed to use this functionality
|
||||
instead of explicit 'dsyslog()' calls inside their Action() function in order
|
||||
to support logging the thread ids.
|
||||
- Added "Slovak Link" and "Czech Link" to 'ca.conf' (thanks to Emil Petersky).
|
||||
However, 'ca.conf' is now pretty much obsolete due to the automatic CA handling.
|
||||
- Mutexes are now created with PTHREAD_MUTEX_ERRORCHECK_NP, which makes the
|
||||
'lockingTid' stuff obsolete (thanks to Stefan Huelswitt).
|
||||
- Changed font handling to allow language specific character sets.
|
||||
- Adopted the small font character set from the "Elchi" patch (originally
|
||||
provided by Alessio Sangalli).
|
||||
- Greek language texts now use iso8859-7 character set (thanks to Dimitrios
|
||||
Dimitrakos).
|
||||
- Rearranged section data handling, so that the actual data handling can be done
|
||||
separately, even from within plugins.
|
||||
- The EPG data structures have been moved from eit.[hc] to epg.[hc] and have been
|
||||
adapted to the general VDR coding style. Plugins that use these data structures
|
||||
may need to change some function names (which should be obvious).
|
||||
The name 'subtitle' has been changed to 'shortText' to avoid clashes with actual
|
||||
subtitles that are part of a movie. The name 'extendedDescription' has been
|
||||
shortened to 'description'.
|
||||
- Replaced 'libdtv' with 'libsi' (thanks to Marcel Wiesweg), which is thread
|
||||
safe and can be used by multiple section filters simultaneously.
|
||||
- Added 'cRwLock' to 'thread.[hc]'. Note that all plugin Makefiles need to
|
||||
define _GNU_SOURCE for this to work (see the example plugin Makefiles and
|
||||
'newplugin').
|
||||
- Fixed a problem with crc32 in SI handling on 64bit systems (thanks to Pedro
|
||||
Miguel Sequeira de Justo Teixeira for reporting this one).
|
||||
- Fixed an alignment problem in CAM access on 64bit systems (thanks to Pedro
|
||||
Miguel Sequeira de Justo Teixeira for reporting this one).
|
||||
- Added 'StreamType' setting to CAM communication, which is important for
|
||||
Aston/SECA CAMs (thanks to Antonino Sergi).
|
||||
- Now the CA descriptors are sent to the CAM in the 'program' or 'ES level'
|
||||
sections, depending on where they are found in the PMT (thanks to Hans-Peter
|
||||
Raschke for reporting this one). This should make SkyCrypt CAMs work.
|
||||
- Now using the 'version number' of EPG events to avoid unnecessary work.
|
||||
- Channel data is now automatically derived from the DVB data stream (inspired
|
||||
by the 'autopid' patch from Andreas Schultz).
|
||||
- The current channel is now automatically re-tuned if the PIDs or other settings
|
||||
change. If a recording is going on on a channel that has a change in its
|
||||
settings, the recording will be stopped and immediately restarted to use the
|
||||
new channel settings.
|
||||
- EPG events now use the complete channel ID with NID, TID and SID.
|
||||
- Channel names in 'channels.conf' can now have a short form, as provided
|
||||
by some tv stations (see man vdr(5)). Currently channels that provide short
|
||||
names in addition to long ones are listed in the OSD as "short,long name",
|
||||
as in "RTL,RTL Television". The short names will be used explicitly later.
|
||||
- The Ca parameter in 'channels.conf' has been extended and now contains all the
|
||||
CA system ids for the given channel. When switching to a channel VDR now tests
|
||||
for a device that provides one of these CA system ids. The devices automatically
|
||||
get their supported ids from the CI handler.
|
||||
- The values in 'ca.conf' are currently without any real meaning. Whether or not
|
||||
a channel with conditional access can be received is now determined automatically
|
||||
by evaluating its CA descriptors and comparing them to the CA system ids
|
||||
provided by the installed CAM. Only the special values 1-16 are used to assign
|
||||
a channel to a particular device.
|
||||
- Increased the maximum number of possible OSD colors to 256.
|
||||
- Limited the line length in the EPG bugfix report, which appears to fix a buffer
|
||||
overflow that caused a crash when cleaning up the EPG data (at 05:00 in the
|
||||
morning).
|
||||
|
12
INSTALL
12
INSTALL
@ -1,19 +1,9 @@
|
||||
Installation of the Video Disk Recorder
|
||||
---------------------------------------
|
||||
|
||||
Version 1.2
|
||||
Version 1.3
|
||||
-----------
|
||||
|
||||
IMPORTANT NOTE:
|
||||
---------------
|
||||
|
||||
VDR currently doesn't work with NPTL ("Native Posix Thread Library").
|
||||
Either don't use NPTL, or set the environment variable
|
||||
|
||||
LD_ASSUME_KERNEL=2.4.1
|
||||
|
||||
before running VDR.
|
||||
|
||||
Compiling and running the program:
|
||||
----------------------------------
|
||||
|
||||
|
50
Makefile
50
Makefile
@ -4,7 +4,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: Makefile 1.58 2003/08/09 11:09:45 kls Exp $
|
||||
# $Id: Makefile 1.62 2003/12/25 13:38:56 kls Exp $
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
@ -15,7 +15,7 @@ CXX ?= g++
|
||||
CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual
|
||||
|
||||
DVBDIR = ../DVB
|
||||
DTVDIR = ./libdtv
|
||||
LSIDIR = ./libsi
|
||||
MANDIR = /usr/local/man
|
||||
BINDIR = /usr/local/bin
|
||||
|
||||
@ -31,16 +31,20 @@ DOXYFILE = Doxyfile
|
||||
|
||||
INCLUDES = -I$(DVBDIR)/include
|
||||
|
||||
DTVLIB = $(DTVDIR)/libdtv.a
|
||||
SILIB = $(LSIDIR)/libsi.a
|
||||
|
||||
OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o dvbosd.o\
|
||||
dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o interface.o keys.o\
|
||||
lirc.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o rcu.o\
|
||||
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sources.o\
|
||||
dvbplayer.o dvbspu.o eit.o eitscan.o epg.o filter.o font.o i18n.o interface.o keys.o\
|
||||
lirc.o menu.o menuitems.o osdbase.o osd.o pat.o player.o plugin.o rcu.o\
|
||||
receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sdt.o sections.o sources.o\
|
||||
spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o
|
||||
|
||||
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||
FIXFONT = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
|
||||
FIXFONT_ISO8859_1 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
|
||||
OSDFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
|
||||
SMLFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859-1
|
||||
FIXFONT_ISO8859_7 = --user-medium-r-normal--26-171-110-110-m-140-iso8859-7
|
||||
OSDFONT_ISO8859_7 = --user-medium-r-normal--23-179-85-85-m-120-iso8859-7
|
||||
SMLFONT_ISO8859_7 = --user-medium-r-normal--19-160-72-72-m-110-iso8859-7
|
||||
|
||||
ifndef NO_KBD
|
||||
DEFINES += -DREMOTE_KBD
|
||||
@ -64,7 +68,9 @@ DEFINES += -DVFAT
|
||||
endif
|
||||
|
||||
all: vdr
|
||||
font: genfontfile fontfix.c fontosd.c
|
||||
font: genfontfile\
|
||||
fontfix.c fontosd.c fontsml.c\
|
||||
fontfix_iso8859_7.c fontosd_iso8859_7.c fontsml_iso8859_7.c
|
||||
@echo "font files created."
|
||||
|
||||
# Implicit rules:
|
||||
@ -83,25 +89,33 @@ $(DEPFILE): Makefile
|
||||
|
||||
# The main program:
|
||||
|
||||
vdr: $(OBJS) $(DTVLIB)
|
||||
$(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(DTVLIB) -o vdr
|
||||
vdr: $(OBJS) $(SILIB)
|
||||
$(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(SILIB) -o vdr
|
||||
|
||||
# The font files:
|
||||
|
||||
fontfix.c:
|
||||
./genfontfile "cFont::tPixelData FontFix" "$(FIXFONT)" > $@
|
||||
./genfontfile "cFont::tPixelData FontFix_iso8859_1" "$(FIXFONT_ISO8859_1)" > $@
|
||||
fontosd.c:
|
||||
./genfontfile "cFont::tPixelData FontOsd" "$(OSDFONT)" > $@
|
||||
./genfontfile "cFont::tPixelData FontOsd_iso8859_1" "$(OSDFONT_ISO8859_1)" > $@
|
||||
fontsml.c:
|
||||
./genfontfile "cFont::tPixelData FontSml_iso8859_1" "$(SMLFONT_ISO8859_1)" > $@
|
||||
fontfix_iso8859_1.c:
|
||||
./genfontfile "cFont::tPixelData FontFix_iso8859_7" "$(FIXFONT_ISO8859_7)" > $@
|
||||
fontosd_iso8859_1.c:
|
||||
./genfontfile "cFont::tPixelData FontOsd_iso8859_7" "$(OSDFONT_ISO8859_7)" > $@
|
||||
fontsml_iso8859_1.c:
|
||||
./genfontfile "cFont::tPixelData FontSml_iso8859_7" "$(SMLFONT_ISO8859_7)" > $@
|
||||
|
||||
# The font file generator:
|
||||
|
||||
genfontfile: genfontfile.c
|
||||
$(CC) $(CFLAGS) -o $@ -L/usr/X11R6/lib $< -lX11
|
||||
|
||||
# The libdtv library:
|
||||
# The libsi library:
|
||||
|
||||
$(DTVLIB) $(DTVDIR)/libdtv.h:
|
||||
$(MAKE) -C $(DTVDIR) all
|
||||
$(SILIB):
|
||||
$(MAKE) -C $(LSIDIR) all
|
||||
|
||||
# The 'include' directory (for plugins):
|
||||
|
||||
@ -140,11 +154,11 @@ srcdoc:
|
||||
# Housekeeping:
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(DTVDIR) clean
|
||||
$(MAKE) -C $(LSIDIR) clean
|
||||
-rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~
|
||||
-rm -rf include
|
||||
-rm -rf srcdoc
|
||||
fontclean:
|
||||
-rm -f fontfix.c fontosd.c
|
||||
-rm -f fontfix*.c fontosd*.c fontsml*.c
|
||||
CLEAN: clean fontclean
|
||||
|
||||
|
223
PLUGINS.html
223
PLUGINS.html
@ -6,7 +6,7 @@
|
||||
|
||||
<center><h1>The VDR Plugin System</h1></center>
|
||||
|
||||
<center><b>Version 1.2.6</b></center>
|
||||
<center><b>Version 1.3</b></center>
|
||||
<p>
|
||||
<center>
|
||||
Copyright © 2003 Klaus Schmidinger<br>
|
||||
@ -14,9 +14,12 @@ Copyright © 2003 Klaus Schmidinger<br>
|
||||
<a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a>
|
||||
</center>
|
||||
<p>
|
||||
<!--X1.1.32--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<!--X1.2.6--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
Important modifications introduced in version 1.2.6 are marked like this.
|
||||
<!--X1.1.32--></td></tr></table>
|
||||
<!--X1.2.6--></td></tr></table>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
Important modifications introduced in version 1.3.0 are marked like this.
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
<p>
|
||||
VDR provides an easy to use plugin interface that allows additional functionality
|
||||
to be added to the program by implementing a dynamically loadable library file.
|
||||
@ -64,6 +67,9 @@ structures and allows it to hook itself into specific areas to perform special a
|
||||
<li><a href="#Status monitor">Status monitor</a>
|
||||
<li><a href="#Players">Players</a>
|
||||
<li><a href="#Receivers">Receivers</a>
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<li><a href="#Filters">Filters</a>
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
<li><a href="#The On Screen Display">The On Screen Display</a>
|
||||
<li><a href="#Devices">Devices</a>
|
||||
<li><a href="#Dolby Digital">Dolby Digital</a>
|
||||
@ -112,7 +118,7 @@ No other characters should be used here.
|
||||
<p>
|
||||
A plugin can access its name through the (non virtual) member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const char *Name(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -127,7 +133,7 @@ By default plugins are located in a directory named <tt>PLUGINS</tt> below the
|
||||
VDR source directory. Inside this directory the following subdirectory structure
|
||||
is used:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
VDR/PLUGINS/src
|
||||
VDR/PLUGINS/src/hello
|
||||
VDR/PLUGINS/lib
|
||||
@ -172,7 +178,7 @@ To use the <tt>plugins</tt> and <tt>plugins-clean</tt> targets from the VDR <tt>
|
||||
you need to unpack such an archive into the <tt>VDR/PLUGINS/src</tt> directory and
|
||||
create a symbolic link with the basic plugin name, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
ln -s hello-0.0.1 hello
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -226,7 +232,7 @@ If your plugin shall not be accessible through VDR's main menu, simply remove
|
||||
<p>
|
||||
At the end of the plugin's source file you will find a line that looks like this:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
VDRPLUGINCREATOR(cPluginHello);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -239,7 +245,7 @@ source directory and adjust the <tt>Makefile</tt> accordingly.
|
||||
Header files usually contain preprocessor statements that prevent the same
|
||||
file (or rather its contents, to be precise) from being included more than once, like
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#ifndef __I18N_H
|
||||
#define __I18N_H
|
||||
|
||||
@ -274,7 +280,7 @@ and two replacing the dot).
|
||||
|
||||
The constructor and destructor of a plugin are defined as
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cPlugin(void);
|
||||
virtual ~cPlugin();
|
||||
</pre></td></tr></table><p>
|
||||
@ -304,7 +310,7 @@ Every plugin must have a version number of its own, which does not necessarily
|
||||
have to be in any way related to the VDR version number.
|
||||
VDR requests a plugin's version number through a call to the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual const char *Version(void) = 0;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -315,7 +321,7 @@ information, like for instance "0.0.1pre2" or the like. The string should only
|
||||
be as long as really necessary, and shall not contain the plugin's name itself.
|
||||
Here's an example:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
static const char *VERSION = "0.0.1";
|
||||
|
||||
const char *cPluginHello::Version(void)
|
||||
@ -347,13 +353,13 @@ would be acceptable.
|
||||
|
||||
In order to tell the user what exactly a plugin does, it must implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual const char *Description(void) = 0;
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which returns a short, one line description of the plugin's purpose:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
static const char *DESCRIPTION = "A friendly greeting";
|
||||
|
||||
virtual const char *Description(void)
|
||||
@ -373,7 +379,7 @@ A VDR plugin can have command line arguments just like any normal program.
|
||||
If a plugin wants to react on command line arguments, it needs to implement
|
||||
the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool ProcessArgs(int argc, char *argv[]);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -390,7 +396,7 @@ these arguments. As with any normal C program, the strings pointed to by <tt>arg
|
||||
will survive the entire lifetime of the plugin, so it is safe to store pointers to
|
||||
these values inside the plugin. Here's an example:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
bool cPluginHello::ProcessArgs(int argc, char *argv[])
|
||||
{
|
||||
// Implement command line argument processing here if applicable.
|
||||
@ -425,7 +431,7 @@ to exit.
|
||||
|
||||
If a plugin accepts command line options, it should implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual const char *CommandLineHelp(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -433,7 +439,7 @@ which will be called if the user enters the <b><tt>-h</tt></b> option when start
|
||||
The returned string should contain the command line help for this plugin, formatted
|
||||
in the same way as done by VDR itself:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const char *cPluginHello::CommandLineHelp(void)
|
||||
{
|
||||
// Return a string that describes all known command line options.
|
||||
@ -456,7 +462,7 @@ If a plugin implements a function that runs in the background (presumably in a
|
||||
thread of its own), or wants to make use of <a href="#Internationalization">internationalization</a>,
|
||||
it needs to implement one of the functions
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool Initialize(void);
|
||||
virtual bool Start(void);
|
||||
</pre></td></tr></table><p>
|
||||
@ -493,7 +499,7 @@ texts, it doesn't need to implement either of these functions.
|
||||
If the plugin implements a feature that the user shall be able to access
|
||||
from VDR's main menu, it needs to implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual const char *MainMenuEntry(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -501,7 +507,7 @@ The default implementation returns a <tt>NULL</tt> pointer, which means that
|
||||
this plugin will not have an item in the main menu. Here's an example of a
|
||||
plugin that will have a main menu item:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
static const char *MAINMENUENTRY = "Hello";
|
||||
|
||||
const char *cPluginHello::MainMenuEntry(void)
|
||||
@ -520,7 +526,7 @@ in the call to VDR.
|
||||
|
||||
If the user selects the main menu entry of a plugin, VDR calls the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual cOsdObject *MainMenuAction(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -554,7 +560,7 @@ the plugin should launch a separate thread to do this.
|
||||
From time to time a plugin may want to do some regular tasks, like cleaning
|
||||
up some files or other things. In order to do this it can implement the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual void Housekeeping(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -579,7 +585,7 @@ the plugin should launch a separate thread to do this.
|
||||
If a plugin requires its own setup parameters, it needs to implement the following
|
||||
functions to handle these parameters:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *Name, const char *Value);
|
||||
</pre></td></tr></table><p>
|
||||
@ -594,7 +600,7 @@ an error. If <i>false</i> is returned, an error message will be written to
|
||||
the log file (and program execution will continue).
|
||||
A possible implementation of <tt>SetupParse()</tt> could look like this:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
bool cPluginHello::SetupParse(const char *Name, const char *Value)
|
||||
{
|
||||
// Parse your own setup parameters and store their values.
|
||||
@ -620,7 +626,7 @@ plugins need not worry about this.
|
||||
<p>
|
||||
To store its values in the global setup, a plugin has to call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
void SetupStore(const char *Name, <i>type</i> Value);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -653,7 +659,7 @@ To implement a <i>Setup</i> menu, a plugin needs to derive a class from
|
||||
<tt>cMenuSetupPage</tt> and implement its constructor and the pure virtual
|
||||
<tt>Store()</tt> member function:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
int GreetingTime = 3;
|
||||
int UseAlternateGreeting = false;
|
||||
|
||||
@ -714,7 +720,7 @@ configuration file. While the plugin is free to store such files anywhere it
|
||||
sees fit, it might be a good idea to put them in a common place, preferably
|
||||
where other configuration data already exists. VDR provides the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const char *ConfigDirectory(const char *PluginName = NULL);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -737,7 +743,7 @@ these in a subdirectory of its own, named after the plugin. To easily get such a
|
||||
the <tt>ConfigDirectory()</tt> function can be given an additional string that will
|
||||
be appended to the returned directory name, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const char *MyConfigDir = ConfigDirectory(Name());
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -754,7 +760,7 @@ The <tt>ConfigDirectory()</tt> function is a static member function of the <tt>c
|
||||
class. This allows it to be called even from outside any member function of the derived
|
||||
plugin class, by writing
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const char *MyConfigDir = cPlugin::ConfigDirectory();
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -765,7 +771,7 @@ const char *MyConfigDir = cPlugin::ConfigDirectory();
|
||||
If a plugin displays texts to the user, it should implement internationalized
|
||||
versions of these texts and call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
void RegisterI18n(const tI18nPhrase * const Phrases);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -774,7 +780,7 @@ to register them with VDR's internationalization mechanism.
|
||||
The call to this function must be done in the <a href="#Getting started"><tt>Initialize()</tt></a>
|
||||
or <a href="#Getting started"><tt>Start()</tt></a> function of the plugin:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const tI18nPhrase Phrases[] = {
|
||||
{ "Hello world!",
|
||||
"Hallo Welt!",
|
||||
@ -815,7 +821,7 @@ you may want to contact the maintainers of these languages (listed in the file
|
||||
The actual runtime selection of the texts corresponding to the selected language
|
||||
is done by wrapping each internationalized text with the <tt>tr()</tt> macro:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
const char *s = tr("Hello world!");
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -833,20 +839,20 @@ core VDR code.
|
||||
|
||||
Plugins are loaded into VDR using the command line option <b><tt>-P</tt></b>, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
vdr -Phello
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If the plugin accepts command line options, they are given as part of the argument
|
||||
to the <b><tt>-P</tt></b> option, which then has to be enclosed in quotes:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
vdr -P"hello -a abc -b"
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
Any number of plugins can be loaded this way, each with its own <b><tt>-P</tt></b> option:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
vdr -P"hello -a abc -b" -Pdvd -Pmp3
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -854,7 +860,7 @@ If you are not starting VDR from the VDR source directory (and thus your plugins
|
||||
cannot be found at their default location) you need to tell VDR the location of
|
||||
the plugins through the <b><tt>-L</tt></b> option:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
vdr -L/usr/lib/vdr -Phello
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -879,14 +885,14 @@ provides the target <tt>dist</tt>, which does this for you.
|
||||
<p>
|
||||
Simply change into your source directory and execute <tt>make dist</tt>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cd VDR/PLUGINS/src/hello
|
||||
make dist
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
After this you should find a file named like
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
vdr-hello-0.0.1.tgz
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -902,7 +908,7 @@ plugin's name, and <tt>0.0.1</tt> will be your plugin's current version number.
|
||||
If a plugin wants to get informed on various events in VDR, it can derive a class from
|
||||
<tt>cStatus</tt>, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/status.h>
|
||||
|
||||
class cMyStatusMonitor : public cStatus {
|
||||
@ -922,7 +928,7 @@ void cMyStatusMonitor::ChannelSwitch(const cDevice *Device, int ChannelNumber)
|
||||
An object of this class will be informed whenever the channel is switched on one of
|
||||
the DVB devices. It could be used in a plugin like this:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/plugin.h>
|
||||
|
||||
class cPluginStatus : public cPlugin {
|
||||
@ -975,7 +981,7 @@ the functions you actually want to use.
|
||||
Implementing a player is a two step process.
|
||||
First you need the actual player class, which is derived from the abstract <tt>cPlayer</tt>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/player.h>
|
||||
|
||||
class cMyPlayer : public cPlayer {
|
||||
@ -991,7 +997,7 @@ What exactly you do in this class is entirely up to you. If you want to run a se
|
||||
thread which, e.g., reads data from a file, you can additionally derive your class from
|
||||
<tt>cThread</tt> and implement the necessary functionality:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/player.h>
|
||||
|
||||
class cMyPlayer : public cPlayer, cThread {
|
||||
@ -1009,7 +1015,7 @@ its own player for the VDR recordings.
|
||||
<p>
|
||||
To play the video data, the player needs to call its member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
int PlayVideo(const uchar *Data, int Length);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1020,7 +1026,7 @@ desired video data stream, and it must be delivered fast enough so that the
|
||||
DVB device doesn't run out of data.
|
||||
To avoid busy loops the player should call its member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
bool DevicePoll(cPoller &Poller, int TimeoutMs = 0);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1029,7 +1035,7 @@ to determine whether the device is ready for further data.
|
||||
If the player can provide more than a single audio track, it can implement the
|
||||
following functions to make them available:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual int NumAudioTracks(void) const;
|
||||
virtual const char **GetAudioTracks(int *CurrentTrack = NULL);
|
||||
virtual void SetAudioTrack(int Index);
|
||||
@ -1039,7 +1045,7 @@ virtual void SetAudioTrack(int Index);
|
||||
If there is an additional audio track that has to be replayed with external hardware,
|
||||
the player shall call its member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
void PlayAudio(const uchar *Data, int Length);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1048,7 +1054,7 @@ where <tt>Data</tt> points to a complete audio PES packet of <tt>Length</tt> byt
|
||||
The second part needed here is a control object that receives user input from the main
|
||||
program loop and reacts on this by telling the player what to do:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/player.h>
|
||||
|
||||
class cMyControl : public cControl {
|
||||
@ -1066,7 +1072,7 @@ public:
|
||||
hand over a pointer to it to the <tt>cControl</tt> base class, so that it
|
||||
can be later attached to the primary DVB device:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cMyControl::cMyControl(void)
|
||||
:cControl(player = new cMyPlayer)
|
||||
{
|
||||
@ -1093,7 +1099,7 @@ Finally, to get things going, a plugin that implements a player (and the surroun
|
||||
infrastructure like displaying a list of playable stuff etc) simply has to call the
|
||||
static function <tt>cControl::Launch()</tt> with the player control object, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cControl::Launch(new cMyControl);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1104,7 +1110,7 @@ use the primary DVB device, or the user decides to start a different replay).
|
||||
<p>
|
||||
The <tt>cPlayer</tt> class has a member function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
void DeviceStillPicture(const uchar *Data, int Length);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1149,7 +1155,7 @@ ahead - it's your show...
|
||||
In order to receive any kind of data from a <tt>cDevice</tt>, a plugin must set up an
|
||||
object derived from the <tt>cReceiver</tt> class:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/receiver.h>
|
||||
|
||||
class cMyReceiver : public cReceiver, cThread {
|
||||
@ -1187,7 +1193,7 @@ a <tt>cReceiver</tt> to be detached from its <tt>cDevice</tt> at any time.
|
||||
Once a <tt>cReceiver</tt> has been created, it needs to be <i>attached</i> to
|
||||
a <tt>cDevice</tt>:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cMyReceiver *Receiver = new cMyReceiver(123);
|
||||
|
||||
cDevice::ActualDevice()->AttachReceiver(Receiver);
|
||||
@ -1201,6 +1207,52 @@ Mode</i>).
|
||||
If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</i>
|
||||
and will automatically detach itself from the <tt>cDevice</tt>.
|
||||
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<a name="Filters"><hr><h2>Filters</h2>
|
||||
|
||||
<center><i><b>A Fistful of Datas</b></i></center><p>
|
||||
|
||||
If you want to receive section data you have to implement a derived <tt>cFilter</tt>
|
||||
class which at least implements the <tt>Process()</tt> function and a constructor
|
||||
that sets the (initial) filter parameters:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/filter.h>
|
||||
|
||||
class cMyFilter : public cFilter {
|
||||
protected:
|
||||
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
|
||||
public:
|
||||
cMyFilter(void);
|
||||
...
|
||||
};
|
||||
|
||||
cMyFilter::cMyFilter(void)
|
||||
{
|
||||
Set(0x14, 0x70); // TDT
|
||||
}
|
||||
|
||||
void cMyFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
|
||||
{
|
||||
// do something with the data here
|
||||
}
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
An instance of such a filter needs to be attached to the device from
|
||||
which it shall receive data, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cMyFilter Filter;
|
||||
|
||||
cDevice::ActualDevice()->AttachFilter(Filter);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
If the <tt>cFilter</tt> isn't needed any more, it may simply be <i>deleted</i>
|
||||
and will automatically detach itself from the <tt>cDevice</tt>.
|
||||
<p>
|
||||
See VDR/eit.c or VDR/pat.c to learn how to process filter data.
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
|
||||
<a name="The On Screen Display"><hr><h2>The On Screen Display</h2>
|
||||
|
||||
<center><i><b>Express yourself</b></i></center><p>
|
||||
@ -1213,7 +1265,7 @@ windows and color depths.
|
||||
If a plugin needs to have total control over the OSD, it can call the
|
||||
static function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/osd.h>
|
||||
|
||||
cOsdBase *MyOsd = cOsd::OpenRaw(x, y);
|
||||
@ -1223,7 +1275,7 @@ where <tt>x</tt> and <tt>y</tt> are the coordinates of the upper left corner
|
||||
of the OSD area on the screen. Such a "raw" OSD doesn't display anything
|
||||
yet, so you need to at least call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
MyOsd->Create(...);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1247,7 +1299,7 @@ stream and displays it, for instance, on an existing graphics adapter.
|
||||
<p>
|
||||
To implement an additional device, a plugin must derive a class from cDevice:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/device.h>
|
||||
|
||||
class cMyDevice : public cDevice {
|
||||
@ -1266,7 +1318,7 @@ the <tt>cDvbDevice</tt>, which is used to access the DVB PCI cards.
|
||||
If the new device can receive, it most likely needs to provide a way of
|
||||
selecting which channel it shall tune to:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool ProvidesSource(int Source) const;
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
|
||||
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
||||
@ -1281,7 +1333,7 @@ repectively.
|
||||
If the device can provide more than a single audio track, it can implement the
|
||||
following functions to make them available:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual int NumAudioTracksDevice(void) const;
|
||||
virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const;
|
||||
virtual void SetAudioTrackDevice(int Index);
|
||||
@ -1292,7 +1344,7 @@ virtual void SetAudioTrackDevice(int Index);
|
||||
<p>
|
||||
A device that can be used for recording must implement the functions
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
|
||||
virtual bool OpenDvr(void);
|
||||
virtual void CloseDvr(void);
|
||||
@ -1308,7 +1360,7 @@ must deliver exactly one such packet (if one is currently available).
|
||||
If this device allows receiving several different data streams, it can
|
||||
implement
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool CanBeReUsed(int Frequency, int Vpid);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1318,13 +1370,13 @@ to indicate this to VDR.
|
||||
<p>
|
||||
The functions to implement replaying capabilites are
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool HasDecoder(void) const;
|
||||
virtual bool CanReplay(void) const;
|
||||
virtual bool SetPlayMode(ePlayMode PlayMode);
|
||||
<!--X1.1.32--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<!--X1.2.6--><table width=100%><tr><td bgcolor=#AA0000> </td><td width=100%>
|
||||
virtual int64_t GetSTC(void);
|
||||
<!--X1.1.32--></td></tr></table>
|
||||
<!--X1.2.6--></td></tr></table>
|
||||
virtual void TrickSpeed(int Speed);
|
||||
virtual void Clear(void);
|
||||
virtual void Play(void);
|
||||
@ -1338,12 +1390,39 @@ virtual int PlayVideo(const uchar *Data, int Length);
|
||||
In addition, the following functions may be implemented to provide further
|
||||
functionality:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int Si
|
||||
virtual void SetVideoFormat(bool VideoFormat16_9);
|
||||
virtual void SetVolumeDevice(int Volume);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000> </td><td width=100%>
|
||||
<p>
|
||||
<b>Section Filtering</b>
|
||||
<p>
|
||||
If your device provides section filtering capabilities it can implement
|
||||
the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
which must open a file handle that delivers section data for the given
|
||||
filter parameters.
|
||||
<p>
|
||||
In order to actually start section handling, the
|
||||
device also needs to call the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
StartSectionHandler();
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
from its constructor.
|
||||
<p>
|
||||
See <a href="#Filters">Filters</a> on how to set up actual filters that can
|
||||
handle section data.
|
||||
<!--X1.3.0--></td></tr></table>
|
||||
|
||||
<p>
|
||||
<b>On Screen Display</b>
|
||||
<p>
|
||||
@ -1351,7 +1430,7 @@ If your device provides On Screen Display (OSD) capabilities (which every device
|
||||
that is supposed to be used as a primary device should do), it can implement
|
||||
the function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual cOsdBase *NewOsd(int x, int y);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1391,7 +1470,7 @@ audio replay facility.
|
||||
To implement a new audio output facility, simply derive a class from <tt>cAudio</tt>,
|
||||
as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/audio.h>
|
||||
#include <vdr/thread.h>
|
||||
|
||||
@ -1435,7 +1514,7 @@ remote control, so a plugin can use the <tt>cRemote</tt> class to do that.
|
||||
The simplest method for a plugin to issue commands to VDR is to call the
|
||||
static function <tt>cRemote::Put(eKeys Key)</tt>, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cRemote::Put(kUp);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1447,7 +1526,7 @@ In cases where the incoming codes are not known, or not all available keys may
|
||||
be supported by the actual remote control in use, you may want to derive your
|
||||
own remote control class from <tt>cRemote</tt>, as in
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
#include <vdr/remote.h>
|
||||
#include <vdr/thread.h>
|
||||
|
||||
@ -1472,7 +1551,7 @@ when the program ends).
|
||||
<p>
|
||||
The constructor of your remote control class should look like this
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
cMyRemote::cMyRemote(const char *Name)
|
||||
:cRemote(Name)
|
||||
{
|
||||
@ -1492,7 +1571,7 @@ member variables, you should do so before calling <tt>Start()</tt>.
|
||||
If your remote control for some reason can't work (maybe because it was unable to
|
||||
open some file handle it requires) it can implement the virtual function
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
virtual bool Ready(void);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1513,7 +1592,7 @@ If your remote control class needs some setup data that shall be
|
||||
readily available next time VDR starts (without having to go through the initialization
|
||||
procedure again) it can use the <tt>cRemote</tt> member functions
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
void PutSetup(const char *Setup);
|
||||
const char *GetSetup(void);
|
||||
</pre></td></tr></table><p>
|
||||
@ -1527,7 +1606,7 @@ The <tt>cRemote</tt> class assumes that any incoming remote control code can be
|
||||
expressed as a character string. So whatever data your remote control provides
|
||||
needs to be given to the base class by calling
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
Put(const char *Code, bool Repeat = false, bool Release = false);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
@ -1538,7 +1617,7 @@ Since a common case for remote control data is to be given as a numerical
|
||||
value, there is another <tt>Put()</tt> function available for your convenience,
|
||||
which takes a 64 bit unsigned integer value instead of a character string:
|
||||
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre><br>
|
||||
<p><table><tr><td bgcolor=#F0F0F0><pre>
|
||||
Put(uint64 Code, bool Repeat = false, bool Release = false);
|
||||
</pre></td></tr></table><p>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for a Video Disk Recorder plugin
|
||||
#
|
||||
# $Id: Makefile 1.8 2002/12/13 14:54:14 kls Exp $
|
||||
# $Id: Makefile 1.9 2003/12/21 15:47:22 kls Exp $
|
||||
|
||||
# The official name of this plugin.
|
||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||
@ -42,7 +42,7 @@ PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
|
||||
|
||||
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for a Video Disk Recorder plugin
|
||||
#
|
||||
# $Id: Makefile 1.2 2002/12/13 14:54:29 kls Exp $
|
||||
# $Id: Makefile 1.3 2003/12/21 15:47:26 kls Exp $
|
||||
|
||||
# The official name of this plugin.
|
||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||
@ -42,7 +42,7 @@ PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
|
||||
|
||||
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
|
@ -12,3 +12,7 @@ VDR Plugin 'sky' Revision History
|
||||
2003-05-09: Version 0.1.1
|
||||
|
||||
- Changed Start() to Initialize().
|
||||
|
||||
2004-01-04: Version 0.2.0
|
||||
|
||||
- Implemented automatic PID switching and channel detection
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for a Video Disk Recorder plugin
|
||||
#
|
||||
# $Id: Makefile 1.2 2002/12/13 14:54:24 kls Exp $
|
||||
# $Id: Makefile 1.3 2003/12/21 15:47:31 kls Exp $
|
||||
|
||||
# The official name of this plugin.
|
||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||
@ -42,7 +42,7 @@ PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
|
||||
|
||||
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: sky.c 1.3 2003/05/09 15:27:16 kls Exp $
|
||||
* $Id: sky.c 1.4 2004/01/04 15:29:15 kls Exp $
|
||||
*/
|
||||
|
||||
#include <sys/socket.h>
|
||||
@ -14,7 +14,7 @@
|
||||
#include <vdr/plugin.h>
|
||||
#include <vdr/sources.h>
|
||||
|
||||
static const char *VERSION = "0.1.1";
|
||||
static const char *VERSION = "0.2.0";
|
||||
static const char *DESCRIPTION = "Sky Digibox interface";
|
||||
|
||||
// --- cDigiboxDevice --------------------------------------------------------
|
||||
@ -37,6 +37,7 @@ public:
|
||||
cDigiboxDevice(void);
|
||||
virtual ~cDigiboxDevice();
|
||||
virtual bool ProvidesSource(int Source) const;
|
||||
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsSetChannel = NULL) const;
|
||||
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
||||
};
|
||||
@ -137,13 +138,18 @@ bool cDigiboxDevice::ProvidesSource(int Source) const
|
||||
return source == Source;
|
||||
}
|
||||
|
||||
bool cDigiboxDevice::ProvidesTransponder(const cChannel *Channel) const
|
||||
{
|
||||
return false; // can't provide any actual transponder
|
||||
}
|
||||
|
||||
bool cDigiboxDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
||||
{
|
||||
bool result = false;
|
||||
bool hasPriority = Priority < 0 || Priority > this->Priority();
|
||||
bool needsDetachReceivers = true;
|
||||
|
||||
if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel->Ca())) {
|
||||
if (ProvidesSource(Channel->Source()) && Channel->Ca() == 0x30) {//XXX
|
||||
if (Receiving()) {
|
||||
if (digiboxChannelNumber == Channel->Frequency()) {
|
||||
needsDetachReceivers = false;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#
|
||||
# Makefile for a Video Disk Recorder plugin
|
||||
#
|
||||
# $Id: Makefile 1.6 2002/12/13 14:54:19 kls Exp $
|
||||
# $Id: Makefile 1.7 2003/12/21 15:47:41 kls Exp $
|
||||
|
||||
# The official name of this plugin.
|
||||
# This name will be used in the '-P...' option of VDR to load the plugin.
|
||||
@ -42,7 +42,7 @@ PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
|
||||
|
||||
DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
|
83
README.developer
Normal file
83
README.developer
Normal file
@ -0,0 +1,83 @@
|
||||
Version 1.3.0 marks the beginning of a new developer version
|
||||
of VDR, in which I am going to integrate functionality from
|
||||
patches that have been written by various people for previous
|
||||
versions of VDR.
|
||||
|
||||
IMPORTANT NOTE: Beginning with version 1.3.0, VDR will automatically
|
||||
=============== modify the 'channels.conf' file. Please run this version
|
||||
of VDR in a controlled environment only, and work with
|
||||
copies of all your config files!
|
||||
|
||||
This version of VDR focuses on some improvements regarding
|
||||
CAM support and, most important, the first step towards automatic
|
||||
PID handling. Some things are still in a raw state, but at least
|
||||
the program should now dynamically react on any changes in the
|
||||
channel settings.
|
||||
|
||||
Here's a list of the highlights - and what _not_ to expect yet
|
||||
(but don't worry, these things will come soon ;-):
|
||||
|
||||
- Automatic switching when PIDs are changed (e.g. for regional
|
||||
programmes).
|
||||
- There is no explicit transponder list yet, so you just
|
||||
have to define one channel for a new transponder and VDR
|
||||
will automatically detect all other channels on that transponder.
|
||||
- New channels are added to the end of the channel list, so
|
||||
it might be a good idea to add a line like
|
||||
|
||||
:@1000 New channels
|
||||
|
||||
to have them start at some high number.
|
||||
- Improved CAM support. Channels with conditional access now automatically
|
||||
use the device that contains the proper CAM.
|
||||
- No NVOD or "linked services" support yet.
|
||||
- No radio support yet.
|
||||
- No transponder scan yet.
|
||||
|
||||
Note that this is currently work in progress, so there may be some
|
||||
areas that don't work as smooth as expected, yet.
|
||||
|
||||
Known issues:
|
||||
=============
|
||||
|
||||
- The Setup/CICAM menu is currently without much meaning.
|
||||
CA detection is done automatically.
|
||||
- The channel "EURO1080" on Astra 19.2E currently broadcasts HDTV
|
||||
test signals. Unfortunately, the full featured DVB cards crash
|
||||
pretty ugly when tuned to that channel, so it might be a good idea
|
||||
to have the channel definition
|
||||
|
||||
EURO1080:12168:v:S19.2E:27500:308:256:0:FF:21100:1:1088:0
|
||||
|
||||
in your 'channels.conf' file. Note the Ca parameter 'F' (255 in hex),
|
||||
which gives this channel a non-existent Ca mode, so that it won't
|
||||
be tuned to at all. If you really want to tune to this channel for
|
||||
tests, do it on your own risk.
|
||||
- The 'sky' plugin now temporarily uses Ca value 30 (this will be changed
|
||||
later).
|
||||
- Since the CA detection is now done automatically, a timer that starts
|
||||
immediately after VDR has been launched and wants to record a CA channel
|
||||
may not work. This will be changed later to make this work safely.
|
||||
|
||||
What to test:
|
||||
=============
|
||||
|
||||
Apart from the usual general functionality, special attention should
|
||||
be given to the following matters:
|
||||
|
||||
- Does the automatic PID switching really work in all cases, especially
|
||||
in conjunction with conditional access channels?
|
||||
- Does CAM support work for all kinds of CAMs?
|
||||
|
||||
Known bugs:
|
||||
===========
|
||||
|
||||
- Sometimes a new channel is created with the wrong 'source'
|
||||
parameter. This presumably happens when the transponder and source
|
||||
are switched, and there is still an SDT data packet being processed.
|
||||
The call to device->HasLock() in sections.c should fix this (and it
|
||||
apparently does for most cases), but there must still be soemthing
|
||||
wrong in that area.
|
||||
- Sometimes the current channel gets re-tuned even though the channel
|
||||
data of this channel didn't change (but that of an other channel did
|
||||
change).
|
2
ca.conf
2
ca.conf
@ -18,6 +18,8 @@
|
||||
# Cryptoworks
|
||||
|
||||
201 GOD-DIGITAL
|
||||
202 Slovak Link
|
||||
203 Czech Link
|
||||
|
||||
# Videoguard
|
||||
|
||||
|
223
channels.c
223
channels.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.c 1.16 2003/10/17 15:42:40 kls Exp $
|
||||
* $Id: channels.c 1.17 2004/01/04 12:28:49 kls Exp $
|
||||
*/
|
||||
|
||||
#include "channels.h"
|
||||
@ -159,6 +159,7 @@ char *cChannel::buffer = NULL;
|
||||
|
||||
cChannel::cChannel(void)
|
||||
{
|
||||
memset(&__BeginData__, 0, (char *)&__EndData__ - (char *)&__BeginData__);
|
||||
strcpy(name, "Pro7");
|
||||
frequency = 12480;
|
||||
source = cSource::FromString("S19.2E");
|
||||
@ -170,7 +171,7 @@ cChannel::cChannel(void)
|
||||
dpid1 = 257;
|
||||
dpid2 = 0;
|
||||
tpid = 32;
|
||||
ca = 0;
|
||||
caids[0] = 0;
|
||||
nid = 0;
|
||||
tid = 0;
|
||||
sid = 888;
|
||||
@ -186,6 +187,28 @@ cChannel::cChannel(void)
|
||||
transmission = TRANSMISSION_MODE_AUTO;
|
||||
guard = GUARD_INTERVAL_AUTO;
|
||||
hierarchy = HIERARCHY_AUTO;
|
||||
modification = CHANNELMOD_NONE;
|
||||
}
|
||||
|
||||
cChannel::cChannel(const cChannel *Channel)
|
||||
{
|
||||
*this = *Channel;
|
||||
*name = 0;
|
||||
vpid = 0;
|
||||
ppid = 0;
|
||||
apid1 = 0;
|
||||
apid2 = 0;
|
||||
dpid1 = 0;
|
||||
dpid2 = 0;
|
||||
tpid = 0;
|
||||
caids[0] = 0;
|
||||
nid = 0;
|
||||
tid = 0;
|
||||
sid = 0;
|
||||
rid = 0;
|
||||
number = 0;
|
||||
groupSep = false;
|
||||
modification = CHANNELMOD_NONE;
|
||||
}
|
||||
|
||||
cChannel& cChannel::operator= (const cChannel &Channel)
|
||||
@ -194,16 +217,117 @@ cChannel& cChannel::operator= (const cChannel &Channel)
|
||||
return *this;
|
||||
}
|
||||
|
||||
static int MHz(int frequency)
|
||||
int cChannel::Transponder(void) const
|
||||
{
|
||||
while (frequency > 20000)
|
||||
frequency /= 1000;
|
||||
return frequency;
|
||||
int tf = frequency;
|
||||
while (tf > 20000)
|
||||
tf /= 1000;
|
||||
return tf;
|
||||
}
|
||||
|
||||
tChannelID cChannel::GetChannelID(void) const
|
||||
{
|
||||
return tChannelID(source, nid, nid ? tid : MHz(frequency), sid, rid);
|
||||
return tChannelID(source, nid, nid ? tid : Transponder(), sid, rid);
|
||||
}
|
||||
|
||||
int cChannel::Modification(int Mask)
|
||||
{
|
||||
int Result = modification & Mask;
|
||||
modification = CHANNELMOD_NONE;
|
||||
return Result;
|
||||
}
|
||||
|
||||
void cChannel::SetId(int Nid, int Tid, int Sid, int Rid, bool Log)
|
||||
{
|
||||
if (nid != Nid || tid != Tid || sid != Sid || rid != Rid) {
|
||||
if (Log)
|
||||
dsyslog("changing id of channel %d from %d-%d-%d-%d to %d-%d-%d-%d", Number(), nid, tid, sid, rid, Nid, Tid, Sid, Rid);
|
||||
nid = Nid;
|
||||
tid = Tid;
|
||||
sid = Sid;
|
||||
rid = Rid;
|
||||
modification |= CHANNELMOD_ID;
|
||||
Channels.SetModified();
|
||||
}
|
||||
}
|
||||
|
||||
void cChannel::SetName(const char *Name, bool Log)
|
||||
{
|
||||
if (!isempty(Name) && strcmp(name, Name) != 0) {
|
||||
if (Log)
|
||||
dsyslog("changing name of channel %d from '%s' to '%s'", Number(), name, Name);
|
||||
strn0cpy(name, Name, MaxChannelName);
|
||||
modification |= CHANNELMOD_NAME;
|
||||
Channels.SetModified();
|
||||
}
|
||||
}
|
||||
|
||||
void cChannel::SetPids(int Vpid, int Ppid, int Apid1, int Apid2, int Dpid1, int Dpid2, int Tpid)
|
||||
{
|
||||
//XXX if (vpid != Vpid || ppid != Ppid || apid1 != Apid1 || apid2 != Apid2 || dpid1 != Dpid1 || dpid2 != Dpid2 || tpid != Tpid) {
|
||||
if (vpid != Vpid || ppid != Ppid || apid1 != Apid1 || (Apid2 && apid2 != Apid2) || dpid1 != Dpid1 || dpid2 != Dpid2 || tpid != Tpid) {
|
||||
dsyslog("changing pids of channel %d from %d+%d:%d,%d;%d,%d:%d to %d+%d:%d,%d;%d,%d:%d", Number(), vpid, ppid, apid1, apid2, dpid1, dpid2, tpid, Vpid, Ppid, Apid1, Apid2, Dpid1, Dpid2, Tpid);
|
||||
vpid = Vpid;
|
||||
ppid = Ppid;
|
||||
apid1 = Apid1;
|
||||
if (Apid2)//XXX should we actually react here?
|
||||
apid2 = Apid2;
|
||||
dpid1 = Dpid1;
|
||||
dpid2 = Dpid2;
|
||||
tpid = Tpid;
|
||||
modification |= CHANNELMOD_PIDS;
|
||||
Channels.SetModified();
|
||||
}
|
||||
}
|
||||
|
||||
void cChannel::SetCaIds(const int *CaIds)
|
||||
{
|
||||
if (caids[0] && caids[0] <= 0x00FF)
|
||||
return; // special values will not be overwritten
|
||||
bool modified = false;
|
||||
for (int i = 0; i < MAXCAIDS; i++) {
|
||||
if (caids[i] != CaIds[i]) {
|
||||
modified = true;
|
||||
break;
|
||||
}
|
||||
if (!caids[i] || !CaIds[i])
|
||||
break;
|
||||
}
|
||||
if (modified) {
|
||||
char OldCaIdsBuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
|
||||
char NewCaIdsBuf[MAXCAIDS * 5 + 10];
|
||||
char *qo = OldCaIdsBuf;
|
||||
char *qn = NewCaIdsBuf;
|
||||
int i;
|
||||
for (i = 0; i < MAXCAIDS; i++) {
|
||||
if (i == 0 || caids[i])
|
||||
qo += snprintf(qo, sizeof(OldCaIdsBuf), "%s%X", i > 0 ? "," : "", caids[i]);
|
||||
if (!caids[i])
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < MAXCAIDS; i++) {
|
||||
if (i == 0 || CaIds[i])
|
||||
qn += snprintf(qn, sizeof(NewCaIdsBuf), "%s%X", i > 0 ? "," : "", CaIds[i]);
|
||||
caids[i] = CaIds[i];
|
||||
if (!CaIds[i])
|
||||
break;
|
||||
}
|
||||
caids[i] = 0;
|
||||
*qo = *qn = 0;
|
||||
dsyslog("changing caids of channel %d from %s to %s", Number(), OldCaIdsBuf, NewCaIdsBuf);
|
||||
modification |= CHANNELMOD_CA;
|
||||
Channels.SetModified();
|
||||
}
|
||||
}
|
||||
|
||||
void cChannel::SetCaDescriptors(int Level)
|
||||
{
|
||||
if (Level > 0) {
|
||||
modification |= CHANNELMOD_CA;
|
||||
Channels.SetModified();
|
||||
if (Level > 1)
|
||||
dsyslog("changing ca descriptors of channel %d", Number());
|
||||
}
|
||||
}
|
||||
|
||||
static int PrintParameter(char *p, char Name, int Value)
|
||||
@ -290,10 +414,10 @@ const char *cChannel::ToText(cChannel *Channel)
|
||||
char vpidbuf[32];
|
||||
char *q = vpidbuf;
|
||||
q += snprintf(q, sizeof(vpidbuf), "%d", Channel->vpid);
|
||||
if (Channel->ppid)
|
||||
if (Channel->ppid && Channel->ppid != Channel->vpid)
|
||||
q += snprintf(q, sizeof(vpidbuf) - (q - vpidbuf), "+%d", Channel->ppid);
|
||||
*q = 0;
|
||||
char apidbuf[32];
|
||||
char apidbuf[MAXAPIDS * 2 * 6 + 10]; // 2: Apids and Dpids, 6: 5 digits plus delimiting ',' or ';', 10: paranoia
|
||||
q = apidbuf;
|
||||
q += snprintf(q, sizeof(apidbuf), "%d", Channel->apid1);
|
||||
if (Channel->apid2)
|
||||
@ -303,7 +427,16 @@ const char *cChannel::ToText(cChannel *Channel)
|
||||
if (Channel->dpid2)
|
||||
q += snprintf(q, sizeof(apidbuf) - (q - apidbuf), ",%d", Channel->dpid2);
|
||||
*q = 0;
|
||||
asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%d:%d:%d:%d:%d\n", s, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, Channel->ca, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
|
||||
char caidbuf[MAXCAIDS * 5 + 10]; // 5: 4 digits plus delimiting ',', 10: paranoia
|
||||
q = caidbuf;
|
||||
for (int i = 0; i < MAXCAIDS; i++) {
|
||||
if (i == 0 || Channel->caids[i])
|
||||
q += snprintf(q, sizeof(caidbuf), "%s%X", i > 0 ? "," : "", Channel->caids[i]);
|
||||
if (!Channel->caids[i])
|
||||
break;
|
||||
}
|
||||
*q = 0;
|
||||
asprintf(&buffer, "%s:%d:%s:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d\n", s, Channel->frequency, Channel->ParametersToString(), cSource::ToString(Channel->source), Channel->srate, vpidbuf, apidbuf, Channel->tpid, caidbuf, Channel->sid, Channel->nid, Channel->tid, Channel->rid);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
@ -336,12 +469,16 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
|
||||
char *parambuf = NULL;
|
||||
char *vpidbuf = NULL;
|
||||
char *apidbuf = NULL;
|
||||
int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%d :%d :%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpid, &ca, &sid, &nid, &tid, &rid);
|
||||
char *caidbuf = NULL;
|
||||
int fields = sscanf(s, "%a[^:]:%d :%a[^:]:%a[^:] :%d :%a[^:]:%a[^:]:%d :%a[^:]:%d :%d :%d :%d ", &namebuf, &frequency, ¶mbuf, &sourcebuf, &srate, &vpidbuf, &apidbuf, &tpid, &caidbuf, &sid, &nid, &tid, &rid);
|
||||
if (fields >= 9) {
|
||||
if (fields == 9) {
|
||||
// allow reading of old format
|
||||
sid = ca;
|
||||
ca = tpid;
|
||||
sid = atoi(caidbuf);
|
||||
delete caidbuf;
|
||||
caidbuf = NULL;
|
||||
caids[0] = tpid;
|
||||
caids[1] = 0;
|
||||
tpid = 0;
|
||||
}
|
||||
vpid = ppid = 0;
|
||||
@ -350,24 +487,46 @@ bool cChannel::Parse(const char *s, bool AllowNonUniqueID)
|
||||
ok = false;
|
||||
if (parambuf && sourcebuf && vpidbuf && apidbuf) {
|
||||
ok = StringToParameters(parambuf) && (source = cSource::FromString(sourcebuf)) >= 0;
|
||||
|
||||
char *p = strchr(vpidbuf, '+');
|
||||
if (p)
|
||||
*p++ = 0;
|
||||
sscanf(vpidbuf, "%d", &vpid);
|
||||
if (p)
|
||||
sscanf(p, "%d", &ppid);
|
||||
else
|
||||
ppid = vpid;
|
||||
|
||||
p = strchr(apidbuf, ';');
|
||||
if (p)
|
||||
*p++ = 0;
|
||||
sscanf(apidbuf, "%d ,%d ", &apid1, &apid2);
|
||||
if (p)
|
||||
sscanf(p, "%d ,%d ", &dpid1, &dpid2);
|
||||
|
||||
if (caidbuf) {
|
||||
char *p = caidbuf;
|
||||
char *q;
|
||||
int NumCaIds = 0;
|
||||
while ((q = strtok(p, ",")) != NULL) {
|
||||
if (NumCaIds < MAXCAIDS) {
|
||||
caids[NumCaIds++] = strtol(q, NULL, 16) & 0xFFFF;
|
||||
if (NumCaIds == 1 && caids[0] <= 0x00FF)
|
||||
break;
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: too many CA ids!"); // no need to set ok to 'false'
|
||||
p = NULL;
|
||||
}
|
||||
caids[NumCaIds] = 0;
|
||||
}
|
||||
}
|
||||
strn0cpy(name, namebuf, MaxChannelName);
|
||||
free(parambuf);
|
||||
free(sourcebuf);
|
||||
free(vpidbuf);
|
||||
free(apidbuf);
|
||||
free(caidbuf);
|
||||
free(namebuf);
|
||||
if (!GetChannelID().Valid()) {
|
||||
esyslog("ERROR: channel data results in invalid ID!");
|
||||
@ -394,6 +553,12 @@ bool cChannel::Save(FILE *f)
|
||||
|
||||
cChannels Channels;
|
||||
|
||||
cChannels::cChannels(void)
|
||||
{
|
||||
maxNumber = 0;
|
||||
modified = false;
|
||||
}
|
||||
|
||||
bool cChannels::Load(const char *FileName, bool AllowComments, bool MustExist)
|
||||
{
|
||||
if (cConfig<cChannel>::Load(FileName, AllowComments, MustExist)) {
|
||||
@ -457,10 +622,10 @@ cChannel *cChannels::GetByNumber(int Number, int SkipGap)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cChannel *cChannels::GetByServiceID(int Source, unsigned short ServiceID)
|
||||
cChannel *cChannels::GetByServiceID(int Source, int Transponder, unsigned short ServiceID)
|
||||
{
|
||||
for (cChannel *channel = First(); channel; channel = Next(channel)) {
|
||||
if (!channel->GroupSep() && channel->Source() == Source && channel->Sid() == ServiceID)
|
||||
if (!channel->GroupSep() && channel->Source() == Source && ISTRANSPONDER(channel->Transponder(), Transponder) && channel->Sid() == ServiceID)
|
||||
return channel;
|
||||
}
|
||||
return NULL;
|
||||
@ -497,3 +662,31 @@ bool cChannels::SwitchTo(int Number)
|
||||
cChannel *channel = GetByNumber(Number);
|
||||
return channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true);
|
||||
}
|
||||
|
||||
void cChannels::SetModified(void)
|
||||
{
|
||||
modified = true;
|
||||
}
|
||||
|
||||
bool cChannels::Modified(void)
|
||||
{
|
||||
bool Result = modified;
|
||||
modified = false;
|
||||
return Result;
|
||||
}
|
||||
|
||||
cChannel *cChannels::NewChannel(int Source, int Transponder, const char *Name, int Nid, int Tid, int Sid, int Rid)
|
||||
{
|
||||
dsyslog("creating new channel '%s' on %s transponder %d with id %d-%d-%d-%d", Name, cSource::ToString(Source), Transponder, Nid, Tid, Sid, Rid);
|
||||
for (cChannel *channel = First(); channel; channel = Next(channel)) {
|
||||
if (!channel->GroupSep() && channel->Source() == Source && ISTRANSPONDER(channel->Transponder(), Transponder)) {
|
||||
cChannel *NewChannel = new cChannel(channel);
|
||||
Add(NewChannel);
|
||||
ReNumber();
|
||||
NewChannel->SetId(Nid, Tid, Sid, Rid, false);
|
||||
NewChannel->SetName(Name, false);
|
||||
return NewChannel;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
254
channels.conf
254
channels.conf
@ -1,162 +1,110 @@
|
||||
RTL:12188:h:S19.2E:27500:163:104:105:0:12003:0:0:0
|
||||
Sat.1:12480:v:S19.2E:27500:1791:1792:34:0:46:0:0:0
|
||||
Pro-7:12480:v:S19.2E:27500:255:256;257:32:0:898:0:0:0
|
||||
RTL2:12188:h:S19.2E:27500:166:128:68:0:12020:0:0:0
|
||||
ARD:11837:h:S19.2E:27500:101:102:104:0:28106:0:0:0
|
||||
BR3:11837:h:S19.2E:27500:201:202:204:0:28107:0:0:0
|
||||
Hessen-3:11837:h:S19.2E:27500:301:302:304:0:28108:0:0:0
|
||||
N3:12110:h:S19.2E:27500:2401:2402:2404:0:28224:0:0:0
|
||||
SR3:11837:h:S19.2E:27500:501:502:504:0:28110:0:0:0
|
||||
WDR:11837:h:S19.2E:27500:601:602:604:0:28111:0:0:0
|
||||
BR-alpha:11837:h:S19.2E:27500:701:702:704:0:28112:0:0:0
|
||||
SWR BW:11837:h:S19.2E:27500:801:802:804:0:28113:0:0:0
|
||||
Phoenix:11837:h:S19.2E:27500:901:902:904:0:28114:0:0:0
|
||||
ZDF:11954:h:S19.2E:27500:110:120:130:0:28006:0:0:0
|
||||
3sat:11954:h:S19.2E:27500:210:220:230:0:28007:0:0:0
|
||||
KiKa:11954:h:S19.2E:27500:310:320:330:0:28008:0:0:0
|
||||
arte:11836:h:S19.2E:27500:401:402:404:0:28109:0:0:0
|
||||
ORF1:12692:h:S19.2E:22000:160:161:165:102:13001:0:0:0
|
||||
ORF2:12692:h:S19.2E:22000:500:501:505:102:13002:0:0:0
|
||||
ZDF.info:11954:h:S19.2E:27500:610:620:0:0:28011:0:0:0
|
||||
CNN:11778:v:S19.2E:27500:165:100:0:0:28522:0:0:0
|
||||
Super RTL:12188:h:S19.2E:27500:165:120:65:0:12040:0:0:0
|
||||
VOX:12188:h:S19.2E:27500:167:136:71:0:12060:0:0:0
|
||||
:#DW TV:10788:v:S19.2E:22000:305:306:0:0:8905:0:0:0
|
||||
Kabel 1:12480:v:S19.2E:27500:511:512:33:0:899:0:0:0
|
||||
Neun Live:12480:v:S19.2E:27500:767:768:35:0:897:0:0:0
|
||||
DSF:12480:v:S19.2E:27500:1023:1024:0:0:900:0:0:0
|
||||
HOT:12480:v:S19.2E:27500:1279:1280:0:0:40:0:0:0
|
||||
Bloomberg TV Germany:12552:v:S19.2E:22000:162:99:0:0:12160:0:0:0
|
||||
Bloomberg TV France:11817:v:S19.2E:27500:163:92:0:0:8004:0:0:0
|
||||
Bloomberg TV Spain:12168:v:S19.2E:27500:167:112:0:0:12721:0:0:0
|
||||
Sky News:11597:v:S19.2E:22000:305:306:0:0:28707:0:0:0
|
||||
Fox Kids Netherlands:12574:h:S19.2E:22000:163:92:0:0:5020:0:0:0
|
||||
BVN:12574:h:S19.2E:22000:164+131:96:0:0:5025:0:0:0
|
||||
Alice:12610:v:S19.2E:22000:162:96:0:0:12200:0:0:0
|
||||
n-tv:12670:v:S19.2E:22000:162:96:55:0:12730:0:0:0
|
||||
Al Jazeera:11568:v:S19.2E:22000:55:56:0:0:9021:0:0:0
|
||||
Grand Tourisme:12670:v:S19.2E:22000:289:290:0:0:17300:0:0:0
|
||||
TW1:12692:h:S19.2E:22000:166:167:0:0:13013:0:0:0
|
||||
Eurosport:11954:h:S19.2E:27500:410:420:0:0:28009:0:0:0
|
||||
EinsExtra:12110:h:S19.2E:27500:101:102:0:0:28201:0:0:0
|
||||
EinsFestival:12110:h:S19.2E:27500:201:202:0:0:28202:0:0:0
|
||||
EinsMuXx:12110:h:S19.2E:27500:301:302:0:0:28203:0:0:0
|
||||
ZDF Theaterkanal:11954:h:S19.2E:27500:1110:1120:0:0:28016:0:0:0
|
||||
ZDF.doku:11954:h:S19.2E:27500:660:670:0:0:28014:0:0:0
|
||||
MDR:12110:h:S19.2E:27500:401:402:404:0:28204:0:0:0
|
||||
RBB Brandenburg:12110:h:S19.2E:27500:501:502:504:0:28205:0:0:0
|
||||
RBB Berlin:12110:h:S19.2E:27500:601:602:604:0:28206:0:0:0
|
||||
RTL,RTL Television:12188:h:S19.2E:27500:163:104:105:0:12003:1:1089:0
|
||||
SAT.1:12480:v:S19.2E:27500:1791:1792;1795:34:0:46:133:33:0
|
||||
ProSieben:12480:v:S19.2E:27500:255:256;257:32:0:898:133:33:0
|
||||
RTL2:12188:h:S19.2E:27500:166:128:68:0:12020:1:1089:0
|
||||
Das Erste:11837:h:S19.2E:27500:101:102:104:0:28106:1:1101:0
|
||||
Bayerisches FS:11837:h:S19.2E:27500:201:202:204:0:28107:1:1101:0
|
||||
hessen fernsehen:11837:h:S19.2E:27500:301:302:304:0:28108:1:1101:0
|
||||
NDR FS MV:12110:h:S19.2E:27500:2401:2402:2404:0:28224:1:1073:0
|
||||
SR Fernsehen Suedwest:11837:h:S19.2E:27500:501:502:504:0:28110:1:1101:0
|
||||
WDR FERNSEHEN:11837:h:S19.2E:27500:601:602:604:0:28111:1:1101:0
|
||||
BR-alpha:11837:h:S19.2E:27500:701:702:704:0:28112:1:1101:0
|
||||
SÜDWEST BW:11837:h:S19.2E:27500:801:802:804:0:28113:1:1101:0
|
||||
Phoenix:11837:h:S19.2E:27500:901:902:904:0:28114:1:1101:0
|
||||
ZDF:11954:h:S19.2E:27500:110:120;125:130:0:28006:1:1079:0
|
||||
3sat:11954:h:S19.2E:27500:210:220:230:0:28007:1:1079:0
|
||||
KiKa:11954:h:S19.2E:27500:310:320:330:0:28008:1:1079:0
|
||||
arte:11836:h:S19.2E:27500:401:402,403:404:0:28109:1:1101:0
|
||||
ORF 1:12692:h:S19.2E:22000:160:161;163:165:1762,D05,1702,1801:13001:1:1117:0
|
||||
ORF 2:12692:h:S19.2E:22000:500:501;503:505:1762,D05,1702,1801:13002:1:1117:0
|
||||
ZDFinfokanal:11954:h:S19.2E:27500:610:620:130:0:28011:1:1079:0
|
||||
CNN Int.:11778:v:S19.2E:27500:165:100:47:0:28522:1:1068:0
|
||||
S RTL,Super RTL:12188:h:S19.2E:27500:165:120:65:0:12040:1:1089:0
|
||||
VOX:12188:h:S19.2E:27500:167:136:71:0:12060:1:1089:0
|
||||
KABEL1:12480:v:S19.2E:27500:511:512:33:0:899:133:33:0
|
||||
NEUN LIVE,NEUN LIVE Television:12480:v:S19.2E:27500:767:768:35:0:897:133:33:0
|
||||
DSF:12480:v:S19.2E:27500:1023:1024:0:0:900:133:33:0
|
||||
HSEurope,Home Shopping Europe:12480:v:S19.2E:27500:1279:1280:37:0:40:133:33:0
|
||||
Bloomberg TV Germany:12552:v:S19.2E:22000:162:99:0:0:12160:1:1108:0
|
||||
EURONEWS:11817:v:S19.2E:27500:163:92,93:0:500,100:8004:1:1070:0
|
||||
Sky News:11597:v:S19.2E:22000:305:306:0:0:28707:1:1026:0
|
||||
Veronica/FoxKids:12574:h:S19.2E:22000:518+8190:92:38:622,602,100:5020:53:1109:0
|
||||
BVN:12574:h:S19.2E:22000:515+8190:96:36:0:5025:53:1109:0
|
||||
CNBC Europe:12610:v:S19.2E:22000:944:945:0:0:12200:1:1112:0
|
||||
n-tv:12670:v:S19.2E:22000:162:96:55:0:12730:1:1116:0
|
||||
Al Jazeera:11568:v:S19.2E:22000:55:56:0:0:9021:1:1024:0
|
||||
TW1:12692:h:S19.2E:22000:166:167:168:0:13013:1:1117:0
|
||||
Eurosport:11954:h:S19.2E:27500:410:420:430:0:28009:1:1079:0
|
||||
EinsExtra:12110:h:S19.2E:27500:101:102:0:0:28201:1:1073:0
|
||||
EinsFestival:12110:h:S19.2E:27500:201:202:0:0:28202:1:1073:0
|
||||
EinsMuXx:12110:h:S19.2E:27500:301:302:0:0:28203:1:1073:0
|
||||
ZDFtheaterkanal:11954:h:S19.2E:27500:1110:1120:130:0:28016:1:1079:0
|
||||
ZDFdokukanal:11954:h:S19.2E:27500:660:670:130:0:28014:1:1079:0
|
||||
MDR FERNSEHEN:12110:h:S19.2E:27500:401:402:404:0:28204:1:1073:0
|
||||
RBB Brandenburg:12110:h:S19.2E:27500:501:502:504:0:28205:1:1073:0
|
||||
RBB Berlin:12110:h:S19.2E:27500:601:602:604:0:28206:1:1073:0
|
||||
:Premiere World
|
||||
Premiere Start:11797:h:S19.2E:27500:255:256:0:101:8:0:0:0
|
||||
Premiere 1:11797:h:S19.2E:27500:511:512,513;515:0:101:10:0:0:0
|
||||
Premiere 2:11797:h:S19.2E:27500:1791:1792,1793;1795:0:101:11:0:0:0
|
||||
Premiere 3:11797:h:S19.2E:27500:2303:2304,2305:0:101:43:0:0:0
|
||||
Premiere 4:11797:h:S19.2E:27500:767:768,769:0:101:9:0:0:0
|
||||
Premiere 5:11797:h:S19.2E:27500:1279:1280,1281:0:101:29:0:0:0
|
||||
Premiere 6:11797:h:S19.2E:27500:1535:1536:0:101:41:0:0:0
|
||||
Premiere 7:11797:h:S19.2E:27500:1023:1024:0:101:20:0:0:0
|
||||
13th Street:11758:h:S19.2E:27500:2303:2304:0:101:42:0:0:0
|
||||
Sci-Fi:11758:h:S19.2E:27500:2047:2048:0:101:36:0:0:0
|
||||
Premiere Serie:12031:h:S19.2E:27500:1023:1024:0:101:16:0:0:0
|
||||
Disney Channel:11758:h:S19.2E:27500:2559:2560:0:101:34:0:0:0
|
||||
Premiere Nostalgie:12031:h:S19.2E:27500:2559:2560:0:101:516:0:0:0
|
||||
Discovery Channel:11758:h:S19.2E:27500:1023:1024:8181:101:14:0:0:0
|
||||
Planet:12090:v:S19.2E:27500:1279:1280:0:101:13:0:0:0
|
||||
Fox Kids:11758:h:S19.2E:27500:1279:1280:0:101:28:0:0:0
|
||||
Junior:11758:h:S19.2E:27500:255:256:0:101:19:0:0:0
|
||||
K-Toon:11758:h:S19.2E:27500:511:512:0:101:12:0:0:0
|
||||
Krimi&Co:12031:h:S19.2E:27500:1535:1536:0:101:23:0:0:0
|
||||
Goldstar TV:11758:h:S19.2E:27500:3839:3840:0:101:518:0:0:0
|
||||
MGM:11758:h:S19.2E:27500:767:768:2:101:515:0:0:0
|
||||
Sonnenklar TV:12090:v:S19.2E:27500:1023:1024:0:0:32:0:0:0
|
||||
START,PREMIERE START:11797:h:S19.2E:27500:255:256:32:1702,1722,1801:8:133:2:0
|
||||
PREM 1,PREMIERE 1:11797:h:S19.2E:27500:511:512,513;515:0:1702,1722,1801:10:133:2:0
|
||||
PREM 2,PREMIERE 2:11797:h:S19.2E:27500:1791:1792,1793;1795:0:1702,1722,1801:11:133:2:0
|
||||
PREM 3,PREMIERE 3:11797:h:S19.2E:27500:2303:2304,2305:0:1702,1722,1801:43:133:2:0
|
||||
PREM 4,PREMIERE 4:11797:h:S19.2E:27500:767:768,769:0:1702,1722,1801:9:133:2:0
|
||||
PREM 5,PREMIERE 5:11797:h:S19.2E:27500:1279:1280,1281:0:1702,1722,1801:29:133:2:0
|
||||
PREM 6,PREMIERE 6:11797:h:S19.2E:27500:1535:1536:0:1702,1722,1801:41:133:2:0
|
||||
PREM 7,PREMIERE 7:11797:h:S19.2E:27500:1023:1024:0:1702,1722,1801:20:133:2:0
|
||||
DISNEY,DISNEY CHANNEL:11758:h:S19.2E:27500:2559:2560:0:1702,1722,1801:34:133:17:0
|
||||
:Premiere Direkt
|
||||
Premiere Direkt Portal:12031:h:S19.2E:27500:2815:2816:0:101:18:0:0:0
|
||||
Premiere Direkt 1A:11719:h:S19.2E:27500:2047:2048:0:101:240:0:0:0
|
||||
Premiere Direkt 1B:11719:h:S19.2E:27500:2303:2304:0:101:241:0:0:0
|
||||
Premiere Direkt 1C:11719:h:S19.2E:27500:2559:2560:0:101:242:0:0:0
|
||||
Premiere Direkt 2A:11719:h:S19.2E:27500:2815:2816:0:101:243:0:0:0
|
||||
Premiere Direkt 2B:11719:h:S19.2E:27500:3071:3072:0:101:244:0:0:0
|
||||
Premiere Direkt 2C:12031:h:S19.2E:27500:3071:3072:0:101:208:0:0:0
|
||||
Premiere Direkt 2D:11719:h:S19.2E:27500:3327:3328:0:101:245:0:0:0
|
||||
Premiere Direkt 3A:12031:h:S19.2E:27500:3327:3328:0:101:209:0:0:0
|
||||
Premiere Direkt 3B:12031:h:S19.2E:27500:2303:2304:0:101:210:0:0:0
|
||||
Premiere Direkt 3C:11758:h:S19.2E:27500:511:512:0:101:211:0:0:0
|
||||
Premiere Direkt 3D:12070:h:S19.2E:27500:511:512:0:101:212:0:0:0
|
||||
DIREKT,PREMIERE DIREKT:12031:h:S19.2E:27500:2815:2816,2817;2819:0:0:18:133:4:0
|
||||
:PW Erotic
|
||||
Beate-Uhse.TV:12071:h:S19.2E:27500:1023:1024:0:101:21:0:0:0
|
||||
Premiere Erotik 1:12031:h:S19.2E:27500:1279:1280:2:101:513:0:0:0
|
||||
Premiere Erotik 2:12070:h:S19.2E:27500:1535:1536:0:101:778:0:0:0
|
||||
Premiere Erotik 3:12070:h:S19.2E:27500:1791:1792:0:101:779:0:0:0
|
||||
Premiere Erotik 4:12070:h:S19.2E:27500:3583:3584:0:101:780:0:0:0
|
||||
B-UHSE,BEATE-UHSE.TV:12071:h:S19.2E:27500:1023:1024:0:1702,1722,1801:21:133:1:0
|
||||
EROTIK,PREMIERE EROTIK:12031:h:S19.2E:27500:1279:0:0:1702,1722,1801:513:133:4:0
|
||||
:Sportsworld
|
||||
Premiere Sport 1:11720:h:S19.2E:27500:255:256,257:0:101:17:0:0:0
|
||||
Premiere Sport 2:12031:h:S19.2E:27500:3839:3840:0:101:27:0:0:0
|
||||
:Formel 1
|
||||
:#Supersignal:12070:h:S19.2E:27500:255:256:0:101:211:0:0:0
|
||||
:#Cockpitkanal:12070:h:S19.2E:27500:511:512:0:101:212:0:0:0
|
||||
:#Boxengasse:12070:h:S19.2E:27500:767:768:0:101:213:0:0:0
|
||||
:#Verfolgerfeld:12070:h:S19.2E:27500:1023:1024:0:101:214:0:0:0
|
||||
:#Infokanal:12070:h:S19.2E:27500:1279:1280:0:101:215:0:0:0
|
||||
:#Multikanal:11720:h:S19.2E:27500:255:256:0:101:17:0:0:0
|
||||
SPORT 1,PREMIERE SPORT 1:11720:h:S19.2E:27500:255:256,257:0:1702,1722,1801:17:133:3:0
|
||||
SPORT 2,PREMIERE SPORT 2:12031:h:S19.2E:27500:3839:3840,3841:0:1702,1722,1801:27:133:4:0
|
||||
:Beta Digital
|
||||
N24:12480:v:S19.2E:27500:2047:2048:0:0:47:0:0:0
|
||||
CNBC:11954:h:S19.2E:27500:510:520:0:0:28010:0:0:0
|
||||
Liberty TV.com:12610:v:S19.2E:22000:941:943,942:0:0:12199:0:0:0
|
||||
:Premiere Bundesliga
|
||||
BL-Konferenz:12031:h:S19.2E:27500:2303:2304,2305:0:101:210:0:0:1
|
||||
BuLi 1:11719:h:S19.2E:27500:255:256,257:0:101:17:0:0:1
|
||||
BuLi 2:11719:h:S19.2E:27500:2047:2048,2049:0:101:240:0:0:1
|
||||
BuLi 3:11719:h:S19.2E:27500:2303:2304,2305:0:101:241:0:0:1
|
||||
BuLi 4:11719:h:S19.2E:27500:2559:2560,2561:0:101:242:0:0:1
|
||||
BuLi 5:11719:h:S19.2E:27500:2815:2816,2817:0:101:243:0:0:1
|
||||
BuLi 6:11719:h:S19.2E:27500:3071:3072,3073:0:101:244:0:0:1
|
||||
BuLi 7:11719:h:S19.2E:27500:3327:3328,3329:0:101:245:0:0:1
|
||||
BuLi 8:12031:h:S19.2E:27500:3071:3072,3073:0:101:208:0:0:1
|
||||
BuLi 9:12031:h:S19.2E:27500:3327:3328,3329:0:101:209:0:0:1
|
||||
N24:12480:v:S19.2E:27500:2047:2048:36:0:47:133:33:0
|
||||
CNBC:11954:h:S19.2E:27500:510:520:530:0:28010:1:1079:0
|
||||
Liberty TV.com:12610:v:S19.2E:22000:941:943:0:0:12199:1:1112:0
|
||||
:-
|
||||
Mosaico:11934:v:S19.2E:27500:165:100:0:0:29010:0:0:0
|
||||
Andalucia TV:11934:v:S19.2E:27500:166:104:0:0:29011:0:0:0
|
||||
Canal J:11934:v:S19.2E:27500:167:108:0:0:8157:0:0:0
|
||||
Extreme Sports Channel:11992:h:S19.2E:27500:165:98,99:0:0:20365:0:0:0
|
||||
Pro 7 Austria:12051:v:S19.2E:27500:161:84:0:0:20002:0:0:0
|
||||
Kabel 1 Schweiz:12051:v:S19.2E:27500:162:163:0:0:20003:0:0:0
|
||||
Kabel 1 Austria:12051:v:S19.2E:27500:166:167:0:0:20004:0:0:0
|
||||
Pro 7 Schweiz:12051:v:S19.2E:27500:289:290:0:0:20001:0:0:0
|
||||
:#KTO:11739:v:S19.2E:27500:163:90:0:0:8304:0:0:0
|
||||
Cartoon Network France:12168:v:S19.2E:27500:161:84:0:0:28511:0:0:0
|
||||
TVBS Europe:12168:v:S19.2E:27500:162:88,89:0:0:28631:0:0:0
|
||||
travel channel:12168:v:S19.2E:27500:163:92,93:0:0:28001:0:0:0
|
||||
TCM Espana:12168:v:S19.2E:27500:164:96,97:0:0:28516:0:0:0
|
||||
TCM France:12168:v:S19.2E:27500:169:64,65:0:0:28515:0:0:0
|
||||
La Cinquieme:12207:v:S19.2E:27500:160:80:0:0:8501:0:0:0
|
||||
LCP:12207:v:S19.2E:27500:165:100:0:0:8506:0:0:0
|
||||
:#AB Moteurs:12266:h:S19.2E:27500:160:80:0:0:17000:0:0:0
|
||||
:#AB 1:12266:h:S19.2E:27500:161:84:0:0:17001:0:0:0
|
||||
Escales:12285:v:S19.2E:27500:165:100:0:0:17025:0:0:0
|
||||
Canal Club:12324:v:S19.2E:27500:160:80:0:0:8612:0:0:0
|
||||
:#RAI Uno:10788:v:S19.2E:22000:289:290:0:0:9004:0:0:0
|
||||
K13:12402:v:S19.2E:27500:163:92:0:0:8704:0:0:0
|
||||
Astra Mosaic 1:12552:v:S19.2E:22000:175:176:0:0:3988:0:0:0
|
||||
Astra Mosaic 2:12552:v:S19.2E:22000:179:120:0:0:3987:0:0:0
|
||||
Astra Mosaic 3:12552:v:S19.2E:22000:182:169:0:0:3986:0:0:0
|
||||
Astra Mosaic 4:12552:v:S19.2E:22000:185:170:0:0:3985:0:0:0
|
||||
Astra Mosaic 5:12552:v:S19.2E:22000:163:170:0:0:3984:0:0:0
|
||||
Chamber TV:12552:v:S19.2E:22000:55:56:0:0:12180:0:0:0
|
||||
RTL Tele Letzebuerg:12552:v:S19.2E:22000:168:144,146:0:0:3994:0:0:0
|
||||
VERONICA:12574:h:S19.2E:22000:161:84:0:0:5010:0:0:0
|
||||
VH1 Classic:12670:v:S19.2E:22000:3071:3072:0:0:28647:0:0:0
|
||||
MTV 2:12225:h:S19.2E:27500:513:661:577:0:28640:0:0:0
|
||||
ProSieben Austria:12051:v:S19.2E:27500:161:84:36:0:20002:1:1082:0
|
||||
Kabel 1 Schweiz:12051:v:S19.2E:27500:162:163:165:0:20003:1:1082:0
|
||||
Kabel 1 Austria:12051:v:S19.2E:27500:166:167:169:0:20004:1:1082:0
|
||||
ProSieben Schweiz:12051:v:S19.2E:27500:289:290:33:0:20001:1:1082:0
|
||||
FRANCE 5:12207:v:S19.2E:27500:160:80:32:0:8501:1:1090:0
|
||||
LCP:12207:v:S19.2E:27500:165:100:0:0:8506:1:1090:0
|
||||
ESCALES:12285:v:S19.2E:27500:165:100:0:500,100:17025:1:1094:0
|
||||
CANAL CLUB:12324:v:S19.2E:27500:160:80:0:0:8612:1:1096:0
|
||||
ASTRA-Mosaic:12552:v:S19.2E:22000:175:176:0:0:3988:1:1108:0
|
||||
ASTRA-Mosaic 2:12552:v:S19.2E:22000:179:120:0:0:3987:1:1108:0
|
||||
ASTRA-Mosaic 3:12552:v:S19.2E:22000:182:169:0:0:3986:1:1108:0
|
||||
ASTRA-Mosaic 4:12552:v:S19.2E:22000:185:170:0:0:3985:1:1108:0
|
||||
ASTRA-Mosaic 5:12552:v:S19.2E:22000:163:164:0:0:3984:1:1108:0
|
||||
Chamber TV:12552:v:S19.2E:22000:55:56:0:0:12180:1:1108:0
|
||||
RTL TELE Letzebuerg:12552:v:S19.2E:22000:168:144,146:74:0:3994:1:1108:0
|
||||
Yorin:12574:h:S19.2E:22000:512+8190:84:33:622,602,100:5010:53:1109:0
|
||||
MTV2 Pop Channel:12225:h:S19.2E:27500:513:661:577:0:28640:1:1091:0
|
||||
Via 1 - Schöner Reisen:12148:h:S19.2E:27500:511:512:0:0:44:0:0:0
|
||||
Video Italia:12610:v:S19.2E:22000:121:122:0:0:12220:0:0:0
|
||||
ORF/ZDF:12670:h:S19.2E:22000:506:507:0:0:13012:0:0:0
|
||||
VIVA:12670:v:S19.2E:22000:309:310:311:0:12732:0:0:0
|
||||
VIVA PLUS:12552:v:S19.2E:22000:171:172:179:0:12120:0:0:0
|
||||
MTV Central:11739:v:S19.2E:27500:3031:3032:3034:0:28653:0:0:0
|
||||
QVC Germany:12552:v:S19.2E:22000:165:166:0:0:12100:0:0:0
|
||||
Tele 5:12480:v:S19.2E:27500:1535:1536:0:0:51:0:0:0
|
||||
VIVA:12670:v:S19.2E:22000:309:310:311:0:12732:1:1116:0
|
||||
VIVA PLUS:12552:v:S19.2E:22000:171:172:173:0:12120:1:1108:0
|
||||
MTV Central:11739:v:S19.2E:27500:3031:3032:3034:0:28653:1:1066:0
|
||||
QVC GERMANY:12552:v:S19.2E:22000:165:166:167:0:12100:1:1108:0
|
||||
TELE 5:12480:v:S19.2E:27500:1535:1536:38:0:51:133:33:0
|
||||
:@201 Sky
|
||||
Sky One:106:h:S28.2E:0:160:80:0:301:222:0:0:0
|
||||
Sky One Mix:107:h:S28.2E:0:160:80:0:301:919:0:0:0
|
||||
itv2:226:h:S28.2E:0:160:80:0:301:451:0:0:0
|
||||
sci-fi:130:h:S28.2E:0:160:80:0:301:161:0:0:0
|
||||
Paramount Comedy:127:h:S28.2E:0:160:80:0:301:185:0:0:0
|
||||
Sky One:106:h:S28.2E:0:160:80:0:30:222:0:0:0
|
||||
Sky One Mix:107:h:S28.2E:0:160:80:0:30:919:0:0:0
|
||||
itv2:226:h:S28.2E:0:160:80:0:30:451:0:0:0
|
||||
sci-fi:130:h:S28.2E:0:160:80:0:30:161:0:0:0
|
||||
Paramount Comedy:127:h:S28.2E:0:160:80:0:30:185:0:0:0
|
||||
:@900 Some 'seed' channels
|
||||
Chelsea TV:11778:v:S28.2E:27500:2308+2304:2309:0:960,961:9307:2:2004:0
|
||||
Sky One:12285:v:S28.2E:27500:2311+2304:2312,2313:2307:960,961:4703:2:2030:0
|
||||
WDR Münster:12421:h:S19.2E:27500:101:102:104:0:28310:1:1201:0
|
||||
Going Places:10921:h:S28.2E:22000:2310+2304:2311:2312:0:5008:2:2055:0
|
||||
Animal Plnt+:12070:h:S28.2E:27500:2315+2307:2316:0:960,961:50002:2:2019:0
|
||||
S1T:11954:h:S28.2E:27500:0:0:0:0:4409:2:2030:0
|
||||
CNN:12032:v:S28.2E:27500:2309:2311:2310:0:7140:2:2018:0
|
||||
BBC PARL'MNT:12129:v:S28.2E:27500:2306:2308,2309:2307:0:7300:2:2022:0
|
||||
AL HAYAT:11200:v:S13.0E:27500:413:414:0:0:4733:318:13400:0
|
||||
EURO1080:12168:v:S19.2E:27500:308:256:0:FF:21100:1:1088:0
|
||||
:@1000 New channels
|
||||
|
52
channels.h
52
channels.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: channels.h 1.9 2003/10/26 13:21:59 kls Exp $
|
||||
* $Id: channels.h 1.10 2004/01/04 12:26:37 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CHANNELS_H
|
||||
@ -12,10 +12,22 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "sources.h"
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define ISTRANSPONDER(f1, f2) (abs((f1) - (f2)) < 4) //XXX
|
||||
|
||||
#define CHANNELMOD_NONE 0x00
|
||||
#define CHANNELMOD_ALL 0xFF
|
||||
#define CHANNELMOD_NAME 0x01
|
||||
#define CHANNELMOD_PIDS 0x02
|
||||
#define CHANNELMOD_ID 0x04
|
||||
#define CHANNELMOD_CA 0x10
|
||||
#define CHANNELMOD_RETUNE (CHANNELMOD_PIDS | CHANNELMOD_CA)
|
||||
|
||||
#define MAXAPIDS 2
|
||||
#define MAXCAIDS 8
|
||||
|
||||
struct tChannelParameterMap {
|
||||
int userValue;
|
||||
int driverValue;
|
||||
@ -46,7 +58,7 @@ public:
|
||||
tChannelID(void) { source = nid = tid = sid = rid = 0; }
|
||||
tChannelID(int Source, int Nid, int Tid, int Sid, int Rid = 0) { source = Source; nid = Nid; tid = Tid; sid = Sid; rid = Rid; }
|
||||
bool operator== (const tChannelID &arg) const;
|
||||
bool Valid(void) { return tid && sid; } // nid and rid are optional and source may be 0
|
||||
bool Valid(void) { return tid && sid; } // nid and rid are optional and source may be 0//XXX source may not be 0???
|
||||
tChannelID &ClrRid(void) { rid = 0; return *this; }
|
||||
static tChannelID FromString(const char *s);
|
||||
const char *ToString(void);
|
||||
@ -58,7 +70,7 @@ class cChannel : public cListObject {
|
||||
private:
|
||||
static char *buffer;
|
||||
static const char *ToText(cChannel *Channel);
|
||||
enum { MaxChannelName = 32 }; // 31 chars + terminating 0!
|
||||
enum { MaxChannelName = 64 }; // 63 chars + terminating 0!
|
||||
int __BeginData__;
|
||||
char name[MaxChannelName];
|
||||
int frequency; // MHz
|
||||
@ -69,7 +81,7 @@ private:
|
||||
int apid1, apid2;
|
||||
int dpid1, dpid2;
|
||||
int tpid;
|
||||
int ca;
|
||||
int caids[MAXCAIDS + 1]; // list is zero-terminated
|
||||
int nid;
|
||||
int tid;
|
||||
int sid;
|
||||
@ -86,16 +98,19 @@ private:
|
||||
int guard;
|
||||
int hierarchy;
|
||||
int __EndData__;
|
||||
int modification;
|
||||
const char *ParametersToString(void);
|
||||
bool StringToParameters(const char *s);
|
||||
public:
|
||||
cChannel(void);
|
||||
cChannel(const cChannel *Channel);
|
||||
cChannel& operator= (const cChannel &Channel);
|
||||
const char *ToText(void);
|
||||
bool Parse(const char *s, bool AllowNonUniqueID = false);
|
||||
bool Save(FILE *f);
|
||||
const char *Name(void) const { return name; }
|
||||
int Frequency(void) const { return frequency; }
|
||||
int Frequency(void) const { return frequency; } ///< Returns the actual frequency, as given in 'channels.conf'
|
||||
int Transponder(void) const; ///< Returns the transponder frequency in MHz
|
||||
int Source(void) const { return source; }
|
||||
int Srate(void) const { return srate; }
|
||||
int Vpid(void) const { return vpid; }
|
||||
@ -105,8 +120,11 @@ public:
|
||||
int Dpid1(void) const { return dpid1; }
|
||||
int Dpid2(void) const { return dpid2; }
|
||||
int Tpid(void) const { return tpid; }
|
||||
int Ca(void) const { return ca; }
|
||||
int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; }
|
||||
int Nid(void) const { return nid; }
|
||||
int Tid(void) const { return tid; }
|
||||
int Sid(void) const { return sid; }
|
||||
int Rid(void) const { return rid; }
|
||||
int Number(void) const { return number; }
|
||||
void SetNumber(int Number) { number = Number; }
|
||||
bool GroupSep(void) const { return groupSep; }
|
||||
@ -123,24 +141,38 @@ public:
|
||||
bool IsSat(void) const { return (source & cSource::st_Mask) == cSource::stSat; }
|
||||
bool IsTerr(void) const { return (source & cSource::st_Mask) == cSource::stTerr; }
|
||||
tChannelID GetChannelID(void) const;
|
||||
int Modification(int Mask = CHANNELMOD_ALL);
|
||||
void SetId(int Nid, int Tid, int Sid, int Rid = 0, bool Log = true);
|
||||
void SetName(const char *Name, bool Log = true);
|
||||
void SetPids(int Vpid, int Ppid, int Apid1, int Apid2, int Dpid1, int Dpid2, int Tpid);
|
||||
void SetCaIds(const int *CaIds); // list must be zero-terminated
|
||||
void SetCaDescriptors(int Level);
|
||||
};
|
||||
|
||||
class cChannels : public cConfig<cChannel> {
|
||||
protected:
|
||||
class cChannels : public cRwLock, public cConfig<cChannel> {
|
||||
private:
|
||||
int maxNumber;
|
||||
bool modified;
|
||||
int beingEdited;
|
||||
public:
|
||||
cChannels(void) { maxNumber = 0; }
|
||||
cChannels(void);
|
||||
virtual bool Load(const char *FileName, bool AllowComments = false, bool MustExist = false);
|
||||
int GetNextGroup(int Idx); // Get next channel group
|
||||
int GetPrevGroup(int Idx); // Get previous channel group
|
||||
int GetNextNormal(int Idx); // Get next normal channel (not group)
|
||||
void ReNumber(void); // Recalculate 'number' based on channel type
|
||||
cChannel *GetByNumber(int Number, int SkipGap = 0);
|
||||
cChannel *GetByServiceID(int Source, unsigned short ServiceID);
|
||||
cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID);
|
||||
cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false);
|
||||
int BeingEdited(void) { return beingEdited; }
|
||||
void IncBeingEdited(void) { beingEdited++; }
|
||||
void DecBeingEdited(void) { beingEdited--; }
|
||||
bool HasUniqueChannelID(cChannel *NewChannel, cChannel *OldChannel = NULL);
|
||||
bool SwitchTo(int Number);
|
||||
int MaxNumber(void) { return maxNumber; }
|
||||
void SetModified(void);
|
||||
bool Modified(void);
|
||||
cChannel *NewChannel(int Source, int Transponder, const char *Name, int Nid, int Tid, int Sid, int Rid = 0);
|
||||
};
|
||||
|
||||
extern cChannels Channels;
|
||||
|
71
ci.c
71
ci.c
@ -4,14 +4,11 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ci.c 1.17 2003/10/26 13:04:23 kls Exp $
|
||||
* $Id: ci.c 1.21 2004/01/02 15:07:36 kls Exp $
|
||||
*/
|
||||
|
||||
/* XXX TODO
|
||||
- update CA descriptors in case they change
|
||||
XXX*/
|
||||
|
||||
#include "ci.h"
|
||||
#include <asm/unaligned.h>
|
||||
#include <ctype.h>
|
||||
#include <linux/dvb/ca.h>
|
||||
#include <malloc.h>
|
||||
@ -21,6 +18,7 @@ XXX*/
|
||||
#include <sys/ioctl.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "pat.h"
|
||||
#include "tools.h"
|
||||
|
||||
/* these might come in handy in case you want to use this code without VDR's other files:
|
||||
@ -793,10 +791,10 @@ bool cCiApplicationInformation::Process(int Length, const uint8_t *Data)
|
||||
if ((l -= 1) < 0) break;
|
||||
applicationType = *d++;
|
||||
if ((l -= 2) < 0) break;
|
||||
applicationManufacturer = ntohs(*(uint16_t *)d);
|
||||
applicationManufacturer = ntohs(get_unaligned((uint16_t *)d));
|
||||
d += 2;
|
||||
if ((l -= 2) < 0) break;
|
||||
manufacturerCode = ntohs(*(uint16_t *)d);
|
||||
manufacturerCode = ntohs(get_unaligned((uint16_t *)d));
|
||||
d += 2;
|
||||
free(menuString);
|
||||
menuString = GetString(l, &d);
|
||||
@ -1265,8 +1263,9 @@ bool cCiEnquiry::Cancel(void)
|
||||
#define CPCI_QUERY 0x03
|
||||
#define CPCI_NOT_SELECTED 0x04
|
||||
|
||||
cCiCaPmt::cCiCaPmt(int ProgramNumber)
|
||||
cCiCaPmt::cCiCaPmt(int Source, int Transponder, int ProgramNumber, const unsigned short *CaSystemIds)
|
||||
{
|
||||
caDescriptorsLength = GetCaDescriptors(Source, Transponder, ProgramNumber, CaSystemIds, sizeof(caDescriptors), caDescriptors, streamFlag);
|
||||
length = 0;
|
||||
capmt[length++] = CPLM_ONLY;
|
||||
capmt[length++] = (ProgramNumber >> 8) & 0xFF;
|
||||
@ -1275,20 +1274,31 @@ cCiCaPmt::cCiCaPmt(int ProgramNumber)
|
||||
esInfoLengthPos = length;
|
||||
capmt[length++] = 0x00; // program_info_length H (at program level)
|
||||
capmt[length++] = 0x00; // program_info_length L
|
||||
if (!streamFlag)
|
||||
AddCaDescriptors(caDescriptorsLength, caDescriptors);
|
||||
}
|
||||
|
||||
void cCiCaPmt::AddPid(int Pid)
|
||||
bool cCiCaPmt::Valid(void)
|
||||
{
|
||||
//XXX buffer overflow check???
|
||||
capmt[length++] = 0x00; //XXX stream_type (apparently doesn't matter)
|
||||
capmt[length++] = (Pid >> 8) & 0xFF;
|
||||
capmt[length++] = Pid & 0xFF;
|
||||
esInfoLengthPos = length;
|
||||
capmt[length++] = 0x00; // ES_info_length H (at ES level)
|
||||
capmt[length++] = 0x00; // ES_info_length L
|
||||
return caDescriptorsLength > 0;
|
||||
}
|
||||
|
||||
void cCiCaPmt::AddCaDescriptor(int Length, uint8_t *Data)
|
||||
void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
|
||||
{
|
||||
if (Pid) {
|
||||
//XXX buffer overflow check???
|
||||
capmt[length++] = StreamType;
|
||||
capmt[length++] = (Pid >> 8) & 0xFF;
|
||||
capmt[length++] = Pid & 0xFF;
|
||||
esInfoLengthPos = length;
|
||||
capmt[length++] = 0x00; // ES_info_length H (at ES level)
|
||||
capmt[length++] = 0x00; // ES_info_length L
|
||||
if (streamFlag)
|
||||
AddCaDescriptors(caDescriptorsLength, caDescriptors);
|
||||
}
|
||||
}
|
||||
|
||||
void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
|
||||
{
|
||||
if (esInfoLengthPos) {
|
||||
if (length + Length < int(sizeof(capmt))) {
|
||||
@ -1355,7 +1365,7 @@ cCiHandler *cCiHandler::CreateCiHandler(const char *FileName)
|
||||
|
||||
int cCiHandler::ResourceIdToInt(const uint8_t *Data)
|
||||
{
|
||||
return (ntohl(*(int *)Data));
|
||||
return (ntohl(get_unaligned((int32_t *)Data)));
|
||||
}
|
||||
|
||||
bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status)
|
||||
@ -1367,10 +1377,10 @@ bool cCiHandler::Send(uint8_t Tag, int SessionId, int ResourceId, int Status)
|
||||
if (Status >= 0)
|
||||
*p++ = Status;
|
||||
if (ResourceId) {
|
||||
*(int *)p = htonl(ResourceId);
|
||||
put_unaligned(htonl(ResourceId), (int32_t *)p);
|
||||
p += 4;
|
||||
}
|
||||
*(short *)p = htons(SessionId);
|
||||
put_unaligned(htons(SessionId), (uint16_t *)p);
|
||||
p += 2;
|
||||
buffer[1] = p - buffer - 2; // length
|
||||
return tc && tc->SendData(p - buffer, buffer) == OK;
|
||||
@ -1481,7 +1491,7 @@ bool cCiHandler::Process(void)
|
||||
if (Data && Length > 1) {
|
||||
switch (*Data) {
|
||||
case ST_SESSION_NUMBER: if (Length > 4) {
|
||||
int SessionId = ntohs(*(short *)&Data[2]);
|
||||
int SessionId = ntohs(get_unaligned((uint16_t *)&Data[2]));
|
||||
cCiSession *Session = GetSessionBySessionId(SessionId);
|
||||
if (Session)
|
||||
Session->Process(Length - 4, Data + 4);
|
||||
@ -1492,7 +1502,7 @@ bool cCiHandler::Process(void)
|
||||
case ST_OPEN_SESSION_REQUEST: OpenSession(Length, Data);
|
||||
break;
|
||||
case ST_CLOSE_SESSION_REQUEST: if (Length == 4)
|
||||
CloseSession(ntohs(*(short *)&Data[2]));
|
||||
CloseSession(ntohs(get_unaligned((uint16_t *)&Data[2])));
|
||||
break;
|
||||
case ST_CREATE_SESSION_RESPONSE: //XXX fall through to default
|
||||
case ST_CLOSE_SESSION_RESPONSE: //XXX fall through to default
|
||||
@ -1556,6 +1566,23 @@ const unsigned short *cCiHandler::GetCaSystemIds(int Slot)
|
||||
return cas ? cas->GetCaSystemIds() : NULL;
|
||||
}
|
||||
|
||||
bool cCiHandler::ProvidesCa(const unsigned short *CaSystemIds)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
for (int Slot = 0; Slot < numSlots; Slot++) {
|
||||
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
|
||||
if (cas) {
|
||||
for (const unsigned short *ids = cas->GetCaSystemIds(); ids && *ids; ids++) {
|
||||
for (const unsigned short *id = CaSystemIds; *id; id++) {
|
||||
if (*id == *ids)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt, int Slot)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
|
13
ci.h
13
ci.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ci.h 1.9 2003/10/26 12:22:09 kls Exp $
|
||||
* $Id: ci.h 1.12 2003/12/31 13:49:49 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CI_H
|
||||
@ -66,10 +66,14 @@ private:
|
||||
int length;
|
||||
int esInfoLengthPos;
|
||||
uint8_t capmt[2048]; ///< XXX is there a specified maximum?
|
||||
int caDescriptorsLength;
|
||||
uint8_t caDescriptors[2048];
|
||||
bool streamFlag;
|
||||
void AddCaDescriptors(int Length, const uint8_t *Data);
|
||||
public:
|
||||
cCiCaPmt(int ProgramNumber);
|
||||
void AddPid(int Pid);
|
||||
void AddCaDescriptor(int Length, uint8_t *Data);
|
||||
cCiCaPmt(int Source, int Transponder, int ProgramNumber, const unsigned short *CaSystemIds);
|
||||
bool Valid(void);
|
||||
void AddPid(int Pid, uint8_t StreamType);
|
||||
};
|
||||
|
||||
#define MAX_CI_SESSION 16 //XXX
|
||||
@ -107,6 +111,7 @@ public:
|
||||
cCiMenu *GetMenu(void);
|
||||
cCiEnquiry *GetEnquiry(void);
|
||||
const unsigned short *GetCaSystemIds(int Slot);
|
||||
bool ProvidesCa(const unsigned short *CaSystemIds); //XXX Slot???
|
||||
bool SetCaPmt(cCiCaPmt &CaPmt, int Slot);
|
||||
bool Reset(int Slot);
|
||||
};
|
||||
|
8
config.h
8
config.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: config.h 1.176.1.6 2003/11/14 13:29:13 kls Exp $
|
||||
* $Id: config.h 1.178 2003/12/27 13:57:56 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
@ -19,8 +19,8 @@
|
||||
#include "device.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define VDRVERSION "1.2.6"
|
||||
#define VDRVERSNUM 10206 // Version * 10000 + Major * 100 + Minor
|
||||
#define VDRVERSION "1.3.0"
|
||||
#define VDRVERSNUM 10300 // Version * 10000 + Major * 100 + Minor
|
||||
|
||||
#define MAXPRIORITY 99
|
||||
#define MAXLIFETIME 99
|
||||
@ -87,7 +87,7 @@ public:
|
||||
cConfig(void) { fileName = NULL; }
|
||||
virtual ~cConfig() { free(fileName); }
|
||||
const char *FileName(void) { return fileName; }
|
||||
bool Load(const char *FileName = NULL, bool AllowComments = false, bool MustExist = false)
|
||||
virtual bool Load(const char *FileName = NULL, bool AllowComments = false, bool MustExist = false)
|
||||
{
|
||||
Clear();
|
||||
if (FileName) {
|
||||
|
6
cutter.c
6
cutter.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: cutter.c 1.5 2003/08/17 09:04:04 kls Exp $
|
||||
* $Id: cutter.c 1.6 2003/10/18 11:29:37 kls Exp $
|
||||
*/
|
||||
|
||||
#include "cutter.h"
|
||||
@ -32,6 +32,7 @@ public:
|
||||
};
|
||||
|
||||
cCuttingThread::cCuttingThread(const char *FromFileName, const char *ToFileName)
|
||||
:cThread("video cutting")
|
||||
{
|
||||
error = NULL;
|
||||
active = false;
|
||||
@ -62,8 +63,6 @@ cCuttingThread::~cCuttingThread()
|
||||
|
||||
void cCuttingThread::Action(void)
|
||||
{
|
||||
dsyslog("video cutting thread started (pid=%d)", getpid());
|
||||
|
||||
cMark *Mark = fromMarks.First();
|
||||
if (Mark) {
|
||||
fromFile = fromFileName->Open();
|
||||
@ -175,7 +174,6 @@ void cCuttingThread::Action(void)
|
||||
}
|
||||
else
|
||||
esyslog("no editing marks found!");
|
||||
dsyslog("end video cutting thread");
|
||||
}
|
||||
|
||||
// --- cCutter ---------------------------------------------------------------
|
||||
|
95
device.c
95
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 1.47.1.1 2003/11/07 13:16:12 kls Exp $
|
||||
* $Id: device.c 1.51 2004/01/04 11:30:05 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -13,7 +13,6 @@
|
||||
#include <sys/mman.h>
|
||||
#include "audio.h"
|
||||
#include "channels.h"
|
||||
#include "eit.h"
|
||||
#include "i18n.h"
|
||||
#include "player.h"
|
||||
#include "receiver.h"
|
||||
@ -36,6 +35,8 @@ cDevice::cDevice(void)
|
||||
{
|
||||
cardIndex = nextCardIndex++;
|
||||
|
||||
SetDescription("receiver on device %d", CardIndex() + 1);
|
||||
|
||||
SetVideoFormat(Setup.VideoFormat);
|
||||
|
||||
active = false;
|
||||
@ -43,6 +44,11 @@ cDevice::cDevice(void)
|
||||
mute = false;
|
||||
volume = Setup.CurrentVolume;
|
||||
|
||||
sectionHandler = NULL;
|
||||
eitFilter = NULL;
|
||||
patFilter = NULL;
|
||||
sdtFilter = NULL;
|
||||
|
||||
ciHandler = NULL;
|
||||
player = NULL;
|
||||
|
||||
@ -63,6 +69,10 @@ cDevice::~cDevice()
|
||||
for (int i = 0; i < MAXRECEIVERS; i++)
|
||||
Detach(receiver[i]);
|
||||
delete ciHandler;
|
||||
delete sdtFilter;
|
||||
delete patFilter;
|
||||
delete eitFilter;
|
||||
delete sectionHandler;
|
||||
}
|
||||
|
||||
void cDevice::SetUseDevice(int n)
|
||||
@ -149,7 +159,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDe
|
||||
if (device[i]->ProvidesChannel(Channel, Priority, &ndr)) { // this device is basicly able to do the job
|
||||
if (device[i]->Receiving() && !ndr)
|
||||
pri = 0; // receiving and allows additional receivers
|
||||
else if (d && !device[i]->Receiving() && device[i]->ProvidesCa(Channel->Ca()) < d->ProvidesCa(Channel->Ca()))
|
||||
else if (d && !device[i]->Receiving() && device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel))
|
||||
pri = 1; // free and fewer Ca's
|
||||
else if (!device[i]->Receiving() && !device[i]->IsPrimaryDevice())
|
||||
pri = 2; // free and not the primary device
|
||||
@ -157,7 +167,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool *NeedsDe
|
||||
pri = 3; // free
|
||||
else if (d && device[i]->Priority() < d->Priority())
|
||||
pri = 4; // receiving but priority is lower
|
||||
else if (d && device[i]->Priority() == d->Priority() && device[i]->ProvidesCa(Channel->Ca()) < d->ProvidesCa(Channel->Ca()))
|
||||
else if (d && device[i]->Priority() == d->Priority() && device[i]->ProvidesCa(Channel) < d->ProvidesCa(Channel))
|
||||
pri = 5; // receiving with same priority but fewer Ca's
|
||||
else
|
||||
pri = 6; // all others
|
||||
@ -311,11 +321,42 @@ bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
||||
return false;
|
||||
}
|
||||
|
||||
void cDevice::StartSectionHandler(void)
|
||||
{
|
||||
if (!sectionHandler) {
|
||||
sectionHandler = new cSectionHandler(this);
|
||||
AttachFilter(eitFilter = new cEitFilter);
|
||||
AttachFilter(patFilter = new cPatFilter);
|
||||
AttachFilter(sdtFilter = new cSdtFilter(patFilter));
|
||||
sectionHandler->SetStatus(true);
|
||||
}
|
||||
}
|
||||
|
||||
int cDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cDevice::AttachFilter(cFilter *Filter)
|
||||
{
|
||||
sectionHandler->Attach(Filter);
|
||||
}
|
||||
|
||||
void cDevice::Detach(cFilter *Filter)
|
||||
{
|
||||
sectionHandler->Detach(Filter);
|
||||
}
|
||||
|
||||
bool cDevice::ProvidesSource(int Source) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cDevice::ProvidesTransponder(const cChannel *Channel) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
||||
{
|
||||
return false;
|
||||
@ -398,16 +439,28 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
|
||||
Result = scrNotAvailable;
|
||||
}
|
||||
else {
|
||||
Channels.Lock(false);
|
||||
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel
|
||||
if (!SetChannelDevice(Channel, LiveView))
|
||||
// Stop section handling:
|
||||
if (sectionHandler) {
|
||||
sectionHandler->SetStatus(false);
|
||||
sectionHandler->SetSource(0, 0);
|
||||
}
|
||||
if (SetChannelDevice(Channel, LiveView)) {
|
||||
// Start section handling:
|
||||
if (sectionHandler) {
|
||||
sectionHandler->SetSource(Channel->Source(), Channel->Transponder());
|
||||
sectionHandler->SetStatus(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
Result = scrFailed;
|
||||
Channels.Unlock();
|
||||
}
|
||||
|
||||
if (Result == scrOk) {
|
||||
if (LiveView && IsPrimaryDevice()) {
|
||||
cSIProcessor::SetCurrentChannelID(Channel->GetChannelID());
|
||||
if (LiveView && IsPrimaryDevice())
|
||||
currentChannel = Channel->Number();
|
||||
}
|
||||
cStatus::MsgChannelSwitch(this, Channel->Number()); // only report status if channel switch successfull
|
||||
}
|
||||
|
||||
@ -419,6 +472,11 @@ bool cDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cDevice::HasLock(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDevice::HasProgramme(void)
|
||||
{
|
||||
return Replaying() || pidHandles[ptAudio].pid || pidHandles[ptVideo].pid;
|
||||
@ -608,6 +666,7 @@ int cDevice::Priority(void) const
|
||||
int cDevice::CanShift(int Ca, int Priority, int UsedCards) const
|
||||
{
|
||||
return -1;//XXX+ too complex with multiple recordings per device
|
||||
/*XXX
|
||||
// Test whether a receiver on this device can be shifted to another one
|
||||
// in order to perform a new receiving with the given Ca and Priority on this device:
|
||||
int ShiftLevel = -1; // default means this device can't be shifted
|
||||
@ -638,25 +697,17 @@ int cDevice::CanShift(int Ca, int Priority, int UsedCards) const
|
||||
else if (Priority > this->Priority())
|
||||
ShiftLevel = 0; // no shifting necessary, this device can do the job
|
||||
return ShiftLevel;
|
||||
XXX*/
|
||||
}
|
||||
|
||||
int cDevice::ProvidesCa(int Ca) const
|
||||
int cDevice::ProvidesCa(const cChannel *Channel) const
|
||||
{
|
||||
int Ca = Channel->Ca();
|
||||
if (Ca == CardIndex() + 1)
|
||||
return 1; // exactly _this_ card was requested
|
||||
if (Ca && Ca <= MAXDEVICES)
|
||||
return 0; // a specific card was requested, but not _this_ one
|
||||
int result = Ca ? 0 : 1; // by default every card can provide FTA
|
||||
int others = Ca ? 1 : 0;
|
||||
for (int i = 0; i < MAXCACAPS; i++) {
|
||||
if (caCaps[i]) {
|
||||
if (caCaps[i] == Ca)
|
||||
result = 1;
|
||||
else
|
||||
others++;
|
||||
}
|
||||
}
|
||||
return result ? result + others : 0;
|
||||
return !Ca; // by default every card can provide FTA
|
||||
}
|
||||
|
||||
bool cDevice::Receiving(bool CheckAny) const
|
||||
@ -670,8 +721,6 @@ bool cDevice::Receiving(bool CheckAny) const
|
||||
|
||||
void cDevice::Action(void)
|
||||
{
|
||||
dsyslog("receiver thread started on device %d (pid=%d)", CardIndex() + 1, getpid());
|
||||
|
||||
if (OpenDvr()) {
|
||||
active = true;
|
||||
for (; active;) {
|
||||
@ -694,8 +743,6 @@ void cDevice::Action(void)
|
||||
}
|
||||
CloseDvr();
|
||||
}
|
||||
|
||||
dsyslog("receiver thread ended on device %d (pid=%d)", CardIndex() + 1, getpid());
|
||||
}
|
||||
|
||||
bool cDevice::OpenDvr(void)
|
||||
|
37
device.h
37
device.h
@ -4,13 +4,18 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.h 1.35 2003/11/07 13:15:45 kls Exp $
|
||||
* $Id: device.h 1.37 2004/01/04 11:52:00 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
#define __DEVICE_H
|
||||
|
||||
#include "ci.h"
|
||||
#include "eit.h"
|
||||
#include "filter.h"
|
||||
#include "pat.h"
|
||||
#include "sdt.h"
|
||||
#include "sections.h"
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
@ -127,7 +132,8 @@ public:
|
||||
///< Returns the card index of this device (0 ... MAXDEVICES - 1).
|
||||
int DeviceNumber(void) const;
|
||||
///< Returns the number of this device (0 ... MAXDEVICES - 1).
|
||||
int ProvidesCa(int Ca) const;
|
||||
virtual int ProvidesCa(const cChannel *Channel) const;//XXX PLUGINS.html!!!
|
||||
//XXX describe changed functionality!!!
|
||||
///< Checks whether this device provides the given value in its
|
||||
///< caCaps. Returns 0 if the value is not provided, 1 if only this
|
||||
///< value is provided, and > 1 if this and other values are provided.
|
||||
@ -157,6 +163,8 @@ protected:
|
||||
public:
|
||||
virtual bool ProvidesSource(int Source) const;
|
||||
///< Returns true if this device can provide the given source.
|
||||
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
||||
///< XXX -> PLUGINS.html!
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||
///< Returns true if this device can provide the given channel.
|
||||
///< In case the device has cReceivers attached to it or it is the primary
|
||||
@ -188,6 +196,10 @@ protected:
|
||||
public:
|
||||
static int CurrentChannel(void) { return primaryDevice ? currentChannel : 0; }
|
||||
///< Returns the number of the current channel on the primary device.
|
||||
virtual bool HasLock(void);//XXX PLUGINS.html
|
||||
///< Returns true if the device has a lock on the requested transponder.
|
||||
///< Default is true, a specific device implementation may return false
|
||||
///< to indicate that it is not ready yet.
|
||||
virtual bool HasProgramme(void);
|
||||
///< Returns true if the device is currently showing any programme to
|
||||
///< the user, either through replaying or live.
|
||||
@ -222,6 +234,27 @@ protected:
|
||||
///< Type indicates some special types of PIDs, which the device may
|
||||
///< need to set in a specific way.
|
||||
|
||||
// Section filter facilities
|
||||
|
||||
private:
|
||||
cSectionHandler *sectionHandler;
|
||||
cEitFilter *eitFilter;
|
||||
cPatFilter *patFilter;
|
||||
cSdtFilter *sdtFilter;
|
||||
protected:
|
||||
void StartSectionHandler(void);
|
||||
///< A derived device that provides section data must call
|
||||
///< this function to actually set up the section handler.
|
||||
public:
|
||||
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
|
||||
///< Opens a file handle for the given filter data.
|
||||
///< A derived device that provides section data must
|
||||
///< implement this function.
|
||||
void AttachFilter(cFilter *Filter);
|
||||
///< Attaches the given filter to this device.
|
||||
void Detach(cFilter *Filter);
|
||||
///< Detaches the given filter from this device.
|
||||
|
||||
// Common Interface facilities:
|
||||
|
||||
protected:
|
||||
|
140
dvbdevice.c
140
dvbdevice.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 1.67.1.4 2003/11/09 11:08:22 kls Exp $
|
||||
* $Id: dvbdevice.c 1.76 2004/01/04 14:48:37 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -86,7 +86,7 @@ public:
|
||||
virtual ~cDvbTuner();
|
||||
bool IsTunedTo(const cChannel *Channel) const;
|
||||
void Set(const cChannel *Channel, bool Tune, bool UseCa);
|
||||
bool Locked(void) { return tunerStatus == tsLocked; }
|
||||
bool Locked(void) { return tunerStatus >= tsLocked; }
|
||||
};
|
||||
|
||||
cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCiHandler *CiHandler)
|
||||
@ -100,6 +100,7 @@ cDvbTuner::cDvbTuner(int Fd_Frontend, int CardIndex, fe_type_t FrontendType, cCi
|
||||
useCa = false;
|
||||
tunerStatus = tsIdle;
|
||||
startTime = time(NULL);
|
||||
SetDescription("tuner on device %d", cardIndex + 1);
|
||||
Start();
|
||||
}
|
||||
|
||||
@ -113,19 +114,18 @@ cDvbTuner::~cDvbTuner()
|
||||
|
||||
bool cDvbTuner::IsTunedTo(const cChannel *Channel) const
|
||||
{
|
||||
return tunerStatus != tsIdle && channel.Source() == Channel->Source() && channel.Frequency() == Channel->Frequency();
|
||||
return tunerStatus != tsIdle && channel.Source() == Channel->Source() && channel.Transponder() == Channel->Transponder();
|
||||
}
|
||||
|
||||
void cDvbTuner::Set(const cChannel *Channel, bool Tune, bool UseCa)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
bool CaChange = !(Channel->GetChannelID() == channel.GetChannelID());
|
||||
if (Tune)
|
||||
tunerStatus = tsSet;
|
||||
else if (tunerStatus == tsCam && CaChange)
|
||||
else if (tunerStatus == tsCam)
|
||||
tunerStatus = tsTuned;
|
||||
useCa = UseCa;
|
||||
if (Channel->Ca() && CaChange)
|
||||
if (Channel->Ca() && tunerStatus != tsCam)
|
||||
startTime = time(NULL);
|
||||
channel = *Channel;
|
||||
newSet.Broadcast();
|
||||
@ -247,7 +247,6 @@ bool cDvbTuner::SetFrontend(void)
|
||||
|
||||
void cDvbTuner::Action(void)
|
||||
{
|
||||
dsyslog("tuner thread started on device %d (pid=%d)", cardIndex + 1, getpid());
|
||||
active = true;
|
||||
while (active) {
|
||||
cMutexLock MutexLock(&mutex);
|
||||
@ -268,41 +267,31 @@ void cDvbTuner::Action(void)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (tunerStatus >= tsLocked) {
|
||||
if (ciHandler) {
|
||||
if (ciHandler->Process() && useCa) {
|
||||
if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed
|
||||
for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) {
|
||||
uchar buffer[2048];
|
||||
int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer);
|
||||
if (length > 0) {
|
||||
cCiCaPmt CaPmt(channel.Sid());
|
||||
CaPmt.AddCaDescriptor(length, buffer);
|
||||
if (channel.Vpid())
|
||||
CaPmt.AddPid(channel.Vpid());
|
||||
if (channel.Apid1())
|
||||
CaPmt.AddPid(channel.Apid1());
|
||||
if (channel.Apid2())
|
||||
CaPmt.AddPid(channel.Apid2());
|
||||
if (channel.Dpid1())
|
||||
CaPmt.AddPid(channel.Dpid1());
|
||||
if (ciHandler->SetCaPmt(CaPmt, Slot)) {
|
||||
tunerStatus = tsCam;
|
||||
startTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ciHandler) {
|
||||
if (ciHandler->Process() && useCa) {
|
||||
if (tunerStatus == tsLocked) {
|
||||
for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) {
|
||||
cCiCaPmt CaPmt(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot));
|
||||
if (CaPmt.Valid()) {
|
||||
CaPmt.AddPid(channel.Vpid(), 2);
|
||||
CaPmt.AddPid(channel.Apid1(), 4);
|
||||
CaPmt.AddPid(channel.Apid2(), 4);
|
||||
CaPmt.AddPid(channel.Dpid1(), 0);
|
||||
if (ciHandler->SetCaPmt(CaPmt, Slot)) {
|
||||
tunerStatus = tsCam;
|
||||
startTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
tunerStatus = tsLocked;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tunerStatus > tsLocked)
|
||||
tunerStatus = tsLocked;
|
||||
}
|
||||
// in the beginning we loop more often to let the CAM connection start up fast
|
||||
newSet.TimedWait(mutex, (ciHandler && (time(NULL) - startTime < 20)) ? 100 : 1000);
|
||||
}
|
||||
dsyslog("tuner thread ended on device %d (pid=%d)", cardIndex + 1, getpid());
|
||||
}
|
||||
|
||||
// --- cDvbDevice ------------------------------------------------------------
|
||||
@ -313,13 +302,12 @@ cDvbDevice::cDvbDevice(int n)
|
||||
{
|
||||
dvbTuner = NULL;
|
||||
frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
|
||||
siProcessor = NULL;
|
||||
spuDecoder = NULL;
|
||||
playMode = pmNone;
|
||||
|
||||
// Devices that are present on all card types:
|
||||
|
||||
int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
|
||||
int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK);
|
||||
|
||||
// Devices that are only present on cards with decoders:
|
||||
|
||||
@ -369,7 +357,6 @@ cDvbDevice::cDvbDevice(int n)
|
||||
|
||||
if (fd_frontend >= 0) {
|
||||
dvb_frontend_info feinfo;
|
||||
siProcessor = new cSIProcessor(DvbName(DEV_DVB_DEMUX, n));
|
||||
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
|
||||
frontendType = feinfo.type;
|
||||
ciHandler = cCiHandler::CreateCiHandler(DvbName(DEV_DVB_CA, n));
|
||||
@ -382,12 +369,13 @@ cDvbDevice::cDvbDevice(int n)
|
||||
esyslog("ERROR: can't open DVB device %d", n);
|
||||
|
||||
aPid1 = aPid2 = 0;
|
||||
|
||||
StartSectionHandler();
|
||||
}
|
||||
|
||||
cDvbDevice::~cDvbDevice()
|
||||
{
|
||||
delete spuDecoder;
|
||||
delete siProcessor;
|
||||
delete dvbTuner;
|
||||
// We're not explicitly closing any device files here, since this sometimes
|
||||
// caused segfaults. Besides, the program is about to terminate anyway...
|
||||
@ -445,6 +433,17 @@ bool cDvbDevice::HasDecoder(void) const
|
||||
return fd_video >= 0 && fd_audio >= 0;
|
||||
}
|
||||
|
||||
int cDvbDevice::ProvidesCa(const cChannel *Channel) const
|
||||
{
|
||||
if (Channel->Ca() >= 0x0100 && ciHandler) {
|
||||
unsigned short ids[MAXCAIDS + 1];
|
||||
for (int i = 0; i <= MAXCAIDS; i++) // '<=' copies the terminating 0!
|
||||
ids[i] = Channel->Ca(i);
|
||||
return ciHandler->ProvidesCa(ids);
|
||||
}
|
||||
return cDevice::ProvidesCa(Channel);
|
||||
}
|
||||
|
||||
cOsdBase *cDvbDevice::NewOsd(int x, int y)
|
||||
{
|
||||
return new cDvbOsd(x, y);
|
||||
@ -618,6 +617,30 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
|
||||
return true;
|
||||
}
|
||||
|
||||
int cDvbDevice::OpenFilter(u_short Pid, u_char Tid, u_char Mask)
|
||||
{
|
||||
const char *FileName = DvbName(DEV_DVB_DEMUX, CardIndex());
|
||||
int f = open(FileName, O_RDWR | O_NONBLOCK);
|
||||
if (f >= 0) {
|
||||
dmx_sct_filter_params sctFilterParams;
|
||||
memset(&sctFilterParams, 0, sizeof(sctFilterParams));
|
||||
sctFilterParams.pid = Pid;
|
||||
sctFilterParams.timeout = 0;
|
||||
sctFilterParams.flags = DMX_IMMEDIATE_START;
|
||||
sctFilterParams.filter.filter[0] = Tid;
|
||||
sctFilterParams.filter.mask[0] = Mask;
|
||||
if (ioctl(f, DMX_SET_FILTER, &sctFilterParams) >= 0)
|
||||
return f;
|
||||
else {
|
||||
esyslog("ERROR: can't set filter (pid=%d, tid=%02X, mask=%02X)", Pid, Tid, Mask);
|
||||
close(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
esyslog("ERROR: can't open filter handle on '%s'", FileName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void cDvbDevice::TurnOffLiveMode(void)
|
||||
{
|
||||
// Avoid noise while switching:
|
||||
@ -646,13 +669,18 @@ bool cDvbDevice::ProvidesSource(int Source) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDvbDevice::ProvidesTransponder(const cChannel *Channel) const
|
||||
{
|
||||
return ProvidesSource(Channel->Source()) && ((Channel->Source() & cSource::st_Mask) != cSource::stSat || Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()));
|
||||
}
|
||||
|
||||
bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const
|
||||
{
|
||||
bool result = false;
|
||||
bool hasPriority = Priority < 0 || Priority > this->Priority();
|
||||
bool needsDetachReceivers = false;
|
||||
|
||||
if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel->Ca())) {
|
||||
if ((Channel->Vpid() || Channel->Apid1()) && ProvidesSource(Channel->Source()) && ProvidesCa(Channel)) {
|
||||
result = hasPriority;
|
||||
if (Priority >= 0 && Receiving()) {
|
||||
if (dvbTuner->IsTunedTo(Channel)) {
|
||||
@ -716,27 +744,19 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
TurnOnLivePIDs = false;
|
||||
}
|
||||
|
||||
// Stop SI filtering:
|
||||
|
||||
if (siProcessor) {
|
||||
siProcessor->SetCurrentTransponder(0, 0);
|
||||
siProcessor->SetStatus(false);
|
||||
}
|
||||
|
||||
// Turn off live PIDs if necessary:
|
||||
|
||||
if (TurnOffLivePIDs)
|
||||
TurnOffLiveMode();
|
||||
|
||||
dvbTuner->Set(Channel, DoTune, !EITScanner.UsesDevice(this)); //XXX 1.3: this is an ugly hack - find a cleaner solution
|
||||
dvbTuner->Set(Channel, DoTune, !EITScanner.UsesDevice(this)); //XXX 1.3: this is an ugly hack - find a cleaner solution//XXX
|
||||
|
||||
// PID settings:
|
||||
|
||||
if (TurnOnLivePIDs) {
|
||||
aPid1 = Channel->Apid1();
|
||||
aPid2 = Channel->Apid2();
|
||||
int pPid = Channel->Ppid() ? Channel->Ppid() : Channel->Vpid();
|
||||
if (!(AddPid(pPid, ptPcr) && AddPid(Channel->Apid1(), ptAudio) && AddPid(Channel->Vpid(), ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached)
|
||||
if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(Channel->Apid1(), ptAudio) && AddPid(Channel->Vpid(), ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached)
|
||||
esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
|
||||
return false;
|
||||
}
|
||||
@ -747,16 +767,14 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
else if (StartTransferMode)
|
||||
cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2()));
|
||||
|
||||
// Start SI filtering:
|
||||
|
||||
if (siProcessor) {
|
||||
siProcessor->SetCurrentTransponder(Channel->Source(), Channel->Frequency());
|
||||
siProcessor->SetStatus(true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cDvbDevice::HasLock(void)
|
||||
{
|
||||
return dvbTuner->Locked();
|
||||
}
|
||||
|
||||
void cDvbDevice::SetVolumeDevice(int Volume)
|
||||
{
|
||||
if (HasDecoder()) {
|
||||
@ -830,16 +848,12 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
|
||||
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
|
||||
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
|
||||
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
|
||||
if (siProcessor)
|
||||
siProcessor->SetStatus(true);
|
||||
break;
|
||||
case pmAudioVideo:
|
||||
if (playMode == pmNone)
|
||||
TurnOffLiveMode();
|
||||
// continue with next...
|
||||
case pmAudioOnlyBlack:
|
||||
if (siProcessor)
|
||||
siProcessor->SetStatus(false);
|
||||
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
|
||||
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
|
||||
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo));
|
||||
@ -848,8 +862,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
|
||||
CHECK(ioctl(fd_video, VIDEO_PLAY));
|
||||
break;
|
||||
case pmAudioOnly:
|
||||
if (siProcessor)
|
||||
siProcessor->SetStatus(false);
|
||||
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
|
||||
CHECK(ioctl(fd_audio, AUDIO_STOP, true));
|
||||
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
|
||||
@ -859,8 +871,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
|
||||
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false));
|
||||
break;
|
||||
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
||||
if (siProcessor)
|
||||
siProcessor->SetStatus(false);
|
||||
close(fd_video);
|
||||
close(fd_audio);
|
||||
fd_video = fd_audio = -1;
|
||||
|
17
dvbdevice.h
17
dvbdevice.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.h 1.24 2003/11/07 13:17:13 kls Exp $
|
||||
* $Id: dvbdevice.h 1.26 2004/01/03 10:21:50 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBDEVICE_H
|
||||
@ -14,7 +14,6 @@
|
||||
#include <linux/dvb/version.h>
|
||||
#include "device.h"
|
||||
#include "dvbspu.h"
|
||||
#include "eit.h"
|
||||
|
||||
#if DVB_API_VERSION != 3
|
||||
#error VDR requires Linux DVB driver API version 3!
|
||||
@ -45,6 +44,7 @@ protected:
|
||||
public:
|
||||
cDvbDevice(int n);
|
||||
virtual ~cDvbDevice();
|
||||
virtual int ProvidesCa(const cChannel *Channel) const;
|
||||
virtual bool HasDecoder(void) const;
|
||||
|
||||
// OSD facilities
|
||||
@ -62,15 +62,23 @@ private:
|
||||
void TurnOffLiveMode(void);
|
||||
public:
|
||||
virtual bool ProvidesSource(int Source) const;
|
||||
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||
protected:
|
||||
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
|
||||
public:
|
||||
virtual bool HasLock(void);
|
||||
|
||||
// PID handle facilities
|
||||
|
||||
protected:
|
||||
virtual bool SetPid(cPidHandle *Handle, int Type, bool On);
|
||||
|
||||
// Section filter facilities
|
||||
|
||||
protected:
|
||||
virtual int OpenFilter(u_short Pid, u_char Tid, u_char Mask);
|
||||
|
||||
// Image Grab facilities
|
||||
|
||||
private:
|
||||
@ -95,11 +103,6 @@ protected:
|
||||
virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const;
|
||||
virtual void SetAudioTrackDevice(int Index);
|
||||
|
||||
// EIT facilities
|
||||
|
||||
private:
|
||||
cSIProcessor *siProcessor;
|
||||
|
||||
// Player facilities
|
||||
|
||||
protected:
|
||||
|
10
dvbplayer.c
10
dvbplayer.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbplayer.c 1.22 2003/05/24 09:04:26 kls Exp $
|
||||
* $Id: dvbplayer.c 1.23 2003/10/18 11:31:54 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbplayer.h"
|
||||
@ -93,6 +93,7 @@ public:
|
||||
};
|
||||
|
||||
cNonBlockingFileReader::cNonBlockingFileReader(void)
|
||||
:cThread("non blocking file reader")
|
||||
{
|
||||
f = -1;
|
||||
buffer = NULL;
|
||||
@ -146,7 +147,6 @@ int cNonBlockingFileReader::Read(int FileHandle, uchar *Buffer, int Length)
|
||||
|
||||
void cNonBlockingFileReader::Action(void)
|
||||
{
|
||||
dsyslog("non blocking file reader thread started (pid=%d)", getpid());
|
||||
active = true;
|
||||
while (active) {
|
||||
cMutexLock MutexLock(&mutex);
|
||||
@ -165,7 +165,6 @@ void cNonBlockingFileReader::Action(void)
|
||||
}
|
||||
newSet.TimedWait(mutex, 1000);
|
||||
}
|
||||
dsyslog("non blocking file reader thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
// --- cDvbPlayer ------------------------------------------------------------
|
||||
@ -235,6 +234,7 @@ public:
|
||||
int cDvbPlayer::Speeds[] = { 0, -2, -4, -8, 1, 2, 4, 12, 0 };
|
||||
|
||||
cDvbPlayer::cDvbPlayer(const char *FileName)
|
||||
:cThread("dvbplayer")
|
||||
{
|
||||
nonBlockingFileReader = NULL;
|
||||
ringBuffer = NULL;
|
||||
@ -405,8 +405,6 @@ void cDvbPlayer::Activate(bool On)
|
||||
|
||||
void cDvbPlayer::Action(void)
|
||||
{
|
||||
dsyslog("dvbplayer thread started (pid=%d)", getpid());
|
||||
|
||||
uchar *b = NULL;
|
||||
uchar *p = NULL;
|
||||
int pc = 0;
|
||||
@ -550,8 +548,6 @@ void cDvbPlayer::Action(void)
|
||||
cNonBlockingFileReader *nbfr = nonBlockingFileReader;
|
||||
nonBlockingFileReader = NULL;
|
||||
delete nbfr;
|
||||
|
||||
dsyslog("dvbplayer thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
void cDvbPlayer::Pause(void)
|
||||
|
190
eit.h
190
eit.h
@ -1,186 +1,22 @@
|
||||
/***************************************************************************
|
||||
eit.h - description
|
||||
-------------------
|
||||
begin : Fri Aug 25 2000
|
||||
copyright : (C) 2000 by Robert Schneider
|
||||
email : Robert.Schneider@web.de
|
||||
|
||||
2001-08-15: Adapted to 'libdtv' by Rolf Hakenes <hakenes@hippomi.de>
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: eit.h 1.29 2003/05/17 09:15:56 kls Exp $
|
||||
***************************************************************************/
|
||||
/*
|
||||
* eit.h: EIT section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eit.h 1.30 2003/12/21 14:51:50 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EIT_H
|
||||
#define __EIT_H
|
||||
|
||||
#include "channels.h"
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
#include "filter.h"
|
||||
|
||||
#define MAXEPGBUGFIXLEVEL 2
|
||||
|
||||
class cEventInfo : public cListObject {
|
||||
friend class cSchedule;
|
||||
friend class cEIT;
|
||||
private:
|
||||
unsigned char uTableID; // Table ID this event came from
|
||||
tChannelID channelID; // Channel ID of program for that event
|
||||
bool bIsFollowing; // true if this is the next event on this channel
|
||||
bool bIsPresent; // true if this is the present event running
|
||||
char *pExtendedDescription; // Extended description of this event
|
||||
char *pSubtitle; // Subtitle of event
|
||||
char *pTitle; // Title of event
|
||||
unsigned short uEventID; // Event ID of this event
|
||||
long lDuration; // duration of event in seconds
|
||||
time_t tTime; // Start time
|
||||
int nChannelNumber; // the actual channel number from VDR's channel list (used in cMenuSchedule for sorting by channel number)
|
||||
class cEitFilter : public cFilter {
|
||||
protected:
|
||||
void SetTableID(unsigned char tableid);
|
||||
void SetFollowing(bool foll);
|
||||
void SetPresent(bool pres);
|
||||
void SetTitle(const char *string);
|
||||
void SetChannelID(tChannelID channelid);
|
||||
void SetEventID(unsigned short evid);
|
||||
void SetDuration(long l);
|
||||
void SetTime(time_t t);
|
||||
void SetExtendedDescription(const char *string);
|
||||
void SetSubtitle(const char *string);
|
||||
cEventInfo(tChannelID channelid, unsigned short eventid);
|
||||
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
|
||||
public:
|
||||
~cEventInfo();
|
||||
const unsigned char GetTableID(void) const;
|
||||
const char *GetTimeString(void) const;
|
||||
const char *GetEndTimeString(void) const;
|
||||
const char *GetDate(void) const;
|
||||
bool IsFollowing(void) const;
|
||||
bool IsPresent(void) const;
|
||||
const char *GetExtendedDescription(void) const;
|
||||
const char *GetSubtitle(void) const;
|
||||
const char *GetTitle(void) const;
|
||||
unsigned short GetEventID(void) const;
|
||||
long GetDuration(void) const;
|
||||
time_t GetTime(void) const;
|
||||
tChannelID GetChannelID(void) const;
|
||||
int GetChannelNumber(void) const { return nChannelNumber; }
|
||||
void SetChannelNumber(int ChannelNumber) const { ((cEventInfo *)this)->nChannelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const'
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
static bool Read(FILE *f, cSchedule *Schedule);
|
||||
void FixEpgBugs(void);
|
||||
cEitFilter(void);
|
||||
};
|
||||
|
||||
class cSchedule : public cListObject {
|
||||
friend class cSchedules;
|
||||
friend class cEIT;
|
||||
private:
|
||||
cEventInfo *pPresent;
|
||||
cEventInfo *pFollowing;
|
||||
tChannelID channelID;
|
||||
cList<cEventInfo> Events;
|
||||
protected:
|
||||
void SetChannelID(tChannelID channelid);
|
||||
bool SetFollowingEvent(cEventInfo *pEvent);
|
||||
bool SetPresentEvent(cEventInfo *pEvent);
|
||||
void Cleanup(time_t tTime);
|
||||
void Cleanup(void);
|
||||
cSchedule(tChannelID channelid = tChannelID::InvalidID);
|
||||
public:
|
||||
~cSchedule();
|
||||
cEventInfo *AddEvent(cEventInfo *EventInfo);
|
||||
const cEventInfo *GetPresentEvent(void) const;
|
||||
const cEventInfo *GetFollowingEvent(void) const;
|
||||
tChannelID GetChannelID(void) const;
|
||||
const cEventInfo *GetEvent(unsigned short uEventID, time_t tTime = 0) const;
|
||||
const cEventInfo *GetEventAround(time_t tTime) const;
|
||||
const cEventInfo *GetEventNumber(int n) const { return Events.Get(n); }
|
||||
int NumEvents(void) const { return Events.Count(); }
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
static bool Read(FILE *f, cSchedules *Schedules);
|
||||
};
|
||||
|
||||
class cSchedules : public cList<cSchedule> {
|
||||
friend class cSchedule;
|
||||
friend class cSIProcessor;
|
||||
private:
|
||||
const cSchedule *pCurrentSchedule;
|
||||
tChannelID currentChannelID;
|
||||
protected:
|
||||
const cSchedule *AddChannelID(tChannelID channelid);
|
||||
const cSchedule *SetCurrentChannelID(tChannelID channelid);
|
||||
void Cleanup();
|
||||
public:
|
||||
cSchedules(void);
|
||||
~cSchedules();
|
||||
const cSchedule *GetSchedule(tChannelID channelid) const;
|
||||
const cSchedule *GetSchedule(void) const;
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
static bool Read(FILE *f);
|
||||
};
|
||||
|
||||
typedef struct sip_filter {
|
||||
|
||||
unsigned short pid;
|
||||
u_char tid;
|
||||
int handle;
|
||||
bool inuse;
|
||||
|
||||
}SIP_FILTER;
|
||||
|
||||
class cCaDescriptor;
|
||||
|
||||
class cSIProcessor : public cThread {
|
||||
private:
|
||||
static int numSIProcessors;
|
||||
static cSchedules *schedules;
|
||||
static cMutex schedulesMutex;
|
||||
static cList<cCaDescriptor> caDescriptors;
|
||||
static cMutex caDescriptorsMutex;
|
||||
static const char *epgDataFileName;
|
||||
static time_t lastDump;
|
||||
bool masterSIProcessor;
|
||||
int currentSource;
|
||||
int currentTransponder;
|
||||
int statusCount;
|
||||
int pmtIndex;
|
||||
int pmtPid;
|
||||
SIP_FILTER *filters;
|
||||
char *fileName;
|
||||
bool active;
|
||||
void Action(void);
|
||||
bool AddFilter(unsigned short pid, u_char tid, u_char mask = 0xFF);
|
||||
bool DelFilter(unsigned short pid, u_char tid);
|
||||
bool ShutDownFilters(void);
|
||||
void NewCaDescriptor(struct Descriptor *d, int ServiceId);
|
||||
public:
|
||||
cSIProcessor(const char *FileName);
|
||||
~cSIProcessor();
|
||||
static void SetEpgDataFileName(const char *FileName);
|
||||
static const char *GetEpgDataFileName(void);
|
||||
static const cSchedules *Schedules(cMutexLock &MutexLock);
|
||||
// Caller must provide a cMutexLock which has to survive the entire
|
||||
// time the returned cSchedules is accessed. Once the cSchedules is no
|
||||
// longer used, the cMutexLock must be destroyed.
|
||||
static int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data);
|
||||
///< Gets all CA descriptors for a given channel.
|
||||
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
|
||||
///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
|
||||
///< are copied that match one of the given CA system IDs.
|
||||
///< \return Returns the number of bytes copied into Data (0 if no CA descriptors are
|
||||
///< available), or -1 if BufSize was too small to hold all CA descriptors.
|
||||
static bool Read(FILE *f = NULL);
|
||||
static void Clear(void);
|
||||
void SetStatus(bool On);
|
||||
void SetCurrentTransponder(int CurrentSource, int CurrentTransponder);
|
||||
static bool SetCurrentChannelID(tChannelID channelid);
|
||||
static void TriggerDump(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif //__EIT_H
|
||||
|
144
eitscan.c
144
eitscan.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eitscan.c 1.14 2003/09/06 13:06:13 kls Exp $
|
||||
* $Id: eitscan.c 1.15 2004/01/04 14:54:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "eitscan.h"
|
||||
@ -12,6 +12,68 @@
|
||||
#include "channels.h"
|
||||
#include "dvbdevice.h"
|
||||
|
||||
// --- cScanData -------------------------------------------------------------
|
||||
|
||||
class cScanData : public cListObject {
|
||||
private:
|
||||
int source;
|
||||
int transponder;
|
||||
public:
|
||||
cScanData(int Source, int Transponder);
|
||||
virtual bool operator< (const cListObject &ListObject);
|
||||
int Source(void) { return source; }
|
||||
int Transponder(void) { return transponder; }
|
||||
cChannel *GetChannel(void);
|
||||
};
|
||||
|
||||
cScanData::cScanData(int Source, int Transponder)
|
||||
{
|
||||
source = Source;
|
||||
transponder = Transponder;
|
||||
}
|
||||
|
||||
bool cScanData::operator< (const cListObject &ListObject)
|
||||
{
|
||||
cScanData *sd = (cScanData *)&ListObject;
|
||||
return source < sd->source || source == sd->source && transponder < sd->transponder;
|
||||
}
|
||||
|
||||
//XXX this might be done differently later...
|
||||
cChannel *cScanData::GetChannel(void)
|
||||
{
|
||||
for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
|
||||
if (!Channel->GroupSep() && Channel->Source() == source && ISTRANSPONDER(Channel->Transponder(), transponder))
|
||||
return Channel;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- cScanList -------------------------------------------------------------
|
||||
|
||||
class cScanList : public cList<cScanData> {
|
||||
public:
|
||||
cScanList(void);
|
||||
void AddTransponder(const cChannel *Channel);
|
||||
};
|
||||
|
||||
cScanList::cScanList(void)
|
||||
{
|
||||
for (cChannel *ch = Channels.First(); ch; ch = Channels.Next(ch))
|
||||
AddTransponder(ch);
|
||||
Sort();
|
||||
}
|
||||
|
||||
void cScanList::AddTransponder(const cChannel *Channel)
|
||||
{
|
||||
for (cScanData *sd = First(); sd; sd = Next(sd)) {
|
||||
if (sd->Source() == Channel->Source() && sd->Transponder() == Channel->Transponder())
|
||||
return;
|
||||
}
|
||||
Add(new cScanData(Channel->Source(), Channel->Transponder()));
|
||||
}
|
||||
|
||||
// --- cEITScanner -----------------------------------------------------------
|
||||
|
||||
cEITScanner EITScanner;
|
||||
|
||||
cEITScanner::cEITScanner(void)
|
||||
@ -20,24 +82,12 @@ cEITScanner::cEITScanner(void)
|
||||
currentDevice = NULL;
|
||||
currentChannel = 0;
|
||||
memset(lastChannel, 0, sizeof(lastChannel));
|
||||
numTransponders = 0;
|
||||
transponders = NULL;
|
||||
scanList = NULL;
|
||||
}
|
||||
|
||||
cEITScanner::~cEITScanner()
|
||||
{
|
||||
free(transponders);
|
||||
}
|
||||
|
||||
bool cEITScanner::TransponderScanned(cChannel *Channel)
|
||||
{
|
||||
for (int i = 0; i < numTransponders; i++) {
|
||||
if (transponders[i] == Channel->Frequency())
|
||||
return true;
|
||||
}
|
||||
transponders = (int *)realloc(transponders, ++numTransponders * sizeof(int));
|
||||
transponders[numTransponders - 1] = Channel->Frequency();
|
||||
return false;
|
||||
delete scanList;
|
||||
}
|
||||
|
||||
void cEITScanner::Activity(void)
|
||||
@ -54,37 +104,51 @@ void cEITScanner::Process(void)
|
||||
if (Setup.EPGScanTimeout && Channels.MaxNumber() > 1) {
|
||||
time_t now = time(NULL);
|
||||
if (now - lastScan > ScanTimeout && now - lastActivity > ActivityTimeout) {
|
||||
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
||||
cDevice *Device = cDevice::GetDevice(i);
|
||||
if (Device && Device->CardIndex() < MAXDVBDEVICES) {
|
||||
if (Device != cDevice::PrimaryDevice() || (cDevice::NumDevices() == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) {
|
||||
if (!(Device->Receiving(true) || Device->Replaying())) {
|
||||
for (;;) {
|
||||
cChannel *Channel = Channels.GetByNumber(lastChannel[Device->DeviceNumber()] + 1, 1);
|
||||
if (Channel) {
|
||||
lastChannel[Device->DeviceNumber()] = Channel->Number();
|
||||
if (Channel->Sid() && Device->ProvidesChannel(Channel) && !TransponderScanned(Channel)) {
|
||||
if (Device == cDevice::PrimaryDevice() && !currentChannel) {
|
||||
currentChannel = Device->CurrentChannel();
|
||||
if (Channels.Lock(false, 10)) {
|
||||
if (!scanList)
|
||||
scanList = new cScanList();
|
||||
for (bool AnyDeviceSwitched = false; !AnyDeviceSwitched; ) {
|
||||
cScanData *ScanData = NULL;
|
||||
for (int i = 0; i < cDevice::NumDevices(); i++) {
|
||||
cDevice *Device = cDevice::GetDevice(i);
|
||||
if (Device) {
|
||||
if (Device != cDevice::PrimaryDevice() || (cDevice::NumDevices() == 1 && Setup.EPGScanTimeout && now - lastActivity > Setup.EPGScanTimeout * 3600)) {
|
||||
if (!(Device->Receiving(true) || Device->Replaying())) {
|
||||
if (!ScanData)
|
||||
ScanData = scanList->First();
|
||||
if (ScanData) {
|
||||
cChannel *Channel = ScanData->GetChannel();
|
||||
//XXX if (Device->ProvidesTransponder(Channel)) {
|
||||
if ((!Channel->Ca() || Channel->Ca() == Device->DeviceNumber() + 1 || Channel->Ca() >= 0x0100) && Device->ProvidesTransponder(Channel)) { //XXX temporary for the 'sky' plugin
|
||||
if (Device == cDevice::PrimaryDevice() && !currentChannel)
|
||||
currentChannel = Device->CurrentChannel();
|
||||
currentDevice = Device;//XXX see also dvbdevice.c!!!
|
||||
Device->SwitchChannel(Channel, false);
|
||||
currentDevice = NULL;
|
||||
scanList->Del(ScanData);
|
||||
ScanData = NULL;
|
||||
AnyDeviceSwitched = true;
|
||||
}
|
||||
currentDevice = Device;
|
||||
Device->SwitchChannel(Channel, false);
|
||||
currentDevice = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (lastChannel[Device->DeviceNumber()])
|
||||
numTransponders = 0;
|
||||
lastChannel[Device->DeviceNumber()] = 0;
|
||||
break;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ScanData && !AnyDeviceSwitched) {
|
||||
scanList->Del(ScanData);
|
||||
ScanData = NULL;
|
||||
}
|
||||
if (!scanList->Count()) {
|
||||
delete scanList;
|
||||
scanList = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lastScan = time(NULL);
|
||||
Channels.Unlock();
|
||||
lastScan = time(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: eitscan.h 1.4 2003/09/06 13:05:51 kls Exp $
|
||||
* $Id: eitscan.h 1.5 2004/01/03 13:08:39 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EITSCAN_H
|
||||
@ -13,6 +13,8 @@
|
||||
#include <time.h>
|
||||
#include "config.h"
|
||||
|
||||
class cScanList;
|
||||
|
||||
class cEITScanner {
|
||||
private:
|
||||
enum { ActivityTimeout = 60,
|
||||
@ -22,8 +24,7 @@ private:
|
||||
cDevice *currentDevice;
|
||||
int currentChannel;
|
||||
int lastChannel[MAXDEVICES];
|
||||
int numTransponders, *transponders;
|
||||
bool TransponderScanned(cChannel *Channel);
|
||||
cScanList *scanList;
|
||||
public:
|
||||
cEITScanner(void);
|
||||
~cEITScanner();
|
||||
|
684
epg.c
Normal file
684
epg.c
Normal file
@ -0,0 +1,684 @@
|
||||
/*
|
||||
* epg.c: Electronic Program Guide
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* Original version (as used in VDR before 1.3.0) written by
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
*
|
||||
* $Id: epg.c 1.3 2004/01/04 14:07:46 kls Exp $
|
||||
*/
|
||||
|
||||
#include "epg.h"
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
// --- cEvent ----------------------------------------------------------------
|
||||
|
||||
cEvent::cEvent(tChannelID ChannelID, u_int16_t EventID)
|
||||
{
|
||||
channelID = ChannelID;
|
||||
eventID = EventID;
|
||||
tableID = 0;
|
||||
version = 0xFF; // actual version numbers are 0..31
|
||||
isPresent = isFollowing = false;
|
||||
title = NULL;
|
||||
shortText = NULL;
|
||||
description = NULL;
|
||||
startTime = 0;
|
||||
duration = 0;
|
||||
channelNumber = 0;
|
||||
}
|
||||
|
||||
cEvent::~cEvent()
|
||||
{
|
||||
free(title);
|
||||
free(shortText);
|
||||
free(description);
|
||||
}
|
||||
|
||||
void cEvent::SetEventID(u_int16_t EventID)
|
||||
{
|
||||
eventID = EventID;
|
||||
}
|
||||
|
||||
void cEvent::SetTableID(uchar TableID)
|
||||
{
|
||||
tableID = TableID;
|
||||
}
|
||||
|
||||
void cEvent::SetVersion(uchar Version)
|
||||
{
|
||||
version = Version;
|
||||
}
|
||||
|
||||
void cEvent::SetIsPresent(bool IsPresent)
|
||||
{
|
||||
isPresent = IsPresent;
|
||||
}
|
||||
|
||||
void cEvent::SetIsFollowing(bool IsFollowing)
|
||||
{
|
||||
isFollowing = IsFollowing;
|
||||
}
|
||||
|
||||
void cEvent::SetTitle(const char *Title)
|
||||
{
|
||||
title = strcpyrealloc(title, Title);
|
||||
}
|
||||
|
||||
void cEvent::SetShortText(const char *ShortText)
|
||||
{
|
||||
shortText = strcpyrealloc(shortText, ShortText);
|
||||
}
|
||||
|
||||
void cEvent::SetDescription(const char *Description)
|
||||
{
|
||||
description = strcpyrealloc(description, Description);
|
||||
}
|
||||
|
||||
void cEvent::SetStartTime(time_t StartTime)
|
||||
{
|
||||
startTime = StartTime;
|
||||
}
|
||||
|
||||
void cEvent::SetDuration(int Duration)
|
||||
{
|
||||
duration = Duration;
|
||||
}
|
||||
|
||||
const char *cEvent::GetDateString(void) const
|
||||
{
|
||||
static char buf[25];
|
||||
struct tm tm_r;
|
||||
strftime(buf, sizeof(buf), "%d.%m.%Y", localtime_r(&startTime, &tm_r));
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *cEvent::GetTimeString(void) const
|
||||
{
|
||||
static char buf[25];
|
||||
struct tm tm_r;
|
||||
strftime(buf, sizeof(buf), "%R", localtime_r(&startTime, &tm_r));
|
||||
return buf;
|
||||
}
|
||||
|
||||
const char *cEvent::GetEndTimeString(void) const
|
||||
{
|
||||
static char buf[25];
|
||||
time_t EndTime = startTime + duration;
|
||||
struct tm tm_r;
|
||||
strftime(buf, sizeof(buf), "%R", localtime_r(&EndTime, &tm_r));
|
||||
return buf;
|
||||
}
|
||||
|
||||
void cEvent::Dump(FILE *f, const char *Prefix) const
|
||||
{
|
||||
if (startTime + duration >= time(NULL)) {
|
||||
fprintf(f, "%sE %u %ld %d %X\n", Prefix, eventID, startTime, duration, tableID);
|
||||
if (!isempty(title))
|
||||
fprintf(f, "%sT %s\n", Prefix, title);
|
||||
if (!isempty(shortText))
|
||||
fprintf(f, "%sS %s\n", Prefix, shortText);
|
||||
if (!isempty(description))
|
||||
fprintf(f, "%sD %s\n", Prefix, description);
|
||||
fprintf(f, "%se\n", Prefix);
|
||||
}
|
||||
}
|
||||
|
||||
bool cEvent::Read(FILE *f, cSchedule *Schedule)
|
||||
{
|
||||
if (Schedule) {
|
||||
cEvent *Event = NULL;
|
||||
char *s;
|
||||
while ((s = readline(f)) != NULL) {
|
||||
char *t = skipspace(s + 1);
|
||||
switch (*s) {
|
||||
case 'E': if (!Event) {
|
||||
unsigned int EventID;
|
||||
time_t StartTime;
|
||||
int Duration;
|
||||
unsigned int TableID = 0;
|
||||
int n = sscanf(t, "%u %ld %d %X", &EventID, &StartTime, &Duration, &TableID);
|
||||
if (n == 3 || n == 4) {
|
||||
Event = (cEvent *)Schedule->GetEvent(EventID, StartTime);
|
||||
if (!Event)
|
||||
Event = Schedule->AddEvent(new cEvent(Schedule->ChannelID(), EventID));
|
||||
if (Event) {
|
||||
Event->SetTableID(TableID);
|
||||
Event->SetStartTime(StartTime);
|
||||
Event->SetDuration(Duration);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'T': if (Event)
|
||||
Event->SetTitle(t);
|
||||
break;
|
||||
case 'S': if (Event)
|
||||
Event->SetShortText(t);
|
||||
break;
|
||||
case 'D': if (Event)
|
||||
Event->SetDescription(t);
|
||||
break;
|
||||
case 'e': Event = NULL;
|
||||
break;
|
||||
case 'c': // to keep things simple we react on 'c' here
|
||||
return true;
|
||||
default: esyslog("ERROR: unexpected tag while reading EPG data: %s", s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
esyslog("ERROR: unexpected end of file while reading EPG data");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#define MAXEPGBUGFIXSTATS 7
|
||||
#define MAXEPGBUGFIXCHANS 100
|
||||
struct tEpgBugFixStats {
|
||||
int hits;
|
||||
int n;
|
||||
tChannelID channelIDs[MAXEPGBUGFIXCHANS];
|
||||
tEpgBugFixStats(void) { hits = n = 0; }
|
||||
};
|
||||
|
||||
tEpgBugFixStats EpgBugFixStats[MAXEPGBUGFIXSTATS];
|
||||
|
||||
static void EpgBugFixStat(int Number, tChannelID ChannelID)
|
||||
{
|
||||
if (0 <= Number && Number < MAXEPGBUGFIXSTATS) {
|
||||
tEpgBugFixStats *p = &EpgBugFixStats[Number];
|
||||
p->hits++;
|
||||
int i = 0;
|
||||
for (; i < p->n; i++) {
|
||||
if (p->channelIDs[i] == ChannelID)
|
||||
break;
|
||||
}
|
||||
if (i == p->n && p->n < MAXEPGBUGFIXCHANS)
|
||||
p->channelIDs[p->n++] = ChannelID;
|
||||
}
|
||||
}
|
||||
|
||||
void ReportEpgBugFixStats(bool Reset)
|
||||
{
|
||||
if (Setup.EPGBugfixLevel > 0) {
|
||||
bool GotHits = false;
|
||||
char buffer[1024];
|
||||
for (int i = 0; i < MAXEPGBUGFIXSTATS; i++) {
|
||||
const char *delim = "\t";
|
||||
tEpgBugFixStats *p = &EpgBugFixStats[i];
|
||||
if (p->hits) {
|
||||
bool PrintedStats = false;
|
||||
char *q = buffer;
|
||||
*buffer = 0;
|
||||
for (int c = 0; c < p->n; c++) {
|
||||
cChannel *channel = Channels.GetByChannelID(p->channelIDs[c], true);
|
||||
if (channel) {
|
||||
if (!GotHits) {
|
||||
dsyslog("=====================");
|
||||
dsyslog("EPG bugfix statistics");
|
||||
dsyslog("=====================");
|
||||
dsyslog("IF SOMEBODY WHO IS IN CHARGE OF THE EPG DATA FOR ONE OF THE LISTED");
|
||||
dsyslog("CHANNELS READS THIS: PLEASE TAKE A LOOK AT THE FUNCTION cEvent::FixEpgBugs()");
|
||||
dsyslog("IN VDR/epg.c TO LEARN WHAT'S WRONG WITH YOUR DATA, AND FIX IT!");
|
||||
dsyslog("=====================");
|
||||
dsyslog("Fix\tHits\tChannels");
|
||||
GotHits = true;
|
||||
}
|
||||
if (!PrintedStats) {
|
||||
q += snprintf(q, sizeof(buffer) - (q - buffer), "%d\t%d", i, p->hits);
|
||||
PrintedStats = true;
|
||||
}
|
||||
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s%s", delim, channel->Name());
|
||||
delim = ", ";
|
||||
if (q - buffer > 80) {
|
||||
q += snprintf(q, sizeof(buffer) - (q - buffer), "%s...", delim);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (*buffer)
|
||||
dsyslog("%s", buffer);
|
||||
}
|
||||
if (Reset)
|
||||
p->hits = p->n = 0;
|
||||
}
|
||||
if (GotHits)
|
||||
dsyslog("=====================");
|
||||
}
|
||||
}
|
||||
|
||||
void cEvent::FixEpgBugs(void)
|
||||
{
|
||||
// VDR can't usefully handle newline characters in the EPG data, so let's
|
||||
// always convert them to blanks (independent of the setting of EPGBugfixLevel):
|
||||
strreplace(title, '\n', ' ');
|
||||
strreplace(shortText, '\n', ' ');
|
||||
strreplace(description, '\n', ' ');
|
||||
|
||||
if (Setup.EPGBugfixLevel == 0)
|
||||
return;
|
||||
|
||||
// Some TV stations apparently have their own idea about how to fill in the
|
||||
// EPG data. Let's fix their bugs as good as we can:
|
||||
if (title) {
|
||||
|
||||
// Some channels put too much information into the ShortText and leave the
|
||||
// Description empty:
|
||||
//
|
||||
// Title
|
||||
// (NAT, Year Min')[ ["ShortText". ]Description]
|
||||
//
|
||||
if (shortText && !description) {
|
||||
if (*shortText == '(') {
|
||||
char *e = strchr(shortText + 1, ')');
|
||||
if (e) {
|
||||
if (*(e + 1)) {
|
||||
if (*++e == ' ')
|
||||
if (*(e + 1) == '"')
|
||||
e++;
|
||||
}
|
||||
else
|
||||
e = NULL;
|
||||
char *s = e ? strdup(e) : NULL;
|
||||
free(shortText);
|
||||
shortText = s;
|
||||
EpgBugFixStat(0, ChannelID());
|
||||
// now the fixes #1 and #2 below will handle the rest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some channels put the ShortText in quotes and use either the ShortText
|
||||
// or the Description field, depending on how long the string is:
|
||||
//
|
||||
// Title
|
||||
// "ShortText". Description
|
||||
//
|
||||
if ((shortText == NULL) != (description == NULL)) {
|
||||
char *p = shortText ? shortText : description;
|
||||
if (*p == '"') {
|
||||
const char *delim = "\".";
|
||||
char *e = strstr(p + 1, delim);
|
||||
if (e) {
|
||||
*e = 0;
|
||||
char *s = strdup(p + 1);
|
||||
char *d = strdup(e + strlen(delim));
|
||||
free(shortText);
|
||||
free(description);
|
||||
shortText = s;
|
||||
description = d;
|
||||
EpgBugFixStat(1, ChannelID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some channels put the Description into the ShortText (preceeded
|
||||
// by a blank) if there is no actual ShortText and the Description
|
||||
// is short enough:
|
||||
//
|
||||
// Title
|
||||
// Description
|
||||
//
|
||||
if (shortText && !description) {
|
||||
if (*shortText == ' ') {
|
||||
memmove(shortText, shortText + 1, strlen(shortText));
|
||||
description = shortText;
|
||||
shortText = NULL;
|
||||
EpgBugFixStat(2, ChannelID());
|
||||
}
|
||||
}
|
||||
|
||||
// Sometimes they repeat the Title in the ShortText:
|
||||
//
|
||||
// Title
|
||||
// Title
|
||||
//
|
||||
if (shortText && strcmp(title, shortText) == 0) {
|
||||
free(shortText);
|
||||
shortText = NULL;
|
||||
EpgBugFixStat(3, ChannelID());
|
||||
}
|
||||
|
||||
// Some channels put the ShortText between double quotes, which is nothing
|
||||
// but annoying (some even put a '.' after the closing '"'):
|
||||
//
|
||||
// Title
|
||||
// "ShortText"[.]
|
||||
//
|
||||
if (shortText && *shortText == '"') {
|
||||
int l = strlen(shortText);
|
||||
if (l > 2 && (shortText[l - 1] == '"' || (shortText[l - 1] == '.' && shortText[l - 2] == '"'))) {
|
||||
memmove(shortText, shortText + 1, l);
|
||||
char *p = strrchr(shortText, '"');
|
||||
if (p)
|
||||
*p = 0;
|
||||
EpgBugFixStat(4, ChannelID());
|
||||
}
|
||||
}
|
||||
|
||||
if (Setup.EPGBugfixLevel <= 1)
|
||||
return;
|
||||
|
||||
// Some channels apparently try to do some formatting in the texts,
|
||||
// which is a bad idea because they have no way of knowing the width
|
||||
// of the window that will actually display the text.
|
||||
// Remove excess whitespace:
|
||||
title = compactspace(title);
|
||||
shortText = compactspace(shortText);
|
||||
description = compactspace(description);
|
||||
// Remove superfluous hyphens:
|
||||
if (description) {
|
||||
char *p = description;
|
||||
while (*p && *(p + 1) && *(p + 2)) {
|
||||
if (*p == '-' && *(p + 1) == ' ' && *(p + 2) && islower(*(p - 1)) && islower(*(p + 2))) {
|
||||
if (!startswith(p + 2, "und ")) { // special case in German, as in "Lach- und Sachgeschichten"
|
||||
memmove(p, p + 2, strlen(p + 2) + 1);
|
||||
EpgBugFixStat(5, ChannelID());
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_USEFUL_EPISODE_LENGTH 40
|
||||
// Some channels put a whole lot of information in the ShortText and leave
|
||||
// the Description totally empty. So if the ShortText length exceeds
|
||||
// MAX_USEFUL_EPISODE_LENGTH, let's put this into the Description
|
||||
// instead:
|
||||
if (!isempty(shortText) && isempty(description)) {
|
||||
if (strlen(shortText) > MAX_USEFUL_EPISODE_LENGTH) {
|
||||
free(description);
|
||||
description = shortText;
|
||||
shortText = NULL;
|
||||
EpgBugFixStat(6, ChannelID());
|
||||
}
|
||||
}
|
||||
|
||||
// Some channels use the ` ("backtick") character, where a ' (single quote)
|
||||
// would be normally used. Actually, "backticks" in normal text don't make
|
||||
// much sense, so let's replace them:
|
||||
strreplace(title, '`', '\'');
|
||||
strreplace(shortText, '`', '\'');
|
||||
strreplace(description, '`', '\'');
|
||||
}
|
||||
}
|
||||
|
||||
// --- cSchedule -------------------------------------------------------------
|
||||
|
||||
cSchedule::cSchedule(tChannelID ChannelID)
|
||||
{
|
||||
channelID = ChannelID;
|
||||
present = following = NULL;
|
||||
}
|
||||
|
||||
cEvent *cSchedule::AddEvent(cEvent *Event)
|
||||
{
|
||||
events.Add(Event);
|
||||
return Event;
|
||||
}
|
||||
|
||||
const cEvent *cSchedule::GetPresentEvent(void) const
|
||||
{
|
||||
return GetEventAround(time(NULL));
|
||||
}
|
||||
|
||||
const cEvent *cSchedule::GetFollowingEvent(void) const
|
||||
{
|
||||
const cEvent *pe = NULL;
|
||||
time_t now = time(NULL);
|
||||
time_t delta = INT_MAX;
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
time_t dt = p->StartTime() - now;
|
||||
if (dt > 0 && dt < delta) {
|
||||
delta = dt;
|
||||
pe = p;
|
||||
}
|
||||
}
|
||||
return pe;
|
||||
}
|
||||
|
||||
const cEvent *cSchedule::GetEvent(u_int16_t EventID, time_t StartTime) const
|
||||
{
|
||||
// Returns either the event info with the given EventID or, if that one can't
|
||||
// be found, the one with the given StartTime (or NULL if neither can be found)
|
||||
cEvent *pt = NULL;
|
||||
for (cEvent *pe = events.First(); pe; pe = events.Next(pe)) {
|
||||
if (pe->EventID() == EventID)
|
||||
return pe;
|
||||
if (StartTime > 0 && pe->StartTime() == StartTime) // 'StartTime < 0' is apparently used with NVOD channels
|
||||
pt = pe;
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
||||
const cEvent *cSchedule::GetEventAround(time_t Time) const
|
||||
{
|
||||
const cEvent *pe = NULL;
|
||||
time_t delta = INT_MAX;
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p)) {
|
||||
time_t dt = Time - p->StartTime();
|
||||
if (dt >= 0 && dt < delta && p->StartTime() + p->Duration() >= Time) {
|
||||
delta = dt;
|
||||
pe = p;
|
||||
}
|
||||
}
|
||||
return pe;
|
||||
}
|
||||
|
||||
bool cSchedule::SetPresentEvent(cEvent *Event)
|
||||
{
|
||||
if (present)
|
||||
present->SetIsPresent(false);
|
||||
present = Event;
|
||||
present->SetIsPresent(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool cSchedule::SetFollowingEvent(cEvent *Event)
|
||||
{
|
||||
if (following)
|
||||
following->SetIsFollowing(false);
|
||||
following = Event;
|
||||
following->SetIsFollowing(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cSchedule::Cleanup(void)
|
||||
{
|
||||
Cleanup(time(NULL));
|
||||
}
|
||||
|
||||
void cSchedule::Cleanup(time_t Time)
|
||||
{
|
||||
cEvent *Event;
|
||||
for (int a = 0; true ; a++) {
|
||||
Event = events.Get(a);
|
||||
if (!Event)
|
||||
break;
|
||||
if (Event->StartTime() + Event->Duration() + 3600 < Time) { // adding one hour for safety
|
||||
events.Del(Event);
|
||||
a--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cSchedule::Dump(FILE *f, const char *Prefix) const
|
||||
{
|
||||
cChannel *channel = Channels.GetByChannelID(channelID, true);
|
||||
if (channel) {
|
||||
fprintf(f, "%sC %s %s\n", Prefix, channel->GetChannelID().ToString(), channel->Name());
|
||||
for (cEvent *p = events.First(); p; p = events.Next(p))
|
||||
p->Dump(f, Prefix);
|
||||
fprintf(f, "%sc\n", Prefix);
|
||||
}
|
||||
}
|
||||
|
||||
bool cSchedule::Read(FILE *f, cSchedules *Schedules)
|
||||
{
|
||||
if (Schedules) {
|
||||
char *s;
|
||||
while ((s = readline(f)) != NULL) {
|
||||
if (*s == 'C') {
|
||||
s = skipspace(s + 1);
|
||||
char *p = strchr(s, ' ');
|
||||
if (p)
|
||||
*p = 0; // strips optional channel name
|
||||
if (*s) {
|
||||
tChannelID channelID = tChannelID::FromString(s);
|
||||
if (channelID.Valid()) {
|
||||
cSchedule *p = Schedules->AddSchedule(channelID);
|
||||
if (p) {
|
||||
if (!cEvent::Read(f, p))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: illegal channel ID: %s", s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: unexpected tag while reading EPG data: %s", s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// --- cSchedulesLock --------------------------------------------------------
|
||||
|
||||
cSchedulesLock::cSchedulesLock(bool WriteLock, int TimeoutMs)
|
||||
{
|
||||
locked = cSchedules::schedules.rwlock.Lock(WriteLock, TimeoutMs);
|
||||
}
|
||||
|
||||
cSchedulesLock::~cSchedulesLock()
|
||||
{
|
||||
if (locked)
|
||||
cSchedules::schedules.rwlock.Unlock();
|
||||
}
|
||||
|
||||
// --- cSchedules ------------------------------------------------------------
|
||||
|
||||
cSchedules cSchedules::schedules;
|
||||
const char *cSchedules::epgDataFileName = NULL;
|
||||
time_t cSchedules::lastCleanup = time(NULL);
|
||||
time_t cSchedules::lastDump = time(NULL);
|
||||
|
||||
const cSchedules *cSchedules::Schedules(cSchedulesLock &SchedulesLock)
|
||||
{
|
||||
return SchedulesLock.Locked() ? &schedules : NULL;
|
||||
}
|
||||
|
||||
void cSchedules::SetEpgDataFileName(const char *FileName)
|
||||
{
|
||||
delete epgDataFileName;
|
||||
if (FileName)
|
||||
epgDataFileName = strdup(FileName);
|
||||
}
|
||||
|
||||
void cSchedules::Cleanup(bool Force)
|
||||
{
|
||||
if (Force)
|
||||
lastDump = 0;
|
||||
time_t now = time(NULL);
|
||||
struct tm tm_r;
|
||||
struct tm *ptm = localtime_r(&now, &tm_r);
|
||||
if (now - lastCleanup > 3600 && ptm->tm_hour == 5) {
|
||||
isyslog("cleaning up schedules data");
|
||||
cSchedulesLock SchedulesLock(true, 1000);
|
||||
cSchedules *s = (cSchedules *)Schedules(SchedulesLock);
|
||||
if (s) {
|
||||
for (cSchedule *p = s->First(); p; p = s->Next(p))
|
||||
p->Cleanup(now);
|
||||
}
|
||||
lastCleanup = now;
|
||||
ReportEpgBugFixStats(true);
|
||||
}
|
||||
if (epgDataFileName && now - lastDump > 600) {
|
||||
cSafeFile f(epgDataFileName);
|
||||
if (f.Open()) {
|
||||
Dump(f);
|
||||
f.Close();
|
||||
}
|
||||
else
|
||||
LOG_ERROR;
|
||||
lastDump = now;
|
||||
}
|
||||
}
|
||||
|
||||
bool cSchedules::ClearAll(void)
|
||||
{
|
||||
cSchedulesLock SchedulesLock(true, 1000);
|
||||
cSchedules *s = (cSchedules *)Schedules(SchedulesLock);
|
||||
if (s) {
|
||||
s->Clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSchedules::Dump(FILE *f, const char *Prefix)
|
||||
{
|
||||
cSchedulesLock SchedulesLock;
|
||||
cSchedules *s = (cSchedules *)Schedules(SchedulesLock);
|
||||
if (s) {
|
||||
for (cSchedule *p = s->First(); p; p = s->Next(p))
|
||||
p->Dump(f, Prefix);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool cSchedules::Read(FILE *f)
|
||||
{
|
||||
cSchedulesLock SchedulesLock(true, 1000);
|
||||
cSchedules *s = (cSchedules *)Schedules(SchedulesLock);
|
||||
if (s) {
|
||||
bool OwnFile = f == NULL;
|
||||
if (OwnFile) {
|
||||
if (epgDataFileName && access(epgDataFileName, R_OK) == 0) {
|
||||
dsyslog("reading EPG data from %s", epgDataFileName);
|
||||
if ((f = fopen(epgDataFileName, "r")) == NULL) {
|
||||
LOG_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
bool result = cSchedule::Read(f, s);
|
||||
if (OwnFile)
|
||||
fclose(f);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
cSchedule *cSchedules::AddSchedule(tChannelID ChannelID)
|
||||
{
|
||||
ChannelID.ClrRid();
|
||||
cSchedule *p = (cSchedule *)GetSchedule(ChannelID);
|
||||
if (!p) {
|
||||
p = new cSchedule(ChannelID);
|
||||
Add(p);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
const cSchedule *cSchedules::GetSchedule(tChannelID ChannelID) const
|
||||
{
|
||||
ChannelID.ClrRid();
|
||||
for (cSchedule *p = First(); p; p = Next(p)) {
|
||||
if (p->ChannelID() == ChannelID)
|
||||
return p;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
134
epg.h
Normal file
134
epg.h
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* epg.h: Electronic Program Guide
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* Original version (as used in VDR before 1.3.0) written by
|
||||
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
|
||||
*
|
||||
* $Id: epg.h 1.3 2004/01/03 17:00:25 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __EPG_H
|
||||
#define __EPG_H
|
||||
|
||||
#include "channels.h"
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
#define MAXEPGBUGFIXLEVEL 2
|
||||
|
||||
class cSchedule;
|
||||
|
||||
class cEvent : public cListObject {
|
||||
private:
|
||||
tChannelID channelID; // Channel ID of program for this event
|
||||
u_int16_t eventID; // Event ID of this event
|
||||
uchar tableID; // Table ID this event came from
|
||||
uchar version; // Version number of section this event came from
|
||||
//XXX present/following obsolete???
|
||||
bool isPresent; // true if this is the present event running
|
||||
bool isFollowing; // true if this is the next event on this channel
|
||||
char *title; // Title of this event
|
||||
char *shortText; // Short description of this event (typically the episode name in case of a series)
|
||||
char *description; // Description of this event
|
||||
time_t startTime; // Start time of this event
|
||||
int duration; // Duration of this event in seconds
|
||||
//XXX find an other solution, avoiding channelNumber???
|
||||
int channelNumber; // the actual channel number from VDR's channel list (used in cMenuSchedule for sorting by channel number)
|
||||
public:
|
||||
cEvent(tChannelID ChannelID, u_int16_t EventID);
|
||||
~cEvent();
|
||||
tChannelID ChannelID(void) const { return channelID; }
|
||||
u_int16_t EventID(void) const { return eventID; }
|
||||
uchar TableID(void) const { return tableID; }
|
||||
uchar Version(void) const { return version; }
|
||||
bool IsPresent(void) const { return isPresent; }
|
||||
bool IsFollowing(void) const { return isFollowing; }
|
||||
const char *Title(void) const { return title; }
|
||||
const char *ShortText(void) const { return shortText; }
|
||||
const char *Description(void) const { return description; }
|
||||
time_t StartTime(void) const { return startTime; }
|
||||
int Duration(void) const { return duration; }
|
||||
int ChannelNumber(void) const { return channelNumber; }
|
||||
const char *GetDateString(void) const;
|
||||
const char *GetTimeString(void) const;
|
||||
const char *GetEndTimeString(void) const;
|
||||
void SetEventID(u_int16_t EventID);
|
||||
void SetTableID(uchar TableID);
|
||||
void SetVersion(uchar Version);
|
||||
void SetIsPresent(bool IsPresent);
|
||||
void SetIsFollowing(bool IsFollowing);
|
||||
void SetTitle(const char *Title);
|
||||
void SetShortText(const char *ShortText);
|
||||
void SetDescription(const char *Description);
|
||||
void SetStartTime(time_t StartTime);
|
||||
void SetDuration(int Duration);
|
||||
void SetChannelNumber(int ChannelNumber) const { ((cEvent *)this)->channelNumber = ChannelNumber; } // doesn't modify the EIT data, so it's ok to make it 'const' //XXX
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
static bool Read(FILE *f, cSchedule *Schedule);
|
||||
void FixEpgBugs(void);
|
||||
};
|
||||
|
||||
class cSchedules;
|
||||
|
||||
class cSchedule : public cListObject {
|
||||
private:
|
||||
tChannelID channelID;
|
||||
cList<cEvent> events;
|
||||
cEvent *present;
|
||||
cEvent *following;
|
||||
public:
|
||||
cSchedule(tChannelID ChannelID);
|
||||
tChannelID ChannelID(void) const { return channelID; }
|
||||
bool SetPresentEvent(cEvent *Event);
|
||||
bool SetFollowingEvent(cEvent *Event);
|
||||
void Cleanup(time_t Time);
|
||||
void Cleanup(void);
|
||||
cEvent *AddEvent(cEvent *Event);
|
||||
const cEvent *GetPresentEvent(void) const;
|
||||
const cEvent *GetFollowingEvent(void) const;
|
||||
const cEvent *GetEvent(u_int16_t EventID, time_t StartTime = 0) const;
|
||||
const cEvent *GetEventAround(time_t Time) const;
|
||||
const cEvent *GetEventNumber(int n) const { return events.Get(n); }
|
||||
int NumEvents(void) const { return events.Count(); }
|
||||
void Dump(FILE *f, const char *Prefix = "") const;
|
||||
static bool Read(FILE *f, cSchedules *Schedules);
|
||||
};
|
||||
|
||||
class cSchedulesLock {
|
||||
private:
|
||||
bool locked;
|
||||
public:
|
||||
cSchedulesLock(bool WriteLock = false, int TimeoutMs = 0);
|
||||
~cSchedulesLock();
|
||||
bool Locked(void) { return locked; }
|
||||
};
|
||||
|
||||
class cSchedules : public cList<cSchedule> {
|
||||
friend class cSchedule;
|
||||
friend class cSchedulesLock;
|
||||
private:
|
||||
cRwLock rwlock;
|
||||
static cSchedules schedules;
|
||||
static const char *epgDataFileName;
|
||||
static time_t lastCleanup;
|
||||
static time_t lastDump;
|
||||
public:
|
||||
static void SetEpgDataFileName(const char *FileName);
|
||||
static const cSchedules *Schedules(cSchedulesLock &SchedulesLock);
|
||||
///< Caller must provide a cSchedulesLock which has to survive the entire
|
||||
///< time the returned cSchedules is accessed. Once the cSchedules is no
|
||||
///< longer used, the cSchedulesLock must be destroyed.
|
||||
static void Cleanup(bool Force = false);
|
||||
static bool ClearAll(void);
|
||||
static bool Dump(FILE *f, const char *Prefix = "");
|
||||
static bool Read(FILE *f = NULL);
|
||||
cSchedule *AddSchedule(tChannelID ChannelID);
|
||||
const cSchedule *GetSchedule(tChannelID ChannelID) const;
|
||||
};
|
||||
|
||||
void ReportEpgBugFixStats(bool Reset = false);
|
||||
|
||||
#endif //__EPG_H
|
126
filter.c
Normal file
126
filter.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* filter.c: Section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: filter.c 1.1 2003/12/21 15:26:16 kls Exp $
|
||||
*/
|
||||
|
||||
#include "filter.h"
|
||||
#include "sections.h"
|
||||
|
||||
// --- cFilterData -----------------------------------------------------------
|
||||
|
||||
cFilterData::cFilterData(void)
|
||||
{
|
||||
pid = 0;
|
||||
tid = 0;
|
||||
mask = 0;
|
||||
sticky = false;
|
||||
}
|
||||
|
||||
cFilterData::cFilterData(u_short Pid, u_char Tid, u_char Mask, bool Sticky)
|
||||
{
|
||||
pid = Pid;
|
||||
tid = Tid;
|
||||
mask = Mask;
|
||||
sticky = Sticky;
|
||||
}
|
||||
|
||||
bool cFilterData::Is(u_short Pid, u_char Tid, u_char Mask)
|
||||
{
|
||||
return pid == Pid && tid == Tid && mask == Mask;
|
||||
}
|
||||
|
||||
bool cFilterData::Matches(u_short Pid, u_char Tid)
|
||||
{
|
||||
return pid == Pid && tid == (Tid & mask);
|
||||
}
|
||||
|
||||
// --- cFilter ---------------------------------------------------------------
|
||||
|
||||
cFilter::cFilter(void)
|
||||
{
|
||||
sectionHandler = NULL;
|
||||
on = false;
|
||||
}
|
||||
|
||||
cFilter::cFilter(u_short Pid, u_char Tid, u_char Mask)
|
||||
{
|
||||
sectionHandler = NULL;
|
||||
on = false;
|
||||
Set(Pid, Tid, Mask);
|
||||
}
|
||||
|
||||
cFilter::~cFilter()
|
||||
{
|
||||
if (sectionHandler)
|
||||
sectionHandler->Detach(this);
|
||||
}
|
||||
|
||||
int cFilter::Source(void)
|
||||
{
|
||||
return sectionHandler ? sectionHandler->Source() : 0;
|
||||
}
|
||||
|
||||
int cFilter::Transponder(void)
|
||||
{
|
||||
return sectionHandler ? sectionHandler->Transponder() : 0;
|
||||
}
|
||||
|
||||
void cFilter::SetStatus(bool On)
|
||||
{
|
||||
if (sectionHandler && on != On) {
|
||||
cFilterData *fd = data.First();
|
||||
while (fd) {
|
||||
if (On)
|
||||
sectionHandler->Add(fd);
|
||||
else {
|
||||
sectionHandler->Del(fd);
|
||||
if (!fd->sticky) {
|
||||
cFilterData *next = data.Next(fd);
|
||||
data.Del(fd);
|
||||
fd = next;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
fd = data.Next(fd);
|
||||
}
|
||||
on = On;
|
||||
}
|
||||
}
|
||||
|
||||
bool cFilter::Matches(u_short Pid, u_char Tid)
|
||||
{
|
||||
for (cFilterData *fd = data.First(); fd; fd = data.Next(fd)) {
|
||||
if (fd->Matches(Pid, Tid))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cFilter::Set(u_short Pid, u_char Tid, u_char Mask)
|
||||
{
|
||||
Add(Pid, Tid, Mask, true);
|
||||
}
|
||||
|
||||
void cFilter::Add(u_short Pid, u_char Tid, u_char Mask, bool Sticky)
|
||||
{
|
||||
cFilterData *fd = new cFilterData(Pid, Tid, Mask, Sticky);
|
||||
data.Add(fd);
|
||||
if (sectionHandler && on)
|
||||
sectionHandler->Add(fd);
|
||||
}
|
||||
|
||||
void cFilter::Del(u_short Pid, u_char Tid, u_char Mask)
|
||||
{
|
||||
for (cFilterData *fd = data.First(); fd; fd = data.Next(fd)) {
|
||||
if (fd->Is(Pid, Tid, Mask)) {
|
||||
if (sectionHandler && on)
|
||||
sectionHandler->Del(fd);
|
||||
data.Del(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
74
filter.h
Normal file
74
filter.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* filter.h: Section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: filter.h 1.1 2003/12/22 11:41:40 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __FILTER_H
|
||||
#define __FILTER_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "tools.h"
|
||||
|
||||
class cFilterData : public cListObject {
|
||||
public:
|
||||
u_short pid;
|
||||
u_char tid;
|
||||
u_char mask;
|
||||
bool sticky;
|
||||
cFilterData(void);
|
||||
cFilterData(u_short Pid, u_char Tid, u_char Mask, bool Sticky);
|
||||
bool Is(u_short Pid, u_char Tid, u_char Mask);
|
||||
bool Matches(u_short Pid, u_char Tid);
|
||||
};
|
||||
|
||||
class cSectionHandler;
|
||||
|
||||
class cFilter : public cListObject {
|
||||
friend class cSectionHandler;
|
||||
private:
|
||||
cSectionHandler *sectionHandler;
|
||||
cList<cFilterData> data;
|
||||
bool on;
|
||||
protected:
|
||||
cFilter(void);
|
||||
cFilter(u_short Pid, u_char Tid, u_char Mask = 0xFF);
|
||||
virtual ~cFilter();
|
||||
virtual void SetStatus(bool On);
|
||||
///< Turns this filter on or off, depending on the value of On.
|
||||
///< If the filter is turned off, any filter data that has been
|
||||
///< added without the Sticky parameter set to 'true' will be
|
||||
///< automatically deleted. Those parameters that have been added
|
||||
///< with Sticky set to 'true' will be automatically reused when
|
||||
///< SetStatus(true) is called.
|
||||
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length) = 0;
|
||||
///< Processes the data delivered to this filter.
|
||||
///< Pid and Tid is one of the combinations added to this filter by
|
||||
///< a previous call to Add(), Data is a pointer to Length bytes of
|
||||
///< data. This function will be called from the section handler's
|
||||
///< thread, so it has to use proper locking mechanisms in case it
|
||||
///< accesses any global data. It is guaranteed that if several cFilters
|
||||
///< are attached to the same cSectionHandler, only _one_ of them has
|
||||
///< its Process() function called at any given time. It is allowed
|
||||
///< that more than one cFilter are set up to receive the same Pid/Tid.
|
||||
///< The Process() function must return as soon as possible.
|
||||
int Source(void);
|
||||
///< Returns the source of the data delivered to this filter.
|
||||
int Transponder(void);
|
||||
///< Returns the transponder of the data delivered to this filter.
|
||||
bool Matches(u_short Pid, u_char Tid);
|
||||
///< Indicates whether this filter wants to receive data from the given Pid/Tid.
|
||||
void Set(u_short Pid, u_char Tid, u_char Mask = 0xFF);
|
||||
///< Sets the given filter data by calling Add() with Sticky = true.
|
||||
void Add(u_short Pid, u_char Tid, u_char Mask = 0xFF, bool Sticky = false);
|
||||
///< Adds the given filter data to this filter.
|
||||
///< If Sticky is true, this will survive a status change, otherwise
|
||||
///< it will be automatically deleted.
|
||||
void Del(u_short Pid, u_char Tid, u_char Mask = 0xFF);
|
||||
///< Deletes the given filter data from this filter.
|
||||
};
|
||||
|
||||
#endif //__FILTER_H
|
80
font.c
80
font.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: font.c 1.2 2000/11/18 15:16:08 kls Exp $
|
||||
* $Id: font.c 1.4 2003/10/24 12:59:35 kls Exp $
|
||||
*/
|
||||
|
||||
#include "font.h"
|
||||
@ -12,24 +12,38 @@
|
||||
|
||||
#include "fontfix.c"
|
||||
#include "fontosd.c"
|
||||
#include "fontsml.c"
|
||||
|
||||
cFont::cFont(eDvbFont Font)
|
||||
#include "fontfix-iso8859-7.c"
|
||||
#include "fontosd-iso8859-7.c"
|
||||
#include "fontsml-iso8859-7.c"
|
||||
|
||||
static void *FontData[eDvbCodeSize][eDvbFontSize] = {
|
||||
{ FontOsd_iso8859_1, FontFix_iso8859_1, FontSml_iso8859_1 },
|
||||
{ FontOsd_iso8859_7, FontFix_iso8859_7, FontSml_iso8859_7 }
|
||||
};
|
||||
|
||||
static const char *FontCode[eDvbCodeSize] = {
|
||||
"iso8859-1",
|
||||
"iso8859-7"
|
||||
};
|
||||
|
||||
eDvbCode cFont::code = code_iso8859_1;
|
||||
cFont *cFont::fonts[eDvbFontSize] = { NULL };
|
||||
|
||||
cFont::cFont(void *Data)
|
||||
{
|
||||
|
||||
#define FONTINDEX(Name)\
|
||||
case font##Name: for (int i = 0; i < NUMCHARS; i++)\
|
||||
data[i] = (tCharData *)&Font##Name[i < 32 ? 0 : i - 32];\
|
||||
break;
|
||||
|
||||
switch (Font) {
|
||||
default:
|
||||
FONTINDEX(Osd);
|
||||
FONTINDEX(Fix);
|
||||
// TODO others...
|
||||
}
|
||||
SetData(Data);
|
||||
}
|
||||
|
||||
int cFont::Width(const char *s)
|
||||
void cFont::SetData(void *Data)
|
||||
{
|
||||
int h = ((tCharData *)Data)->height;
|
||||
for (int i = 0; i < NUMCHARS; i++)
|
||||
data[i] = (tCharData *)&((tPixelData *)Data)[(i < 32 ? 0 : i - 32) * (h + 2)];
|
||||
}
|
||||
|
||||
int cFont::Width(const char *s) const
|
||||
{
|
||||
int w = 0;
|
||||
while (s && *s)
|
||||
@ -37,7 +51,7 @@ int cFont::Width(const char *s)
|
||||
return w;
|
||||
}
|
||||
|
||||
int cFont::Height(const char *s)
|
||||
int cFont::Height(const char *s) const
|
||||
{
|
||||
int h = 0;
|
||||
if (s && *s)
|
||||
@ -45,3 +59,37 @@ int cFont::Height(const char *s)
|
||||
return h;
|
||||
}
|
||||
|
||||
bool cFont::SetCode(const char *Code)
|
||||
{
|
||||
for (int i = 0; i < eDvbCodeSize; i++) {
|
||||
if (strcmp(Code, FontCode[i]) == 0) {
|
||||
SetCode(eDvbCode(i));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void cFont::SetCode(eDvbCode Code)
|
||||
{
|
||||
if (code != Code) {
|
||||
code = Code;
|
||||
for (int i = 0; i < eDvbFontSize; i++) {
|
||||
if (fonts[i])
|
||||
fonts[i]->SetData(FontData[code][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cFont::SetFont(eDvbFont Font, void *Data)
|
||||
{
|
||||
delete fonts[Font];
|
||||
fonts[Font] = new cFont(Data ? Data : FontData[code][Font]);
|
||||
}
|
||||
|
||||
const cFont *cFont::GetFont(eDvbFont Font)
|
||||
{
|
||||
if (!fonts[Font])
|
||||
SetFont(Font);
|
||||
return fonts[Font];
|
||||
}
|
||||
|
35
font.h
35
font.h
@ -4,19 +4,25 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: font.h 1.2 2000/11/18 14:51:45 kls Exp $
|
||||
* $Id: font.h 1.4 2003/10/24 12:59:45 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __FONT_H
|
||||
#define __FONT_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
enum eDvbFont {
|
||||
fontOsd,
|
||||
fontFix,
|
||||
/* TODO as soon as we have the font files...
|
||||
fontTtxSmall,
|
||||
fontTtxLarge,
|
||||
*/
|
||||
fontSml
|
||||
#define eDvbFontSize (fontSml + 1)
|
||||
};
|
||||
|
||||
enum eDvbCode {
|
||||
code_iso8859_1,
|
||||
code_iso8859_7
|
||||
#define eDvbCodeSize (code_iso8859_7 + 1)
|
||||
};
|
||||
|
||||
class cFont {
|
||||
@ -28,14 +34,21 @@ public:
|
||||
tPixelData lines[1];
|
||||
};
|
||||
private:
|
||||
static eDvbCode code;
|
||||
static cFont *fonts[];
|
||||
const tCharData *data[NUMCHARS];
|
||||
public:
|
||||
cFont(eDvbFont Font);
|
||||
int Width(unsigned char c) { return data[c]->width; }
|
||||
int Width(const char *s);
|
||||
int Height(unsigned char c) { return data[c]->height; }
|
||||
int Height(const char *s);
|
||||
const tCharData *CharData(unsigned char c) { return data[c]; }
|
||||
cFont(void *Data);
|
||||
void SetData(void *Data);
|
||||
int Width(unsigned char c) const { return data[c]->width; }
|
||||
int Width(const char *s) const;
|
||||
int Height(unsigned char c) const { return data[c]->height; }
|
||||
int Height(const char *s) const;
|
||||
const tCharData *CharData(unsigned char c) const { return data[c]; }
|
||||
static bool SetCode(const char *Code);
|
||||
static void SetCode(eDvbCode Code);
|
||||
static void SetFont(eDvbFont Font, void *Data = NULL);
|
||||
static const cFont *GetFont(eDvbFont Font);
|
||||
};
|
||||
|
||||
#endif //__FONT_H
|
||||
|
6498
fontfix-iso8859-7.c
Normal file
6498
fontfix-iso8859-7.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
cFont::tPixelData FontFix[][28] = {
|
||||
cFont::tPixelData FontFix_iso8859_1[][28] = {
|
||||
{ // 32
|
||||
15, 26,
|
||||
0x00000000, // ...............
|
||||
|
5826
fontosd-iso8859-7.c
Normal file
5826
fontosd-iso8859-7.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
cFont::tPixelData FontOsd[][29] = {
|
||||
cFont::tPixelData FontOsd_iso8859_1[][29] = {
|
||||
{ // 32
|
||||
6, 27,
|
||||
0x00000000, // ......
|
||||
|
4930
fontsml-iso8859-7.c
Normal file
4930
fontsml-iso8859-7.c
Normal file
File diff suppressed because it is too large
Load Diff
3
i18n.h
3
i18n.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: i18n.h 1.6 2003/05/16 12:48:52 kls Exp $
|
||||
* $Id: i18n.h 1.7 2003/10/19 15:02:05 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __I18N_H
|
||||
@ -21,6 +21,7 @@ void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin);
|
||||
const char *I18nTranslate(const char *s, const char *Plugin = NULL);
|
||||
|
||||
const char * const * I18nLanguages(void);
|
||||
const char * const * I18nCharSets(void);
|
||||
|
||||
#ifdef PLUGIN_NAME_I18N
|
||||
#define tr(s) I18nTranslate(s, PLUGIN_NAME_I18N)
|
||||
|
339
libdtv/COPYING
339
libdtv/COPYING
@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@ -1,73 +0,0 @@
|
||||
##############################################################
|
||||
### ###
|
||||
### Makefile: global makefile for libdtv ###
|
||||
### ###
|
||||
##############################################################
|
||||
|
||||
## $Revision: 1.3 $
|
||||
## $Date: 2001/06/25 12:51:41 $
|
||||
## $Author: hakenes $
|
||||
##
|
||||
## (C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
##
|
||||
## libdtv 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, or (at your option)
|
||||
## any later version.
|
||||
##
|
||||
## libdtv 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 may have received a copy of the GNU General Public License
|
||||
## along with libdtv; see the file COPYING. If not, write to the
|
||||
## Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
## Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
#
|
||||
# adapt this to your GNU make executable
|
||||
#
|
||||
MAKE = make
|
||||
|
||||
AR = ar
|
||||
ARFLAGS = ru
|
||||
RANLIB = ranlib
|
||||
|
||||
SUBDIRS = liblx libsi libvdr
|
||||
|
||||
all: newdist
|
||||
|
||||
new: clean newdist
|
||||
|
||||
clean:
|
||||
@echo "making all clean..."
|
||||
@for i in $(SUBDIRS);\
|
||||
do \
|
||||
( echo $$i; cd $$i ;\
|
||||
$(MAKE) clean ) ;\
|
||||
done
|
||||
@rm -rf lib include libdtv.*
|
||||
|
||||
newdist:
|
||||
@mkdir -p include lib
|
||||
@echo "making all distributions..."
|
||||
@for i in $(SUBDIRS) ;\
|
||||
do \
|
||||
( cd $$i ;\
|
||||
$(MAKE) new dist ) ;\
|
||||
done
|
||||
@echo "making libdtv.a/libdtv.h..."
|
||||
@cat include/* > libdtv.h
|
||||
@mkdir -p tmp
|
||||
@for i in $(SUBDIRS) ;\
|
||||
do \
|
||||
( cd tmp;\
|
||||
$(AR) x ../lib/$$i.a;\
|
||||
$(AR) $(ARFLAGS) ../libdtv.a *;\
|
||||
rm -f *) ;\
|
||||
done
|
||||
@rm -rf lib include tmp
|
@ -1,27 +0,0 @@
|
||||
DTV System Information Library
|
||||
==============================
|
||||
|
||||
This is intended to support the VDR application of Klaus Schmidinger with
|
||||
extended EIT support, mainly on NVOD channels.
|
||||
Bug reports and suggestions are very appreciated and should be sent to
|
||||
hakenes@hippomi.de
|
||||
|
||||
Have fun,
|
||||
|
||||
(C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
|
||||
libdtv 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, or (at your option)
|
||||
any later version.
|
||||
|
||||
libdtv 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 may have received a copy of the GNU General Public License
|
||||
along with libdtv; see the file COPYING. If not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@ -1,62 +0,0 @@
|
||||
##############################################################
|
||||
### ###
|
||||
### Makefile: local makefile for liblx ###
|
||||
### ###
|
||||
##############################################################
|
||||
|
||||
## $Revision: 1.2 $
|
||||
## $Date: 2001/06/25 19:39:00 $
|
||||
## $Author: hakenes $
|
||||
##
|
||||
## (C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
##
|
||||
## dtv_scan 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, or (at your option)
|
||||
## any later version.
|
||||
##
|
||||
## dtv_scan 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 may have received a copy of the GNU General Public License
|
||||
## along with dtv_scan; see the file COPYING. If not, write to the
|
||||
## Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
## Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
#
|
||||
CC ?= gcc
|
||||
CFLAGS ?= -O2 -g -pedantic -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-Wimplicit -D__USE_FIXED_PROTOTYPES__ # -DDEBUG
|
||||
|
||||
|
||||
AR = ar
|
||||
ARFLAGS = r
|
||||
RANLIB = ranlib
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
|
||||
LXINCLUDE = liblx.h
|
||||
LXLIB = liblx.a
|
||||
LXOBJS = xMemMgt.o xListFuncs.o
|
||||
|
||||
all : $(LXLIB)
|
||||
|
||||
clean :
|
||||
@echo "cleaning workspace..."
|
||||
@$(RM) $(LXOBJS) $(LXLIB)
|
||||
|
||||
new : clean all
|
||||
|
||||
$(LXLIB) : $(LXOBJS)
|
||||
@echo "updating library..."
|
||||
@$(AR) $(ARFLAGS) $(LXLIB) $(LXOBJS)
|
||||
@$(RANLIB) $(LXLIB)
|
||||
|
||||
dist: all
|
||||
@echo "distributing liblx.a and liblx.h..."
|
||||
@$(CP) $(LXLIB) ../lib
|
||||
@$(CP) $(LXINCLUDE) ../include
|
||||
|
@ -1,449 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* liblx.h: definitions necessary for the liblx package
|
||||
*
|
||||
*
|
||||
* $Revision: 1.2 $
|
||||
* $Date: 2001/06/25 19:39:00 $
|
||||
* $Author: hakenes $
|
||||
*
|
||||
* (C) 1992-2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
*
|
||||
* liblx 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* liblx 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 may have received a copy of the GNU General Public License
|
||||
* along with liblx; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIBLX_H
|
||||
#define LIBLX_H
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* list support structures
|
||||
*
|
||||
*/
|
||||
struct NODE
|
||||
{
|
||||
struct NODE *Succ;
|
||||
struct NODE *Pred;
|
||||
char *Name;
|
||||
unsigned short HashKey;
|
||||
};
|
||||
|
||||
struct LIST
|
||||
{
|
||||
struct NODE *Head;
|
||||
struct NODE *Tail;
|
||||
char *Name;
|
||||
unsigned long Size;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* memory managment structures
|
||||
*
|
||||
*/
|
||||
struct MEM_ENTRY
|
||||
{
|
||||
struct MEM_ENTRY *Succ;
|
||||
struct MEM_ENTRY *Pred;
|
||||
unsigned long Size;
|
||||
};
|
||||
|
||||
struct MEM_CHUNK
|
||||
{
|
||||
struct MEM_CHUNK *Succ;
|
||||
struct MEM_CHUNK *Pred;
|
||||
unsigned long Size;
|
||||
struct MEM_ENTRY *FirstFreeMemEntry;
|
||||
struct MEM_ENTRY *FirstUsedMemEntry;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
*
|
||||
* list functions (package xList)
|
||||
*
|
||||
*/
|
||||
unsigned short xHashKey (char *);
|
||||
struct LIST *xNewList (char *);
|
||||
struct NODE *xNewNode (char *, unsigned long);
|
||||
struct NODE *xFindName (struct LIST *, char *);
|
||||
/*
|
||||
*
|
||||
* memory management
|
||||
*
|
||||
*/
|
||||
void xMemAllo (unsigned long, unsigned char **);
|
||||
void xMemFre (unsigned char *);
|
||||
void xMemFreeAll (struct MEM_CHUNK **);
|
||||
void xMemMerge (struct MEM_CHUNK **);
|
||||
struct MEM_CHUNK **xGetRemember (void);
|
||||
void xSetRemember (struct MEM_CHUNK **);
|
||||
void xPrintMemList (struct MEM_CHUNK **);
|
||||
unsigned long xGetMemSize (struct MEM_CHUNK **);
|
||||
extern unsigned long xAllocatedMemory;
|
||||
char *xSetText (char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define MEM_CHUNK_SIZE 65536
|
||||
|
||||
#define xMemAlloc(size, ptr) \
|
||||
xMemAllo (((unsigned long)((size))), ((unsigned char **)((ptr))))
|
||||
#define xMemFree(ptr) xMemFre (((unsigned char *)((ptr))))
|
||||
/*
|
||||
*
|
||||
* list support macros
|
||||
*
|
||||
*/
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xCreateNode (NodeStruct,Name) allocates a correctly sized and |
|
||||
| typed node struct. |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xCreateNode(NodeStruct,Name) \
|
||||
(NodeStruct) = (void *) xNewNode(Name, sizeof(*(NodeStruct)))
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xSize (List) scans for the ->Size field of a list struct |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xSize(List) ((List) ? ((struct LIST *)(List))->Size : 0)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xName (NodeStruct) scans for the ->Node.Name of a node struct |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xName(NodeStruct) (((struct NODE *)(NodeStruct))->Name)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xSucc (NodeStruct) scans for the ->Node.Succ of a node struct |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xSucc(NodeStruct) (((struct NODE *)(NodeStruct))->Succ)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xPred (NodeStruct) scans for the ->Node.Pred of a node struct |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xPred(NodeStruct) (((struct NODE *)(NodeStruct))->Pred)
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xForeach(List,NodeStruct) builds a loop to process each list |
|
||||
| element. |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xForeach(List,NodeStruct) \
|
||||
if (List) for ((NodeStruct) = (void *) ((struct LIST *)(List))->Head; \
|
||||
(NodeStruct); (NodeStruct) = (void *) xSucc (NodeStruct))
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xForeachReverse(List,NodeStruct) builds a loop to process each |
|
||||
| element in reverse order. |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xForeachReverse(List,NodeStruct) \
|
||||
if (List) for ((NodeStruct) = (void *) ((struct LIST *)(List))->Tail; \
|
||||
NodeStruct; (NodeStruct) = (void *) xPred (NodeStruct))
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------*
|
||||
| |
|
||||
| xRemove(List,NodeStruct) unchains a node struct out of a list. |
|
||||
| |
|
||||
*---------------------------------------------------------------------*/
|
||||
#define xRemove(List,NodeStruct) \
|
||||
do \
|
||||
{ \
|
||||
struct NODE *TmpNode; \
|
||||
struct LIST *TmpList; \
|
||||
\
|
||||
TmpNode = ((struct NODE *)(NodeStruct)); \
|
||||
TmpList = ((struct LIST *)(List)); \
|
||||
\
|
||||
if (TmpNode->Pred) \
|
||||
(TmpNode->Pred)->Succ = TmpNode->Succ; \
|
||||
else TmpList->Head = TmpNode->Succ; \
|
||||
if (TmpNode->Succ) \
|
||||
(TmpNode->Succ)->Pred = TmpNode->Pred; \
|
||||
else TmpList->Tail = TmpNode->Pred; \
|
||||
TmpList->Size --; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xAddHead *
|
||||
* *
|
||||
* arguments : List - pointer to a LIST structure *
|
||||
* *
|
||||
* Node - pointer to a NODE structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xAddHead() inserts 'Node' at the head of 'List'. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#define xAddHead(List, NodeStruct) \
|
||||
do { \
|
||||
struct NODE *TmpNode; \
|
||||
struct LIST *TmpList; \
|
||||
\
|
||||
TmpNode = ((struct NODE *)(NodeStruct)); \
|
||||
TmpList = ((struct LIST *)(List)); \
|
||||
\
|
||||
if (TmpList->Head) { \
|
||||
TmpNode->Pred = NULL; \
|
||||
TmpNode->Succ = TmpList->Head; \
|
||||
(TmpList->Head)->Pred = TmpNode; \
|
||||
TmpList->Head = TmpNode; } \
|
||||
else { \
|
||||
TmpList->Head = TmpNode; \
|
||||
TmpList->Tail = TmpNode; \
|
||||
TmpNode->Pred = NULL; \
|
||||
TmpNode->Succ = NULL; } \
|
||||
TmpList->Size++; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xAddTail *
|
||||
* *
|
||||
* arguments : List - pointer to a LIST structure *
|
||||
* *
|
||||
* Node - pointer to a NODE structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xAddTail() inserts 'Node' at the tail of 'List'. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#define xAddTail(List, NodeStruct) \
|
||||
do { \
|
||||
struct NODE *TmpNode; \
|
||||
struct LIST *TmpList; \
|
||||
\
|
||||
TmpNode = ((struct NODE *)(NodeStruct)); \
|
||||
TmpList = ((struct LIST *)(List)); \
|
||||
\
|
||||
if (TmpList->Head) { \
|
||||
TmpNode->Succ = NULL; \
|
||||
TmpNode->Pred = TmpList->Tail; \
|
||||
(TmpList->Tail)->Succ = TmpNode; \
|
||||
TmpList->Tail = TmpNode; } \
|
||||
else { \
|
||||
TmpList->Head = TmpNode; \
|
||||
TmpList->Tail = TmpNode; \
|
||||
TmpNode->Pred = NULL; \
|
||||
TmpNode->Succ = NULL; } \
|
||||
TmpList->Size++; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xRemHead *
|
||||
* *
|
||||
* arguments : List - pointer to a LIST structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xRemHead() removes a Node from head of 'List'. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#define xRemHead(List) \
|
||||
do { \
|
||||
struct LIST *TmpList; \
|
||||
\
|
||||
TmpList = ((struct LIST *)(List)); \
|
||||
\
|
||||
if (TmpList->Head) \
|
||||
{ \
|
||||
TmpList->Head = (TmpList->Head)->Succ; \
|
||||
if (TmpList->Head) (TmpList->Head)->Pred = NULL; \
|
||||
else TmpList->Tail = NULL; \
|
||||
TmpList->Size--; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xRemTail *
|
||||
* *
|
||||
* arguments : List - pointer to a LIST structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xRemTail() removes a Node from the tail of 'List'. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#define xRemTail(List) \
|
||||
do { \
|
||||
struct LIST *TmpList; \
|
||||
\
|
||||
TmpList = ((struct LIST *)(List)); \
|
||||
\
|
||||
if (TmpList->Tail) \
|
||||
{ \
|
||||
TmpList->Tail = (TmpList->Tail)->Pred; \
|
||||
if (TmpList->Tail) (TmpList->Tail)->Succ = NULL; \
|
||||
else TmpList->Head = NULL; \
|
||||
TmpList->Size--; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xConCat *
|
||||
* *
|
||||
* arguments : DestinationList - pointer to the destination *
|
||||
* LIST structure *
|
||||
* *
|
||||
* SourceList - pointer to the source LIST structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xConCat() concats 'SourceList' with 'DestinationList' and clears *
|
||||
* 'SourceList'. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
#define xConCat(DestinationList, SourceList) \
|
||||
do { \
|
||||
struct LIST *SrcList; \
|
||||
struct LIST *DstList; \
|
||||
\
|
||||
SrcList = ((struct LIST *)(SourceList)); \
|
||||
DstList = ((struct LIST *)(DestinationList)); \
|
||||
\
|
||||
if (DstList && SrcList) \
|
||||
{ \
|
||||
if (DstList->Head) { \
|
||||
if (SrcList->Head) { \
|
||||
(DstList->Tail)->Succ = SrcList->Head; \
|
||||
(SrcList->Head)->Pred = DstList->Tail; \
|
||||
DstList->Tail = SrcList->Tail; \
|
||||
DstList->Size += SrcList->Size; \
|
||||
SrcList->Size = 0; \
|
||||
SrcList->Head = NULL; \
|
||||
SrcList->Tail = NULL; } } \
|
||||
else { \
|
||||
DstList->Head = SrcList->Head; \
|
||||
DstList->Tail = SrcList->Tail; \
|
||||
DstList->Size += SrcList->Size; \
|
||||
SrcList->Size = 0; \
|
||||
SrcList->Head = NULL; \
|
||||
SrcList->Tail = NULL; } \
|
||||
} \
|
||||
else if (SrcList) ((struct LIST *)(DestinationList)) = SrcList; \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
#define xJoinList(SourceList, DestinationList, NodeStruct) \
|
||||
do { \
|
||||
struct NODE *KeyNode; \
|
||||
struct NODE *TmpNode; \
|
||||
struct LIST *SrcList; \
|
||||
struct LIST *DstList; \
|
||||
\
|
||||
KeyNode = ((struct NODE *)(NodeStruct)); \
|
||||
SrcList = ((struct LIST *)(SourceList)); \
|
||||
DstList = ((struct LIST *)(DestinationList)); \
|
||||
\
|
||||
if (SrcList->Head) \
|
||||
{ \
|
||||
TmpNode = KeyNode->Succ; \
|
||||
KeyNode->Succ = SrcList->Head; \
|
||||
SrcList->Tail->Succ = TmpNode; \
|
||||
SrcList->Head->Pred = KeyNode; \
|
||||
if (!TmpNode) DstList->Tail = SrcList->Tail; \
|
||||
else TmpNode->Pred = SrcList->Tail; \
|
||||
DstList->Size += SrcList->Size; \
|
||||
SrcList->Size = 0; \
|
||||
SrcList->Head = NULL; \
|
||||
SrcList->Tail = NULL; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define xJoin(SourceNode, DestinationList, NodeStruct) \
|
||||
do { \
|
||||
struct NODE *KeyNode; \
|
||||
struct NODE *TmpNode; \
|
||||
struct NODE *SrcNode; \
|
||||
struct LIST *DstList; \
|
||||
\
|
||||
KeyNode = ((struct NODE *)(NodeStruct)); \
|
||||
SrcNode = ((struct NODE *)(SourceNode)); \
|
||||
DstList = ((struct LIST *)(DestinationList)); \
|
||||
\
|
||||
if (SrcNode) \
|
||||
{ \
|
||||
TmpNode = KeyNode->Succ; \
|
||||
KeyNode->Succ = SrcNode; \
|
||||
SrcNode->Succ = TmpNode; \
|
||||
SrcNode->Pred = KeyNode; \
|
||||
if (!TmpNode) DstList->Tail = SrcNode; \
|
||||
else TmpNode->Pred = SrcNode; \
|
||||
DstList->Size += 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define xClearList(SrcList) \
|
||||
do { \
|
||||
(SrcList)->Size = 0; \
|
||||
(SrcList)->Head = NULL; \
|
||||
(SrcList)->Tail = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define xSetName(nodestruct, name) \
|
||||
do { \
|
||||
struct NODE *TmpNode; \
|
||||
\
|
||||
TmpNode = (struct NODE *) (nodestruct); \
|
||||
\
|
||||
TmpNode->Name = xSetText (name); \
|
||||
TmpNode->HashKey = xHashKey (name); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
@ -1,189 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* xListFuncs.c: list handling functions of liblx
|
||||
*
|
||||
*
|
||||
* $Revision: 1.1 $
|
||||
* $Date: 2001/06/25 12:29:47 $
|
||||
* $Author: hakenes $
|
||||
*
|
||||
* (C) 1992-2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
*
|
||||
* liblx 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* liblx 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 may have received a copy of the GNU General Public License
|
||||
* along with liblx; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "liblx.h"
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xHashKey *
|
||||
* *
|
||||
* arguments : Name - character pointer *
|
||||
* *
|
||||
* return : 16 Bit CRC checksum as hashkey *
|
||||
* *
|
||||
*************************************************************************/
|
||||
unsigned short xHashKey (Name)
|
||||
|
||||
char *Name;
|
||||
{
|
||||
unsigned short Key = 0;
|
||||
unsigned long Value;
|
||||
char *Ptr;
|
||||
|
||||
if (!Name) return (0);
|
||||
|
||||
for (Ptr = Name; *Ptr; Ptr++) {
|
||||
Value = ((Key >> 8) ^ (*Ptr)) & 0xFF;
|
||||
Value = Value ^ (Value >> 4);
|
||||
Key = 0xFFFF & ((Key << 8) ^ Value ^ (Value << 5) ^ (Value << 12));
|
||||
}
|
||||
return (Key);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xNewNode *
|
||||
* *
|
||||
* arguments : Name - character pointer to the node's name *
|
||||
* *
|
||||
* Size - size of the surrounding structure in bytes *
|
||||
* *
|
||||
* return : pointer to a correct initialized NODE structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xNewNode() allocates memory for a NODE structure and initializes *
|
||||
* it properly. If argument Name points to a string, it copies that *
|
||||
* into a new allocated memory area and assigns Node->Name to it. *
|
||||
* Because NODE's are often part of bigger structures, the size of *
|
||||
* the surrounding structure could be specified to allocate it. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
struct NODE *xNewNode (Name, Size)
|
||||
|
||||
char *Name;
|
||||
unsigned long Size;
|
||||
{
|
||||
struct NODE *Node;
|
||||
|
||||
if (Size < sizeof(struct NODE)) Size = sizeof(struct NODE);
|
||||
|
||||
xMemAlloc (Size, &Node);
|
||||
|
||||
Node->Succ = NULL;
|
||||
Node->Pred = NULL;
|
||||
|
||||
if (Name == NULL)
|
||||
{
|
||||
Node->Name = NULL;
|
||||
Node->HashKey = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
xMemAlloc (strlen (Name) + 1, &(Node->Name));
|
||||
strcpy (Node->Name, Name);
|
||||
Node->HashKey = xHashKey (Name);
|
||||
}
|
||||
|
||||
return (Node);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xNewList *
|
||||
* *
|
||||
* arguments : Name - character pointer to the list's name *
|
||||
* *
|
||||
* return : pointer to a correct initialized LIST structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xNewList() allocates memory for a LIST structure and initializes *
|
||||
* it properly. If argument Name points to a string, it copies that *
|
||||
* into a new allocated memory area and assigns List->Name to it. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
struct LIST *xNewList (Name)
|
||||
|
||||
char *Name;
|
||||
{
|
||||
struct LIST *List;
|
||||
|
||||
xMemAlloc (sizeof(struct LIST), &List);
|
||||
|
||||
List->Head = NULL;
|
||||
List->Tail = NULL;
|
||||
List->Size = 0;
|
||||
|
||||
if (Name == NULL)
|
||||
{
|
||||
List->Name = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
xMemAlloc (strlen (Name) + 1, &(List->Name));
|
||||
strcpy (List->Name, Name);
|
||||
}
|
||||
|
||||
return (List);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xFindName *
|
||||
* *
|
||||
* arguments : List - pointer to a LIST structure *
|
||||
* *
|
||||
* Name - pointer to a name string *
|
||||
* *
|
||||
* return : pointer to a NODE structure *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xFindName() looks for element with name 'Name' in list 'List' and *
|
||||
* returns its NODE structure. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
struct NODE *xFindName (List, Name)
|
||||
|
||||
struct LIST *List;
|
||||
char *Name;
|
||||
{
|
||||
struct NODE *Node;
|
||||
unsigned short HashKey;
|
||||
|
||||
if (!Name || !List) return (NULL);
|
||||
|
||||
HashKey = xHashKey (Name);
|
||||
|
||||
for (Node = List->Head; Node; Node = Node->Succ)
|
||||
if (HashKey == Node->HashKey)
|
||||
if (Node->Name)
|
||||
if (strcmp (Node->Name, Name) == 0) return (Node);
|
||||
|
||||
return (NULL);
|
||||
}
|
@ -1,624 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* xMemMgt.c: memory management functions of liblx
|
||||
*
|
||||
*
|
||||
* $Revision: 1.1 $
|
||||
* $Date: 2001/06/25 12:29:47 $
|
||||
* $Author: hakenes $
|
||||
*
|
||||
* (C) 1992-2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
*
|
||||
* liblx 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, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* liblx 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 may have received a copy of the GNU General Public License
|
||||
* along with liblx; see the file COPYING. If not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "liblx.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
void logPrintf(int, char *, ...);
|
||||
#endif
|
||||
|
||||
static struct MEM_CHUNK *xRememberKey = NULL;
|
||||
|
||||
static struct MEM_CHUNK **xRememberPtr = &xRememberKey;
|
||||
|
||||
unsigned long xAllocatedMemory = 0;
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xMemAlloc *
|
||||
* *
|
||||
* parameter : Size - size of the requested memory area *
|
||||
* *
|
||||
* DataPointer - pointer to data pointer *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xMemAlloc() is a clustered, remembering memory management routine. *
|
||||
* It uses its own tables for free and used memory blocks on private *
|
||||
* memory area. With xMemFree(), you can free this memory likewise *
|
||||
* the C free() routine, with xMemFreeAll() all memory at once. *
|
||||
* By changing the current remember key with xSetRemember() you can *
|
||||
* define a local memory area, which can be freed by only one call of *
|
||||
* xMemFreeAll() (see xSetRemember() / xGetRemember()). *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
void xMemAllo (Size, DataPointer)
|
||||
|
||||
unsigned long Size;
|
||||
unsigned char **DataPointer;
|
||||
{
|
||||
struct MEM_CHUNK *MemChunk, *MemChunkPred;
|
||||
struct MEM_ENTRY *MemEntry, *MemEntryPred;
|
||||
long int NewSize;
|
||||
unsigned short FoundFlag;
|
||||
#ifdef DEBUG
|
||||
unsigned char *ptr;
|
||||
#endif
|
||||
|
||||
while (Size % 4) Size++;
|
||||
|
||||
if (Size > (MEM_CHUNK_SIZE - sizeof(struct MEM_CHUNK) -
|
||||
sizeof(struct MEM_ENTRY)))
|
||||
{
|
||||
NewSize = Size + sizeof(struct MEM_CHUNK) + sizeof(struct MEM_ENTRY);
|
||||
|
||||
if (MemChunk = (*xRememberPtr))
|
||||
{
|
||||
do
|
||||
{
|
||||
MemChunkPred = MemChunk;
|
||||
} while (MemChunk = MemChunk->Succ);
|
||||
}
|
||||
else MemChunkPred = (struct MEM_CHUNK *) &(*xRememberPtr);
|
||||
|
||||
MemChunk = MemChunkPred->Succ = (struct MEM_CHUNK *) malloc (NewSize);
|
||||
xAllocatedMemory += NewSize;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (ptr = (unsigned char *) MemChunk; ptr < (unsigned char *)
|
||||
(MemChunk) + NewSize; ptr++)
|
||||
*ptr = (((unsigned long)ptr)&1) ? 0x55 : 0xAA;
|
||||
#endif
|
||||
|
||||
if (!MemChunk)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logPrintf (0, "Not enough memory...\r\n");
|
||||
#endif
|
||||
exit (1);
|
||||
}
|
||||
|
||||
MemChunk->Size = NewSize;
|
||||
MemChunk->Pred = MemChunkPred;
|
||||
MemChunk->Succ = NULL;
|
||||
MemChunk->FirstFreeMemEntry = NULL;
|
||||
MemChunk->FirstUsedMemEntry =
|
||||
MemEntry = (struct MEM_ENTRY *) ((unsigned char *)MemChunk +
|
||||
sizeof(struct MEM_CHUNK));
|
||||
|
||||
MemEntry->Size = Size;
|
||||
MemEntry->Pred = (struct MEM_ENTRY *) &MemChunk->FirstUsedMemEntry;
|
||||
MemEntry->Succ = NULL;
|
||||
|
||||
*DataPointer = (unsigned char *) ((unsigned char *)MemEntry +
|
||||
sizeof(struct MEM_ENTRY));
|
||||
#ifdef DEBUG_CALLS
|
||||
logPrintf (0, "xMemAlloc: %x, %d bytes\r\n", *DataPointer, Size);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
MemEntry = NULL;
|
||||
FoundFlag = 0;
|
||||
|
||||
if (MemChunk = (*xRememberPtr))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (MemEntry = MemChunk->FirstFreeMemEntry)
|
||||
do
|
||||
{
|
||||
if (Size <= MemEntry->Size) FoundFlag = 1;
|
||||
} while ((FoundFlag == 0) && (MemEntry = MemEntry->Succ));
|
||||
MemChunkPred = MemChunk;
|
||||
} while ((FoundFlag == 0) && (MemChunk = MemChunk->Succ));
|
||||
}
|
||||
else MemChunkPred = (struct MEM_CHUNK *) &(*xRememberPtr);
|
||||
|
||||
if (!MemEntry)
|
||||
{
|
||||
MemChunk = MemChunkPred->Succ =
|
||||
(struct MEM_CHUNK *) malloc (MEM_CHUNK_SIZE);
|
||||
xAllocatedMemory += MEM_CHUNK_SIZE;
|
||||
|
||||
#ifdef DEBUG
|
||||
for (ptr = (unsigned char *) MemChunk; ptr < (unsigned char *)
|
||||
(MemChunk) + MEM_CHUNK_SIZE; ptr++)
|
||||
*ptr = (((unsigned long)ptr)&1) ? 0x55 : 0xAA;
|
||||
#endif
|
||||
|
||||
if (!MemChunk)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logPrintf (0, "Not enough memory...\r\n");
|
||||
#endif
|
||||
exit (1);
|
||||
}
|
||||
|
||||
MemChunk->Size = MEM_CHUNK_SIZE;
|
||||
MemChunk->Pred = MemChunkPred;
|
||||
MemChunk->Succ = NULL;
|
||||
MemChunk->FirstUsedMemEntry = NULL;
|
||||
MemChunk->FirstFreeMemEntry =
|
||||
MemEntry = (struct MEM_ENTRY *)
|
||||
((unsigned char *)MemChunk + sizeof(struct MEM_CHUNK));
|
||||
|
||||
MemEntry->Size = MEM_CHUNK_SIZE - sizeof(struct MEM_CHUNK) -
|
||||
sizeof(struct MEM_ENTRY);
|
||||
MemEntry->Pred = (struct MEM_ENTRY *) &MemChunk->FirstFreeMemEntry;
|
||||
MemEntry->Succ = NULL;
|
||||
}
|
||||
|
||||
NewSize = MemEntry->Size - sizeof(struct MEM_ENTRY) - Size;
|
||||
|
||||
MemEntry->Size = Size;
|
||||
*DataPointer = (unsigned char *)
|
||||
((unsigned char *)MemEntry + sizeof(struct MEM_ENTRY));
|
||||
|
||||
#ifdef DEBUG
|
||||
for (ptr = *DataPointer; ptr < (unsigned char *)
|
||||
(*DataPointer) + Size; ptr++)
|
||||
{
|
||||
if (((unsigned long )ptr)&1)
|
||||
{ if (*ptr != 0x55)
|
||||
logPrintf (0, "freed memory was used\r\n"); }
|
||||
else { if (*ptr != 0xAA)
|
||||
logPrintf (0, "freed memory was used\r\n"); }
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MemEntry->Succ)
|
||||
((struct MEM_ENTRY *)MemEntry->Succ)->Pred = MemEntry->Pred;
|
||||
((struct MEM_ENTRY *)MemEntry->Pred)->Succ = MemEntry->Succ;
|
||||
|
||||
if (MemChunk->FirstUsedMemEntry)
|
||||
MemChunk->FirstUsedMemEntry->Pred = MemEntry;
|
||||
MemEntry->Succ = MemChunk->FirstUsedMemEntry;
|
||||
MemChunk->FirstUsedMemEntry = MemEntry;
|
||||
MemEntry->Pred = (struct MEM_ENTRY *) &MemChunk->FirstUsedMemEntry;
|
||||
|
||||
if (NewSize > 0)
|
||||
{
|
||||
MemEntry = (struct MEM_ENTRY *)
|
||||
((unsigned char *)MemEntry + sizeof(struct MEM_ENTRY) + Size);
|
||||
MemEntry->Size = NewSize;
|
||||
|
||||
if (MemChunk->FirstFreeMemEntry)
|
||||
MemChunk->FirstFreeMemEntry->Pred = MemEntry;
|
||||
MemEntry->Succ = MemChunk->FirstFreeMemEntry;
|
||||
MemChunk->FirstFreeMemEntry = MemEntry;
|
||||
MemEntry->Pred = (struct MEM_ENTRY *) &MemChunk->FirstFreeMemEntry;
|
||||
}
|
||||
#ifdef DEBUG_CALLS
|
||||
logPrintf (0, "xMemAlloc: %x, %d bytes\r\n", *DataPointer, Size);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xMemFree *
|
||||
* *
|
||||
* parameter : DataPointer - data pointer *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xMemFree() frees with xMemAlloc() allocated memory. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
void xMemFre (DataPointer)
|
||||
|
||||
unsigned char *DataPointer;
|
||||
{
|
||||
struct MEM_CHUNK *MemChunk, *MemChunkPred;
|
||||
struct MEM_ENTRY *MemEntry, *TempEntry, *PredEntry, *SuccEntry;
|
||||
unsigned short FoundFlag;
|
||||
#ifdef DEBUG
|
||||
unsigned char *ptr;
|
||||
#endif
|
||||
|
||||
if (!DataPointer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
MemEntry = NULL;
|
||||
FoundFlag = 0;
|
||||
|
||||
if (MemChunk = (*xRememberPtr))
|
||||
do
|
||||
{
|
||||
if (MemEntry = MemChunk->FirstUsedMemEntry)
|
||||
do
|
||||
{
|
||||
if (DataPointer == (unsigned char *) ((unsigned char *) MemEntry +
|
||||
sizeof(struct MEM_ENTRY))) FoundFlag = 1;
|
||||
} while ((FoundFlag == 0) && (MemEntry = MemEntry->Succ));
|
||||
} while ((FoundFlag == 0) && (MemChunk = MemChunk->Succ));
|
||||
|
||||
if (FoundFlag == 1)
|
||||
{
|
||||
#ifdef DEBUG_CALLS
|
||||
logPrintf (0, "xMemFree: %x, %d bytes\r\n", DataPointer, MemEntry->Size);
|
||||
#endif
|
||||
if (MemEntry->Succ)
|
||||
((struct MEM_ENTRY *)MemEntry->Succ)->Pred = MemEntry->Pred;
|
||||
((struct MEM_ENTRY *)MemEntry->Pred)->Succ = MemEntry->Succ;
|
||||
|
||||
if (!MemChunk->FirstUsedMemEntry)
|
||||
{
|
||||
if (MemChunk->Succ)
|
||||
((struct MEM_CHUNK *)MemChunk->Succ)->Pred = MemChunk->Pred;
|
||||
((struct MEM_CHUNK *)MemChunk->Pred)->Succ = MemChunk->Succ;
|
||||
if (xAllocatedMemory > 0) xAllocatedMemory -= MemChunk->Size;
|
||||
free (MemChunk);
|
||||
return;
|
||||
}
|
||||
|
||||
FoundFlag = 0;
|
||||
PredEntry = NULL;
|
||||
SuccEntry = NULL;
|
||||
if (TempEntry = MemChunk->FirstFreeMemEntry)
|
||||
do
|
||||
{
|
||||
if ((struct MEM_ENTRY *)((unsigned char *)TempEntry +
|
||||
TempEntry->Size + sizeof(struct MEM_ENTRY)) == MemEntry)
|
||||
{
|
||||
FoundFlag ++;
|
||||
PredEntry = TempEntry;
|
||||
}
|
||||
if ((struct MEM_ENTRY *)((unsigned char *)MemEntry +
|
||||
MemEntry->Size + sizeof(struct MEM_ENTRY)) == TempEntry)
|
||||
{
|
||||
FoundFlag ++;
|
||||
SuccEntry = TempEntry;
|
||||
}
|
||||
} while ((FoundFlag != 2) && (TempEntry = TempEntry->Succ));
|
||||
|
||||
if (PredEntry)
|
||||
{
|
||||
if (SuccEntry)
|
||||
{
|
||||
/* Vorgdnger + Nachfolger */
|
||||
|
||||
if (SuccEntry->Succ)
|
||||
((struct MEM_ENTRY *)SuccEntry->Succ)->Pred = SuccEntry->Pred;
|
||||
((struct MEM_ENTRY *)SuccEntry->Pred)->Succ = SuccEntry->Succ;
|
||||
|
||||
PredEntry->Size += MemEntry->Size + sizeof(struct MEM_ENTRY) +
|
||||
SuccEntry->Size + sizeof(struct MEM_ENTRY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nur Vorgaenger */
|
||||
|
||||
PredEntry->Size += MemEntry->Size + sizeof(struct MEM_ENTRY);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
for (ptr = (unsigned char *) (PredEntry) + sizeof(struct MEM_ENTRY);
|
||||
ptr < (unsigned char *) (PredEntry) + sizeof(struct MEM_ENTRY) +
|
||||
PredEntry->Size; ptr++)
|
||||
*ptr = (((unsigned long)ptr)&1) ? 0x55 : 0xAA;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SuccEntry)
|
||||
{
|
||||
/* nur Nachfolger */
|
||||
|
||||
if (SuccEntry->Succ)
|
||||
((struct MEM_ENTRY *)SuccEntry->Succ)->Pred = SuccEntry->Pred;
|
||||
((struct MEM_ENTRY *)SuccEntry->Pred)->Succ = SuccEntry->Succ;
|
||||
|
||||
MemEntry->Size += SuccEntry->Size + sizeof(struct MEM_ENTRY);
|
||||
}
|
||||
|
||||
if (MemChunk->FirstFreeMemEntry)
|
||||
MemChunk->FirstFreeMemEntry->Pred = MemEntry;
|
||||
MemEntry->Succ = MemChunk->FirstFreeMemEntry;
|
||||
MemChunk->FirstFreeMemEntry = MemEntry;
|
||||
MemEntry->Pred = (struct MEM_ENTRY *) &MemChunk->FirstFreeMemEntry;
|
||||
#ifdef DEBUG
|
||||
for (ptr = (unsigned char *) (MemEntry) + sizeof(struct MEM_ENTRY);
|
||||
ptr < (unsigned char *) (MemEntry) + sizeof(struct MEM_ENTRY) +
|
||||
MemEntry->Size; ptr++)
|
||||
*ptr = (((unsigned long)ptr)&1) ? 0x55 : 0xAA;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_CALLS
|
||||
else
|
||||
logPrintf (0, "xMemFree: tried to free unallocated data %x\r\n", DataPointer);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xMemFreeAll *
|
||||
* *
|
||||
* parameter : RememberPtr *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xMemFreeAll() frees all with xMemAlloc() allocated memory. If Re- *
|
||||
* memberPtr is not NULL, the MEM_CHUNK structure from the specified *
|
||||
* Address is freed, otherwise the natural MEM_CHUNK will be done. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
void xMemFreeAll (RememberPtr)
|
||||
|
||||
struct MEM_CHUNK **RememberPtr;
|
||||
{
|
||||
struct MEM_CHUNK *MemChunk, *MemChunkPred;
|
||||
|
||||
if (RememberPtr)
|
||||
{
|
||||
if (MemChunkPred = (*RememberPtr))
|
||||
do
|
||||
{
|
||||
MemChunk = MemChunkPred->Succ;
|
||||
if (xAllocatedMemory > 0) xAllocatedMemory -= MemChunkPred->Size;
|
||||
free (MemChunkPred);
|
||||
} while (MemChunkPred = MemChunk);
|
||||
*RememberPtr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (MemChunkPred = (*xRememberPtr))
|
||||
do
|
||||
{
|
||||
MemChunk = MemChunkPred->Succ;
|
||||
if (xAllocatedMemory > 0) xAllocatedMemory -= MemChunkPred->Size;
|
||||
free (MemChunkPred);
|
||||
} while (MemChunkPred = MemChunk);
|
||||
*xRememberPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xMemMerge *
|
||||
* *
|
||||
* parameter : RememberPtr *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xMemMerge() merges the memory area pointed to by RememberKey with *
|
||||
* the currently used in xRememberPtr. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
void xMemMerge (RememberPtr)
|
||||
|
||||
struct MEM_CHUNK **RememberPtr;
|
||||
{
|
||||
struct MEM_CHUNK *MemChunk, *MemChunkPred;
|
||||
|
||||
if (RememberPtr)
|
||||
{
|
||||
if (MemChunk = (*xRememberPtr))
|
||||
{
|
||||
while (MemChunk->Succ) MemChunk = MemChunk->Succ;
|
||||
MemChunk->Succ = (*RememberPtr);
|
||||
*RememberPtr = NULL;
|
||||
}
|
||||
else (*xRememberPtr = *RememberPtr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xGetRemember *
|
||||
* *
|
||||
* parameter : none *
|
||||
* *
|
||||
* return : pointer to a MEM_CHUNK tree *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xGetRemember() returns the currently used MEM_CHUNK tree. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
struct MEM_CHUNK **xGetRemember ()
|
||||
{
|
||||
return (xRememberPtr);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xSetRemember *
|
||||
* *
|
||||
* parameter : pointer to a MEM_CHUNK tree *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xSetRemember() redefines the currently used MEM_CHUNK pointer. If *
|
||||
* RememberPtr is NULL, the natural MEM_CHUNK is reloaded. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
void xSetRemember (RememberPtr)
|
||||
|
||||
struct MEM_CHUNK **RememberPtr;
|
||||
{
|
||||
if (RememberPtr)
|
||||
xRememberPtr = RememberPtr;
|
||||
else
|
||||
xRememberPtr = &xRememberKey;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xPrintMemList *
|
||||
* *
|
||||
* parameter : pointer to a MEM_CHUNK tree *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xPrintMemList() prints the currently allocated memory blocks of *
|
||||
* the specified RememberPtr. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
void xPrintMemList (Remember)
|
||||
|
||||
struct MEM_CHUNK **Remember;
|
||||
{
|
||||
struct MEM_CHUNK *MemChunk;
|
||||
struct MEM_ENTRY *MemEntry;
|
||||
|
||||
fprintf (stderr, "MemChunkPtr = %x\n", (int) Remember);
|
||||
|
||||
if (MemChunk = *Remember)
|
||||
do
|
||||
{
|
||||
fprintf (stderr, "\tMemChunk at %x with Size %d\n", (int) MemChunk,
|
||||
(int) MemChunk->Size);
|
||||
|
||||
if (MemEntry = MemChunk->FirstFreeMemEntry)
|
||||
do
|
||||
{
|
||||
fprintf (stderr, "\t\tFree MemEntry at %x (%x) with Size %d\n",
|
||||
(int) MemEntry, (int)((unsigned char *)MemEntry +
|
||||
sizeof(struct MEM_ENTRY)), (int) MemEntry->Size);
|
||||
|
||||
} while (MemEntry = MemEntry->Succ);
|
||||
|
||||
if (MemEntry = MemChunk->FirstUsedMemEntry)
|
||||
do
|
||||
{
|
||||
fprintf (stderr, "\t\tUsed MemEntry at %x (%x) with Size %d\n",
|
||||
(int) MemEntry, (int)((unsigned char *)MemEntry +
|
||||
sizeof(struct MEM_ENTRY)), (int) MemEntry->Size);
|
||||
|
||||
} while (MemEntry = MemEntry->Succ);
|
||||
|
||||
} while (MemChunk = MemChunk->Succ);
|
||||
else fprintf (stderr, "\tNo current MemChunk\n");
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xGetMemSize *
|
||||
* *
|
||||
* parameter : pointer to a MEM_CHUNK tree *
|
||||
* *
|
||||
* return : none *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xGetMemSize() gets the size of the currently allocated memory *
|
||||
* blocks of the specified (or natural if NULL) RememberPtr *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
|
||||
unsigned long xGetMemSize (RememberPtr)
|
||||
|
||||
struct MEM_CHUNK **RememberPtr;
|
||||
{
|
||||
struct MEM_CHUNK *MemChunk;
|
||||
struct MEM_ENTRY *MemEntry;
|
||||
unsigned long Result = 0;
|
||||
|
||||
if (RememberPtr) MemChunk = *RememberPtr;
|
||||
else MemChunk = xRememberKey;
|
||||
|
||||
if (MemChunk)
|
||||
do { Result += (unsigned long) MemChunk->Size; }
|
||||
while (MemChunk = MemChunk->Succ);
|
||||
|
||||
return (Result);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* *
|
||||
* function : xSetText *
|
||||
* *
|
||||
* arguments : xText - pointer to a string *
|
||||
* *
|
||||
* return : pointer to an new allocated string *
|
||||
* *
|
||||
*-----------------------------------------------------------------------*
|
||||
* *
|
||||
* xSetText() allocates memory for the string pointed to by 'xText' *
|
||||
* and duplicates it. *
|
||||
* *
|
||||
*************************************************************************/
|
||||
|
||||
char *xSetText (xText)
|
||||
|
||||
char *xText;
|
||||
{
|
||||
char *NewText;
|
||||
|
||||
if (!xText) return (NULL);
|
||||
|
||||
xMemAlloc (strlen(xText) + 1, &NewText);
|
||||
strcpy (NewText, xText);
|
||||
|
||||
return (NewText);
|
||||
}
|
@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@ -1,83 +0,0 @@
|
||||
##############################################################
|
||||
### ###
|
||||
### Makefile: local makefile for libsi ###
|
||||
### ###
|
||||
##############################################################
|
||||
|
||||
## $Revision: 1.4 $
|
||||
## $Date: 2001/10/07 10:24:46 $
|
||||
## $Author: hakenes $
|
||||
##
|
||||
## (C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
##
|
||||
## dtv_scan 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, or (at your option)
|
||||
## any later version.
|
||||
##
|
||||
## dtv_scan 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 may have received a copy of the GNU General Public License
|
||||
## along with dtv_scan; see the file COPYING. If not, write to the
|
||||
## Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
## Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
CC ?= gcc
|
||||
CFLAGS ?= -O2 -g -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-DNAPI -Wimplicit -D__USE_FIXED_PROTOTYPES__ # -ansi -pedantic
|
||||
|
||||
INCDIRS = -Iinclude -I../include
|
||||
DISTDIR = ../lib
|
||||
DISTINCDIR = ../include
|
||||
INCLUDES = include/libsi.h include/si_tables.h
|
||||
MAKEDEPEND = gcc -M
|
||||
|
||||
LIBDIRS = -L. -L../lib
|
||||
LIBS = -lsi -llx
|
||||
|
||||
AR = ar
|
||||
ARFLAGS = ru
|
||||
RANLIB = ranlib
|
||||
|
||||
SILIB = libsi.a
|
||||
OBJS = si_parser.o si_debug_services.o
|
||||
|
||||
all : $(SILIB)
|
||||
|
||||
clean :
|
||||
@echo cleaning workspace...
|
||||
@rm -f $(OBJS) $(SILIB) *~
|
||||
@rm -f Makefile.dep
|
||||
|
||||
depend : Makefile.dep
|
||||
Makefile.dep :
|
||||
@echo "updating dependencies..."
|
||||
@$(MAKEDEPEND) $(INCDIRS) $(OBJS:%.o=%.c) $(SITEST_OBJS:%.o=%.c) \
|
||||
$(SISCAN_OBJS:%.o=%.c) > Makefile.dep
|
||||
|
||||
new : clean depend all
|
||||
|
||||
dist: all
|
||||
@echo "distributing $(SILIB) to $(DISTDIR)..."
|
||||
@cp $(SILIB) $(DISTDIR)
|
||||
@cp $(INCLUDES) $(DISTINCDIR)
|
||||
@$(RANLIB) $(DISTDIR)/$(SILIB)
|
||||
|
||||
$(SILIB) : $(OBJS)
|
||||
@echo updating library...
|
||||
@$(AR) $(ARFLAGS) $(SILIB) $(OBJS)
|
||||
@$(RANLIB) $(SILIB)
|
||||
|
||||
.c.o :
|
||||
@echo compiling $<...
|
||||
@$(CC) $(DEFINES) $(CFLAGS) $(INCDIRS) -c $<
|
||||
|
||||
-include Makefile.dep
|
@ -1,2 +0,0 @@
|
||||
DVB - System Information Library
|
||||
================================
|
File diff suppressed because it is too large
Load Diff
@ -1,674 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// ///
|
||||
/// si_debug_services.c: debugging functions for libsi ///
|
||||
/// ///
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// $Revision: 1.5 $
|
||||
// $Date: 2003/02/04 18:45:35 $
|
||||
// $Author: hakenes $
|
||||
//
|
||||
// (C) 2001-03 Rolf Hakenes <hakenes@hippomi.de>, under the
|
||||
// GNU GPL with contribution of Oleg Assovski,
|
||||
// www.satmania.com
|
||||
//
|
||||
// libsi 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, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// libsi 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 may have received a copy of the GNU General Public License
|
||||
// along with libsi; see the file COPYING. If not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../liblx/liblx.h"
|
||||
#include "libsi.h"
|
||||
#include "si_tables.h"
|
||||
#include "si_debug_services.h"
|
||||
|
||||
|
||||
void siDebugServices (struct LIST *Services)
|
||||
{
|
||||
struct Service *Service;
|
||||
|
||||
if (!Services) return;
|
||||
|
||||
xForeach (Services, Service)
|
||||
{
|
||||
printf ("Service\n=======\n");
|
||||
printf (" ServiceID: %d\n", Service->ServiceID);
|
||||
printf (" TransportStreamID: %d\n", Service->TransportStreamID);
|
||||
printf (" OriginalNetworkID: %d\n", Service->OriginalNetworkID);
|
||||
printf (" SdtVersion: %d\n", Service->SdtVersion);
|
||||
printf (" Status: ");
|
||||
if (GetScheduleFlag (Service->Status))
|
||||
printf ("SCHEDULE_INFO ");
|
||||
if (GetPresentFollowing(Service->Status))
|
||||
printf ("PRESENT_FOLLOWING ");
|
||||
switch (GetRunningStatus (Service->Status))
|
||||
{
|
||||
case RUNNING_STATUS_NOT_RUNNING:
|
||||
printf ("RUNNING_STATUS_NOT_RUNNING\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_AWAITING:
|
||||
printf ("RUNNING_STATUS_AWAITING\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_PAUSING:
|
||||
printf ("RUNNING_STATUS_PAUSING\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_RUNNING:
|
||||
printf ("RUNNING_STATUS_RUNNING\n");
|
||||
break;
|
||||
}
|
||||
siDebugDescriptors (" ", Service->Descriptors);
|
||||
siDebugEvents (" ", Service->Events);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void siDebugService (struct Service *Service)
|
||||
{
|
||||
if (!Service) return;
|
||||
|
||||
printf ("Service\r\n=======\r\n");
|
||||
printf (" ServiceID: %d\r\n", Service->ServiceID);
|
||||
printf (" TransportStreamID: %d\r\n", Service->TransportStreamID);
|
||||
printf (" OriginalNetworkID: %d\r\n", Service->OriginalNetworkID);
|
||||
printf (" SdtVersion: %d\r\n", Service->SdtVersion);
|
||||
printf (" Status: ");
|
||||
if (GetScheduleFlag (Service->Status))
|
||||
printf ("SCHEDULE_INFO ");
|
||||
if (GetPresentFollowing(Service->Status))
|
||||
printf ("PRESENT_FOLLOWING ");
|
||||
switch (GetRunningStatus (Service->Status))
|
||||
{
|
||||
case RUNNING_STATUS_NOT_RUNNING:
|
||||
printf ("RUNNING_STATUS_NOT_RUNNING\r\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_AWAITING:
|
||||
printf ("RUNNING_STATUS_AWAITING\r\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_PAUSING:
|
||||
printf ("RUNNING_STATUS_PAUSING\r\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_RUNNING:
|
||||
printf ("RUNNING_STATUS_RUNNING\r\n");
|
||||
break;
|
||||
}
|
||||
siDebugDescriptors ("\r ", Service->Descriptors);
|
||||
siDebugEvents ("\r ", Service->Events);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void siDebugEvents (char *Prepend, struct LIST *EventList)
|
||||
{
|
||||
struct Event *Event;
|
||||
char NewPrepend[32];
|
||||
|
||||
if (!EventList) return;
|
||||
|
||||
xForeach (EventList, Event)
|
||||
{
|
||||
printf ("%sEvent\n%s=====\n", Prepend, Prepend);
|
||||
printf ("%s EventID: %d\n", Prepend, Event->EventID);
|
||||
printf ("%s ServiceID: %d\n", Prepend, Event->ServiceID);
|
||||
printf ("%s TransportStreamID: %d\n", Prepend, Event->TransportStreamID);
|
||||
printf ("%s OriginalNetworkID: %d\n", Prepend, Event->OriginalNetworkID);
|
||||
printf ("%s EitVersion: %d\n", Prepend, Event->EitVersion);
|
||||
printf ("%s StartTime: %s", Prepend, ctime (&Event->StartTime));
|
||||
printf ("%s Duration: %d Minuten\n", Prepend, Event->Duration/60);
|
||||
printf ("%s Status: ");
|
||||
switch (GetRunningStatus (Event->Status))
|
||||
{
|
||||
case RUNNING_STATUS_NOT_RUNNING:
|
||||
printf ("RUNNING_STATUS_NOT_RUNNING\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_AWAITING:
|
||||
printf ("RUNNING_STATUS_AWAITING\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_PAUSING:
|
||||
printf ("RUNNING_STATUS_PAUSING\n");
|
||||
break;
|
||||
|
||||
case RUNNING_STATUS_RUNNING:
|
||||
printf ("RUNNING_STATUS_RUNNING\n");
|
||||
break;
|
||||
}
|
||||
sprintf (NewPrepend, "%s ", Prepend);
|
||||
siDebugDescriptors (NewPrepend, Event->Descriptors);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void siDebugPrograms (char *Prepend, struct LIST *ProgramList)
|
||||
{
|
||||
struct Program *Program;
|
||||
char NewPrepend[32];
|
||||
|
||||
if (!ProgramList) return;
|
||||
|
||||
xForeach (ProgramList, Program)
|
||||
{
|
||||
printf ("%sProgram\n%s=======\n", Prepend, Prepend);
|
||||
printf ("%s ProgramID: %d\n", Prepend, Program->ProgramID);
|
||||
printf ("%s TransportStreamID: %d\n", Prepend, Program->TransportStreamID);
|
||||
printf ("%s NetworkPID: %d\n", Prepend, Program->NetworkPID);
|
||||
printf ("%s PatVersion: %d\n", Prepend, Program->PatVersion);
|
||||
|
||||
sprintf (NewPrepend, "%s ", Prepend);
|
||||
siDebugPids (NewPrepend, Program->Pids);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void siDebugProgram (struct Program *Program)
|
||||
{
|
||||
if (!Program) return;
|
||||
|
||||
printf ("Program\r\n=======\r\n");
|
||||
printf (" ProgramID: %d\r\n", Program->ProgramID);
|
||||
printf (" TransportStreamID: %d\r\n", Program->TransportStreamID);
|
||||
printf (" NetworkPID: %d\r\n", Program->NetworkPID);
|
||||
printf (" PatVersion: %d\r\n", Program->PatVersion);
|
||||
|
||||
siDebugPids ("\r ", Program->Pids);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void siDebugPids (char *Prepend, struct LIST *PidList)
|
||||
{
|
||||
struct Pid *Pid;
|
||||
struct PidInfo *PidInfo;
|
||||
char NewPrepend[32];
|
||||
int index;
|
||||
|
||||
if (!PidList) return;
|
||||
|
||||
xForeach (PidList, Pid)
|
||||
{
|
||||
printf ("%sPid\n%s===\n", Prepend, Prepend);
|
||||
printf ("%s ProgramID: %d\n", Prepend, Pid->ProgramID);
|
||||
printf ("%s PcrPid: %d\n", Prepend, Pid->PcrPID);
|
||||
printf ("%s PmtVersion: %d\n", Prepend, Pid->PmtVersion);
|
||||
sprintf (NewPrepend, "%s ", Prepend);
|
||||
siDebugDescriptors (NewPrepend, Pid->Descriptors);
|
||||
|
||||
xForeach (Pid->InfoList, PidInfo)
|
||||
{
|
||||
printf ("%s PidInfo\n%s =======\n", Prepend, Prepend);
|
||||
index = PidInfo->StreamType;
|
||||
if (index > 0x0F && index <= 0x7F) index = 0x0E;
|
||||
if (index >= 0x80) index = 0x0F;
|
||||
printf ("%s StreamType: %s\n", Prepend, StreamTypes[index]);
|
||||
printf ("%s ElementaryPid: %d\n", Prepend, PidInfo->ElementaryPid);
|
||||
|
||||
sprintf (NewPrepend, "%s ", Prepend);
|
||||
siDebugDescriptors (NewPrepend, PidInfo->Descriptors);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void siDebugDescriptors (char *Prepend, struct LIST *Descriptors)
|
||||
{
|
||||
struct Descriptor *Descriptor;
|
||||
int i;
|
||||
|
||||
xForeach (Descriptors, Descriptor)
|
||||
{
|
||||
switch (DescriptorTag (Descriptor))
|
||||
{
|
||||
case DESCR_ANCILLARY_DATA:
|
||||
printf ("%sDescriptor: Ancillary Data\n", Prepend);
|
||||
printf ("%s Identifier: ", Prepend);
|
||||
if (((struct AncillaryDataDescriptor *)Descriptor)->
|
||||
Identifier & ANCILLARY_DATA_DVD_VIDEO)
|
||||
printf ("DVD-Video Ancillary Data ");
|
||||
if (((struct AncillaryDataDescriptor *)Descriptor)->
|
||||
Identifier & ANCILLARY_DATA_EXTENDED)
|
||||
printf ("Extended Ancillary Data ");
|
||||
if (((struct AncillaryDataDescriptor *)Descriptor)->
|
||||
Identifier & ANCILLARY_DATA_SWITCHING)
|
||||
printf ("Announcement Switching Data ");
|
||||
if (((struct AncillaryDataDescriptor *)Descriptor)->
|
||||
Identifier & ANCILLARY_DATA_DAB)
|
||||
printf ("DAB Ancillary Data ");
|
||||
if (((struct AncillaryDataDescriptor *)Descriptor)->
|
||||
Identifier & ANCILLARY_DATA_SCALE_FACTOR)
|
||||
printf ("Scale Factor Error Check (ScF-CRC) ");
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case DESCR_NW_NAME:
|
||||
printf ("%sDescriptor: Network Name\n", Prepend);
|
||||
printf ("%s Name: %s\n", Prepend, xName (Descriptor));
|
||||
break;
|
||||
|
||||
case DESCR_BOUQUET_NAME:
|
||||
printf ("%sDescriptor: Bouquet Name\n", Prepend);
|
||||
printf ("%s Name: %s\n", Prepend, xName (Descriptor));
|
||||
break;
|
||||
|
||||
case DESCR_COMPONENT:
|
||||
printf ("%sDescriptor: Component\n", Prepend);
|
||||
printf ("%s Text: %s\n", Prepend, xName (Descriptor));
|
||||
printf ("%s Content/Type: ", Prepend);
|
||||
for (i = 0; i < COMPONENT_TYPE_NUMBER; i++)
|
||||
if ((((struct ComponentDescriptor *)Descriptor)->
|
||||
StreamContent == ComponentTypes[i].Content) &&
|
||||
(((struct ComponentDescriptor *)Descriptor)->
|
||||
ComponentType == ComponentTypes[i].Type))
|
||||
{ printf ("%s\n", ComponentTypes[i].Description); break; }
|
||||
if (i == COMPONENT_TYPE_NUMBER) { printf ("unbekannt\n"); }
|
||||
printf ("%s ComponentTag: 0x%02x\n", Prepend,
|
||||
((struct ComponentDescriptor *)Descriptor)->ComponentTag);
|
||||
printf ("%s LanguageCode: %s\n", Prepend,
|
||||
((struct ComponentDescriptor *)Descriptor)->LanguageCode);
|
||||
break;
|
||||
|
||||
case DESCR_SERVICE:
|
||||
printf ("%sDescriptor: Service\n", Prepend);
|
||||
printf ("%s Name: %s\n", Prepend, xName (Descriptor));
|
||||
printf ("%s ServiceType: ", Prepend);
|
||||
for (i = 0; i < SERVICE_TYPE_NUMBER; i++)
|
||||
if ((((struct ServiceDescriptor *)Descriptor)->
|
||||
ServiceType == ServiceTypes[i].Type))
|
||||
{ printf ("%s\n", ServiceTypes[i].Description); break; }
|
||||
if (i == SERVICE_TYPE_NUMBER) { printf ("unbekannt\n"); }
|
||||
printf ("%s ServiceProvider: %s\n", Prepend,
|
||||
((struct ServiceDescriptor *)Descriptor)->ServiceProvider);
|
||||
break;
|
||||
|
||||
case DESCR_COUNTRY_AVAIL:
|
||||
printf ("%sDescriptor: Country Availability\n", Prepend);
|
||||
printf ("%s Type: %s\n", Prepend, (((struct CountryAvailabilityDescriptor *)Descriptor)->
|
||||
AvailibilityFlag == COUNTRIES_ARE_AVAILABLE) ? "countries are available" :
|
||||
"countries are unavailable");
|
||||
{
|
||||
char *cptr = ((struct CountryAvailabilityDescriptor *)Descriptor)->CountryCodes; int j;
|
||||
for (j = 0; j < ((struct CountryAvailabilityDescriptor *)Descriptor)->Amount; j++)
|
||||
{ printf ("%s Country: %s\n", Prepend, cptr); cptr += 4; }
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_SHORT_EVENT:
|
||||
printf ("%sDescriptor: Short Event\n", Prepend);
|
||||
printf ("%s Name: %s\n", Prepend, xName (Descriptor));
|
||||
printf ("%s LanguageCode: %s\n", Prepend,
|
||||
((struct ShortEventDescriptor *)Descriptor)->LanguageCode);
|
||||
printf ("%s Text: %s\n", Prepend,
|
||||
((struct ShortEventDescriptor *)Descriptor)->Text);
|
||||
break;
|
||||
|
||||
case DESCR_EXTENDED_EVENT:
|
||||
{
|
||||
struct ExtendedEventItem *Item;
|
||||
|
||||
printf ("%sDescriptor: Extended Event\n", Prepend);
|
||||
printf ("%s Text: %s\n", Prepend, xName (Descriptor));
|
||||
printf ("%s DescriptorNumber: %d\n", Prepend,
|
||||
((struct ExtendedEventDescriptor *)Descriptor)->DescriptorNumber);
|
||||
printf ("%s LastDescriptorNumber: %d\n", Prepend,
|
||||
((struct ExtendedEventDescriptor *)Descriptor)->LastDescriptorNumber);
|
||||
printf ("%s LanguageCode: %s\n", Prepend,
|
||||
((struct ExtendedEventDescriptor *)Descriptor)->LanguageCode);
|
||||
xForeach (((struct ExtendedEventDescriptor *)Descriptor)->Items, Item)
|
||||
{
|
||||
printf ("%s Item:\n", Prepend);
|
||||
printf ("%s Description: %s\n", Prepend, xName(Item));
|
||||
printf ("%s Text: %s\n", Prepend, Item->Text);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_CA_IDENT:
|
||||
printf ("%sDescriptor: Conditional Access Identity\n", Prepend);
|
||||
{
|
||||
int j,k;
|
||||
for (j = 0; j < ((struct CaIdentifierDescriptor *)Descriptor)->Amount; j++)
|
||||
{
|
||||
printf ("%s SystemID: 0x%04x", Prepend, GetCaIdentifierID (Descriptor, j));
|
||||
k = GetCaIdentifierID (Descriptor, j) >> 8;
|
||||
if (k < 0 || k > MAX_CA_IDENT) printf (" (unknown)\n");
|
||||
else printf (" (%s)\n", CaIdents[k]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_CA:
|
||||
{
|
||||
int j,k;
|
||||
|
||||
printf ("%sDescriptor: Conditional Access\n", Prepend);
|
||||
printf ("%s CA type: 0x%04x", Prepend, (((struct CaDescriptor *)Descriptor)->CA_type));
|
||||
k = (((struct CaDescriptor *)Descriptor)->CA_type) >> 8;
|
||||
if (k < 0 || k > MAX_CA_IDENT) printf (" (unknown)\n");
|
||||
else printf (" (%s)\n", CaIdents[k]);
|
||||
printf ("%s CA PID: %d\n", Prepend, (((struct CaDescriptor *)Descriptor)->CA_PID));
|
||||
printf ("%s ProviderID: 0x%04X\n", Prepend, (((struct CaDescriptor *)Descriptor)->ProviderID));
|
||||
if (((struct CaDescriptor *)Descriptor)->DataLength > 0)
|
||||
{
|
||||
printf ("%s CA data:", Prepend);
|
||||
for (j = 0; j < ((struct CaDescriptor *)Descriptor)->DataLength; j++)
|
||||
printf (" 0x%02x", GetCaData (Descriptor, j));
|
||||
printf ("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_CONTENT:
|
||||
printf ("%sDescriptor: Content\n", Prepend);
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < ((struct ContentDescriptor *)Descriptor)->Amount; j++)
|
||||
{
|
||||
printf ("%s Content: ", Prepend);
|
||||
for (i = 0; i < CONTENT_TYPE_NUMBER; i++)
|
||||
if ((GetContentContentNibble1(Descriptor, j) == ContentTypes[i].Nibble1) &&
|
||||
(GetContentContentNibble2(Descriptor, j) == ContentTypes[i].Nibble2))
|
||||
{ printf ("%s\n", ContentTypes[i].Description); break; }
|
||||
if (i == CONTENT_TYPE_NUMBER) { printf ("unbekannt\n"); }
|
||||
printf ("%s User-Nibble 1: 0x%1x\n", Prepend, GetContentUserNibble1(Descriptor, j));
|
||||
printf ("%s User-Nibble 2: 0x%1x\n", Prepend, GetContentUserNibble2(Descriptor, j));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_PARENTAL_RATING:
|
||||
{
|
||||
struct ParentalRating *Rating;
|
||||
|
||||
printf ("%sDescriptor: Parental Rating\n", Prepend);
|
||||
xForeach (((struct ParentalRatingDescriptor *)Descriptor)->Ratings, Rating)
|
||||
{
|
||||
printf ("%s Rating:\n");
|
||||
printf ("%s LanguageCode: %s\n", Rating->LanguageCode);
|
||||
printf ("%s Rating: ");
|
||||
if (Rating->Rating == 0) printf ("(undefined)\n");
|
||||
else { if (Rating->Rating <= 0x10) printf ("minimum age is %d\n", Rating->Rating + 3);
|
||||
else printf ("(rating is provider defined)\n"); }
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_NVOD_REF:
|
||||
{
|
||||
struct NvodReferenceItem *Item;
|
||||
|
||||
printf ("%sDescriptor: NVOD Reference\n", Prepend);
|
||||
xForeach (((struct NvodReferenceDescriptor *)Descriptor)->Items, Item)
|
||||
{
|
||||
printf ("%s Item:\n", Prepend);
|
||||
printf ("%s ServiceID: %d\n", Prepend, Item->ServiceID);
|
||||
printf ("%s TransportStreamID: %d\n", Prepend, Item->TransportStreamID);
|
||||
printf ("%s OriginalNetworkID: %d\n", Prepend, Item->OriginalNetworkID);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_TIME_SHIFTED_SERVICE:
|
||||
printf ("%sDescriptor: Time Shifted Service\n", Prepend);
|
||||
printf ("%s ReferenceServiceID: %d\n", Prepend,
|
||||
((struct TimeShiftedServiceDescriptor *)
|
||||
Descriptor)->ReferenceServiceID);
|
||||
break;
|
||||
|
||||
case DESCR_TIME_SHIFTED_EVENT:
|
||||
printf ("%sDescriptor: Time Shifted Event\n", Prepend);
|
||||
printf ("%s ReferenceServiceID: %d\n", Prepend,
|
||||
((struct TimeShiftedEventDescriptor *)
|
||||
Descriptor)->ReferenceServiceID);
|
||||
printf ("%s ReferenceEventID: %d\n", Prepend,
|
||||
((struct TimeShiftedEventDescriptor *)
|
||||
Descriptor)->ReferenceEventID);
|
||||
break;
|
||||
|
||||
case DESCR_ISO_639_LANGUAGE:
|
||||
printf ("%sDescriptor: ISO 639 Language\n", Prepend);
|
||||
printf ("%s LanguageCode: %s\n", Prepend,
|
||||
((struct Iso639LanguageDescriptor *)Descriptor)->LanguageCode);
|
||||
break;
|
||||
|
||||
case DESCR_STREAM_ID:
|
||||
printf ("%sDescriptor: Stream Identifier\n", Prepend);
|
||||
printf ("%s ComponentTag: %d\n", Prepend,
|
||||
((struct StreamIdentifierDescriptor *)Descriptor)->ComponentTag);
|
||||
break;
|
||||
|
||||
case DESCR_LINKAGE:
|
||||
printf ("%sDescriptor: Linkage\n", Prepend);
|
||||
printf ("%s TransportStreamID: %d\n", Prepend,
|
||||
((struct LinkageDescriptor *)Descriptor)->TransportStreamID);
|
||||
printf ("%s OriginalNetworkID: %d\n", Prepend,
|
||||
((struct LinkageDescriptor *)Descriptor)->OriginalNetworkID);
|
||||
printf ("%s ServiceID: %d\n", Prepend,
|
||||
((struct LinkageDescriptor *)Descriptor)->ServiceID);
|
||||
printf ("%s LinkageType: %d\n", Prepend,
|
||||
((struct LinkageDescriptor *)Descriptor)->LinkageType);
|
||||
if (((struct LinkageDescriptor *)Descriptor)->PrivateDataLength)
|
||||
{
|
||||
int j;
|
||||
printf ("%s PrivateData: ", Prepend);
|
||||
for (j = 0; j < ((struct LinkageDescriptor *)
|
||||
Descriptor)->PrivateDataLength; j++)
|
||||
printf ("0x%02X ", ((struct LinkageDescriptor *)
|
||||
Descriptor)->PrivateData[j]);
|
||||
printf ("\n");
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_TELETEXT:
|
||||
{
|
||||
struct TeletextItem *Item;
|
||||
|
||||
printf ("%sDescriptor: Teletext\n", Prepend);
|
||||
xForeach (((struct TeletextDescriptor *)Descriptor)->Items, Item)
|
||||
{
|
||||
printf ("%s Item:\n");
|
||||
printf ("%s LanguageCode: %s\n", Prepend, Item->LanguageCode);
|
||||
printf ("%s Type: ", Prepend);
|
||||
switch (Item->Type)
|
||||
{
|
||||
case 0x01: printf ("initial Teletext page\n"); break;
|
||||
case 0x02: printf ("Teletext subtitle page\n"); break;
|
||||
case 0x03: printf ("additional information page\n"); break;
|
||||
case 0x04: printf ("programme schedule page\n"); break;
|
||||
case 0x05: printf ("Teletext subtitle page ");
|
||||
printf ("for hearing impaired people\n"); break;
|
||||
default: printf ("reserved for future use\n"); break;
|
||||
}
|
||||
printf ("%s MagazineNumber: %x\n", Prepend, Item->MagazineNumber);
|
||||
printf ("%s PageNumber: %x\n", Prepend, Item->PageNumber);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_SUBTITLING:
|
||||
{
|
||||
struct SubtitlingItem *Item;
|
||||
|
||||
printf ("%sDescriptor: Subtitling\n", Prepend);
|
||||
xForeach (((struct SubtitlingDescriptor *)Descriptor)->Items, Item)
|
||||
{
|
||||
printf ("%s Item:\n");
|
||||
printf ("%s LanguageCode: %s\n", Prepend, Item->LanguageCode);
|
||||
printf ("%s Type: ", Prepend);
|
||||
for (i = 0; i < COMPONENT_TYPE_NUMBER; i++)
|
||||
if ((0x03 == ComponentTypes[i].Content) &&
|
||||
(Item->Type == ComponentTypes[i].Type))
|
||||
{ printf ("%s\n", ComponentTypes[i].Description); break; }
|
||||
printf ("%s CompositionPageId: %x\n", Prepend, Item->CompositionPageId);
|
||||
printf ("%s AncillaryPageId: %x\n", Prepend, Item->AncillaryPageId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_SAT_DEL_SYS:
|
||||
{
|
||||
struct SatelliteDeliverySystemDescriptor *sds =
|
||||
(struct SatelliteDeliverySystemDescriptor *)Descriptor;
|
||||
|
||||
printf ("%sDescriptor: Satellite Delivery System\n", Prepend);
|
||||
printf ("%s Frequency: %ld\n", Prepend, sds->Frequency);
|
||||
printf ("%s OrbitalPosition: %d\n", Prepend, sds->OrbitalPosition);
|
||||
printf ("%s Polarization: %c\n", Prepend, sds->Polarization);
|
||||
printf ("%s Modulation: %c\n", Prepend, sds->Modulation);
|
||||
printf ("%s SymbolRate: %ld\n", Prepend, sds->SymbolRate);
|
||||
printf ("%s FEC: %c\n", Prepend, sds->FEC);
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_CABLE_DEL_SYS:
|
||||
{
|
||||
struct CableDeliverySystemDescriptor *cds =
|
||||
(struct CableDeliverySystemDescriptor *)Descriptor;
|
||||
|
||||
printf ("%sDescriptor: Cable Delivery System\n", Prepend);
|
||||
printf ("%s Frequency: %ld\n", Prepend, cds->Frequency);
|
||||
printf ("%s SymbolRate: %ld\n", Prepend, cds->SymbolRate);
|
||||
printf ("%s FEC outer: %d\n", Prepend, cds->FECouter);
|
||||
printf ("%s FEC inner: %d\n", Prepend, cds->FECinner);
|
||||
printf ("%s Modulation: %d\n", Prepend, cds->Modulation);
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_TERR_DEL_SYS:
|
||||
{
|
||||
struct TerrestrialDeliverySystemDescriptor *tds =
|
||||
(struct TerrestrialDeliverySystemDescriptor *)Descriptor;
|
||||
|
||||
printf ("%sDescriptor: Terrestrial Delivery System\n", Prepend);
|
||||
printf ("%s Frequency: %ld\n", Prepend, tds->Frequency);
|
||||
printf ("%s Bandwidth: %d\n", Prepend, tds->Bandwidth);
|
||||
printf ("%s Constellation: %d\n", Prepend, tds->Constellation);
|
||||
printf ("%s Hierarchy: %d\n", Prepend, tds->Hierarchy);
|
||||
printf ("%s CodeRateHP: %d\n", Prepend, tds->CodeRateHP);
|
||||
printf ("%s CodeRateLP: %d\n", Prepend, tds->CodeRateLP);
|
||||
printf ("%s GuardInterval: %d\n", Prepend, tds->GuardInterval);
|
||||
printf ("%s TransmissionMode: %d\n", Prepend, tds->TransmissionMode);
|
||||
printf ("%s OtherFrequencyFlag: %d\n", Prepend, tds->OtherFrequencyFlag);
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_SERVICE_LIST:
|
||||
{
|
||||
struct ServiceListEntry *Entry;
|
||||
|
||||
printf ("%sDescriptor: Service List\n", Prepend);
|
||||
xForeach (((struct ServiceListDescriptor *)Descriptor)->ServiceList, Entry)
|
||||
{
|
||||
printf ("%s Entry:\n");
|
||||
printf ("%s ServiceID: %d\n", Prepend, Entry->ServiceID);
|
||||
printf ("%s ServiceType: %04x\n", Prepend, Entry->ServiceType);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_LOCAL_TIME_OFF:
|
||||
{
|
||||
struct LocalTimeOffsetEntry *Offset;
|
||||
|
||||
printf ("%sDescriptor: Local Time Offset\n", Prepend);
|
||||
xForeach (((struct LocalTimeOffsetDescriptor *)Descriptor)->LocalTimeOffsets, Offset)
|
||||
{
|
||||
printf ("%s Offset:\n");
|
||||
printf ("%s CountryCode: %s\n", Offset->CountryCode);
|
||||
printf ("%s RegionID: %c\n", Offset->RegionID);
|
||||
printf ("%s CurrentOffset: %ld\n", Offset->CurrentOffset);
|
||||
printf ("%s ChangeTime: %ld\n", Offset->ChangeTime);
|
||||
printf ("%s NextOffset: %ld\n", Offset->NextOffset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_STUFFING:
|
||||
case DESCR_VBI_DATA:
|
||||
case DESCR_VBI_TELETEXT:
|
||||
case DESCR_MOSAIC:
|
||||
case DESCR_TELEPHONE:
|
||||
case DESCR_ML_NW_NAME:
|
||||
case DESCR_ML_BQ_NAME:
|
||||
case DESCR_ML_SERVICE_NAME:
|
||||
case DESCR_ML_COMPONENT:
|
||||
case DESCR_PRIV_DATA_SPEC:
|
||||
case DESCR_SERVICE_MOVE:
|
||||
case DESCR_SHORT_SMOOTH_BUF:
|
||||
case DESCR_FREQUENCY_LIST:
|
||||
case DESCR_PARTIAL_TP_STREAM:
|
||||
case DESCR_DATA_BROADCAST:
|
||||
case DESCR_CA_SYSTEM:
|
||||
case DESCR_DATA_BROADCAST_ID:
|
||||
case DESCR_TRANSPORT_STREAM:
|
||||
case DESCR_DSNG:
|
||||
case DESCR_PDC:
|
||||
case DESCR_AC3:
|
||||
case DESCR_CELL_LIST:
|
||||
case DESCR_CELL_FREQ_LINK:
|
||||
case DESCR_ANNOUNCEMENT_SUPPORT:
|
||||
default:
|
||||
printf ("%sDescriptor: %02x (noch nicht unterstützt)\n", Prepend, DescriptorTag (Descriptor));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void siDumpDescriptor (void * Descriptor)
|
||||
{
|
||||
int Length, i;
|
||||
unsigned char *ptr;
|
||||
|
||||
Length = GetDescriptorLength (Descriptor);
|
||||
for (i = 0, ptr = (char*) Descriptor; i < Length; i++) {
|
||||
if ((i % 8) == 0)
|
||||
printf ("\n");
|
||||
printf ("0x%02X ", (unsigned int) ptr[i]);
|
||||
}
|
||||
printf ( "\n");
|
||||
}
|
||||
|
||||
void siDumpSection (void *Section)
|
||||
{
|
||||
int Length, i;
|
||||
unsigned char *ptr;
|
||||
char str[9];
|
||||
|
||||
Length = GetSectionLength (Section) + 3;
|
||||
for (i = 0, ptr = (unsigned char*) Section, memset (str, 0, 9); i < Length; i++) {
|
||||
if ((i % 8) == 0)
|
||||
{
|
||||
printf (" %s\n", str);
|
||||
memset (str, 0, 8);
|
||||
}
|
||||
printf ("0x%02X ", (unsigned int) ptr[i]);
|
||||
if (ptr[i] < 0x20 || (ptr[i] > 'z' && ptr[i] < ((unsigned char )'À')) )
|
||||
str[i % 8] = '.';
|
||||
else
|
||||
str[i % 8] = ptr[i];
|
||||
}
|
||||
printf (" %*s\n", (8 - ((abs(i - 1) % 8) ? (abs(i - 1) % 8) : 8)) * 5, str);
|
||||
}
|
||||
|
@ -1,245 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// ///
|
||||
/// si_debug_services.h: local debugging definitions ///
|
||||
/// ///
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// $Revision: 1.2 $
|
||||
// $Date: 2003/02/04 18:45:35 $
|
||||
// $Author: hakenes $
|
||||
//
|
||||
// (C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
//
|
||||
// libsi 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, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// libsi 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 may have received a copy of the GNU General Public License
|
||||
// along with libsi; see the file COPYING. If not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
|
||||
struct component_type {
|
||||
u_char Content;
|
||||
u_char Type;
|
||||
char *Description;
|
||||
};
|
||||
|
||||
static struct component_type ComponentTypes[] = {
|
||||
{ 0x01, 0x01, "video, 4:3 aspect ratio, 25 Hz" },
|
||||
{ 0x01, 0x02, "video, 16:9 aspect ratio with pan vectors, 25 Hz" },
|
||||
{ 0x01, 0x03, "video, 16:9 aspect ratio without pan vectors, 25 Hz" },
|
||||
{ 0x01, 0x04, "video, > 16:9 aspect ratio, 25 Hz" },
|
||||
{ 0x01, 0x05, "video, 4:3 aspect ratio, 30 Hz" },
|
||||
{ 0x01, 0x06, "video, 16:9 aspect ratio with pan vectors, 30 Hz" },
|
||||
{ 0x01, 0x07, "video, 16:9 aspect ratio without pan vectors, 30 Hz" },
|
||||
{ 0x01, 0x08, "video, > 16:9 aspect ratio, 30 Hz" },
|
||||
{ 0x01, 0x09, "HD video, 4:3 aspect ratio, 25 Hz" },
|
||||
{ 0x01, 0x0A, "HD video, 16:9 aspect ratio with pan vectors, 25 Hz" },
|
||||
{ 0x01, 0x0B, "HD video, 16:9 aspect ratio without pan vectors, 25 Hz" },
|
||||
{ 0x01, 0x0C, "HD video, > 16:9 aspect ratio, 25 Hz" },
|
||||
{ 0x01, 0x0D, "HD video, 4:3 aspect ratio, 30 Hz" },
|
||||
{ 0x01, 0x0E, "HD video, 16:9 aspect ratio with pan vectors, 30 Hz" },
|
||||
{ 0x01, 0x0F, "HD video, 16:9 aspect ratio without pan vectors, 30 Hz" },
|
||||
{ 0x01, 0x10, "HD video, > 16:9 aspect ratio, 30 Hz" },
|
||||
{ 0x02, 0x01, "audio, single mono channel" },
|
||||
{ 0x02, 0x02, "audio, dual mono channel" },
|
||||
{ 0x02, 0x03, "audio, stereo (2 channel)" },
|
||||
{ 0x02, 0x04, "audio, multi lingual, multi channel" },
|
||||
{ 0x02, 0x05, "audio, surround sound" },
|
||||
{ 0x02, 0x40, "audio description for the visually impaired" },
|
||||
{ 0x02, 0x41, "audio for the hard of hearing" },
|
||||
{ 0x03, 0x01, "EBU Teletext subtitles" },
|
||||
{ 0x03, 0x02, "associated EBU Teletext" },
|
||||
{ 0x03, 0x03, "VBI data" },
|
||||
{ 0x03, 0x10, "DVB subtitles (normal), no aspect criticality" },
|
||||
{ 0x03, 0x11, "DVB subtitles (normal), aspect 4:3 only" },
|
||||
{ 0x03, 0x12, "DVB subtitles (normal), aspect 16:9 only" },
|
||||
{ 0x03, 0x13, "DVB subtitles (normal), aspect 2.21:1 only" },
|
||||
{ 0x03, 0x20, "DVB subtitles (hard of hearing), no aspect criticality" },
|
||||
{ 0x03, 0x21, "DVB subtitles (hard of hearing), aspect 4:3 only" },
|
||||
{ 0x03, 0x22, "DVB subtitles (hard of hearing), aspect 16:9 only" },
|
||||
{ 0x03, 0x23, "DVB subtitles (hard of hearing), aspect 2.21:1 only" }
|
||||
};
|
||||
#define COMPONENT_TYPE_NUMBER 35
|
||||
|
||||
|
||||
struct service_type {
|
||||
u_char Type;
|
||||
char *Description;
|
||||
};
|
||||
|
||||
static struct service_type ServiceTypes[] = {
|
||||
{ 0x01, "digital television service" },
|
||||
{ 0x02, "digital radio sound service" },
|
||||
{ 0x03, "Teletext service" },
|
||||
{ 0x04, "NVOD reference service" },
|
||||
{ 0x05, "NVOD time-shifted service" },
|
||||
{ 0x06, "mosaic service" },
|
||||
{ 0x07, "PAL coded signal" },
|
||||
{ 0x08, "SECAM coded signal" },
|
||||
{ 0x09, "D/D2-MAC" },
|
||||
{ 0x0A, "FM Radio" },
|
||||
{ 0x0B, "NTSC coded signal" },
|
||||
{ 0x0C, "data broadcast service" },
|
||||
{ 0x0D, "common interface data" },
|
||||
{ 0x0E, "RCS Map" },
|
||||
{ 0x0F, "RCS FLS" },
|
||||
{ 0x10, "DVB MHP service" }
|
||||
};
|
||||
#define SERVICE_TYPE_NUMBER 16
|
||||
|
||||
|
||||
struct content_type {
|
||||
u_char Nibble1;
|
||||
u_char Nibble2;
|
||||
char *Description;
|
||||
};
|
||||
|
||||
static struct content_type ContentTypes[] = {
|
||||
/* Movie/Drama: */
|
||||
{ 0x01, 0x00, "movie/drama (general)" },
|
||||
{ 0x01, 0x01, "detective/thriller" },
|
||||
{ 0x01, 0x02, "adventure/western/war" },
|
||||
{ 0x01, 0x03, "science fiction/fantasy/horror" },
|
||||
{ 0x01, 0x04, "comedy" },
|
||||
{ 0x01, 0x05, "soap/melodrama/folkloric" },
|
||||
{ 0x01, 0x06, "romance" },
|
||||
{ 0x01, 0x07, "serious/classical/religious/historical movie/drama" },
|
||||
{ 0x01, 0x08, "adult movie/drama" },
|
||||
/* News/Current affairs: */
|
||||
{ 0x02, 0x00, "news/current affairs (general)" },
|
||||
{ 0x02, 0x01, "news/weather report" },
|
||||
{ 0x02, 0x02, "news magazine" },
|
||||
{ 0x02, 0x03, "documentary" },
|
||||
{ 0x02, 0x04, "discussion/interview/debate" },
|
||||
/* Show/Game show: */
|
||||
{ 0x03, 0x00, "show/game show (general)" },
|
||||
{ 0x03, 0x01, "game show/quiz/contest" },
|
||||
{ 0x03, 0x02, "variety show" },
|
||||
{ 0x03, 0x03, "talk show" },
|
||||
/* Sports: */
|
||||
{ 0x04, 0x00, "sports (general)" },
|
||||
{ 0x04, 0x01, "special events (Olympic Games, World Cup etc.)" },
|
||||
{ 0x04, 0x02, "sports magazines" },
|
||||
{ 0x04, 0x03, "football/soccer" },
|
||||
{ 0x04, 0x04, "tennis/squash" },
|
||||
{ 0x04, 0x05, "team sports (excluding football)" },
|
||||
{ 0x04, 0x06, "athletics" },
|
||||
{ 0x04, 0x07, "motor sport" },
|
||||
{ 0x04, 0x08, "water sport" },
|
||||
{ 0x04, 0x09, "winter sports" },
|
||||
{ 0x04, 0x0A, "equestrian" },
|
||||
{ 0x04, 0x0B, "martial sports" },
|
||||
/* Children's/Youth programmes: */
|
||||
{ 0x05, 0x00, "children's/youth programmes (general)" },
|
||||
{ 0x05, 0x01, "pre-school children's programmes" },
|
||||
{ 0x05, 0x02, "entertainment programmes for 6 to14" },
|
||||
{ 0x05, 0x03, "entertainment programmes for 10 to 16" },
|
||||
{ 0x05, 0x04, "informational/educational/school programmes" },
|
||||
{ 0x05, 0x05, "cartoons/puppets" },
|
||||
/* Music/Ballet/Dance: */
|
||||
{ 0x06, 0x00, "music/ballet/dance (general)" },
|
||||
{ 0x06, 0x01, "rock/pop" },
|
||||
{ 0x06, 0x02, "serious music/classical music" },
|
||||
{ 0x06, 0x03, "folk/traditional music" },
|
||||
{ 0x06, 0x04, "jazz" },
|
||||
{ 0x06, 0x05, "musical/opera" },
|
||||
{ 0x06, 0x06, "ballet" },
|
||||
/* Arts/Culture (without music): */
|
||||
{ 0x07, 0x00, "arts/culture (without music, general)" },
|
||||
{ 0x07, 0x01, "performing arts" },
|
||||
{ 0x07, 0x02, "fine arts" },
|
||||
{ 0x07, 0x03, "religion" },
|
||||
{ 0x07, 0x04, "popular culture/traditional arts" },
|
||||
{ 0x07, 0x05, "literature" },
|
||||
{ 0x07, 0x06, "film/cinema" },
|
||||
{ 0x07, 0x07, "experimental film/video" },
|
||||
{ 0x07, 0x08, "broadcasting/press" },
|
||||
{ 0x07, 0x09, "new media" },
|
||||
{ 0x07, 0x0A, "arts/culture magazines" },
|
||||
{ 0x07, 0x0B, "fashion" },
|
||||
/* Social/Political issues/Economics: */
|
||||
{ 0x08, 0x00, "social/political issues/economics (general)" },
|
||||
{ 0x08, 0x01, "magazines/reports/documentary" },
|
||||
{ 0x08, 0x02, "economics/social advisory" },
|
||||
{ 0x08, 0x03, "remarkable people" },
|
||||
/* Children's/Youth programmes: */
|
||||
/* Education/ Science/Factual topics: */
|
||||
{ 0x09, 0x00, "education/science/factual topics (general)" },
|
||||
{ 0x09, 0x01, "nature/animals/environment" },
|
||||
{ 0x09, 0x02, "technology/natural sciences" },
|
||||
{ 0x09, 0x03, "medicine/physiology/psychology" },
|
||||
{ 0x09, 0x04, "foreign countries/expeditions" },
|
||||
{ 0x09, 0x05, "social/spiritual sciences" },
|
||||
{ 0x09, 0x06, "further education" },
|
||||
{ 0x09, 0x07, "languages" },
|
||||
/* Leisure hobbies: */
|
||||
{ 0x0A, 0x00, "leisure hobbies (general)" },
|
||||
{ 0x0A, 0x01, "tourism/travel" },
|
||||
{ 0x0A, 0x02, "handicraft" },
|
||||
{ 0x0A, 0x03, "motoring" },
|
||||
{ 0x0A, 0x04, "fitness & health" },
|
||||
{ 0x0A, 0x05, "cooking" },
|
||||
{ 0x0A, 0x06, "advertisement/shopping" },
|
||||
{ 0x0A, 0x07, "gardening" },
|
||||
{ 0x0B, 0x00, "original language" },
|
||||
{ 0x0B, 0x01, "black & white" },
|
||||
{ 0x0B, 0x02, "unpublished" },
|
||||
{ 0x0B, 0x03, "live broadcast" }
|
||||
};
|
||||
#define CONTENT_TYPE_NUMBER 79
|
||||
|
||||
static char *StreamTypes[] = {
|
||||
"ITU-T|ISO/IEC Reserved",
|
||||
"ISO/IEC Video",
|
||||
"13818-2 Video or 11172-2 constrained parameter video stream",
|
||||
"ISO/IEC 11172 Audio",
|
||||
"ISO/IEC 13818-3 Audio",
|
||||
"private_sections",
|
||||
"packets containing private data / Videotext",
|
||||
"ISO/IEC 13522 MPEG",
|
||||
"ITU-T Rec. H.222.1",
|
||||
"ISO/IEC 13818-6 type A",
|
||||
"ISO/IEC 13818-6 type B",
|
||||
"ISO/IEC 13818-6 type C",
|
||||
"ISO/IEC 13818-6 type D",
|
||||
"ISO/IEC 13818-1 auxiliary",
|
||||
"ITU-T Rec. H.222.0 | ISO 13818-1 Reserved",
|
||||
"User private"
|
||||
};
|
||||
|
||||
static char *CaIdents[] = {
|
||||
"Standardized systems",
|
||||
"Canal Plus",
|
||||
"CCETT",
|
||||
"Deutsche Telecom",
|
||||
"Eurodec",
|
||||
"France Telecom",
|
||||
"Irdeto",
|
||||
"Jerrold/GI",
|
||||
"Matra Communication",
|
||||
"News Datacom",
|
||||
"Nokia",
|
||||
"Norwegian Telekom",
|
||||
"NTL",
|
||||
"Philips",
|
||||
"Scientific Atlanta",
|
||||
"Sony",
|
||||
"Tandberg Television",
|
||||
"Thomson",
|
||||
"TV/Com",
|
||||
"HPT - Croatian Post and Telecommunications",
|
||||
"HRT - Croatian Radio and Television",
|
||||
"IBM",
|
||||
"Nera",
|
||||
"BetaTechnik"
|
||||
};
|
||||
#define MAX_CA_IDENT 24
|
File diff suppressed because it is too large
Load Diff
@ -1,339 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
@ -1,63 +0,0 @@
|
||||
##############################################################
|
||||
### ###
|
||||
### Makefile: local makefile for libvdr ###
|
||||
### ###
|
||||
##############################################################
|
||||
|
||||
## $Revision: 1.3 $
|
||||
## $Date: 2001/10/06 15:33:46 $
|
||||
## $Author: hakenes $
|
||||
##
|
||||
## (C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
##
|
||||
## libdtv 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, or (at your option)
|
||||
## any later version.
|
||||
##
|
||||
## libdtv 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 may have received a copy of the GNU General Public License
|
||||
## along with libdtv; see the file COPYING. If not, write to the
|
||||
## Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
## Boston, MA 02111-1307, USA.
|
||||
#
|
||||
#
|
||||
#
|
||||
CC ?= gcc
|
||||
CFLAGS ?= -O2 -g -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-Wimplicit -D__USE_FIXED_PROTOTYPES__ # -DDEBUG
|
||||
|
||||
CFLAGS += -I../include
|
||||
|
||||
AR = ar
|
||||
ARFLAGS = r
|
||||
RANLIB = ranlib
|
||||
RM = rm -f
|
||||
CP = cp
|
||||
|
||||
VDRINCLUDE = libvdr.h
|
||||
VDRLIB = libvdr.a
|
||||
VDROBJS = libvdr.o
|
||||
|
||||
all : $(VDRLIB)
|
||||
|
||||
clean :
|
||||
@echo "cleaning workspace..."
|
||||
@$(RM) $(VDROBJS) $(VDRLIB)
|
||||
|
||||
new : clean all
|
||||
|
||||
$(VDRLIB) : $(VDROBJS)
|
||||
@echo "updating library..."
|
||||
@$(AR) $(ARFLAGS) $(VDRLIB) $(VDROBJS)
|
||||
@$(RANLIB) $(VDRLIB)
|
||||
|
||||
dist: all
|
||||
@echo "distributing libvdr.a and libvdr.h..."
|
||||
@$(CP) $(VDRLIB) ../lib
|
||||
@$(CP) $(VDRINCLUDE) ../include
|
||||
|
@ -1,157 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// ///
|
||||
/// libvdr.c: routines to parse the DVB-SI stream ///
|
||||
/// ///
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// $Revision: 1.1 $
|
||||
// $Date: 2001/10/07 10:25:33 $
|
||||
// $Author: hakenes $
|
||||
//
|
||||
// (C) 2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
//
|
||||
// libvdr 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, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// libvdr 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 may have received a copy of the GNU General Public License
|
||||
// along with libvdr; see the file COPYING. If not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <liblx.h>
|
||||
#include <libsi.h>
|
||||
#include <si_tables.h>
|
||||
#include "libvdr.h"
|
||||
|
||||
|
||||
|
||||
struct LIST *createVdrProgramInfos (unsigned char *siBuffer)
|
||||
{
|
||||
struct VdrProgramInfo *VdrProgramInfo;
|
||||
struct LIST *Result, *EventList;
|
||||
struct Event *Event;
|
||||
struct Descriptor *Descriptor;
|
||||
int GotVdrProgramInfo;
|
||||
|
||||
if (!siBuffer) return (NULL);
|
||||
|
||||
if (!(EventList = siParseEIT (siBuffer))) return (NULL);
|
||||
|
||||
Result = xNewList (NULL);
|
||||
|
||||
xForeach (EventList, Event)
|
||||
{
|
||||
VdrProgramInfo = NULL;
|
||||
GotVdrProgramInfo = 0;
|
||||
|
||||
xForeach (Event->Descriptors, Descriptor)
|
||||
{
|
||||
if (!VdrProgramInfo)
|
||||
{
|
||||
CreateVdrProgramInfo(VdrProgramInfo,
|
||||
Event->EventID, Event->TransportStreamID,
|
||||
Event->ServiceID, Event->StartTime,
|
||||
Event->Duration, Event->Status);
|
||||
}
|
||||
|
||||
switch (Descriptor->Tag)
|
||||
{
|
||||
case DESCR_SHORT_EVENT:
|
||||
{
|
||||
if (!xName(Descriptor) || !xName(Descriptor)[0])
|
||||
break;
|
||||
|
||||
VdrProgramInfo->ShortName =
|
||||
xSetText (xName (Descriptor));
|
||||
VdrProgramInfo->ShortText =
|
||||
xSetText (((struct ShortEventDescriptor
|
||||
*)Descriptor)->Text);
|
||||
memcpy (VdrProgramInfo->LanguageCode, ((struct
|
||||
ShortEventDescriptor *)Descriptor)->
|
||||
LanguageCode, 4);
|
||||
GotVdrProgramInfo = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_TIME_SHIFTED_EVENT:
|
||||
{
|
||||
struct tm *StartTime;
|
||||
|
||||
VdrProgramInfo->ReferenceServiceID =
|
||||
((struct TimeShiftedEventDescriptor
|
||||
*)Descriptor)->ReferenceServiceID;
|
||||
VdrProgramInfo->ReferenceEventID =
|
||||
((struct TimeShiftedEventDescriptor
|
||||
*)Descriptor)->ReferenceEventID;
|
||||
GotVdrProgramInfo = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_EXTENDED_EVENT:
|
||||
{
|
||||
struct ExtendedEventItem *Item;
|
||||
|
||||
if (xName (Descriptor))
|
||||
AddToText (xName (Descriptor),
|
||||
VdrProgramInfo->ExtendedName);
|
||||
xForeach (((struct ExtendedEventDescriptor*)
|
||||
Descriptor)->Items, Item)
|
||||
{
|
||||
AddItemToText (xName (Item),
|
||||
VdrProgramInfo->ExtendedText);
|
||||
AddItemToText (Item->Text,
|
||||
VdrProgramInfo->ExtendedText);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_CONTENT:
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (j = 0; j < ((struct ContentDescriptor*)
|
||||
Descriptor)->Amount; j++)
|
||||
{
|
||||
VdrProgramInfo->ContentNibble1 =
|
||||
GetContentContentNibble1(Descriptor, j);
|
||||
VdrProgramInfo->ContentNibble2 =
|
||||
GetContentContentNibble2(Descriptor, j);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DESCR_PARENTAL_RATING:
|
||||
{
|
||||
struct ParentalRating *Rating;
|
||||
|
||||
xForeach (((struct ParentalRatingDescriptor *)
|
||||
Descriptor)->Ratings, Rating)
|
||||
if (!strncmp (VdrProgramInfo->LanguageCode,
|
||||
Rating->LanguageCode, 3))
|
||||
VdrProgramInfo->Rating = Rating->Rating;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (GotVdrProgramInfo) xAddTail (Result, VdrProgramInfo);
|
||||
else xMemFree (VdrProgramInfo);
|
||||
}
|
||||
|
||||
return (Result);
|
||||
}
|
@ -1,111 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
/// ///
|
||||
/// libvdr.h: definitions necessary for the libvdr package ///
|
||||
/// ///
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// $Revision: 1.4 $
|
||||
// $Date: 2001/10/06 15:33:46 $
|
||||
// $Author: hakenes $
|
||||
//
|
||||
// (C) 1992-2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
|
||||
//
|
||||
// libvdr 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, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// libvdr 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 may have received a copy of the GNU General Public License
|
||||
// along with libvdr; see the file COPYING. If not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef LIBVDR_H
|
||||
#define LIBVDR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct LIST *createVdrProgramInfos (unsigned char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
struct VdrProgramInfo {
|
||||
struct NODE Node;
|
||||
int EventID;
|
||||
int TransportStreamID;
|
||||
int ServiceID;
|
||||
time_t StartTime;
|
||||
time_t Duration;
|
||||
unsigned short Status;
|
||||
char LanguageCode[4];
|
||||
unsigned short Rating;
|
||||
unsigned short ContentNibble1;
|
||||
unsigned short ContentNibble2;
|
||||
char *ShortName;
|
||||
char *ShortText;
|
||||
char *ExtendedName;
|
||||
char *ExtendedText;
|
||||
int ReferenceServiceID;
|
||||
int ReferenceEventID;
|
||||
};
|
||||
|
||||
|
||||
#define CreateVdrProgramInfo(cinf, evid, tpid, svid, stst, dura, sta) \
|
||||
do \
|
||||
{ \
|
||||
xCreateNode (cinf, NULL); \
|
||||
cinf->EventID = evid; \
|
||||
cinf->TransportStreamID = tpid; \
|
||||
cinf->ServiceID = svid; \
|
||||
cinf->StartTime = stst; \
|
||||
cinf->Duration = dura; \
|
||||
cinf->Status = sta; \
|
||||
cinf->LanguageCode[0] = 0; \
|
||||
cinf->Rating = 0; \
|
||||
cinf->ContentNibble1 = 0; \
|
||||
cinf->ContentNibble2 = 0; \
|
||||
cinf->ShortName = NULL; \
|
||||
cinf->ShortText = NULL; \
|
||||
cinf->ExtendedName = NULL; \
|
||||
cinf->ExtendedText = NULL; \
|
||||
cinf->ReferenceServiceID = 0; \
|
||||
cinf->ReferenceEventID = 0; \
|
||||
} while (0)
|
||||
|
||||
#define AddToText(src, dest) \
|
||||
do { \
|
||||
if (dest) \
|
||||
{ \
|
||||
char *tmbuf; \
|
||||
xMemAlloc (strlen (src) + strlen (dest) + 4, &tmbuf); \
|
||||
sprintf (tmbuf, "%s%s", (dest), (src)); \
|
||||
xMemFree (dest); (dest) = tmbuf; \
|
||||
} else { \
|
||||
(dest) = xSetText (src); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define AddItemToText(src, dest) \
|
||||
do { \
|
||||
if (dest) \
|
||||
{ \
|
||||
char *tmbuf; \
|
||||
xMemAlloc (strlen (src) + strlen (dest) + 4, &tmbuf); \
|
||||
sprintf (tmbuf, "%s|%s", (dest), (src)); \
|
||||
xMemFree (dest); (dest) = tmbuf; \
|
||||
} else { \
|
||||
(dest) = xSetText (src); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
52
libsi/Makefile
Normal file
52
libsi/Makefile
Normal file
@ -0,0 +1,52 @@
|
||||
#
|
||||
# Makefile for a libsi
|
||||
#
|
||||
# $Id: Makefile 1.2 2003/12/13 10:41:39 kls Exp $
|
||||
|
||||
### The C++ compiler and options:
|
||||
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -O2 -g -Wall -Woverloaded-virtual
|
||||
AR = ar
|
||||
ARFLAGS = ru
|
||||
RANLIB = ranlib
|
||||
|
||||
### The directory environment:
|
||||
|
||||
INCLUDES +=
|
||||
|
||||
DEFINES +=
|
||||
|
||||
LIBS +=
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
OBJS = util.o si.o section.o descriptor.o
|
||||
|
||||
### Implicit rules:
|
||||
|
||||
%.o: %.c
|
||||
$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
|
||||
|
||||
# Dependencies:
|
||||
|
||||
MAKEDEP = g++ -MM -MG
|
||||
DEPFILE = .dependencies
|
||||
$(DEPFILE): Makefile
|
||||
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
|
||||
|
||||
-include $(DEPFILE)
|
||||
|
||||
### Targets:
|
||||
|
||||
all: libsi.a
|
||||
|
||||
libsi.a : $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJS)
|
||||
|
||||
clean:
|
||||
@-rm -f $(OBJS) $(DEPFILE) *.a *.so *.tgz core* *~
|
||||
|
||||
dist:
|
||||
tar cvzf libsi.tar.gz -C .. libsi/util.c libsi/si.c libsi/section.c libsi/descriptor.c \
|
||||
libsi/util.h libsi/si.h libsi/section.h libsi/descriptor.h libsi/headers.h libsi/Makefile libsi/gendescr.pl
|
635
libsi/descriptor.c
Normal file
635
libsi/descriptor.c
Normal file
@ -0,0 +1,635 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: descriptor.c 1.2 2003/12/13 10:42:05 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "descriptor.h"
|
||||
|
||||
namespace SI {
|
||||
|
||||
void ShortEventDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
const descr_short_event *s;
|
||||
data.setPointerAndOffset<const descr_short_event>(s, offset);
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
name.setDataAndOffset(data+offset, s->event_name_length, offset);
|
||||
const descr_short_event_mid *mid;
|
||||
data.setPointerAndOffset<const descr_short_event_mid>(mid, offset);
|
||||
text.setData(data+offset, mid->text_length);
|
||||
}
|
||||
|
||||
int ExtendedEventDescriptor::getDescriptorNumber() {
|
||||
return s->descriptor_number;
|
||||
}
|
||||
|
||||
int ExtendedEventDescriptor::getLastDescriptorNumber() {
|
||||
return s->last_descriptor_number;
|
||||
}
|
||||
|
||||
void ExtendedEventDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_extended_event>(s, offset);
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
itemLoop.setDataAndOffset(data+offset, s->length_of_items, offset);
|
||||
const descr_extended_event_mid *mid;
|
||||
data.setPointerAndOffset<const descr_extended_event_mid>(mid, offset);
|
||||
text.setData(data+offset, mid->text_length);
|
||||
}
|
||||
|
||||
void ExtendedEventDescriptor::Item::Parse() {
|
||||
unsigned int offset=0;
|
||||
const item_extended_event *first;
|
||||
data.setPointerAndOffset<const item_extended_event>(first, offset);
|
||||
itemDescription.setDataAndOffset(data+offset, first->item_description_length, offset);
|
||||
const item_extended_event_mid *mid;
|
||||
data.setPointerAndOffset<const item_extended_event_mid>(mid, offset);
|
||||
item.setData(data+offset, mid->item_length);
|
||||
}
|
||||
|
||||
int ExtendedEventDescriptors::getTextLength() {
|
||||
int ret=0;
|
||||
for (int i=0;i<length;i++) {
|
||||
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||
if (!d)
|
||||
continue;
|
||||
ret+=d->text.getLength()+1; //plus a blank
|
||||
ExtendedEventDescriptor::Item item;
|
||||
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
||||
item=d->itemLoop.getNext(it);
|
||||
ret+=item.item.getLength();
|
||||
ret+=item.itemDescription.getLength();
|
||||
ret+=2; //the blanks
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//is there a case where this function does not return the same as getTextLength?
|
||||
int ExtendedEventDescriptors::getMaximumTextLength() {
|
||||
int ret=0;
|
||||
for (int i=0;i<length;i++) {
|
||||
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||
if (!d)
|
||||
continue;
|
||||
ret+=d->text.getLength()+1; //plus a blank
|
||||
ret+=d->itemLoop.getLength();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *ExtendedEventDescriptors::getText() {
|
||||
char *text=new char[getMaximumTextLength()];
|
||||
return getText(text);
|
||||
}
|
||||
|
||||
//appends the Strings of every Descriptor in the group
|
||||
char *ExtendedEventDescriptors::getText(char *buffer) {
|
||||
int index=0, len;
|
||||
char tempbuf[256];
|
||||
for (int i=0;i<length;i++) {
|
||||
ExtendedEventDescriptor *d=(ExtendedEventDescriptor *)array[i];
|
||||
if (!d)
|
||||
continue;
|
||||
d->text.getText(tempbuf);
|
||||
len=strlen(tempbuf);
|
||||
if (len) {
|
||||
memcpy(buffer+index, tempbuf, len);
|
||||
index+=len;
|
||||
}
|
||||
|
||||
ExtendedEventDescriptor::Item item;
|
||||
for (Loop::Iterator it; d->itemLoop.hasNext(it); ) {
|
||||
item=d->itemLoop.getNext(it);
|
||||
|
||||
item.item.getText(tempbuf);
|
||||
len=strlen(tempbuf);
|
||||
if (len) {
|
||||
memcpy(buffer+index, tempbuf, len);
|
||||
index+=len;
|
||||
}
|
||||
|
||||
item.itemDescription.getText(tempbuf);
|
||||
len=strlen(tempbuf);
|
||||
if (len) {
|
||||
memcpy(buffer+index, tempbuf, len);
|
||||
index+=len;
|
||||
}
|
||||
}
|
||||
}
|
||||
buffer[index]='\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int TimeShiftedEventDescriptor::getReferenceServiceId() const {
|
||||
return HILO(s->reference_service_id);
|
||||
}
|
||||
|
||||
int TimeShiftedEventDescriptor::getReferenceEventId() const {
|
||||
return HILO(s->reference_event_id);
|
||||
}
|
||||
|
||||
void TimeShiftedEventDescriptor::Parse() {
|
||||
s=data.getData<const descr_time_shifted_event>();
|
||||
}
|
||||
|
||||
void ContentDescriptor::Parse() {
|
||||
//this descriptor is only a header and a loop
|
||||
nibbleLoop.setData(data+sizeof(SectionHeader), getLength()-sizeof(SectionHeader));
|
||||
}
|
||||
|
||||
int ContentDescriptor::Nibble::getContentNibbleLevel1() const {
|
||||
return s->content_nibble_level_1;
|
||||
}
|
||||
|
||||
int ContentDescriptor::Nibble::getContentNibbleLevel2() const {
|
||||
return s->content_nibble_level_2;
|
||||
}
|
||||
|
||||
int ContentDescriptor::Nibble::getUserNibble1() const {
|
||||
return s->user_nibble_1;
|
||||
}
|
||||
|
||||
int ContentDescriptor::Nibble::getUserNibble2() const {
|
||||
return s->user_nibble_2;
|
||||
}
|
||||
|
||||
void ContentDescriptor::Nibble::Parse() {
|
||||
s=data.getData<const nibble_content>();
|
||||
}
|
||||
|
||||
void ParentalRatingDescriptor::Parse() {
|
||||
//this descriptor is only a header and a loop
|
||||
ratingLoop.setData(data+sizeof(SectionHeader), getLength()-sizeof(SectionHeader));
|
||||
}
|
||||
|
||||
int ParentalRatingDescriptor::Rating::getRating() const {
|
||||
return s->rating;
|
||||
}
|
||||
|
||||
void ParentalRatingDescriptor::Rating::Parse() {
|
||||
s=data.getData<const parental_rating>();
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
}
|
||||
|
||||
int CaDescriptor::getCaType() const {
|
||||
return HILO(s->CA_type);
|
||||
}
|
||||
|
||||
int CaDescriptor::getCaPid() const {
|
||||
return HILO(s->CA_PID);
|
||||
}
|
||||
|
||||
void CaDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_ca>(s, offset);
|
||||
privateData.assign(data.getData(offset), getLength()-offset);
|
||||
}
|
||||
|
||||
int StreamIdentifierDescriptor::getComponentTag() const {
|
||||
return s->component_tag;
|
||||
}
|
||||
|
||||
void StreamIdentifierDescriptor::Parse() {
|
||||
s=data.getData<const descr_stream_identifier>();
|
||||
}
|
||||
|
||||
void NetworkNameDescriptor::Parse() {
|
||||
name.setData(data+sizeof(descr_network_name), getLength()-sizeof(descr_network_name));
|
||||
}
|
||||
|
||||
void CaIdentifierDescriptor::Parse() {
|
||||
identifiers.setData(data+sizeof(descr_ca_identifier), getLength()-sizeof(descr_ca_identifier));
|
||||
}
|
||||
|
||||
int CarouselIdentifierDescriptor::getCarouselId() const {
|
||||
return (HILO(s->carousel_id_hi) << 16) | HILO(s->carousel_id_lo);
|
||||
}
|
||||
|
||||
int CarouselIdentifierDescriptor::getFormatId() const {
|
||||
return s->FormatId;
|
||||
}
|
||||
|
||||
void CarouselIdentifierDescriptor::Parse() {
|
||||
s=data.getData<const descr_carousel_identifier>();
|
||||
}
|
||||
|
||||
void ServiceListDescriptor::Parse() {
|
||||
serviceLoop.setData(data+sizeof(descr_service_list), getLength()-sizeof(descr_service_list));
|
||||
}
|
||||
|
||||
int ServiceListDescriptor::Service::getServiceId() const {
|
||||
return HILO(s->service_id);
|
||||
}
|
||||
|
||||
int ServiceListDescriptor::Service::getServiceType() const {
|
||||
return s->service_type;
|
||||
}
|
||||
|
||||
void ServiceListDescriptor::Service::Parse() {
|
||||
s=data.getData<const descr_service_list_loop>();
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getFrequency() const {
|
||||
return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getOrbitalPosition() const {
|
||||
return HILO(s->orbital_position);
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getWestEastFlag() const {
|
||||
return s->west_east_flag;
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getPolarization() const {
|
||||
return s->polarization;
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getModulation() const {
|
||||
return s->modulation;
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getSymbolRate() const {
|
||||
return (HILO(s->symbol_rate_hi) << 12) | (s->symbol_rate_lo_1 << 4) | s->symbol_rate_lo_2;
|
||||
}
|
||||
|
||||
int SatelliteDeliverySystemDescriptor::getFecInner() const {
|
||||
return s->fec_inner;
|
||||
}
|
||||
|
||||
void SatelliteDeliverySystemDescriptor::Parse() {
|
||||
s=data.getData<const descr_satellite_delivery_system>();
|
||||
}
|
||||
|
||||
int CableDeliverySystemDescriptor::getFrequency() const {
|
||||
return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
|
||||
}
|
||||
|
||||
int CableDeliverySystemDescriptor::getFecOuter() const {
|
||||
return s->fec_outer;
|
||||
}
|
||||
|
||||
int CableDeliverySystemDescriptor::getModulation() const {
|
||||
return s->modulation;
|
||||
}
|
||||
|
||||
int CableDeliverySystemDescriptor::getSymbolRate() const {
|
||||
return (HILO(s->symbol_rate_hi) << 12) | (s->symbol_rate_lo_1 << 4) | s->symbol_rate_lo_2;
|
||||
}
|
||||
|
||||
int CableDeliverySystemDescriptor::getFecInner() const {
|
||||
return s->fec_inner;
|
||||
}
|
||||
|
||||
void CableDeliverySystemDescriptor::Parse() {
|
||||
s=data.getData<const descr_cable_delivery_system>();
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getFrequency() const {
|
||||
return (HILO(s->frequency_hi) << 16) | HILO(s->frequency_lo);
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getBandwidth() const {
|
||||
return s->bandwidth;
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getConstellation() const {
|
||||
return s->constellation;
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getHierarchy() const {
|
||||
return s->hierarchy;
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getCodeRateHP() const {
|
||||
return s->code_rate_HP;
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getCodeRateLP() const {
|
||||
return s->code_rate_LP;
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getGuardInterval() const {
|
||||
return s->guard_interval;
|
||||
}
|
||||
|
||||
int TerrestrialDeliverySystemDescriptor::getTransmissionMode() const {
|
||||
return s->transmission_mode;
|
||||
}
|
||||
|
||||
bool TerrestrialDeliverySystemDescriptor::getOtherFrequency() const {
|
||||
return s->other_frequency_flag;
|
||||
}
|
||||
|
||||
void TerrestrialDeliverySystemDescriptor::Parse() {
|
||||
s=data.getData<const descr_terrestrial_delivery>();
|
||||
}
|
||||
|
||||
int ServiceDescriptor::getServiceType() const {
|
||||
return s->service_type;
|
||||
}
|
||||
|
||||
void ServiceDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_service>(s, offset);
|
||||
providerName.setDataAndOffset(data+offset, s->provider_name_length, offset);
|
||||
const descr_service_mid *mid;
|
||||
data.setPointerAndOffset<const descr_service_mid>(mid, offset);
|
||||
serviceName.setData(data+offset, mid->service_name_length);
|
||||
}
|
||||
|
||||
void NVODReferenceDescriptor::Parse() {
|
||||
serviceLoop.setData(data+sizeof(descr_nvod_reference), getLength()-sizeof(descr_nvod_reference));
|
||||
}
|
||||
|
||||
int NVODReferenceDescriptor::Service::getTransportStream() const {
|
||||
return HILO(s->transport_stream_id);
|
||||
}
|
||||
|
||||
int NVODReferenceDescriptor::Service::getOriginalNetworkId() const {
|
||||
return HILO(s->original_network_id);
|
||||
}
|
||||
|
||||
int NVODReferenceDescriptor::Service::getServiceId() const {
|
||||
return HILO(s->service_id);
|
||||
}
|
||||
|
||||
void NVODReferenceDescriptor::Service::Parse() {
|
||||
s=data.getData<const item_nvod_reference>();
|
||||
}
|
||||
|
||||
int TimeShiftedServiceDescriptor::getReferenceServiceId() const {
|
||||
return HILO(s->reference_service_id);
|
||||
}
|
||||
|
||||
void TimeShiftedServiceDescriptor::Parse() {
|
||||
s=data.getData<const descr_time_shifted_service>();
|
||||
}
|
||||
|
||||
int ComponentDescriptor::getStreamContent() const {
|
||||
return s->stream_content;
|
||||
}
|
||||
|
||||
int ComponentDescriptor::getComponentType() const {
|
||||
return s->component_type;
|
||||
}
|
||||
|
||||
int ComponentDescriptor::getComponentTag() const {
|
||||
return s->component_tag;
|
||||
}
|
||||
|
||||
void ComponentDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_component>(s, offset);
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
description.setData(data+offset, getLength()-offset);
|
||||
}
|
||||
|
||||
void SubtitlingDescriptor::Parse() {
|
||||
subtitlingLoop.setData(data+sizeof(descr_subtitling), getLength()-sizeof(descr_subtitling));
|
||||
}
|
||||
|
||||
int SubtitlingDescriptor::Subtitling::getSubtitlingType() const {
|
||||
return s->subtitling_type;
|
||||
}
|
||||
|
||||
int SubtitlingDescriptor::Subtitling::getCompositionPageId() const {
|
||||
return HILO(s->composition_page_id);
|
||||
}
|
||||
|
||||
int SubtitlingDescriptor::Subtitling::getAncillaryPageId() const {
|
||||
return HILO(s->ancillary_page_id);
|
||||
}
|
||||
|
||||
void SubtitlingDescriptor::Subtitling::Parse() {
|
||||
s=data.getData<const item_subtitling>();
|
||||
}
|
||||
|
||||
int ServiceMoveDescriptor::getNewOriginalNetworkId() const {
|
||||
return HILO(s->new_original_network_id);
|
||||
}
|
||||
|
||||
int ServiceMoveDescriptor::getNewTransportStreamId() const {
|
||||
return HILO(s->new_transport_stream_id);
|
||||
}
|
||||
|
||||
int ServiceMoveDescriptor::getNewServiceId() const {
|
||||
return HILO(s->new_service_id);
|
||||
}
|
||||
|
||||
void ServiceMoveDescriptor::Parse() {
|
||||
s=data.getData<const descr_service_move>();
|
||||
}
|
||||
|
||||
int FrequencyListDescriptor::getCodingType() const {
|
||||
return s->coding_type;
|
||||
}
|
||||
|
||||
void FrequencyListDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_frequency_list>(s, offset);
|
||||
frequencies.setData(data+offset, getLength()-offset);
|
||||
}
|
||||
|
||||
void ServiceIdentifierDescriptor::Parse() {
|
||||
textualServiceIdentifier.setData(data+sizeof(descr_service_identifier), getLength()-sizeof(descr_service_identifier));
|
||||
}
|
||||
|
||||
void MultilingualNameDescriptor::Parse() {
|
||||
nameLoop.setData(data+sizeof(descr_multilingual_network_name), getLength()-sizeof(descr_multilingual_network_name));
|
||||
}
|
||||
|
||||
void MultilingualNameDescriptor::Name::Parse() {
|
||||
unsigned int offset=0;
|
||||
const entry_multilingual_name *s;
|
||||
data.setPointerAndOffset<const entry_multilingual_name>(s, offset);
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
name.setData(data+offset, s->text_length);
|
||||
}
|
||||
|
||||
int MultilingualComponentDescriptor::getComponentTag() const {
|
||||
return s->component_tag;
|
||||
}
|
||||
|
||||
void MultilingualComponentDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_multilingual_component>(s, offset);
|
||||
nameLoop.setData(data+sizeof(descr_multilingual_component), getLength()-sizeof(descr_multilingual_component));
|
||||
}
|
||||
|
||||
void MultilingualServiceNameDescriptor::Parse() {
|
||||
nameLoop.setData(data+sizeof(descr_multilingual_network_name), getLength()-sizeof(descr_multilingual_network_name));
|
||||
}
|
||||
|
||||
void MultilingualServiceNameDescriptor::Name::Parse() {
|
||||
unsigned int offset=0;
|
||||
const entry_multilingual_name *s;
|
||||
data.setPointerAndOffset<const entry_multilingual_name>(s, offset);
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
providerName.setDataAndOffset(data+offset, s->text_length, offset);
|
||||
const entry_multilingual_service_name_mid *mid;
|
||||
data.setPointerAndOffset<const entry_multilingual_service_name_mid>(mid, offset);
|
||||
name.setData(data+offset, mid->service_name_length);
|
||||
}
|
||||
|
||||
void ApplicationSignallingDescriptor::Parse() {
|
||||
entryLoop.setData(data+sizeof(descr_application_signalling), getLength()-sizeof(descr_application_signalling));
|
||||
}
|
||||
|
||||
int ApplicationSignallingDescriptor::ApplicationEntryDescriptor::getApplicationType() const {
|
||||
return HILO(s->application_type);
|
||||
}
|
||||
|
||||
int ApplicationSignallingDescriptor::ApplicationEntryDescriptor::getAITVersionNumber() const {
|
||||
return s->AIT_version_number;
|
||||
}
|
||||
|
||||
void ApplicationSignallingDescriptor::ApplicationEntryDescriptor::Parse() {
|
||||
s=data.getData<const application_signalling_entry>();
|
||||
}
|
||||
|
||||
bool MHP_ApplicationDescriptor::isServiceBound() const {
|
||||
return s->service_bound_flag;
|
||||
}
|
||||
|
||||
int MHP_ApplicationDescriptor::getVisibility() const {
|
||||
return s->visibility;
|
||||
}
|
||||
|
||||
int MHP_ApplicationDescriptor::getApplicationPriority() const {
|
||||
return s->application_priority;
|
||||
}
|
||||
|
||||
void MHP_ApplicationDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
const descr_application *dapp;
|
||||
data.setPointerAndOffset<const descr_application>(dapp, offset);
|
||||
profileLoop.setDataAndOffset(data+offset, dapp->application_profiles_length, offset);
|
||||
data.setPointerAndOffset<const descr_application_end>(s, offset);
|
||||
transportProtocolLabels.setData(data+offset, getLength()-offset);
|
||||
}
|
||||
|
||||
int MHP_ApplicationDescriptor::Profile::getApplicationProfile() const {
|
||||
return HILO(s->application_profile);
|
||||
}
|
||||
|
||||
int MHP_ApplicationDescriptor::Profile::getVersionMajor() const {
|
||||
return s->version_major;
|
||||
}
|
||||
|
||||
int MHP_ApplicationDescriptor::Profile::getVersionMinor() const {
|
||||
return s->version_minor;
|
||||
}
|
||||
|
||||
int MHP_ApplicationDescriptor::Profile::getVersionMicro() const {
|
||||
return s->version_micro;
|
||||
}
|
||||
|
||||
void MHP_ApplicationDescriptor::Profile::Parse() {
|
||||
s=data.getData<application_profile_entry>();
|
||||
}
|
||||
|
||||
void MHP_ApplicationNameDescriptor::Parse() {
|
||||
nameLoop.setData(data+sizeof(descr_application_name), getLength()-sizeof(descr_application_name));
|
||||
}
|
||||
|
||||
void MHP_ApplicationNameDescriptor::NameEntry::Parse() {
|
||||
const descr_application_name_entry *s;
|
||||
s=data.getData<const descr_application_name_entry>();
|
||||
name.setData(data+sizeof(descr_application_name_entry), s->application_name_length);
|
||||
languageCode[0]=s->lang_code1;
|
||||
languageCode[1]=s->lang_code2;
|
||||
languageCode[2]=s->lang_code3;
|
||||
}
|
||||
|
||||
int MHP_TransportProtocolDescriptor::getProtocolId() const {
|
||||
return HILO(s->protocol_id);
|
||||
}
|
||||
|
||||
int MHP_TransportProtocolDescriptor::getProtocolLabel() const {
|
||||
return s->transport_protocol_label;
|
||||
}
|
||||
|
||||
bool MHP_TransportProtocolDescriptor::isRemote() const {
|
||||
return remote;
|
||||
}
|
||||
|
||||
int MHP_TransportProtocolDescriptor::getComponentTag() const {
|
||||
return componentTag;
|
||||
}
|
||||
|
||||
void MHP_TransportProtocolDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const descr_transport_protocol>(s, offset);
|
||||
if (getProtocolId() == ObjectCarousel) {
|
||||
const transport_via_oc *oc;
|
||||
data.setPointerAndOffset<const transport_via_oc>(oc, offset);
|
||||
remote=oc->remote;
|
||||
if (remote) {
|
||||
const transport_via_oc_remote_end *rem;
|
||||
data.setPointerAndOffset<const transport_via_oc_remote_end>(rem, offset);
|
||||
componentTag=rem->component_tag;
|
||||
} else {
|
||||
const transport_via_oc_end *rem;
|
||||
data.setPointerAndOffset<const transport_via_oc_end>(rem, offset);
|
||||
componentTag=rem->component_tag;
|
||||
}
|
||||
} else { //unimplemented
|
||||
remote=false;
|
||||
componentTag=-1;
|
||||
}
|
||||
}
|
||||
|
||||
void MHP_DVBJApplicationDescriptor::Parse() {
|
||||
applicationLoop.setData(data+sizeof(descr_dvbj_application), getLength()-sizeof(descr_dvbj_application));
|
||||
}
|
||||
|
||||
void MHP_DVBJApplicationDescriptor::ApplicationEntry::Parse() {
|
||||
const descr_dvbj_application_entry *entry=data.getData<const descr_dvbj_application_entry>();
|
||||
parameter.setData(data+sizeof(descr_dvbj_application_entry), entry->parameter_length);
|
||||
}
|
||||
|
||||
void MHP_DVBJApplicationLocationDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
const descr_dvbj_application_location *first;
|
||||
data.setPointerAndOffset<const descr_dvbj_application_location>(first, offset);
|
||||
baseDirectory.setDataAndOffset(data+offset, first->base_directory_length, offset);
|
||||
const descr_dvbj_application_location_mid *mid;
|
||||
data.setPointerAndOffset<const descr_dvbj_application_location_mid>(mid, offset);
|
||||
classPath.setDataAndOffset(data+offset, mid->classpath_extension_length, offset);
|
||||
initialClass.setData(data+offset, getLength()-offset);
|
||||
}
|
||||
|
||||
int MHP_ApplicationIconsDescriptor::getIconFlags() const {
|
||||
return HILO(s->icon_flags);
|
||||
}
|
||||
|
||||
void MHP_ApplicationIconsDescriptor::Parse() {
|
||||
unsigned int offset=0;
|
||||
const descr_application_icons_descriptor *first;
|
||||
data.setPointerAndOffset<const descr_application_icons_descriptor>(first, offset);
|
||||
iconLocator.setDataAndOffset(data+offset, first->icon_locator_length, offset);
|
||||
data.setPointerAndOffset<const descr_application_icons_descriptor_end>(s, offset);
|
||||
}
|
||||
|
||||
} //end of namespace
|
477
libsi/descriptor.h
Normal file
477
libsi/descriptor.h
Normal file
@ -0,0 +1,477 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: descriptor.h 1.2 2003/12/13 10:42:08 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LIBSI_DESCRIPTOR_H
|
||||
#define LIBSI_DESCRIPTOR_H
|
||||
|
||||
#include "si.h"
|
||||
#include "headers.h"
|
||||
|
||||
namespace SI {
|
||||
|
||||
class ShortEventDescriptor : public Descriptor {
|
||||
public:
|
||||
char languageCode[3];
|
||||
String name; //name of the event
|
||||
String text; //short description
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class ExtendedEventDescriptor : public GroupDescriptor {
|
||||
public:
|
||||
class Item : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(item_extended_event)+sizeof(item_extended_event_mid)+item.getLength()+itemDescription.getLength(); }
|
||||
String item;
|
||||
String itemDescription;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
char languageCode[3];
|
||||
int getDescriptorNumber();
|
||||
int getLastDescriptorNumber();
|
||||
StructureLoop<Item> itemLoop;
|
||||
String text;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_extended_event *s;
|
||||
};
|
||||
|
||||
class ExtendedEventDescriptors : public DescriptorGroup {
|
||||
public:
|
||||
//don't use
|
||||
int getTextLength();
|
||||
//really fast
|
||||
int getMaximumTextLength();
|
||||
//same semantics as with SI::String
|
||||
char *getText();
|
||||
//buffer must at least be getTextLength(), getMaximumTextLength() is a good choice
|
||||
char *getText(char *buffer);
|
||||
};
|
||||
|
||||
class TimeShiftedEventDescriptor : public Descriptor {
|
||||
public:
|
||||
int getReferenceServiceId() const;
|
||||
int getReferenceEventId() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_time_shifted_event *s;
|
||||
};
|
||||
|
||||
class ContentDescriptor : public Descriptor {
|
||||
public:
|
||||
class Nibble : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(nibble_content); }
|
||||
int getContentNibbleLevel1() const;
|
||||
int getContentNibbleLevel2() const;
|
||||
int getUserNibble1() const;
|
||||
int getUserNibble2() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const nibble_content *s;
|
||||
};
|
||||
StructureLoop<Nibble> nibbleLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class ParentalRatingDescriptor : public Descriptor {
|
||||
public:
|
||||
class Rating : public LoopElement {
|
||||
public:
|
||||
char languageCode[3];
|
||||
int getRating() const;
|
||||
virtual int getLength() { return sizeof(parental_rating); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const parental_rating *s;
|
||||
};
|
||||
StructureLoop<Rating> ratingLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class CaDescriptor : public Descriptor {
|
||||
public:
|
||||
int getCaType() const;
|
||||
int getCaPid() const;
|
||||
CharArray privateData;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_ca *s;
|
||||
};
|
||||
|
||||
class StreamIdentifierDescriptor : public Descriptor {
|
||||
public:
|
||||
int getComponentTag() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_stream_identifier *s;
|
||||
};
|
||||
|
||||
class NetworkNameDescriptor : public Descriptor {
|
||||
public:
|
||||
String name;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class CaIdentifierDescriptor : public Descriptor {
|
||||
public:
|
||||
TypeLoop<SixteenBit> identifiers;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class CarouselIdentifierDescriptor : public Descriptor {
|
||||
public:
|
||||
int getCarouselId() const;
|
||||
int getFormatId() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_carousel_identifier *s;
|
||||
};
|
||||
|
||||
class BouquetNameDescriptor : public NetworkNameDescriptor {
|
||||
};
|
||||
|
||||
class ServiceListDescriptor : public Descriptor {
|
||||
public:
|
||||
class Service : public LoopElement {
|
||||
public:
|
||||
int getServiceId() const;
|
||||
int getServiceType() const;
|
||||
virtual int getLength() { return sizeof(descr_service_list_loop); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_service_list_loop *s;
|
||||
};
|
||||
StructureLoop<Service> serviceLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class SatelliteDeliverySystemDescriptor : public Descriptor {
|
||||
public:
|
||||
int getFrequency() const;
|
||||
int getOrbitalPosition() const;
|
||||
int getWestEastFlag() const;
|
||||
int getPolarization() const;
|
||||
int getModulation() const;
|
||||
int getSymbolRate() const;
|
||||
int getFecInner() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_satellite_delivery_system *s;
|
||||
};
|
||||
|
||||
class CableDeliverySystemDescriptor : public Descriptor {
|
||||
public:
|
||||
int getFrequency() const;
|
||||
int getFecOuter() const;
|
||||
int getModulation() const;
|
||||
int getSymbolRate() const;
|
||||
int getFecInner() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_cable_delivery_system *s;
|
||||
};
|
||||
|
||||
class TerrestrialDeliverySystemDescriptor : public Descriptor {
|
||||
public:
|
||||
int getFrequency() const;
|
||||
int getBandwidth() const;
|
||||
int getConstellation() const;
|
||||
int getHierarchy() const;
|
||||
int getCodeRateHP() const;
|
||||
int getCodeRateLP() const;
|
||||
int getGuardInterval() const;
|
||||
int getTransmissionMode() const;
|
||||
bool getOtherFrequency() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_terrestrial_delivery *s;
|
||||
};
|
||||
|
||||
class ServiceDescriptor : public Descriptor {
|
||||
public:
|
||||
int getServiceType() const;
|
||||
String serviceName;
|
||||
String providerName;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_service *s;
|
||||
};
|
||||
|
||||
class NVODReferenceDescriptor : public Descriptor {
|
||||
public:
|
||||
class Service : public LoopElement {
|
||||
public:
|
||||
int getTransportStream() const;
|
||||
int getOriginalNetworkId() const;
|
||||
int getServiceId() const;
|
||||
virtual int getLength() { return sizeof(item_nvod_reference); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const item_nvod_reference *s;
|
||||
};
|
||||
StructureLoop<Service> serviceLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class TimeShiftedServiceDescriptor : public Descriptor {
|
||||
public:
|
||||
int getReferenceServiceId() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_time_shifted_service *s;
|
||||
};
|
||||
|
||||
class ComponentDescriptor : public Descriptor {
|
||||
public:
|
||||
int getStreamContent() const;
|
||||
int getComponentType() const;
|
||||
int getComponentTag() const;
|
||||
char languageCode[3];
|
||||
String description;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_component *s;
|
||||
};
|
||||
|
||||
class SubtitlingDescriptor : public Descriptor {
|
||||
public:
|
||||
class Subtitling : public Descriptor {
|
||||
public:
|
||||
int getSubtitlingType() const;
|
||||
int getCompositionPageId() const;
|
||||
int getAncillaryPageId() const;
|
||||
virtual int getLength() { return sizeof(item_nvod_reference); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const item_subtitling *s;
|
||||
};
|
||||
StructureLoop<Subtitling> subtitlingLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class ServiceMoveDescriptor : public Descriptor {
|
||||
public:
|
||||
int getNewOriginalNetworkId() const;
|
||||
int getNewTransportStreamId() const;
|
||||
int getNewServiceId() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_service_move *s;
|
||||
};
|
||||
|
||||
class FrequencyListDescriptor : public Descriptor {
|
||||
public:
|
||||
int getCodingType() const;
|
||||
TypeLoop<ThirtyTwoBit> frequencies;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_frequency_list *s;
|
||||
};
|
||||
|
||||
class ServiceIdentifierDescriptor : public Descriptor {
|
||||
public:
|
||||
String textualServiceIdentifier;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
//abstract base class
|
||||
class MultilingualNameDescriptor : public Descriptor {
|
||||
public:
|
||||
class Name : public LoopElement {
|
||||
public:
|
||||
char languageCode[3];
|
||||
String name;
|
||||
virtual int getLength() { return sizeof(entry_multilingual_name)+name.getLength(); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
StructureLoop<Name> nameLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class MultilingualNetworkNameDescriptor : public MultilingualNameDescriptor {
|
||||
//inherits nameLoop from MultilingualNameDescriptor
|
||||
};
|
||||
|
||||
class MultilingualBouquetNameDescriptor : public MultilingualNameDescriptor {
|
||||
//inherits nameLoop from MultilingualNameDescriptor
|
||||
};
|
||||
|
||||
class MultilingualComponentDescriptor : public MultilingualNameDescriptor {
|
||||
public:
|
||||
int getComponentTag() const;
|
||||
//inherits nameLoop from MultilingualNameDescriptor
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_multilingual_component *s;
|
||||
};
|
||||
|
||||
class MultilingualServiceNameDescriptor : public Descriptor {
|
||||
public:
|
||||
class Name : public MultilingualNameDescriptor::Name {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(entry_multilingual_name)+providerName.getLength()+sizeof(entry_multilingual_service_name_mid)+name.getLength(); }
|
||||
String providerName;
|
||||
//inherits name, meaning: service name;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
StructureLoop<Name> nameLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
//a descriptor currently unimplemented in this library
|
||||
class UnimplementedDescriptor : public Descriptor {
|
||||
protected:
|
||||
virtual void Parse() {}
|
||||
};
|
||||
|
||||
class ApplicationSignallingDescriptor : public Descriptor {
|
||||
public:
|
||||
class ApplicationEntryDescriptor : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(application_signalling_entry); }
|
||||
int getApplicationType() const;
|
||||
int getAITVersionNumber() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const application_signalling_entry *s;
|
||||
};
|
||||
StructureLoop<ApplicationEntryDescriptor> entryLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class MHP_ApplicationDescriptor : public Descriptor {
|
||||
public:
|
||||
class Profile : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(application_profile_entry); }
|
||||
int getApplicationProfile() const;
|
||||
int getVersionMajor() const;
|
||||
int getVersionMinor() const;
|
||||
int getVersionMicro() const;
|
||||
private:
|
||||
const application_profile_entry *s;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
StructureLoop<Profile> profileLoop;
|
||||
bool isServiceBound() const;
|
||||
int getVisibility() const;
|
||||
int getApplicationPriority() const;
|
||||
TypeLoop<EightBit> transportProtocolLabels;
|
||||
private:
|
||||
const descr_application_end *s;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class MHP_ApplicationNameDescriptor : public Descriptor {
|
||||
public:
|
||||
class NameEntry : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(descr_application_name_entry)+name.getLength(); }
|
||||
char languageCode[3];
|
||||
String name;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
StructureLoop<NameEntry> nameLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class MHP_TransportProtocolDescriptor : public Descriptor {
|
||||
public:
|
||||
enum Protocol { ObjectCarousel = 0x01, IPviaDVB = 0x02, HTTPoverInteractionChannel = 0x03 };
|
||||
int getProtocolId() const;
|
||||
int getProtocolLabel() const;
|
||||
bool isRemote() const;
|
||||
int getComponentTag() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_transport_protocol *s;
|
||||
bool remote;
|
||||
int componentTag;
|
||||
};
|
||||
|
||||
class MHP_DVBJApplicationDescriptor : public Descriptor {
|
||||
public:
|
||||
class ApplicationEntry : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(descr_dvbj_application_entry)+parameter.getLength(); }
|
||||
String parameter;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
StructureLoop<ApplicationEntry> applicationLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class MHP_DVBJApplicationLocationDescriptor : public Descriptor {
|
||||
public:
|
||||
String baseDirectory;
|
||||
String classPath;
|
||||
String initialClass;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class MHP_ApplicationIconsDescriptor : public Descriptor {
|
||||
public:
|
||||
String iconLocator;
|
||||
int getIconFlags() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const descr_application_icons_descriptor_end *s;
|
||||
};
|
||||
|
||||
} //end of namespace
|
||||
|
||||
#endif //LIBSI_TABLE_H
|
83
libsi/gendescr.pl
Executable file
83
libsi/gendescr.pl
Executable file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# $Id: gendescr.pl 1.2 2003/12/13 10:40:53 kls Exp $
|
||||
|
||||
print "Name (ohne ...Descriptor):";
|
||||
$name=<STDIN>;
|
||||
$name =~ s/\n$//;
|
||||
$inner = ($name =~ s/ä$//);
|
||||
$name .= "Descriptor" unless ($inner);
|
||||
|
||||
print "Struct:";
|
||||
$struct=<STDIN>;
|
||||
$struct =~ s/\n$//;
|
||||
|
||||
mm:
|
||||
$index=0;
|
||||
$which=1;
|
||||
print "Variablen:";
|
||||
while ( <STDIN> ) {
|
||||
if (/ä/) {
|
||||
goto vv;
|
||||
} elsif (/ü/) {
|
||||
$which=1;
|
||||
next;
|
||||
}
|
||||
$eingabe=$_;
|
||||
$eingabe =~ s/(.{75,120} )/\1\n/g;
|
||||
$eingabe =~ s/\n$//;
|
||||
if ($which) {
|
||||
$members[$index]=$eingabe;
|
||||
} else {
|
||||
$members_comments[$index]=$eingabe;
|
||||
$index++;
|
||||
print "Jep!\n";
|
||||
}
|
||||
$which= (! $which);
|
||||
}
|
||||
|
||||
vv:
|
||||
$filename_h="tempdescr.h";
|
||||
$filename_c="tempdescr.c";
|
||||
schreib();
|
||||
|
||||
sub schreib {
|
||||
print "Danke.\n";
|
||||
open(OUTPUT_H, ">>".$filename_h) or die "Could not open file!!";
|
||||
open(OUTPUT_C, ">>".$filename_c) or die "Could not open file!!";
|
||||
|
||||
if ($inner) {
|
||||
$offset=" ";
|
||||
} else {
|
||||
$offset="";
|
||||
}
|
||||
print(OUTPUT_H $offset."class ".$name);
|
||||
if ($inner) {
|
||||
print(OUTPUT_H " : public LoopElement {\n".$offset."public:");
|
||||
} else {
|
||||
print(OUTPUT_H " : public Descriptor {\n".$offset."public:");
|
||||
}
|
||||
#for ($i=0; $i<=$#vars;$i++) {
|
||||
# print (OUTPUT "/*\n".$vars_comments[$i]." */\n".$vars[$i].";\n\n\n");
|
||||
#}
|
||||
for ($i=0; $i<=$#members;$i++) {
|
||||
print (OUTPUT_H "\n".$offset." int get".$members[$i]."() const;");
|
||||
}
|
||||
print(OUTPUT_H "\n".$offset."virtual int getLength() { return sizeof(".$struct."); }") if ($inner);
|
||||
|
||||
print(OUTPUT_H "\n".$offset."protected:\n".$offset." virtual void Parse();");
|
||||
print(OUTPUT_H "\n".$offset."private:\n".$offset." const ".$struct." *s;") if ($struct ne "");
|
||||
print(OUTPUT_H "\n".$offset."};\n\n");
|
||||
for ($i=0; $i<=$#members_comments;$i++) {
|
||||
print (OUTPUT_C "int ".$name."::get".$members[$i]."() const {\n");
|
||||
if ($members_comments[$i] =~ /^(.+)_hi$/) {
|
||||
$varbase=$1;
|
||||
print (OUTPUT_C " return HILO(s->".$varbase.");\n}\n\n");
|
||||
} else {
|
||||
print (OUTPUT_C " return s->".$members_comments[$i].";\n}\n\n");
|
||||
}
|
||||
}
|
||||
print (OUTPUT_C "void ".$name."::Parse() {\n}\n\n");
|
||||
print (OUTPUT_C "\n\n\n");
|
||||
exit;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
328
libsi/section.c
Normal file
328
libsi/section.c
Normal file
@ -0,0 +1,328 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: section.c 1.2 2003/12/13 10:42:14 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "section.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace SI {
|
||||
|
||||
/*********************** PAT ***********************/
|
||||
|
||||
void PAT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const pat>(s, offset);
|
||||
associationLoop.setData(data+offset, getLength()-offset-4);
|
||||
}
|
||||
|
||||
int PAT::getTransportStreamId() const {
|
||||
return HILO(s->transport_stream_id);
|
||||
}
|
||||
|
||||
int PAT::Association::getServiceId() const {
|
||||
return HILO(s->program_number);
|
||||
}
|
||||
|
||||
int PAT::Association::getPid() const {
|
||||
return HILO(s->network_pid);
|
||||
}
|
||||
|
||||
void PAT::Association::Parse() {
|
||||
s=data.getData<pat_prog>();
|
||||
}
|
||||
|
||||
/*********************** CAT ***********************/
|
||||
|
||||
void CAT::Parse() {
|
||||
loop.setData(data+sizeof(cat), getLength()-sizeof(cat)-4);
|
||||
}
|
||||
|
||||
/*********************** PMT ***********************/
|
||||
|
||||
void PMT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const pmt>(s, offset);
|
||||
commonDescriptors.setDataAndOffset(data+offset, HILO(s->program_info_length), offset);
|
||||
streamLoop.setData(data+offset, getLength()-offset-4);
|
||||
}
|
||||
|
||||
int PMT::getServiceId() const {
|
||||
return HILO(s->program_number);
|
||||
}
|
||||
|
||||
int PMT::getPCRPid() const {
|
||||
return HILO(s->PCR_PID);
|
||||
}
|
||||
|
||||
int PMT::Stream::getPid() const {
|
||||
return HILO(s->elementary_PID);
|
||||
}
|
||||
|
||||
int PMT::Stream::getStreamType() const {
|
||||
return s->stream_type;
|
||||
}
|
||||
|
||||
void PMT::Stream::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const pmt_info>(s, offset);
|
||||
streamDescriptors.setData(data+offset, HILO(s->ES_info_length));
|
||||
}
|
||||
|
||||
/*********************** NIT ***********************/
|
||||
|
||||
int NIT::getNetworkId() const {
|
||||
return HILO(s->network_id);
|
||||
}
|
||||
|
||||
void NIT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const nit>(s, offset);
|
||||
commonDescriptors.setDataAndOffset(data+offset, HILO(s->network_descriptor_length), offset);
|
||||
const nit_mid *mid;
|
||||
data.setPointerAndOffset<const nit_mid>(mid, offset);
|
||||
transportStreamLoop.setData(data+offset, HILO(mid->transport_stream_loop_length));
|
||||
}
|
||||
|
||||
int NIT::TransportStream::getTransportStreamId() const {
|
||||
return HILO(s->transport_stream_id);
|
||||
}
|
||||
|
||||
int NIT::TransportStream::getOriginalNetworkId() const {
|
||||
return HILO(s->original_network_id);
|
||||
}
|
||||
|
||||
void NIT::TransportStream::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const ni_ts>(s, offset);
|
||||
transportStreamDescriptors.setData(data+offset, HILO(s->transport_descriptors_length));
|
||||
}
|
||||
|
||||
/*********************** SDT ***********************/
|
||||
|
||||
void SDT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const sdt>(s, offset);
|
||||
serviceLoop.setData(data+offset, getLength()-offset-4); //4 is for CRC
|
||||
}
|
||||
|
||||
int SDT::getTransportStreamId() const {
|
||||
return HILO(s->transport_stream_id);
|
||||
}
|
||||
|
||||
int SDT::getOriginalNetworkId() const {
|
||||
return HILO(s->original_network_id);
|
||||
}
|
||||
|
||||
int SDT::Service::getServiceId() const {
|
||||
return HILO(s->service_id);
|
||||
}
|
||||
|
||||
int SDT::Service::getEITscheduleFlag() const {
|
||||
return s->eit_schedule_flag;
|
||||
}
|
||||
|
||||
int SDT::Service::getEITpresentFollowingFlag() const {
|
||||
return s->eit_present_following_flag;
|
||||
}
|
||||
|
||||
RunningStatus SDT::Service::getRunningStatus() const {
|
||||
return (RunningStatus)s->running_status;
|
||||
}
|
||||
|
||||
int SDT::Service::getFreeCaMode() const {
|
||||
return s->free_ca_mode;
|
||||
}
|
||||
|
||||
void SDT::Service::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const sdt_descr>(s, offset);
|
||||
serviceDescriptors.setData(data+offset, HILO(s->descriptors_loop_length));
|
||||
}
|
||||
|
||||
/*********************** EIT ***********************/
|
||||
|
||||
int EIT::getServiceId() const {
|
||||
return HILO(s->service_id);
|
||||
}
|
||||
|
||||
int EIT::getTransportStreamId() const {
|
||||
return HILO(s->transport_stream_id);
|
||||
}
|
||||
|
||||
int EIT::getOriginalNetworkId() const {
|
||||
return HILO(s->original_network_id);
|
||||
}
|
||||
|
||||
bool EIT::isPresentFollowing() const {
|
||||
return getTableId() == TableIdEIT_presentFollowing || getTableId() == TableIdEIT_presentFollowing_other;
|
||||
}
|
||||
|
||||
bool EIT::isActualTS() const {
|
||||
return
|
||||
(getTableId() ==TableIdEIT_presentFollowing)
|
||||
|| (TableIdEIT_schedule_first <= getTableId() && getTableId() <= TableIdEIT_schedule_last);
|
||||
}
|
||||
|
||||
void EIT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const eit>(s, offset);
|
||||
//printf("%d %d %d %d %d\n", getServiceId(), getTransportStreamId(), getOriginalNetworkId(), isPresentFollowing(), isActualTS());
|
||||
eventLoop.setData(data+offset, getLength()-offset-4); //4 is for CRC
|
||||
}
|
||||
|
||||
time_t EIT::Event::getStartTime() const {
|
||||
return DVBTime::getTime(s->mjd_hi, s->mjd_lo, s->start_time_h, s->start_time_m, s->start_time_s);
|
||||
}
|
||||
|
||||
time_t EIT::Event::getDuration() const {
|
||||
return DVBTime::getDuration(s->duration_h, s->duration_m, s->duration_s);
|
||||
}
|
||||
|
||||
int EIT::Event::getEventId() const {
|
||||
return HILO(s->event_id);
|
||||
}
|
||||
|
||||
int EIT::Event::getMJD() const {
|
||||
return HILO(s->mjd);
|
||||
}
|
||||
|
||||
int EIT::Event::getStartTimeHour() const {
|
||||
return DVBTime::bcdToDec(s->start_time_h);
|
||||
}
|
||||
|
||||
int EIT::Event::getStartTimeMinute() const {
|
||||
return DVBTime::bcdToDec(s->start_time_m);
|
||||
}
|
||||
|
||||
int EIT::Event::getStartTimeSecond() const {
|
||||
return DVBTime::bcdToDec(s->start_time_s);
|
||||
}
|
||||
|
||||
int EIT::Event::getDurationHour() const {
|
||||
return DVBTime::bcdToDec(s->duration_h);
|
||||
}
|
||||
|
||||
int EIT::Event::getDurationMinute() const {
|
||||
return DVBTime::bcdToDec(s->duration_m);
|
||||
}
|
||||
|
||||
int EIT::Event::getDurationSecond() const {
|
||||
return DVBTime::bcdToDec(s->duration_s);
|
||||
}
|
||||
|
||||
RunningStatus EIT::Event::getRunningStatus() const {
|
||||
return (RunningStatus)s->running_status;
|
||||
}
|
||||
|
||||
int EIT::Event::getFreeCaMode() const {
|
||||
return s->free_ca_mode;
|
||||
}
|
||||
|
||||
void EIT::Event::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const eit_event>(s, offset);
|
||||
//printf("%d %d %d\n", getStartTime(), getDuration(), getRunningStatus());
|
||||
eventDescriptors.setData(data+offset, HILO(s->descriptors_loop_length));
|
||||
}
|
||||
|
||||
/*********************** TDT ***********************/
|
||||
|
||||
time_t TDT::getTime() const {
|
||||
return DVBTime::getTime(s->utc_mjd_hi, s->utc_mjd_lo, s->utc_time_h, s->utc_time_m, s->utc_time_s);
|
||||
}
|
||||
|
||||
void TDT::Parse() {
|
||||
s=data.getData<const tdt>();
|
||||
}
|
||||
|
||||
/*********************** TOT ***********************/
|
||||
|
||||
time_t TOT::getTime() const {
|
||||
return DVBTime::getTime(s->utc_mjd_hi, s->utc_mjd_lo, s->utc_time_h, s->utc_time_m, s->utc_time_s);
|
||||
}
|
||||
|
||||
void TOT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const tot>(s, offset);
|
||||
descriptorLoop.setData(data+offset, getLength()-offset-4);
|
||||
}
|
||||
|
||||
/*********************** RST ***********************/
|
||||
|
||||
void RST::Parse() {
|
||||
unsigned int offset=0;
|
||||
const rst *s;
|
||||
data.setPointerAndOffset<const rst>(s, offset);
|
||||
infoLoop.setData(data+offset, getLength()-offset);
|
||||
}
|
||||
|
||||
int RST::RunningInfo::getTransportStreamId() const {
|
||||
return HILO(s->transport_stream_id);
|
||||
}
|
||||
|
||||
int RST::RunningInfo::getOriginalNetworkId() const {
|
||||
return HILO(s->original_network_id);
|
||||
}
|
||||
|
||||
int RST::RunningInfo::getServiceId() const {
|
||||
return HILO(s->service_id);
|
||||
}
|
||||
|
||||
int RST::RunningInfo::getEventId() const {
|
||||
return HILO(s->event_id);
|
||||
}
|
||||
|
||||
RunningStatus RST::RunningInfo::getRunningStatus() const {
|
||||
return (RunningStatus)s->running_status;
|
||||
}
|
||||
|
||||
void RST::RunningInfo::Parse() {
|
||||
s=data.getData<const rst_info>();
|
||||
}
|
||||
|
||||
/*********************** AIT ***********************/
|
||||
|
||||
int AIT::getApplicationType() const {
|
||||
return HILO(first->application_type);
|
||||
}
|
||||
|
||||
int AIT::getAITVersion() const {
|
||||
return first->version_number;
|
||||
}
|
||||
|
||||
void AIT::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const ait>(first, offset);
|
||||
commonDescriptors.setDataAndOffset(data+offset, HILO(first->common_descriptors_length), offset);
|
||||
const ait_mid *mid;
|
||||
data.setPointerAndOffset<const ait_mid>(mid, offset);
|
||||
applicationLoop.setData(data+offset, HILO(mid->application_loop_length));
|
||||
}
|
||||
|
||||
long AIT::Application::getOrganisationId() const {
|
||||
return data.FourBytes(0);
|
||||
}
|
||||
|
||||
int AIT::Application::getApplicationId() const {
|
||||
return HILO(s->application_id);
|
||||
}
|
||||
|
||||
int AIT::Application::getControlCode() const {
|
||||
return s->application_control_code;
|
||||
}
|
||||
|
||||
void AIT::Application::Parse() {
|
||||
unsigned int offset=0;
|
||||
data.setPointerAndOffset<const ait_app>(s, offset);
|
||||
applicationDescriptors.setData(data+offset, HILO(s->application_descriptors_length));
|
||||
}
|
||||
|
||||
} //end of namespace
|
252
libsi/section.h
Normal file
252
libsi/section.h
Normal file
@ -0,0 +1,252 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: section.h 1.2 2003/12/13 10:42:15 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LIBSI_SECTION_H
|
||||
#define LIBSI_SECTION_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "si.h"
|
||||
#include "headers.h"
|
||||
|
||||
namespace SI {
|
||||
|
||||
class PAT : public NumberedSection {
|
||||
public:
|
||||
PAT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
PAT() {}
|
||||
class Association : public LoopElement {
|
||||
public:
|
||||
int getServiceId() const;
|
||||
int getPid() const;
|
||||
bool isNITPid() const { return getServiceId()==0; }
|
||||
virtual int getLength() { return sizeof(pat_prog); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const pat_prog *s;
|
||||
};
|
||||
int getTransportStreamId() const;
|
||||
StructureLoop<Association> associationLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const pat *s;
|
||||
};
|
||||
|
||||
class CAT : public NumberedSection {
|
||||
public:
|
||||
CAT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
CAT() {}
|
||||
DescriptorLoop loop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class PMT : public NumberedSection {
|
||||
public:
|
||||
PMT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
PMT() {}
|
||||
class Stream : public LoopElement {
|
||||
public:
|
||||
int getPid() const;
|
||||
int getStreamType() const;
|
||||
DescriptorLoop streamDescriptors;
|
||||
virtual int getLength() { return sizeof(pmt_info)+streamDescriptors.getLength(); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const pmt_info *s;
|
||||
};
|
||||
DescriptorLoop commonDescriptors;
|
||||
StructureLoop<Stream> streamLoop;
|
||||
int getServiceId() const;
|
||||
int getPCRPid() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const pmt *s;
|
||||
};
|
||||
|
||||
class NIT : public NumberedSection {
|
||||
public:
|
||||
NIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
NIT() {}
|
||||
class TransportStream : public LoopElement {
|
||||
public:
|
||||
int getTransportStreamId() const;
|
||||
int getOriginalNetworkId() const;
|
||||
virtual int getLength() { return sizeof(ni_ts)+transportStreamDescriptors.getLength(); }
|
||||
DescriptorLoop transportStreamDescriptors;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const ni_ts *s;
|
||||
};
|
||||
DescriptorLoop commonDescriptors;
|
||||
StructureLoop<TransportStream> transportStreamLoop;
|
||||
int getNetworkId() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const nit *s;
|
||||
};
|
||||
|
||||
//BAT has the same structure as NIT but different allowed descriptors
|
||||
class BAT : public NIT {
|
||||
public:
|
||||
BAT(const unsigned char *data, bool doCopy=true) : NIT(data, doCopy) {}
|
||||
BAT() {}
|
||||
int getBouquetId() const { return getNetworkId(); }
|
||||
};
|
||||
|
||||
class SDT : public NumberedSection {
|
||||
public:
|
||||
SDT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
SDT() {}
|
||||
class Service : public LoopElement {
|
||||
public:
|
||||
int getServiceId() const;
|
||||
int getEITscheduleFlag() const;
|
||||
int getEITpresentFollowingFlag() const;
|
||||
RunningStatus getRunningStatus() const;
|
||||
int getFreeCaMode() const;
|
||||
virtual int getLength() { return sizeof(sdt_descr)+serviceDescriptors.getLength(); }
|
||||
DescriptorLoop serviceDescriptors;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const sdt_descr *s;
|
||||
};
|
||||
int getTransportStreamId() const;
|
||||
int getOriginalNetworkId() const;
|
||||
StructureLoop<Service> serviceLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const sdt *s;
|
||||
};
|
||||
|
||||
class EIT : public NumberedSection {
|
||||
public:
|
||||
EIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
EIT() {}
|
||||
class Event : public LoopElement {
|
||||
public:
|
||||
int getEventId() const;
|
||||
time_t getStartTime() const; //UTC
|
||||
time_t getDuration() const;
|
||||
|
||||
int getMJD() const;
|
||||
int getStartTimeHour() const; //UTC
|
||||
int getStartTimeMinute() const; //UTC
|
||||
int getStartTimeSecond() const; //UTC
|
||||
int getDurationHour() const;
|
||||
int getDurationMinute() const;
|
||||
int getDurationSecond() const;
|
||||
RunningStatus getRunningStatus() const;
|
||||
int getFreeCaMode() const;
|
||||
|
||||
DescriptorLoop eventDescriptors;
|
||||
virtual int getLength() { return sizeof(eit_event)+eventDescriptors.getLength(); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const eit_event *s;
|
||||
};
|
||||
int getServiceId() const;
|
||||
int getTransportStreamId() const;
|
||||
int getOriginalNetworkId() const;
|
||||
StructureLoop<Event> eventLoop;
|
||||
|
||||
//true if table conveys present/following information, false if it conveys schedule information
|
||||
bool isPresentFollowing() const;
|
||||
//true if table describes TS on which it is broadcast, false if it describes other TS
|
||||
bool isActualTS() const;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const eit *s;
|
||||
};
|
||||
|
||||
class TDT : public Section {
|
||||
public:
|
||||
TDT(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
|
||||
TDT() {}
|
||||
time_t getTime() const; //UTC
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const tdt *s;
|
||||
};
|
||||
|
||||
class TOT : public CRCSection {
|
||||
public:
|
||||
TOT(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {}
|
||||
TOT() {}
|
||||
time_t getTime() const;
|
||||
DescriptorLoop descriptorLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const tot *s;
|
||||
};
|
||||
|
||||
class RST : public Section {
|
||||
public:
|
||||
RST(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
|
||||
RST() {}
|
||||
class RunningInfo : public LoopElement {
|
||||
public:
|
||||
int getTransportStreamId() const;
|
||||
int getOriginalNetworkId() const;
|
||||
int getServiceId() const;
|
||||
int getEventId() const;
|
||||
RunningStatus getRunningStatus() const;
|
||||
virtual int getLength() { return sizeof(rst_info); }
|
||||
protected:
|
||||
virtual void Parse();
|
||||
private:
|
||||
const rst_info *s;
|
||||
};
|
||||
StructureLoop<RunningInfo> infoLoop;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
class AIT : public NumberedSection {
|
||||
public:
|
||||
AIT(const unsigned char *data, bool doCopy=true) : NumberedSection(data, doCopy) {}
|
||||
AIT() {}
|
||||
class Application : public LoopElement {
|
||||
public:
|
||||
virtual int getLength() { return sizeof(ait_app)+applicationDescriptors.getLength(); }
|
||||
long getOrganisationId() const;
|
||||
int getApplicationId() const;
|
||||
int getControlCode() const;
|
||||
MHP_DescriptorLoop applicationDescriptors;
|
||||
protected:
|
||||
virtual void Parse();
|
||||
const ait_app *s;
|
||||
};
|
||||
MHP_DescriptorLoop commonDescriptors;
|
||||
StructureLoop<Application> applicationLoop;
|
||||
int getApplicationType() const;
|
||||
int getAITVersion() const;
|
||||
protected:
|
||||
const ait *first;
|
||||
virtual void Parse();
|
||||
};
|
||||
|
||||
} //end of namespace
|
||||
|
||||
#endif //LIBSI_TABLE_H
|
415
libsi/si.c
Normal file
415
libsi/si.c
Normal file
@ -0,0 +1,415 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: si.c 1.3 2004/01/04 14:26:53 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "si.h"
|
||||
#include "descriptor.h"
|
||||
|
||||
namespace SI {
|
||||
|
||||
Object::Object() {
|
||||
}
|
||||
|
||||
Object::Object(CharArray &d) : data(d) {
|
||||
}
|
||||
|
||||
void Object::setData(const unsigned char*d, unsigned int size, bool doCopy) {
|
||||
data.assign(d, size, doCopy);
|
||||
}
|
||||
|
||||
void Object::setData(CharArray &d) {
|
||||
data=d;
|
||||
}
|
||||
|
||||
Section::Section(const unsigned char *data, bool doCopy) {
|
||||
setData(data, getLength(data), doCopy);
|
||||
}
|
||||
|
||||
TableId Section::getTableId() const {
|
||||
return getTableId(data.getData());
|
||||
}
|
||||
|
||||
int Section::getLength() {
|
||||
return getLength(data.getData());
|
||||
}
|
||||
|
||||
TableId Section::getTableId(const unsigned char *d) {
|
||||
return (TableId)((const SectionHeader *)d)->table_id;
|
||||
}
|
||||
|
||||
int Section::getLength(const unsigned char *d) {
|
||||
return HILO(((const SectionHeader *)d)->section_length)+sizeof(SectionHeader);
|
||||
}
|
||||
|
||||
bool CRCSection::isValid() {
|
||||
return CRC32::isValid((const char *)data.getData(), getLength()/*, data.FourBytes(getLength()-4)*/);
|
||||
}
|
||||
|
||||
bool CRCSection::CheckCRCAndParse() {
|
||||
if (!isValid())
|
||||
return false;
|
||||
CheckParse();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NumberedSection::getCurrentNextIndicator() const {
|
||||
return data.getData<ExtendedSectionHeader>()->current_next_indicator;
|
||||
}
|
||||
|
||||
int NumberedSection::getVersionNumber() const {
|
||||
return data.getData<ExtendedSectionHeader>()->version_number;
|
||||
}
|
||||
|
||||
int NumberedSection::getSectionNumber() const {
|
||||
return data.getData<ExtendedSectionHeader>()->section_number;
|
||||
}
|
||||
|
||||
int NumberedSection::getLastSectionNumber() const {
|
||||
return data.getData<ExtendedSectionHeader>()->last_section_number;
|
||||
}
|
||||
|
||||
int Descriptor::getLength() {
|
||||
return getLength(data.getData());
|
||||
}
|
||||
|
||||
DescriptorTag Descriptor::getDescriptorTag() const {
|
||||
return getDescriptorTag(data.getData());
|
||||
}
|
||||
|
||||
int Descriptor::getLength(const unsigned char *d) {
|
||||
return ((const DescriptorHeader*)d)->descriptor_length+sizeof(DescriptorHeader);
|
||||
}
|
||||
|
||||
DescriptorTag Descriptor::getDescriptorTag(const unsigned char *d) {
|
||||
return (DescriptorTag)((const DescriptorHeader*)d)->descriptor_tag;
|
||||
}
|
||||
|
||||
Descriptor *DescriptorLoop::getNext(Iterator &it) {
|
||||
if (it.i<getLength()) {
|
||||
return createDescriptor(it.i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor) {
|
||||
Descriptor *d=0;
|
||||
if (it.i<getLength()) {
|
||||
const unsigned char *p=data.getData(it.i);
|
||||
const unsigned char *end=p+getLength();
|
||||
while (p < end) {
|
||||
if (Descriptor::getDescriptorTag(p) == tag) {
|
||||
d=createDescriptor(it.i);
|
||||
break;
|
||||
}
|
||||
it.i+=Descriptor::getLength(p);
|
||||
p+=Descriptor::getLength(p);
|
||||
}
|
||||
}
|
||||
if (d && d->getDescriptorTag()==UnimplementedDescriptorTag)
|
||||
return returnUnimplemetedDescriptor ? d : 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
Descriptor *DescriptorLoop::getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor) {
|
||||
Descriptor *d=0;
|
||||
if (it.i<getLength()) {
|
||||
const unsigned char *p=data.getData(it.i);
|
||||
const unsigned char *end=p+getLength();
|
||||
while (p < end) {
|
||||
for (int u=0; u<arrayLength;u++)
|
||||
if (Descriptor::getDescriptorTag(p) == tags[u]) {
|
||||
d=createDescriptor(it.i);
|
||||
break;
|
||||
}
|
||||
if (d)
|
||||
break;
|
||||
it.i+=Descriptor::getLength(p);
|
||||
p+=Descriptor::getLength(p);
|
||||
}
|
||||
}
|
||||
if (d && d->getDescriptorTag()==UnimplementedDescriptorTag)
|
||||
return returnUnimplemetedDescriptor ? d : 0;
|
||||
return d;
|
||||
}
|
||||
|
||||
Descriptor *DescriptorLoop::createDescriptor(int &i) {
|
||||
Descriptor *d=Descriptor::getDescriptor(data+i, domain);
|
||||
i+=d->getLength();
|
||||
d->CheckParse();
|
||||
return d;
|
||||
}
|
||||
|
||||
DescriptorGroup::DescriptorGroup(bool del) {
|
||||
array=0;
|
||||
length=0;
|
||||
deleteOnDesctruction=del;
|
||||
}
|
||||
|
||||
DescriptorGroup::~DescriptorGroup() {
|
||||
if (deleteOnDesctruction)
|
||||
Delete();
|
||||
delete[] array;
|
||||
}
|
||||
|
||||
void DescriptorGroup::Delete() {
|
||||
for (int i=0;i<length;i++)
|
||||
if (array[i]!=0) {
|
||||
delete array[i];
|
||||
array[i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
void DescriptorGroup::Add(GroupDescriptor *d) {
|
||||
if (!array) {
|
||||
length=d->getLastDescriptorNumber()+1;
|
||||
array=new GroupDescriptor*[length]; //numbering is zero-based
|
||||
for (int i=0;i<length;i++)
|
||||
array[i]=0;
|
||||
} else if (length != d->getLastDescriptorNumber()+1)
|
||||
return; //avoid crash in case of misuse
|
||||
array[d->getDescriptorNumber()]=d;
|
||||
}
|
||||
|
||||
bool DescriptorGroup::isComplete() {
|
||||
for (int i=0;i<length;i++)
|
||||
if (array[i]==0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
char *String::getText() {
|
||||
if (getLength() < 0 || getLength() >4095)
|
||||
return "text error";
|
||||
char *data=new char(getLength()+1);
|
||||
decodeText(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
char *String::getText(char *buffer) {
|
||||
if (getLength() < 0 || getLength() >4095) {
|
||||
strncpy(buffer, "text error", getLength()+1);
|
||||
return buffer;
|
||||
}
|
||||
decodeText(buffer);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//taken from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
|
||||
void String::decodeText(char *buffer) {
|
||||
const unsigned char *from=data.getData(0);
|
||||
char *to=buffer;
|
||||
|
||||
/* Disable detection of coding tables - libdtv doesn't do it either
|
||||
if ( (0x01 <= *from) && (*from <= 0x1f) ) {
|
||||
codeTable=*from
|
||||
}
|
||||
*/
|
||||
|
||||
for (int i = 0; i < getLength(); i++) {
|
||||
if (*from == 0)
|
||||
break;
|
||||
if ( ((' ' <= *from) && (*from <= '~'))
|
||||
|| (*from == '\n')
|
||||
|| ((0xA0 <= *from) && (*from <= 0xFF))
|
||||
)
|
||||
*to++ = *from;
|
||||
else if (*from == 0x8A)
|
||||
*to++ = '\n';
|
||||
else if (*from == 0x86 || *from == 0x87) //&& !(GDT_NAME_DESCRIPTOR & type))
|
||||
*to++ = *from;
|
||||
from++;
|
||||
}
|
||||
*to = '\0';
|
||||
}
|
||||
|
||||
Descriptor *Descriptor::getDescriptor(CharArray da, DescriptorTagDomain domain) {
|
||||
Descriptor *d=0;
|
||||
switch (domain) {
|
||||
case SI:
|
||||
switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
|
||||
case CaDescriptorTag:
|
||||
d=new CaDescriptor();
|
||||
break;
|
||||
case CarouselIdentifierDescriptorTag:
|
||||
d=new CarouselIdentifierDescriptor();
|
||||
break;
|
||||
case NetworkNameDescriptorTag:
|
||||
d=new NetworkNameDescriptor();
|
||||
break;
|
||||
case ServiceListDescriptorTag:
|
||||
d=new ServiceListDescriptor();
|
||||
break;
|
||||
case SatelliteDeliverySystemDescriptorTag:
|
||||
d=new SatelliteDeliverySystemDescriptor();
|
||||
break;
|
||||
case CableDeliverySystemDescriptorTag:
|
||||
d=new CableDeliverySystemDescriptor();
|
||||
break;
|
||||
case TerrestrialDeliverySystemDescriptorTag:
|
||||
d=new TerrestrialDeliverySystemDescriptor();
|
||||
break;
|
||||
case BouquetNameDescriptorTag:
|
||||
d=new BouquetNameDescriptor();
|
||||
break;
|
||||
case ServiceDescriptorTag:
|
||||
d=new ServiceDescriptor();
|
||||
break;
|
||||
case NVODReferenceDescriptorTag:
|
||||
d=new NVODReferenceDescriptor();
|
||||
break;
|
||||
case TimeShiftedServiceDescriptorTag:
|
||||
d=new TimeShiftedServiceDescriptor();
|
||||
break;
|
||||
case ComponentDescriptorTag:
|
||||
d=new ComponentDescriptor();
|
||||
break;
|
||||
case StreamIdentifierDescriptorTag:
|
||||
d=new StreamIdentifierDescriptor();
|
||||
break;
|
||||
case SubtitlingDescriptorTag:
|
||||
d=new SubtitlingDescriptor();
|
||||
break;
|
||||
case MultilingualNetworkNameDescriptorTag:
|
||||
d=new MultilingualNetworkNameDescriptor();
|
||||
break;
|
||||
case MultilingualBouquetNameDescriptorTag:
|
||||
d=new MultilingualBouquetNameDescriptor();
|
||||
break;
|
||||
case MultilingualServiceNameDescriptorTag:
|
||||
d=new MultilingualServiceNameDescriptor();
|
||||
break;
|
||||
case MultilingualComponentDescriptorTag:
|
||||
d=new MultilingualComponentDescriptor();
|
||||
break;
|
||||
case ServiceMoveDescriptorTag:
|
||||
d=new ServiceMoveDescriptor();
|
||||
break;
|
||||
case FrequencyListDescriptorTag:
|
||||
d=new FrequencyListDescriptor();
|
||||
break;
|
||||
case ServiceIdentifierDescriptorTag:
|
||||
d=new ServiceIdentifierDescriptor();
|
||||
break;
|
||||
case CaIdentifierDescriptorTag:
|
||||
d=new CaIdentifierDescriptor();
|
||||
break;
|
||||
case ShortEventDescriptorTag:
|
||||
d=new ShortEventDescriptor();
|
||||
break;
|
||||
case ExtendedEventDescriptorTag:
|
||||
d=new ExtendedEventDescriptor();
|
||||
break;
|
||||
case TimeShiftedEventDescriptorTag:
|
||||
d=new TimeShiftedEventDescriptor();
|
||||
break;
|
||||
case ContentDescriptorTag:
|
||||
d=new ContentDescriptor();
|
||||
break;
|
||||
case ParentalRatingDescriptorTag:
|
||||
d=new ParentalRatingDescriptor();
|
||||
break;
|
||||
case ApplicationSignallingDescriptorTag:
|
||||
d=new ApplicationSignallingDescriptor();
|
||||
break;
|
||||
|
||||
//note that it is no problem to implement one
|
||||
//of the unimplemented descriptors.
|
||||
|
||||
//defined in ISO-13818-1
|
||||
case VideoStreamDescriptorTag:
|
||||
case AudioStreamDescriptorTag:
|
||||
case HierarchyDescriptorTag:
|
||||
case RegistrationDescriptorTag:
|
||||
case DataStreamAlignmentDescriptorTag:
|
||||
case TargetBackgroundGridDescriptorTag:
|
||||
case VideoWindowDescriptorTag:
|
||||
case ISO639LanguageDescriptorTag:
|
||||
case SystemClockDescriptorTag:
|
||||
case MultiplexBufferUtilizationDescriptorTag:
|
||||
case CopyrightDescriptorTag:
|
||||
case MaximumBitrateDescriptorTag:
|
||||
case PrivateDataIndicatorDescriptorTag:
|
||||
case SmoothingBufferDescriptorTag:
|
||||
case STDDescriptorTag:
|
||||
case IBPDescriptorTag:
|
||||
|
||||
//defined in ETSI EN 300 468
|
||||
case StuffingDescriptorTag:
|
||||
case VBIDataDescriptorTag:
|
||||
case VBITeletextDescriptorTag:
|
||||
case CountryAvailabilityDescriptorTag:
|
||||
case MocaicDescriptorTag:
|
||||
case LinkageDescriptorTag:
|
||||
case TeletextDescriptorTag:
|
||||
case TelephoneDescriptorTag:
|
||||
case LocalTimeOffsetDescriptorTag:
|
||||
case PrivateDataSpecifierDescriptorTag:
|
||||
case CellListDescriptorTag:
|
||||
case CellFrequencyLinkDescriptorTag:
|
||||
case ServiceAvailabilityDescriptorTag:
|
||||
case ShortSmoothingBufferDescriptorTag:
|
||||
case PartialTransportStreamDescriptorTag:
|
||||
case DataBroadcastDescriptorTag:
|
||||
case DataBroadcastIdDescriptorTag:
|
||||
case CaSystemDescriptorTag:
|
||||
case AC3DescriptorTag:
|
||||
case DSNGDescriptorTag:
|
||||
case PDCDescriptorTag:
|
||||
case AncillaryDataDescriptorTag:
|
||||
case AnnouncementSupportDescriptorTag:
|
||||
case AdaptationFieldDataDescriptorTag:
|
||||
case TransportStreamDescriptorTag:
|
||||
default:
|
||||
d=new UnimplementedDescriptor();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MHP:
|
||||
switch ((DescriptorTag)da.getData<DescriptorHeader>()->descriptor_tag) {
|
||||
// They once again start with 0x00 (see page 234, MHP specification)
|
||||
case MHP_ApplicationDescriptorTag:
|
||||
d=new MHP_ApplicationDescriptor();
|
||||
break;
|
||||
case MHP_ApplicationNameDescriptorTag:
|
||||
d=new MHP_ApplicationNameDescriptor();
|
||||
break;
|
||||
case MHP_TransportProtocolDescriptorTag:
|
||||
d=new MHP_TransportProtocolDescriptor();
|
||||
break;
|
||||
case MHP_DVBJApplicationDescriptorTag:
|
||||
d=new MHP_DVBJApplicationDescriptor();
|
||||
break;
|
||||
case MHP_DVBJApplicationLocationDescriptorTag:
|
||||
d=new MHP_DVBJApplicationLocationDescriptor();
|
||||
break;
|
||||
// 0x05 - 0x0A is unimplemented this library
|
||||
case MHP_ExternalApplicationAuthorisationDescriptorTag:
|
||||
case MHP_IPv4RoutingDescriptorTag:
|
||||
case MHP_IPv6RoutingDescriptorTag:
|
||||
case MHP_DVBHTMLApplicationDescriptorTag:
|
||||
case MHP_DVBHTMLApplicationLocationDescriptorTag:
|
||||
case MHP_DVBHTMLApplicationBoundaryDescriptorTag:
|
||||
case MHP_ApplicationIconsDescriptorTag:
|
||||
case MHP_PrefetchDescriptorTag:
|
||||
case MHP_DelegatedApplicationDescriptorTag:
|
||||
case MHP_ApplicationStorageDescriptorTag:
|
||||
default:
|
||||
d=new UnimplementedDescriptor();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
d->setData(da);
|
||||
return d;
|
||||
}
|
||||
|
||||
} //end of namespace
|
392
libsi/si.h
Normal file
392
libsi/si.h
Normal file
@ -0,0 +1,392 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: si.h 1.3 2003/12/26 14:09:30 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LIBSI_SI_H
|
||||
#define LIBSI_SI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "headers.h"
|
||||
|
||||
namespace SI {
|
||||
|
||||
enum TableId { TableIdPAT = 0x00, //program association section
|
||||
TableIdCAT = 0x01, //conditional access section
|
||||
TableIdPMT = 0x02, //program map section
|
||||
TableIdTSDT = 0x03,//transport stream description section
|
||||
TableIdNIT = 0x40, //network information, actual network section
|
||||
TableIdNIT_other = 0x41, //network information section, other network
|
||||
TableIdSDT = 0x42, //service description section
|
||||
TableIdSDT_other = 0x46,
|
||||
TableIdBAT = 0x46, //bouquet association section
|
||||
TableIdEIT_presentFollowing = 0x4E, //event information section
|
||||
TableIdEIT_presentFollowing_other = 0x4F,
|
||||
//range from 0x50 to 0x5F
|
||||
TableIdEIT_schedule_first = 0x50,
|
||||
TableIdEIT_schedule_last = 0x5F,
|
||||
//range from 0x60 to 0x6F
|
||||
TableIdEIT_schedule_Other_first = 0x60,
|
||||
TableIdEIT_schedule_Other_fast = 0x6F,
|
||||
TableIdTDT = 0x70, //time date section
|
||||
TableIdRST = 0x71, //running status section
|
||||
TableIdST = 0x72, //stuffing section
|
||||
TableIdTOT = 0x73, //time offset section
|
||||
TableIdDIT = 0x7E, //discontinuity information section
|
||||
TableIdSIT = 0x7F, //service information section
|
||||
TableIdAIT = 0x74 //application information section
|
||||
};
|
||||
|
||||
|
||||
enum DescriptorTag {
|
||||
// defined by ISO/IEC 13818-1
|
||||
VideoStreamDescriptorTag = 0x02,
|
||||
AudioStreamDescriptorTag = 0x03,
|
||||
HierarchyDescriptorTag = 0x04,
|
||||
RegistrationDescriptorTag = 0x05,
|
||||
DataStreamAlignmentDescriptorTag = 0x06,
|
||||
TargetBackgroundGridDescriptorTag = 0x07,
|
||||
VideoWindowDescriptorTag = 0x08,
|
||||
CaDescriptorTag = 0x09,
|
||||
ISO639LanguageDescriptorTag = 0x0A,
|
||||
SystemClockDescriptorTag = 0x0B,
|
||||
MultiplexBufferUtilizationDescriptorTag = 0x0C,
|
||||
CopyrightDescriptorTag = 0x0D,
|
||||
MaximumBitrateDescriptorTag = 0x0E,
|
||||
PrivateDataIndicatorDescriptorTag = 0x0F,
|
||||
SmoothingBufferDescriptorTag = 0x10,
|
||||
STDDescriptorTag = 0x11,
|
||||
IBPDescriptorTag = 0x12,
|
||||
// defined by ISO-13818-6 (DSM-CC)
|
||||
CarouselIdentifierDescriptorTag = 0x13,
|
||||
// 0x14 - 0x3F Reserved
|
||||
// defined by ETSI (EN 300 468)
|
||||
NetworkNameDescriptorTag = 0x40,
|
||||
ServiceListDescriptorTag = 0x41,
|
||||
StuffingDescriptorTag = 0x42,
|
||||
SatelliteDeliverySystemDescriptorTag = 0x43,
|
||||
CableDeliverySystemDescriptorTag = 0x44,
|
||||
VBIDataDescriptorTag = 0x45,
|
||||
VBITeletextDescriptorTag = 0x46,
|
||||
BouquetNameDescriptorTag = 0x47,
|
||||
ServiceDescriptorTag = 0x48,
|
||||
CountryAvailabilityDescriptorTag = 0x49,
|
||||
LinkageDescriptorTag = 0x4A,
|
||||
NVODReferenceDescriptorTag = 0x4B,
|
||||
TimeShiftedServiceDescriptorTag = 0x4C,
|
||||
ShortEventDescriptorTag = 0x4D,
|
||||
ExtendedEventDescriptorTag = 0x4E,
|
||||
TimeShiftedEventDescriptorTag = 0x4F,
|
||||
ComponentDescriptorTag = 0x50,
|
||||
MocaicDescriptorTag = 0x51,
|
||||
StreamIdentifierDescriptorTag = 0x52,
|
||||
CaIdentifierDescriptorTag = 0x53,
|
||||
ContentDescriptorTag = 0x54,
|
||||
ParentalRatingDescriptorTag = 0x55,
|
||||
TeletextDescriptorTag = 0x56,
|
||||
TelephoneDescriptorTag = 0x57,
|
||||
LocalTimeOffsetDescriptorTag = 0x58,
|
||||
SubtitlingDescriptorTag = 0x59,
|
||||
TerrestrialDeliverySystemDescriptorTag = 0x5A,
|
||||
MultilingualNetworkNameDescriptorTag = 0x5B,
|
||||
MultilingualBouquetNameDescriptorTag = 0x5C,
|
||||
MultilingualServiceNameDescriptorTag = 0x5D,
|
||||
MultilingualComponentDescriptorTag = 0x5E,
|
||||
PrivateDataSpecifierDescriptorTag = 0x5F,
|
||||
ServiceMoveDescriptorTag = 0x60,
|
||||
ShortSmoothingBufferDescriptorTag = 0x61,
|
||||
FrequencyListDescriptorTag = 0x62,
|
||||
PartialTransportStreamDescriptorTag = 0x63,
|
||||
DataBroadcastDescriptorTag = 0x64,
|
||||
CaSystemDescriptorTag = 0x65,
|
||||
DataBroadcastIdDescriptorTag = 0x66,
|
||||
TransportStreamDescriptorTag = 0x67,
|
||||
DSNGDescriptorTag = 0x68,
|
||||
PDCDescriptorTag = 0x69,
|
||||
AC3DescriptorTag = 0x6A,
|
||||
AncillaryDataDescriptorTag = 0x6B,
|
||||
CellListDescriptorTag = 0x6C,
|
||||
CellFrequencyLinkDescriptorTag = 0x6D,
|
||||
AnnouncementSupportDescriptorTag = 0x6E,
|
||||
ApplicationSignallingDescriptorTag = 0x6F,
|
||||
AdaptationFieldDataDescriptorTag = 0x70,
|
||||
ServiceIdentifierDescriptorTag = 0x71,
|
||||
ServiceAvailabilityDescriptorTag = 0x72,
|
||||
// Defined by ETSI TS 102 812 (MHP)
|
||||
// They once again start with 0x00 (see page 234, MHP specification)
|
||||
MHP_ApplicationDescriptorTag = 0x00,
|
||||
MHP_ApplicationNameDescriptorTag = 0x01,
|
||||
MHP_TransportProtocolDescriptorTag = 0x02,
|
||||
MHP_DVBJApplicationDescriptorTag = 0x03,
|
||||
MHP_DVBJApplicationLocationDescriptorTag = 0x04,
|
||||
// 0x05 - 0x0A is unimplemented this library
|
||||
MHP_ExternalApplicationAuthorisationDescriptorTag = 0x05,
|
||||
MHP_IPv4RoutingDescriptorTag = 0x06,
|
||||
MHP_IPv6RoutingDescriptorTag = 0x07,
|
||||
MHP_DVBHTMLApplicationDescriptorTag = 0x08,
|
||||
MHP_DVBHTMLApplicationLocationDescriptorTag = 0x09,
|
||||
MHP_DVBHTMLApplicationBoundaryDescriptorTag = 0x0A,
|
||||
MHP_ApplicationIconsDescriptorTag = 0x0B,
|
||||
MHP_PrefetchDescriptorTag = 0x0C,
|
||||
MHP_DelegatedApplicationDescriptorTag = 0x0E,
|
||||
MHP_ApplicationStorageDescriptorTag = 0x10,
|
||||
|
||||
//a descriptor currently unimplemented in this library
|
||||
//the actual value 0xFF is "forbidden" according to the spec.
|
||||
UnimplementedDescriptorTag = 0xFF
|
||||
};
|
||||
|
||||
enum DescriptorTagDomain { SI, MHP };
|
||||
|
||||
enum RunningStatus { RunningStatusUndefined = 0,
|
||||
RunningStatusNotRunning = 1,
|
||||
RunningStatusStartsInAFewSeconds = 2,
|
||||
RunningStatusPausing = 3,
|
||||
RunningStatusRunning = 4
|
||||
};
|
||||
|
||||
/* Some principles:
|
||||
- Objects that return references to other objects contained in their data must make sure
|
||||
that the returned objects have been parsed.
|
||||
(the Loop subclasses take care of that.)
|
||||
Note that this does not apply to Loops and Strings (their are never returned by reference, BTW).
|
||||
*/
|
||||
|
||||
class Object : public Parsable {
|
||||
public:
|
||||
Object();
|
||||
Object(CharArray &d);
|
||||
//can only be called once since data is immutable
|
||||
void setData(const unsigned char*data, unsigned int size, bool doCopy=true);
|
||||
virtual int getLength() = 0;
|
||||
protected:
|
||||
CharArray data;
|
||||
//is protected - not used for sections
|
||||
template <class T> friend class StructureLoop;
|
||||
void setData(CharArray &d);
|
||||
};
|
||||
|
||||
class Section : public Object {
|
||||
public:
|
||||
//convenience: sets data and parses if doParse
|
||||
Section(const unsigned char *data, bool doCopy=true);
|
||||
Section() {}
|
||||
TableId getTableId() const;
|
||||
virtual int getLength();
|
||||
|
||||
static int getLength(const unsigned char *d);
|
||||
static TableId getTableId(const unsigned char *d);
|
||||
};
|
||||
|
||||
class CRCSection : public Section {
|
||||
public:
|
||||
//convenience: sets data and parses if doParse
|
||||
CRCSection(const unsigned char *data, bool doCopy=true) : Section(data, doCopy) {}
|
||||
CRCSection() {}
|
||||
bool isValid();
|
||||
//convenience: isValid+CheckParse
|
||||
bool CheckCRCAndParse();
|
||||
};
|
||||
|
||||
/* A section which has the ExtendedSectionHeader
|
||||
(section_syntax_indicator==1) */
|
||||
class NumberedSection : public CRCSection {
|
||||
public:
|
||||
NumberedSection(const unsigned char *data, bool doCopy=true) : CRCSection(data, doCopy) {}
|
||||
NumberedSection() {}
|
||||
bool getCurrentNextIndicator() const;
|
||||
int getVersionNumber() const;
|
||||
int getSectionNumber() const;
|
||||
int getLastSectionNumber() const;
|
||||
bool moreThanOneSection() const { return getLastSectionNumber()>1; }
|
||||
};
|
||||
|
||||
class VariableLengthPart : public Object {
|
||||
public:
|
||||
//never forget to call this
|
||||
void setData(CharArray d, int l) { Object::setData(d); length=l; }
|
||||
//convenience method
|
||||
void setDataAndOffset(CharArray d, int l, unsigned int &offset) { Object::setData(d); length=l; offset+=l; }
|
||||
virtual int getLength() { return length; }
|
||||
private:
|
||||
int length;
|
||||
};
|
||||
|
||||
class LoopElement : public Object {
|
||||
};
|
||||
|
||||
class SubStructure : public LoopElement {
|
||||
};
|
||||
|
||||
class Descriptor : public LoopElement {
|
||||
public:
|
||||
virtual int getLength();
|
||||
DescriptorTag getDescriptorTag() const;
|
||||
|
||||
static int getLength(const unsigned char *d);
|
||||
static DescriptorTag getDescriptorTag(const unsigned char *d);
|
||||
protected:
|
||||
friend class DescriptorLoop;
|
||||
//returns a subclass of descriptor according to the data given.
|
||||
//The object is allocated with new and must be delete'd.
|
||||
//setData() will have been called, CheckParse() not.
|
||||
//Never returns null - maybe the UnimplementedDescriptor.
|
||||
static Descriptor *getDescriptor(CharArray d, DescriptorTagDomain domain);
|
||||
};
|
||||
|
||||
class Loop : public VariableLengthPart {
|
||||
public:
|
||||
class Iterator {
|
||||
public:
|
||||
Iterator() { i=0; }
|
||||
void reset() { i=0; }
|
||||
private:
|
||||
template <class T> friend class StructureLoop;
|
||||
friend class DescriptorLoop;
|
||||
template <class T> friend class TypeLoop;
|
||||
int i;
|
||||
};
|
||||
protected:
|
||||
virtual void Parse() {}
|
||||
};
|
||||
|
||||
//contains LoopElements of one type only
|
||||
template <class T> class StructureLoop : public Loop {
|
||||
public:
|
||||
//currently you must use a while-loop testing for hasNext()
|
||||
//i must be 0 to get the first descriptor (with the first call)
|
||||
T getNext(Iterator &it)
|
||||
{
|
||||
CharArray d=data;
|
||||
d.addOffset(it.i);
|
||||
T ret;
|
||||
ret.setData(d);
|
||||
ret.CheckParse();
|
||||
it.i+=ret.getLength();
|
||||
return ret;
|
||||
}
|
||||
T* getNextAsPointer(Iterator &it)
|
||||
{
|
||||
if (getLength() <= it.i)
|
||||
return 0;
|
||||
CharArray d=data;
|
||||
d.addOffset(it.i);
|
||||
T *ret=new T();
|
||||
ret->setData(d);
|
||||
ret->CheckParse();
|
||||
it.i+=ret->getLength();
|
||||
return ret;
|
||||
}
|
||||
bool hasNext(Iterator &it) { return getLength() > it.i; }
|
||||
};
|
||||
|
||||
//contains descriptors of different types
|
||||
class DescriptorLoop : public Loop {
|
||||
public:
|
||||
DescriptorLoop() { domain=SI; }
|
||||
//i must be 0 to get the first descriptor (with the first call)
|
||||
//All returned descriptors must be delete'd.
|
||||
//returns null if no more descriptors available
|
||||
Descriptor *getNext(Iterator &it);
|
||||
//return the next descriptor with given tag, or 0 if not available.
|
||||
//if the descriptor found is not implemented,
|
||||
// an UnimplementedDescriptor will be returned if returnUnimplemetedDescriptor==true,
|
||||
// 0 will be returned if returnUnimplemetedDescriptor==false
|
||||
Descriptor *getNext(Iterator &it, DescriptorTag tag, bool returnUnimplemetedDescriptor=false);
|
||||
//return the next descriptor with one of the given tags, or 0 if not available.
|
||||
Descriptor *getNext(Iterator &it, DescriptorTag *tags, int arrayLength, bool returnUnimplemetedDescriptor=false);
|
||||
protected:
|
||||
Descriptor *createDescriptor(int &i);
|
||||
DescriptorTagDomain domain;
|
||||
};
|
||||
|
||||
typedef uint8_t EightBit;
|
||||
typedef uint16_t SixteenBit;
|
||||
typedef uint32_t ThirtyTwoBit;
|
||||
typedef uint64_t SixtyFourBit;
|
||||
|
||||
template <typename T> class TypeLoop : public Loop {
|
||||
public:
|
||||
int getCount() const { return getLength()/sizeof(T); }
|
||||
T operator[](const unsigned int index) const
|
||||
{
|
||||
switch (sizeof(T)) {
|
||||
case 1:
|
||||
return data[index];
|
||||
case 2:
|
||||
return data.TwoBytes(index);
|
||||
case 4:
|
||||
return data.FourBytes(index);
|
||||
case 8:
|
||||
return (SixtyFourBit(data.FourBytes(index)) << 32) | data.FourBytes(index+4);
|
||||
}
|
||||
}
|
||||
T getNext(Iterator &it) const
|
||||
{
|
||||
T ret=operator[](it.i);
|
||||
it.i+=sizeof(T);
|
||||
return ret;
|
||||
}
|
||||
bool hasNext(Iterator &it) { return getLength() > it.i; }
|
||||
};
|
||||
|
||||
class MHP_DescriptorLoop : public DescriptorLoop {
|
||||
public:
|
||||
MHP_DescriptorLoop() { domain=MHP; }
|
||||
};
|
||||
|
||||
//The content of the ExtendedEventDescriptor may be split over several
|
||||
//descriptors if the text is longer than 256 bytes.
|
||||
//The following classes provide base functionality to handle this case.
|
||||
class GroupDescriptor : public Descriptor {
|
||||
public:
|
||||
virtual int getDescriptorNumber() = 0;
|
||||
virtual int getLastDescriptorNumber() = 0;
|
||||
};
|
||||
|
||||
class DescriptorGroup {
|
||||
public:
|
||||
DescriptorGroup(bool deleteOnDesctruction=true);
|
||||
~DescriptorGroup();
|
||||
void Add(GroupDescriptor *d);
|
||||
void Delete();
|
||||
int getLength() { return length; }
|
||||
GroupDescriptor **getDescriptors() { return array; }
|
||||
bool isComplete(); //if all descriptors have been added
|
||||
protected:
|
||||
int length;
|
||||
GroupDescriptor **array;
|
||||
bool deleteOnDesctruction;
|
||||
};
|
||||
|
||||
class String : public VariableLengthPart {
|
||||
public:
|
||||
//A note to the length: getLength() returns the length of the raw data.
|
||||
//The text may be shorter. Its length can be obtained with one of the
|
||||
//above functions and strlen.
|
||||
|
||||
//returns text. Data is allocated with new and must be delete'd by the user.
|
||||
char *getText();
|
||||
//copies text into given buffer.
|
||||
//a buffer of size getLength()+1 is guaranteed to be sufficiently large.
|
||||
//In most descriptors the string length is an 8-bit field,
|
||||
//so the maximum there is 256.
|
||||
//returns the given buffer for convenience.
|
||||
char * getText(char *buffer);
|
||||
protected:
|
||||
virtual void Parse() {}
|
||||
void decodeText(char *buffer);
|
||||
};
|
||||
|
||||
} //end of namespace
|
||||
|
||||
#endif //LIBSI_SI_H
|
281
libsi/util.c
Normal file
281
libsi/util.c
Normal file
@ -0,0 +1,281 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg, Rolf Hakenes *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: util.c 1.3 2003/12/22 14:03:03 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
namespace SI {
|
||||
|
||||
/*---------------------------- CharArray ----------------------------*/
|
||||
|
||||
CharArray::CharArray() : data_(0), off(0) {
|
||||
}
|
||||
|
||||
CharArray::~CharArray() {
|
||||
if (!data_)
|
||||
return;
|
||||
if (--data_->count_ == 0)
|
||||
delete data_;
|
||||
}
|
||||
|
||||
CharArray::CharArray(const CharArray &f) : data_(f.data_), off(f.off) {
|
||||
if (data_)
|
||||
++ data_->count_;
|
||||
}
|
||||
|
||||
CharArray& CharArray::operator=(const CharArray &f) {
|
||||
// DO NOT CHANGE THE ORDER OF THESE STATEMENTS!
|
||||
// (This order properly handles self-assignment)
|
||||
if (f.data_) {
|
||||
++ f.data_->count_;
|
||||
}
|
||||
if (data_) {
|
||||
if (--data_->count_ == 0)
|
||||
delete data_;
|
||||
}
|
||||
data_ = f.data_;
|
||||
off = f.off;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CharArray::assign(const unsigned char*data, unsigned int size, bool doCopy) {
|
||||
//immutable
|
||||
if (!data_)
|
||||
data_= doCopy ? (Data*)new DataOwnData() : (Data*)new DataForeignData();
|
||||
// This method might need to change things in *data_
|
||||
// Thus it first checks if this is the only pointer to *data_
|
||||
if (data_->count_ > 1) {
|
||||
Data* d = doCopy ? (Data*)new DataOwnData() : (Data*)new DataForeignData();
|
||||
-- data_->count_;
|
||||
data_ = d;
|
||||
}
|
||||
data_->assign(data, size);
|
||||
}
|
||||
|
||||
bool CharArray::operator==(const char *string) const {
|
||||
//here we can use strcmp, string is null-terminated.
|
||||
if (!data_)
|
||||
return false;
|
||||
return data_->size ? (!strcmp((const char*)data_->data, string)) : string[0]==0;
|
||||
}
|
||||
|
||||
bool CharArray::operator==(const CharArray &other) const {
|
||||
if (!data_ || !other.data_)
|
||||
return !(data_ || other.data_); //true if both empty
|
||||
|
||||
if (data_->size != other.data_->size)
|
||||
return false;
|
||||
|
||||
//do _not_ use strcmp! Data is not necessarily null-terminated.
|
||||
for (unsigned int i=0;i<data_->size;i++)
|
||||
if (data_->data[i] != other.data_->data[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
CharArray CharArray::operator+(const unsigned int offset) const {
|
||||
CharArray f(*this);
|
||||
f.off+=offset;
|
||||
return f;
|
||||
}
|
||||
|
||||
CharArray::Data::Data() : count_(1) {
|
||||
size=0;
|
||||
data=0;
|
||||
/*
|
||||
lockingPid = 0;
|
||||
locked = 0;
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
*/
|
||||
}
|
||||
|
||||
CharArray::Data::~Data() {
|
||||
/*
|
||||
if (locked)
|
||||
pthread_mutex_unlock(&mutex);
|
||||
pthread_mutex_destroy(&mutex);
|
||||
*/
|
||||
}
|
||||
|
||||
/*CharArray::Data::Data(const Data& d) : count_(1) {
|
||||
size=0;
|
||||
data=0;
|
||||
|
||||
lockingPid = 0;
|
||||
locked = 0;
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
}*/
|
||||
|
||||
CharArray::DataOwnData::~DataOwnData() {
|
||||
Delete();
|
||||
}
|
||||
|
||||
void CharArray::DataOwnData::assign(const unsigned char*d, unsigned int s) {
|
||||
Delete();
|
||||
size=s;
|
||||
unsigned char *newdata=new unsigned char[size];
|
||||
memcpy(newdata, d, size);
|
||||
data=newdata;
|
||||
}
|
||||
|
||||
void CharArray::DataOwnData::Delete() {
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
CharArray::DataForeignData::~DataForeignData() {
|
||||
Delete();
|
||||
}
|
||||
|
||||
void CharArray::DataForeignData::assign(const unsigned char*d, unsigned int s) {
|
||||
size=s;
|
||||
data=d;
|
||||
}
|
||||
|
||||
void CharArray::DataForeignData::Delete() {
|
||||
//do not delete!
|
||||
}
|
||||
|
||||
/*
|
||||
void CharArray::Data::assign(unsigned int s) {
|
||||
if (data)
|
||||
delete[] data;
|
||||
size=s;
|
||||
if (size) { //new assignment may be zero length
|
||||
data=new unsigned char[size];
|
||||
memset(data, 0, size);
|
||||
}
|
||||
}
|
||||
|
||||
void CharArray::Data::Lock(void)
|
||||
{
|
||||
if ( !pthread_equal(pthread_self(), lockingPid) || !locked) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
lockingPid = pthread_self();
|
||||
}
|
||||
locked++;
|
||||
}
|
||||
|
||||
void CharArray::Data::Unlock(void)
|
||||
{
|
||||
if (!--locked) {
|
||||
lockingPid = 0;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Parsable::Parsable() {
|
||||
parsed=false;
|
||||
}
|
||||
|
||||
void Parsable::CheckParse() {
|
||||
if (!parsed) {
|
||||
parsed=true;
|
||||
Parse();
|
||||
}
|
||||
}
|
||||
|
||||
//taken and adapted from libdtv, (c) Rolf Hakenes and VDR, (c) Klaus Schmidinger
|
||||
time_t DVBTime::getTime(unsigned char date_hi, unsigned char date_lo, unsigned char time_hour, unsigned char time_minute, unsigned char time_second) {
|
||||
u_int16_t mjd = date_hi << 8 | date_lo;
|
||||
struct tm t;
|
||||
|
||||
t.tm_sec = bcdToDec(time_second);
|
||||
t.tm_min = bcdToDec(time_minute);
|
||||
t.tm_hour = bcdToDec(time_hour);
|
||||
|
||||
int k;
|
||||
t.tm_year = (int) ((mjd - 15078.2) / 365.25);
|
||||
t.tm_mon = (int) ((mjd - 14956.1 - (int)(t.tm_year * 365.25)) / 30.6001);
|
||||
t.tm_mday = (int) (mjd - 14956 - (int)(t.tm_year * 365.25) - (int)(t.tm_mon * 30.6001));
|
||||
k = (t.tm_mon == 14 || t.tm_mon == 15) ? 1 : 0;
|
||||
t.tm_year = t.tm_year + k;
|
||||
t.tm_mon = t.tm_mon - 1 - k * 12;
|
||||
t.tm_mon--;
|
||||
|
||||
t.tm_isdst = -1;
|
||||
t.tm_gmtoff = 0;
|
||||
|
||||
return timegm(&t);
|
||||
}
|
||||
|
||||
time_t DVBTime::getDuration(unsigned char time_hour, unsigned char time_minute, unsigned char time_second) {
|
||||
return
|
||||
bcdToDec(time_second)
|
||||
+ bcdToDec(time_minute) * 60
|
||||
+ bcdToDec(time_hour) *3600;
|
||||
}
|
||||
|
||||
//taken and adapted from libdtv, (c) Rolf Hakenes
|
||||
// CRC32 lookup table for polynomial 0x04c11db7
|
||||
u_int32_t CRC32::crc_table[256] = {
|
||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
|
||||
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
|
||||
0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
|
||||
0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
|
||||
0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
|
||||
0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
|
||||
0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
|
||||
0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
|
||||
0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
|
||||
0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
|
||||
0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
|
||||
0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
|
||||
0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
|
||||
0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
|
||||
0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
|
||||
0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
|
||||
0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
|
||||
0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
|
||||
0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
|
||||
0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
|
||||
0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
|
||||
0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
|
||||
0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
|
||||
0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
|
||||
0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
|
||||
0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
|
||||
0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
|
||||
0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
|
||||
0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
|
||||
0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
|
||||
0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
|
||||
0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
|
||||
0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
|
||||
0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
|
||||
0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
|
||||
0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
|
||||
0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
|
||||
0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
|
||||
0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
|
||||
0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
|
||||
0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
|
||||
0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
|
||||
|
||||
u_int32_t CRC32::crc32 (const char *d, int len, u_int32_t crc)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i=0; i<len; i++)
|
||||
crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *d++) & 0xff];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
CRC32::CRC32(const char *d, int len, u_int32_t CRCvalue) {
|
||||
data=d;
|
||||
length=len;
|
||||
value=CRCvalue;
|
||||
}
|
||||
|
||||
} //end of namespace
|
157
libsi/util.h
Normal file
157
libsi/util.h
Normal file
@ -0,0 +1,157 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2003 by Marcel Wiesweg *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* $Id: util.h 1.3 2003/12/22 14:07:41 kls Exp $
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef LIBSI_UTIL_H
|
||||
#define LIBSI_UTIL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
|
||||
#define HILO(x) (x##_hi << 8 | x##_lo)
|
||||
#define BCD_TIME_TO_SECONDS(x) ((3600 * ((10*((x##_h & 0xF0)>>4)) + (x##_h & 0xF))) + \
|
||||
(60 * ((10*((x##_m & 0xF0)>>4)) + (x##_m & 0xF))) + \
|
||||
((10*((x##_s & 0xF0)>>4)) + (x##_s & 0xF)))
|
||||
|
||||
namespace SI {
|
||||
|
||||
//Holds an array of unsigned char which is deleted
|
||||
//when the last object pointing to it is deleted.
|
||||
//Optimized for use in libsi.
|
||||
class CharArray {
|
||||
public:
|
||||
CharArray();
|
||||
|
||||
CharArray(const CharArray &source);
|
||||
CharArray& operator=(const CharArray &source);
|
||||
~CharArray();
|
||||
|
||||
//can be called exactly once
|
||||
void assign(const unsigned char*data, unsigned int size, bool doCopy=true);
|
||||
//compares to a null-terminated string
|
||||
bool operator==(const char *string) const;
|
||||
//compares to another CharArray (data not necessarily null-terminated)
|
||||
bool operator==(const CharArray &other) const;
|
||||
|
||||
//returns another CharArray with its offset incremented by offset
|
||||
CharArray operator+(const unsigned int offset) const;
|
||||
|
||||
//access and convenience methods
|
||||
const unsigned char* getData() const { return data_->data+off; }
|
||||
const unsigned char* getData(int offset) const { return data_->data+offset+off; }
|
||||
template <typename T> const T* getData() const { return (T*)(data_->data+off); }
|
||||
template <typename T> const T* getData(int offset) const { return (T*)(data_->data+offset+off); }
|
||||
//sets p to point to data+offset, increments offset
|
||||
template <typename T> void setPointerAndOffset(const T* &p, unsigned int &offset) const { p=(T*)getData(offset); offset+=sizeof(T); }
|
||||
unsigned char operator[](const unsigned int index) const { return data_->data ? data_->data[off+index] : 0; }
|
||||
int getLength() const { return data_->size; }
|
||||
u_int16_t TwoBytes(const unsigned int index) const { return data_->data ? data_->TwoBytes(off+index) : 0; }
|
||||
u_int32_t FourBytes(const unsigned int index) const { return data_->data ? data_->FourBytes(off+index) : 0; }
|
||||
|
||||
void addOffset(unsigned int offset) { off+=offset; }
|
||||
private:
|
||||
class Data {
|
||||
public:
|
||||
Data();
|
||||
virtual ~Data();
|
||||
|
||||
virtual void assign(const unsigned char*data, unsigned int size) = 0;
|
||||
virtual void Delete() = 0;
|
||||
|
||||
u_int16_t TwoBytes(const unsigned int index) const
|
||||
{ return (data[index] << 8) | data[index+1]; }
|
||||
u_int32_t FourBytes(const unsigned int index) const
|
||||
{ return (data[index] << 24) | (data[index+1] << 16) | (data[index+2] << 8) | data[index+3]; }
|
||||
/*#ifdef CHARARRAY_THREADSAFE
|
||||
void Lock();
|
||||
void Unlock();
|
||||
#else
|
||||
void Lock() {}
|
||||
void Unlock() {}
|
||||
#endif
|
||||
Data(const Data& d);
|
||||
void assign(unsigned int size);
|
||||
*/
|
||||
|
||||
const unsigned char*data;
|
||||
unsigned int size;
|
||||
|
||||
unsigned count_;
|
||||
// count_ is the number of CharArray objects that point at this
|
||||
// count_ must be initialized to 1 by all constructors
|
||||
// (it starts as 1 since it is pointed to by the CharArray object that created it)
|
||||
|
||||
/*
|
||||
pthread_mutex_t mutex;
|
||||
pid_t lockingPid;
|
||||
pthread_t locked;
|
||||
*/
|
||||
};
|
||||
class DataOwnData : public Data {
|
||||
public:
|
||||
DataOwnData() {}
|
||||
virtual ~DataOwnData();
|
||||
virtual void assign(const unsigned char*data, unsigned int size);
|
||||
virtual void Delete();
|
||||
};
|
||||
class DataForeignData : public Data {
|
||||
public:
|
||||
DataForeignData() {}
|
||||
virtual ~DataForeignData();
|
||||
virtual void assign(const unsigned char*data, unsigned int size);
|
||||
virtual void Delete();
|
||||
};
|
||||
Data* data_;
|
||||
unsigned int off;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//abstract base class
|
||||
class Parsable {
|
||||
public:
|
||||
void CheckParse();
|
||||
protected:
|
||||
Parsable();
|
||||
virtual ~Parsable() {}
|
||||
//actually parses given data.
|
||||
virtual void Parse() = 0;
|
||||
private:
|
||||
bool parsed;
|
||||
};
|
||||
|
||||
//taken and adapted from libdtv, (c) Rolf Hakenes and VDR, (c) Klaus Schmidinger
|
||||
namespace DVBTime {
|
||||
time_t getTime(unsigned char date_hi, unsigned char date_lo, unsigned char timehr, unsigned char timemi, unsigned char timese);
|
||||
time_t getDuration(unsigned char timehr, unsigned char timemi, unsigned char timese);
|
||||
inline unsigned char bcdToDec(unsigned char b) { return ((b >> 4) & 0x0F) * 10 + (b & 0x0F); }
|
||||
};
|
||||
|
||||
//taken and adapted from libdtv, (c) Rolf Hakenes
|
||||
class CRC32 {
|
||||
public:
|
||||
CRC32(const char *d, int len, u_int32_t CRCvalue=0xFFFFFFFF);
|
||||
bool isValid() { return crc32(data, length, value) == 0; }
|
||||
static bool isValid(const char *d, int len, u_int32_t CRCvalue=0xFFFFFFFF) { return crc32(d, len, CRCvalue) == 0; }
|
||||
protected:
|
||||
static u_int32_t crc_table[256];
|
||||
static u_int32_t crc32 (const char *d, int len, u_int32_t CRCvalue);
|
||||
|
||||
const char *data;
|
||||
int length;
|
||||
u_int32_t value;
|
||||
};
|
||||
|
||||
} //end of namespace
|
||||
|
||||
#endif
|
5
lirc.c
5
lirc.c
@ -6,7 +6,7 @@
|
||||
*
|
||||
* LIRC support added by Carsten Koch <Carsten.Koch@icem.de> 2000-06-16.
|
||||
*
|
||||
* $Id: lirc.c 1.6 2003/04/27 11:39:47 kls Exp $
|
||||
* $Id: lirc.c 1.7 2003/10/18 11:34:02 kls Exp $
|
||||
*/
|
||||
|
||||
#include "lirc.h"
|
||||
@ -20,6 +20,7 @@
|
||||
|
||||
cLircRemote::cLircRemote(char *DeviceName)
|
||||
:cRemote("LIRC")
|
||||
,cThread("LIRC remote control")
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
@ -49,8 +50,6 @@ bool cLircRemote::Ready(void)
|
||||
|
||||
void cLircRemote::Action(void)
|
||||
{
|
||||
dsyslog("LIRC remote control thread started (pid=%d)", getpid());
|
||||
|
||||
int FirstTime = 0;
|
||||
int LastTime = 0;
|
||||
char buf[LIRC_BUFFER_SIZE];
|
||||
|
245
menu.c
245
menu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.c 1.273 2003/10/03 14:36:20 kls Exp $
|
||||
* $Id: menu.c 1.276 2004/01/04 11:12:43 kls Exp $
|
||||
*/
|
||||
|
||||
#include "menu.h"
|
||||
@ -16,7 +16,6 @@
|
||||
#include "channels.h"
|
||||
#include "config.h"
|
||||
#include "cutter.h"
|
||||
#include "eit.h"
|
||||
#include "i18n.h"
|
||||
#include "menuitems.h"
|
||||
#include "plugin.h"
|
||||
@ -69,7 +68,7 @@ eOSState cMenuEditChanItem::ProcessKey(eKeys Key)
|
||||
case kLeft|k_Repeat:
|
||||
case kLeft: delta = -1;
|
||||
case kRight|k_Repeat:
|
||||
case kRight:
|
||||
case kRight:
|
||||
{
|
||||
cChannel *channel = Channels.GetByNumber(*value + delta, delta);
|
||||
if (channel) {
|
||||
@ -458,7 +457,7 @@ eOSState cMenuEditSrcItem::ProcessKey(eKeys Key)
|
||||
}
|
||||
}
|
||||
else if (NORMALKEY(Key) == kRight) {
|
||||
if (source) {
|
||||
if (source) {
|
||||
if (source->Next())
|
||||
source = (cSource *)source->Next();
|
||||
}
|
||||
@ -582,7 +581,7 @@ void cMenuEditChannel::Setup(void)
|
||||
Add(new cMenuEditIntItem( tr("Dpid1"), &data.dpid1, 0, 0x1FFF));
|
||||
Add(new cMenuEditIntItem( tr("Dpid2"), &data.dpid2, 0, 0x1FFF));
|
||||
Add(new cMenuEditIntItem( tr("Tpid"), &data.tpid, 0, 0x1FFF));
|
||||
Add(new cMenuEditCaItem( tr("CA"), &data.ca, true));
|
||||
Add(new cMenuEditCaItem( tr("CA"), &data.caids[0], true));//XXX
|
||||
Add(new cMenuEditIntItem( tr("Sid"), &data.sid, 0));
|
||||
/* XXX not yet used
|
||||
Add(new cMenuEditIntItem( tr("Nid"), &data.nid, 0));
|
||||
@ -616,7 +615,6 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
|
||||
if (channel) {
|
||||
*channel = data;
|
||||
isyslog("edited channel %d %s", channel->Number(), data.ToText());
|
||||
Timers.Save();
|
||||
state = osBack;
|
||||
}
|
||||
else {
|
||||
@ -627,7 +625,7 @@ eOSState cMenuEditChannel::ProcessKey(eKeys Key)
|
||||
isyslog("added channel %d %s", channel->Number(), data.ToText());
|
||||
state = osUser1;
|
||||
}
|
||||
Channels.Save();
|
||||
Channels.SetModified();
|
||||
}
|
||||
else {
|
||||
Interface->Error(tr("Channel settings are not unique!"));
|
||||
@ -683,6 +681,7 @@ protected:
|
||||
virtual void Move(int From, int To);
|
||||
public:
|
||||
cMenuChannels(void);
|
||||
~cMenuChannels();
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
@ -694,6 +693,12 @@ cMenuChannels::cMenuChannels(void)
|
||||
Add(new cMenuChannelItem(channel), channel->Number() == cDevice::CurrentChannel());
|
||||
}
|
||||
SetHelp(tr("Edit"), tr("New"), tr("Delete"), tr("Mark"));
|
||||
Channels.IncBeingEdited();
|
||||
}
|
||||
|
||||
cMenuChannels::~cMenuChannels()
|
||||
{
|
||||
Channels.DecBeingEdited();
|
||||
}
|
||||
|
||||
cChannel *cMenuChannels::GetChannel(int Index)
|
||||
@ -705,11 +710,10 @@ cChannel *cMenuChannels::GetChannel(int Index)
|
||||
void cMenuChannels::Propagate(void)
|
||||
{
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
for (cMenuChannelItem *ci = (cMenuChannelItem *)First(); ci; ci = (cMenuChannelItem *)ci->Next())
|
||||
ci->Set();
|
||||
Timers.Save(); // channel numbering has changed!
|
||||
Display();
|
||||
Channels.SetModified();
|
||||
}
|
||||
|
||||
eOSState cMenuChannels::Switch(void)
|
||||
@ -904,7 +908,7 @@ eOSState cMenuEditTimer::ProcessKey(eKeys Key)
|
||||
|
||||
if (state == osUnknown) {
|
||||
switch (Key) {
|
||||
case kOk: {
|
||||
case kOk: {
|
||||
cChannel *ch = Channels.GetByNumber(channel);
|
||||
if (ch)
|
||||
data.channel = ch;
|
||||
@ -1128,29 +1132,29 @@ eOSState cMenuTimers::ProcessKey(eKeys Key)
|
||||
|
||||
class cMenuEvent : public cOsdMenu {
|
||||
private:
|
||||
const cEventInfo *eventInfo;
|
||||
const cEvent *event;
|
||||
public:
|
||||
cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch = false);
|
||||
cMenuEvent(const cEvent *Event, bool CanSwitch = false);
|
||||
cMenuEvent(bool Now);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
cMenuEvent::cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch)
|
||||
cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch)
|
||||
:cOsdMenu(tr("Event"))
|
||||
{
|
||||
eventInfo = EventInfo;
|
||||
if (eventInfo) {
|
||||
cChannel *channel = Channels.GetByChannelID(eventInfo->GetChannelID(), true);
|
||||
event = Event;
|
||||
if (event) {
|
||||
cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true);
|
||||
if (channel) {
|
||||
char *buffer;
|
||||
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->Name(), 5, eventInfo->GetDate(), eventInfo->GetTimeString(), eventInfo->GetEndTimeString());
|
||||
asprintf(&buffer, "%-17.*s\t%.*s %s - %s", 17, channel->Name(), 5, event->GetDateString(), event->GetTimeString(), event->GetEndTimeString());
|
||||
SetTitle(buffer, false);
|
||||
free(buffer);
|
||||
int Line = 2;
|
||||
cMenuTextItem *item;
|
||||
const char *Title = eventInfo->GetTitle();
|
||||
const char *Subtitle = eventInfo->GetSubtitle();
|
||||
const char *ExtendedDescription = eventInfo->GetExtendedDescription();
|
||||
const char *Title = event->Title();
|
||||
const char *Subtitle = event->ShortText();
|
||||
const char *ExtendedDescription = event->Description();
|
||||
if (!isempty(Title)) {
|
||||
Add(item = new cMenuTextItem(Title, 1, Line, Setup.OSDwidth - 2, -1, clrCyan));
|
||||
Line += item->Height() + 1;
|
||||
@ -1185,16 +1189,16 @@ eOSState cMenuEvent::ProcessKey(eKeys Key)
|
||||
|
||||
class cMenuWhatsOnItem : public cOsdItem {
|
||||
public:
|
||||
const cEventInfo *eventInfo;
|
||||
cMenuWhatsOnItem(const cEventInfo *EventInfo);
|
||||
const cEvent *event;
|
||||
cMenuWhatsOnItem(const cEvent *Event);
|
||||
};
|
||||
|
||||
cMenuWhatsOnItem::cMenuWhatsOnItem(const cEventInfo *EventInfo)
|
||||
cMenuWhatsOnItem::cMenuWhatsOnItem(const cEvent *Event)
|
||||
{
|
||||
eventInfo = EventInfo;
|
||||
event = Event;
|
||||
char *buffer = NULL;
|
||||
cChannel *channel = Channels.GetByNumber(eventInfo->GetChannelNumber());
|
||||
asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", eventInfo->GetChannelNumber(), 6, channel ? channel->Name() : "???", 5, eventInfo->GetTimeString(), eventInfo->GetTitle());
|
||||
cChannel *channel = Channels.GetByNumber(event->ChannelNumber());
|
||||
asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", event->ChannelNumber(), 6, channel ? channel->Name() : "???", 5, event->GetTimeString(), event->Title());
|
||||
SetText(buffer, false);
|
||||
}
|
||||
|
||||
@ -1205,36 +1209,36 @@ private:
|
||||
eOSState Record(void);
|
||||
eOSState Switch(void);
|
||||
static int currentChannel;
|
||||
static const cEventInfo *scheduleEventInfo;
|
||||
static const cEvent *scheduleEvent;
|
||||
public:
|
||||
cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr);
|
||||
static int CurrentChannel(void) { return currentChannel; }
|
||||
static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; }
|
||||
static const cEventInfo *ScheduleEventInfo(void);
|
||||
static const cEvent *ScheduleEvent(void);
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
int cMenuWhatsOn::currentChannel = 0;
|
||||
const cEventInfo *cMenuWhatsOn::scheduleEventInfo = NULL;
|
||||
const cEvent *cMenuWhatsOn::scheduleEvent = NULL;
|
||||
|
||||
static int CompareEventChannel(const void *p1, const void *p2)
|
||||
{
|
||||
return (int)( (*(const cEventInfo **)p1)->GetChannelNumber() - (*(const cEventInfo **)p2)->GetChannelNumber());
|
||||
return (int)( (*(const cEvent **)p1)->ChannelNumber() - (*(const cEvent **)p2)->ChannelNumber());
|
||||
}
|
||||
|
||||
cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr)
|
||||
:cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, 7, 6)
|
||||
{
|
||||
const cSchedule *Schedule = Schedules->First();
|
||||
const cEventInfo **pArray = NULL;
|
||||
const cEvent **pArray = NULL;
|
||||
int num = 0;
|
||||
|
||||
while (Schedule) {
|
||||
pArray = (const cEventInfo **)realloc(pArray, (num + 1) * sizeof(cEventInfo *));
|
||||
pArray = (const cEvent **)realloc(pArray, (num + 1) * sizeof(cEvent *));
|
||||
|
||||
pArray[num] = Now ? Schedule->GetPresentEvent() : Schedule->GetFollowingEvent();
|
||||
if (pArray[num]) {
|
||||
cChannel *channel = Channels.GetByChannelID(pArray[num]->GetChannelID(), true);
|
||||
cChannel *channel = Channels.GetByChannelID(pArray[num]->ChannelID(), true);
|
||||
if (channel) {
|
||||
pArray[num]->SetChannelNumber(channel->Number());
|
||||
num++;
|
||||
@ -1243,20 +1247,20 @@ cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentCha
|
||||
Schedule = (const cSchedule *)Schedules->Next(Schedule);
|
||||
}
|
||||
|
||||
qsort(pArray, num, sizeof(cEventInfo *), CompareEventChannel);
|
||||
qsort(pArray, num, sizeof(cEvent *), CompareEventChannel);
|
||||
|
||||
for (int a = 0; a < num; a++)
|
||||
Add(new cMenuWhatsOnItem(pArray[a]), pArray[a]->GetChannelNumber() == CurrentChannelNr);
|
||||
Add(new cMenuWhatsOnItem(pArray[a]), pArray[a]->ChannelNumber() == CurrentChannelNr);
|
||||
|
||||
currentChannel = CurrentChannelNr;
|
||||
free(pArray);
|
||||
SetHelp(Count() ? tr("Record") : NULL, Now ? tr("Next") : tr("Now"), tr("Button$Schedule"), tr("Switch"));
|
||||
}
|
||||
|
||||
const cEventInfo *cMenuWhatsOn::ScheduleEventInfo(void)
|
||||
const cEvent *cMenuWhatsOn::ScheduleEvent(void)
|
||||
{
|
||||
const cEventInfo *ei = scheduleEventInfo;
|
||||
scheduleEventInfo = NULL;
|
||||
const cEvent *ei = scheduleEvent;
|
||||
scheduleEvent = NULL;
|
||||
return ei;
|
||||
}
|
||||
|
||||
@ -1264,7 +1268,7 @@ eOSState cMenuWhatsOn::Switch(void)
|
||||
{
|
||||
cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current());
|
||||
if (item) {
|
||||
cChannel *channel = Channels.GetByChannelID(item->eventInfo->GetChannelID(), true);
|
||||
cChannel *channel = Channels.GetByChannelID(item->event->ChannelID(), true);
|
||||
if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
|
||||
return osEnd;
|
||||
}
|
||||
@ -1276,7 +1280,7 @@ eOSState cMenuWhatsOn::Record(void)
|
||||
{
|
||||
cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current());
|
||||
if (item) {
|
||||
cTimer *timer = new cTimer(item->eventInfo);
|
||||
cTimer *timer = new cTimer(item->event);
|
||||
cTimer *t = Timers.GetTimer(timer);
|
||||
if (t) {
|
||||
delete timer;
|
||||
@ -1300,14 +1304,14 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key)
|
||||
case kGreen: {
|
||||
cMenuWhatsOnItem *mi = (cMenuWhatsOnItem *)Get(Current());
|
||||
if (mi) {
|
||||
scheduleEventInfo = mi->eventInfo;
|
||||
currentChannel = mi->eventInfo->GetChannelNumber();
|
||||
scheduleEvent = mi->event;
|
||||
currentChannel = mi->event->ChannelNumber();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kBlue: return Switch();
|
||||
case kOk: if (Count())
|
||||
return AddSubMenu(new cMenuEvent(((cMenuWhatsOnItem *)Get(Current()))->eventInfo, true));
|
||||
return AddSubMenu(new cMenuEvent(((cMenuWhatsOnItem *)Get(Current()))->event, true));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
@ -1319,15 +1323,15 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key)
|
||||
|
||||
class cMenuScheduleItem : public cOsdItem {
|
||||
public:
|
||||
const cEventInfo *eventInfo;
|
||||
cMenuScheduleItem(const cEventInfo *EventInfo);
|
||||
const cEvent *event;
|
||||
cMenuScheduleItem(const cEvent *Event);
|
||||
};
|
||||
|
||||
cMenuScheduleItem::cMenuScheduleItem(const cEventInfo *EventInfo)
|
||||
cMenuScheduleItem::cMenuScheduleItem(const cEvent *Event)
|
||||
{
|
||||
eventInfo = EventInfo;
|
||||
event = Event;
|
||||
char *buffer = NULL;
|
||||
asprintf(&buffer, "%.*s\t%.*s\t%s", 5, eventInfo->GetDate(), 5, eventInfo->GetTimeString(), eventInfo->GetTitle());
|
||||
asprintf(&buffer, "%.*s\t%.*s\t%s", 5, event->GetDateString(), 5, event->GetTimeString(), event->Title());
|
||||
SetText(buffer, false);
|
||||
}
|
||||
|
||||
@ -1335,7 +1339,7 @@ cMenuScheduleItem::cMenuScheduleItem(const cEventInfo *EventInfo)
|
||||
|
||||
class cMenuSchedule : public cOsdMenu {
|
||||
private:
|
||||
cMutexLock mutexLock;
|
||||
cSchedulesLock schedulesLock;
|
||||
const cSchedules *schedules;
|
||||
bool now, next;
|
||||
int otherChannel;
|
||||
@ -1356,7 +1360,7 @@ cMenuSchedule::cMenuSchedule(void)
|
||||
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
if (channel) {
|
||||
cMenuWhatsOn::SetCurrentChannel(channel->Number());
|
||||
schedules = cSIProcessor::Schedules(mutexLock);
|
||||
schedules = cSchedules::Schedules(schedulesLock);
|
||||
PrepareSchedule(channel);
|
||||
SetHelp(Count() ? tr("Record") : NULL, tr("Now"), tr("Next"));
|
||||
}
|
||||
@ -1364,12 +1368,12 @@ cMenuSchedule::cMenuSchedule(void)
|
||||
|
||||
cMenuSchedule::~cMenuSchedule()
|
||||
{
|
||||
cMenuWhatsOn::ScheduleEventInfo(); // makes sure any posted data is cleared
|
||||
cMenuWhatsOn::ScheduleEvent(); // makes sure any posted data is cleared
|
||||
}
|
||||
|
||||
static int CompareEventTime(const void *p1, const void *p2)
|
||||
{
|
||||
return (int)((*(cEventInfo **)p1)->GetTime() - (*(cEventInfo **)p2)->GetTime());
|
||||
return (int)((*(cEvent **)p1)->StartTime() - (*(cEvent **)p2)->StartTime());
|
||||
}
|
||||
|
||||
void cMenuSchedule::PrepareSchedule(cChannel *Channel)
|
||||
@ -1381,22 +1385,24 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel)
|
||||
free(buffer);
|
||||
if (schedules) {
|
||||
const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID());
|
||||
int num = Schedule->NumEvents();
|
||||
const cEventInfo **pArray = MALLOC(const cEventInfo *, num);
|
||||
if (pArray) {
|
||||
time_t now = time(NULL);
|
||||
int numreal = 0;
|
||||
for (int a = 0; a < num; a++) {
|
||||
const cEventInfo *EventInfo = Schedule->GetEventNumber(a);
|
||||
if (EventInfo->GetTime() + EventInfo->GetDuration() > now)
|
||||
pArray[numreal++] = EventInfo;
|
||||
}
|
||||
|
||||
qsort(pArray, numreal, sizeof(cEventInfo *), CompareEventTime);
|
||||
|
||||
for (int a = 0; a < numreal; a++)
|
||||
Add(new cMenuScheduleItem(pArray[a]));
|
||||
free(pArray);
|
||||
if (Schedule) {
|
||||
int num = Schedule->NumEvents();
|
||||
const cEvent **pArray = MALLOC(const cEvent *, num);
|
||||
if (pArray) {
|
||||
time_t now = time(NULL);
|
||||
int numreal = 0;
|
||||
for (int a = 0; a < num; a++) {
|
||||
const cEvent *Event = Schedule->GetEventNumber(a);
|
||||
if (Event->StartTime() + Event->Duration() > now)
|
||||
pArray[numreal++] = Event;
|
||||
}
|
||||
|
||||
qsort(pArray, numreal, sizeof(cEvent *), CompareEventTime);
|
||||
|
||||
for (int a = 0; a < numreal; a++)
|
||||
Add(new cMenuScheduleItem(pArray[a]));
|
||||
free(pArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1405,7 +1411,7 @@ eOSState cMenuSchedule::Record(void)
|
||||
{
|
||||
cMenuScheduleItem *item = (cMenuScheduleItem *)Get(Current());
|
||||
if (item) {
|
||||
cTimer *timer = new cTimer(item->eventInfo);
|
||||
cTimer *timer = new cTimer(item->event);
|
||||
cTimer *t = Timers.GetTimer(timer);
|
||||
if (t) {
|
||||
delete timer;
|
||||
@ -1438,7 +1444,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
|
||||
if (!now && !next) {
|
||||
int ChannelNr = 0;
|
||||
if (Count()) {
|
||||
cChannel *channel = Channels.GetByChannelID(((cMenuScheduleItem *)Get(Current()))->eventInfo->GetChannelID(), true);
|
||||
cChannel *channel = Channels.GetByChannelID(((cMenuScheduleItem *)Get(Current()))->event->ChannelID(), true);
|
||||
if (channel)
|
||||
ChannelNr = channel->Number();
|
||||
}
|
||||
@ -1456,16 +1462,16 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
|
||||
return Switch();
|
||||
break;
|
||||
case kOk: if (Count())
|
||||
return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->eventInfo, otherChannel));
|
||||
return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
else if (!HasSubMenu()) {
|
||||
now = next = false;
|
||||
const cEventInfo *ei = cMenuWhatsOn::ScheduleEventInfo();
|
||||
const cEvent *ei = cMenuWhatsOn::ScheduleEvent();
|
||||
if (ei) {
|
||||
cChannel *channel = Channels.GetByChannelID(ei->GetChannelID(), true);
|
||||
cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true);
|
||||
if (channel) {
|
||||
PrepareSchedule(channel);
|
||||
if (channel->Number() != cDevice::CurrentChannel()) {
|
||||
@ -1985,6 +1991,7 @@ private:
|
||||
virtual void Set(void);
|
||||
public:
|
||||
cMenuSetupOSD(void) { Set(); }
|
||||
virtual ~cMenuSetupOSD() { cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]); }
|
||||
virtual eOSState ProcessKey(eKeys Key);
|
||||
};
|
||||
|
||||
@ -2011,6 +2018,7 @@ eOSState cMenuSetupOSD::ProcessKey(eKeys Key)
|
||||
if (data.OSDLanguage != osdLanguage) {
|
||||
int OriginalOSDLanguage = Setup.OSDLanguage;
|
||||
Setup.OSDLanguage = data.OSDLanguage;
|
||||
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
|
||||
Set();
|
||||
Display();
|
||||
Setup.OSDLanguage = OriginalOSDLanguage;
|
||||
@ -2631,10 +2639,10 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
|
||||
int EpgLines = withInfo ? 5 : 1;
|
||||
lines = 0;
|
||||
number = 0;
|
||||
cChannel *channel = Channels.GetByNumber(Number);
|
||||
channel = Channels.GetByNumber(Number);
|
||||
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
|
||||
if (channel) {
|
||||
DisplayChannel(channel);
|
||||
DisplayChannel();
|
||||
DisplayInfo();
|
||||
}
|
||||
lastTime = time_ms();
|
||||
@ -2658,16 +2666,16 @@ cDisplayChannel::~cDisplayChannel()
|
||||
Interface->Close();
|
||||
}
|
||||
|
||||
void cDisplayChannel::DisplayChannel(const cChannel *Channel)
|
||||
void cDisplayChannel::DisplayChannel(void)
|
||||
{
|
||||
int BufSize = Width() + 1;
|
||||
char buffer[BufSize];
|
||||
*buffer = 0;
|
||||
if (Channel) {
|
||||
if (Channel->GroupSep())
|
||||
snprintf(buffer, BufSize, "%s", Channel->Name());
|
||||
if (channel) {
|
||||
if (channel->GroupSep())
|
||||
snprintf(buffer, BufSize, "%s", channel->Name());
|
||||
else
|
||||
snprintf(buffer, BufSize, "%d%s %s", Channel->Number(), number ? "-" : "", Channel->Name());
|
||||
snprintf(buffer, BufSize, "%d%s %s", channel->Number(), number ? "-" : "", channel->Name());
|
||||
}
|
||||
else if (number)
|
||||
snprintf(buffer, BufSize, "%d-", number);
|
||||
@ -2682,28 +2690,28 @@ void cDisplayChannel::DisplayChannel(const cChannel *Channel)
|
||||
|
||||
void cDisplayChannel::DisplayInfo(void)
|
||||
{
|
||||
if (withInfo) {
|
||||
const cEventInfo *Present = NULL, *Following = NULL;
|
||||
cMutexLock MutexLock;
|
||||
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
|
||||
if (withInfo && channel) {
|
||||
const cEvent *Present = NULL, *Following = NULL;
|
||||
cSchedulesLock SchedulesLock;
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule();
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
const char *PresentTitle = NULL, *PresentSubtitle = NULL, *FollowingTitle = NULL, *FollowingSubtitle = NULL;
|
||||
int Lines = 0;
|
||||
if ((Present = Schedule->GetPresentEvent()) != NULL) {
|
||||
PresentTitle = Present->GetTitle();
|
||||
PresentTitle = Present->Title();
|
||||
if (!isempty(PresentTitle))
|
||||
Lines++;
|
||||
PresentSubtitle = Present->GetSubtitle();
|
||||
PresentSubtitle = Present->ShortText();
|
||||
if (!isempty(PresentSubtitle))
|
||||
Lines++;
|
||||
}
|
||||
if ((Following = Schedule->GetFollowingEvent()) != NULL) {
|
||||
FollowingTitle = Following->GetTitle();
|
||||
FollowingTitle = Following->Title();
|
||||
if (!isempty(FollowingTitle))
|
||||
Lines++;
|
||||
FollowingSubtitle = Following->GetSubtitle();
|
||||
FollowingSubtitle = Following->ShortText();
|
||||
if (!isempty(FollowingSubtitle))
|
||||
Lines++;
|
||||
}
|
||||
@ -2731,7 +2739,7 @@ void cDisplayChannel::DisplayInfo(void)
|
||||
Interface->Flush();
|
||||
lines = Lines;
|
||||
lastTime = time_ms();
|
||||
cStatus::MsgOsdProgramme(Present ? Present->GetTime() : 0, PresentTitle, PresentSubtitle, Following ? Following->GetTime() : 0, FollowingTitle, FollowingSubtitle);
|
||||
cStatus::MsgOsdProgramme(Present ? Present->StartTime() : 0, PresentTitle, PresentSubtitle, Following ? Following->StartTime() : 0, FollowingTitle, FollowingSubtitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2741,7 +2749,8 @@ void cDisplayChannel::DisplayInfo(void)
|
||||
void cDisplayChannel::Refresh(void)
|
||||
{
|
||||
Interface->Clear();
|
||||
DisplayChannel(Channels.GetByNumber(cDevice::CurrentChannel()));
|
||||
channel = Channels.GetByNumber(cDevice::CurrentChannel());
|
||||
DisplayChannel();
|
||||
lastTime = time_ms();
|
||||
lines = 0;
|
||||
}
|
||||
@ -2759,20 +2768,21 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
if (number >= 0) {
|
||||
number = number * 10 + Key - k0;
|
||||
if (number > 0) {
|
||||
cChannel *channel = Channels.GetByNumber(number);
|
||||
channel = Channels.GetByNumber(number);
|
||||
Interface->Clear();
|
||||
withInfo = false;
|
||||
DisplayChannel(channel);
|
||||
DisplayChannel();
|
||||
lastTime = time_ms();
|
||||
// Lets see if there can be any useful further input:
|
||||
int n = channel ? number * 10 : 0;
|
||||
while (channel && (channel = Channels.Next(channel)) != NULL) {
|
||||
if (!channel->GroupSep()) {
|
||||
if (n <= channel->Number() && channel->Number() <= n + 9) {
|
||||
cChannel *ch = channel;
|
||||
while (ch && (ch = Channels.Next(ch)) != NULL) {
|
||||
if (!ch->GroupSep()) {
|
||||
if (n <= ch->Number() && ch->Number() <= n + 9) {
|
||||
n = 0;
|
||||
break;
|
||||
}
|
||||
if (channel->Number() > n)
|
||||
if (ch->Number() > n)
|
||||
n *= 10;
|
||||
}
|
||||
}
|
||||
@ -2803,10 +2813,10 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
group = Channels.GetPrevGroup(group < 1 ? 1 : group);
|
||||
if (group < 0)
|
||||
group = SaveGroup;
|
||||
cChannel *channel = Channels.Get(group);
|
||||
channel = Channels.Get(group);
|
||||
if (channel) {
|
||||
Interface->Clear();
|
||||
DisplayChannel(channel);
|
||||
DisplayChannel();
|
||||
if (!channel->GroupSep())
|
||||
group = -1;
|
||||
}
|
||||
@ -2833,7 +2843,8 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
|
||||
Channels.SwitchTo(number);
|
||||
else {
|
||||
number = 0;
|
||||
DisplayChannel(NULL);
|
||||
channel = NULL;
|
||||
DisplayChannel();
|
||||
lastTime = time_ms();
|
||||
return osContinue;
|
||||
}
|
||||
@ -2965,7 +2976,7 @@ eOSState cDisplayVolume::ProcessKey(eKeys Key)
|
||||
|
||||
cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
|
||||
{
|
||||
eventInfo = NULL;
|
||||
event = NULL;
|
||||
instantId = NULL;
|
||||
fileName = NULL;
|
||||
recorder = NULL;
|
||||
@ -2984,10 +2995,10 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
|
||||
const char *Title = NULL;
|
||||
const char *Subtitle = NULL;
|
||||
const char *Summary = NULL;
|
||||
if (GetEventInfo()) {
|
||||
Title = eventInfo->GetTitle();
|
||||
Subtitle = eventInfo->GetSubtitle();
|
||||
Summary = eventInfo->GetExtendedDescription();
|
||||
if (GetEvent()) {
|
||||
Title = event->Title();
|
||||
Subtitle = event->ShortText();
|
||||
Summary = event->Description();
|
||||
dsyslog("Title: '%s' Subtitle: '%s'", Title, Subtitle);
|
||||
}
|
||||
cRecording Recording(timer, Title, Subtitle, Summary);
|
||||
@ -3036,19 +3047,19 @@ cRecordControl::~cRecordControl()
|
||||
|
||||
#define INSTANT_REC_EPG_LOOKAHEAD 300 // seconds to look into the EPG data for an instant recording
|
||||
|
||||
bool cRecordControl::GetEventInfo(void)
|
||||
bool cRecordControl::GetEvent(void)
|
||||
{
|
||||
const cChannel *channel = timer->Channel();
|
||||
time_t Time = timer->Active() == taActInst ? timer->StartTime() + INSTANT_REC_EPG_LOOKAHEAD : timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2;
|
||||
for (int seconds = 0; seconds <= MAXWAIT4EPGINFO; seconds++) {
|
||||
{
|
||||
cMutexLock MutexLock;
|
||||
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
|
||||
cSchedulesLock SchedulesLock;
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
|
||||
if (Schedule) {
|
||||
eventInfo = Schedule->GetEventAround(Time);
|
||||
if (eventInfo) {
|
||||
event = Schedule->GetEventAround(Time);
|
||||
if (event) {
|
||||
if (seconds > 0)
|
||||
dsyslog("got EPG info after %d seconds", seconds);
|
||||
return true;
|
||||
@ -3215,6 +3226,20 @@ void cRecordControls::Process(time_t t)
|
||||
}
|
||||
}
|
||||
|
||||
void cRecordControls::ChannelDataModified(cChannel *Channel)
|
||||
{
|
||||
for (int i = 0; i < MAXRECORDCONTROLS; i++) {
|
||||
if (RecordControls[i]) {
|
||||
if (RecordControls[i]->Timer() && RecordControls[i]->Timer()->Channel() == Channel) {
|
||||
isyslog("stopping recording due to modification of channel %d", Channel->Number());
|
||||
RecordControls[i]->Stop(true);
|
||||
// This will restart the recording, maybe even from a different
|
||||
// device in case conditional access has changed.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cRecordControls::Active(void)
|
||||
{
|
||||
for (int i = 0; i < MAXRECORDCONTROLS; i++) {
|
||||
|
13
menu.h
13
menu.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: menu.h 1.57 2003/08/03 09:37:18 kls Exp $
|
||||
* $Id: menu.h 1.59 2004/01/04 11:01:13 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __MENU_H
|
||||
@ -12,6 +12,7 @@
|
||||
|
||||
#include "ci.h"
|
||||
#include "device.h"
|
||||
#include "epg.h"
|
||||
#include "osd.h"
|
||||
#include "dvbplayer.h"
|
||||
#include "recorder.h"
|
||||
@ -36,7 +37,8 @@ private:
|
||||
int lines;
|
||||
int lastTime;
|
||||
int number;
|
||||
void DisplayChannel(const cChannel *Channel);
|
||||
cChannel *channel;
|
||||
void DisplayChannel(void);
|
||||
void DisplayInfo(void);
|
||||
void Refresh(void);
|
||||
public:
|
||||
@ -113,10 +115,10 @@ private:
|
||||
cDevice *device;
|
||||
cTimer *timer;
|
||||
cRecorder *recorder;
|
||||
const cEventInfo *eventInfo;
|
||||
const cEvent *event;
|
||||
char *instantId;
|
||||
char *fileName;
|
||||
bool GetEventInfo(void);
|
||||
bool GetEvent(void);
|
||||
public:
|
||||
cRecordControl(cDevice *Device, cTimer *Timer = NULL, bool Pause = false);
|
||||
virtual ~cRecordControl();
|
||||
@ -141,6 +143,7 @@ public:
|
||||
static const char *GetInstantId(const char *LastInstantId);
|
||||
static cRecordControl *GetRecordControl(const char *FileName);
|
||||
static void Process(time_t t);
|
||||
static void ChannelDataModified(cChannel *Channel);
|
||||
static bool Active(void);
|
||||
static void Shutdown(void);
|
||||
};
|
||||
@ -151,7 +154,7 @@ private:
|
||||
bool visible, modeOnly, shown, displayFrames;
|
||||
int lastCurrent, lastTotal;
|
||||
time_t timeoutShow;
|
||||
bool timeSearchActive, timeSearchHide;
|
||||
bool timeSearchActive, timeSearchHide;
|
||||
int timeSearchTime, timeSearchPos;
|
||||
void TimeSearchDisplay(void);
|
||||
void TimeSearchProcess(eKeys Key);
|
||||
|
@ -12,7 +12,7 @@
|
||||
# See the main source file 'vdr.c' for copyright information and
|
||||
# how to reach the author.
|
||||
#
|
||||
# $Id: newplugin 1.15 2003/05/09 14:59:28 kls Exp $
|
||||
# $Id: newplugin 1.16 2003/12/21 15:45:18 kls Exp $
|
||||
|
||||
$PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
|
||||
|
||||
@ -97,7 +97,7 @@ PACKAGE = vdr-\$(ARCHIVE)
|
||||
|
||||
INCLUDES += -I\$(VDRDIR)/include -I\$(DVBDIR)/include
|
||||
|
||||
DEFINES += -DPLUGIN_NAME_I18N='"\$(PLUGIN)"'
|
||||
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"\$(PLUGIN)"'
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osdbase.c 1.10 2003/08/24 11:38:27 kls Exp $
|
||||
* $Id: osdbase.c 1.11 2003/10/19 14:32:32 kls Exp $
|
||||
*/
|
||||
|
||||
#include "osdbase.h"
|
||||
@ -131,7 +131,6 @@ cBitmap::cBitmap(int Width, int Height, int Bpp, bool ClearWithBackground)
|
||||
|
||||
cBitmap::~cBitmap()
|
||||
{
|
||||
delete font;
|
||||
free(bitmap);
|
||||
}
|
||||
|
||||
@ -139,8 +138,7 @@ eDvbFont cBitmap::SetFont(eDvbFont Font)
|
||||
{
|
||||
eDvbFont oldFont = fontType;
|
||||
if (fontType != Font || !font) {
|
||||
delete font;
|
||||
font = new cFont(Font);
|
||||
font = cFont::GetFont(Font);
|
||||
fontType = Font;
|
||||
}
|
||||
return oldFont;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: osdbase.h 1.6 2002/09/08 14:12:41 kls Exp $
|
||||
* $Id: osdbase.h 1.8 2004/01/04 14:22:43 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __OSDBASE_H
|
||||
@ -13,7 +13,7 @@
|
||||
#include <stdio.h>
|
||||
#include "font.h"
|
||||
|
||||
#define MAXNUMCOLORS 16
|
||||
#define MAXNUMCOLORS 256
|
||||
|
||||
enum eDvbColor {
|
||||
#ifdef DEBUG_OSD
|
||||
@ -73,7 +73,7 @@ public:
|
||||
|
||||
class cBitmap : public cPalette {
|
||||
private:
|
||||
cFont *font;
|
||||
const cFont *font;
|
||||
eDvbFont fontType;
|
||||
char *bitmap;
|
||||
bool clearWithBackground;
|
||||
|
378
pat.c
Normal file
378
pat.c
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
* pat.c: PAT section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: pat.c 1.3 2004/01/04 12:27:06 kls Exp $
|
||||
*/
|
||||
|
||||
#include "pat.h"
|
||||
#include <malloc.h>
|
||||
#include "channels.h"
|
||||
#include "libsi/section.h"
|
||||
#include "libsi/descriptor.h"
|
||||
#include "thread.h"
|
||||
|
||||
#define PMT_SCAN_TIMEOUT 10 // seconds
|
||||
|
||||
// --- cCaDescriptor ---------------------------------------------------------
|
||||
|
||||
class cCaDescriptor : public cListObject {
|
||||
private:
|
||||
int caSystem;
|
||||
bool stream;
|
||||
int length;
|
||||
uchar *data;
|
||||
public:
|
||||
cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data);
|
||||
virtual ~cCaDescriptor();
|
||||
bool operator== (const cCaDescriptor &arg) const;
|
||||
int CaSystem(void) { return caSystem; }
|
||||
int Stream(void) { return stream; }
|
||||
int Length(void) const { return length; }
|
||||
const uchar *Data(void) const { return data; }
|
||||
};
|
||||
|
||||
cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data)
|
||||
{
|
||||
caSystem = CaSystem;
|
||||
stream = Stream;
|
||||
length = Length + 6;
|
||||
data = MALLOC(uchar, length);
|
||||
data[0] = SI::CaDescriptorTag;
|
||||
data[1] = length - 2;
|
||||
data[2] = (caSystem >> 8) & 0xFF;
|
||||
data[3] = caSystem & 0xFF;
|
||||
data[4] = ((CaPid >> 8) & 0x1F) | 0xE0;
|
||||
data[5] = CaPid & 0xFF;
|
||||
if (Length)
|
||||
memcpy(&data[6], Data, Length);
|
||||
}
|
||||
|
||||
cCaDescriptor::~cCaDescriptor()
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
bool cCaDescriptor::operator== (const cCaDescriptor &arg) const
|
||||
{
|
||||
return length == arg.length && memcmp(data, arg.data, length) == 0;
|
||||
}
|
||||
|
||||
// --- cCaDescriptors --------------------------------------------------------
|
||||
|
||||
class cCaDescriptors : public cListObject {
|
||||
private:
|
||||
int source;
|
||||
int transponder;
|
||||
int serviceId;
|
||||
int numCaIds;
|
||||
int caIds[MAXCAIDS + 1];
|
||||
cList<cCaDescriptor> caDescriptors;
|
||||
void AddCaId(int CaId);
|
||||
public:
|
||||
cCaDescriptors(int Source, int Transponder, int ServiceId);
|
||||
bool operator== (const cCaDescriptors &arg) const;
|
||||
bool Is(int Source, int Transponder, int ServiceId);
|
||||
bool Is(cCaDescriptors * CaDescriptors);
|
||||
bool Empty(void) { return caDescriptors.Count() == 0; }
|
||||
void AddCaDescriptor(SI::CaDescriptor *d, bool Stream);
|
||||
int GetCaDescriptors(const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
|
||||
const int *CaIds(void) { return caIds; }
|
||||
};
|
||||
|
||||
cCaDescriptors::cCaDescriptors(int Source, int Transponder, int ServiceId)
|
||||
{
|
||||
source = Source;
|
||||
transponder = Transponder;
|
||||
serviceId = ServiceId;
|
||||
numCaIds = 0;
|
||||
caIds[0] = 0;
|
||||
}
|
||||
|
||||
bool cCaDescriptors::operator== (const cCaDescriptors &arg) const
|
||||
{
|
||||
cCaDescriptor *ca1 = caDescriptors.First();
|
||||
cCaDescriptor *ca2 = arg.caDescriptors.First();
|
||||
while (ca1 && ca2) {
|
||||
if (!(*ca1 == *ca2))
|
||||
return false;
|
||||
ca1 = caDescriptors.Next(ca1);
|
||||
ca2 = arg.caDescriptors.Next(ca2);
|
||||
}
|
||||
return !ca1 && !ca2;
|
||||
}
|
||||
|
||||
bool cCaDescriptors::Is(int Source, int Transponder, int ServiceId)
|
||||
{
|
||||
return source == Source && transponder == Transponder && serviceId == ServiceId;
|
||||
}
|
||||
|
||||
bool cCaDescriptors::Is(cCaDescriptors * CaDescriptors)
|
||||
{
|
||||
return Is(CaDescriptors->source, CaDescriptors->transponder, CaDescriptors->serviceId);
|
||||
}
|
||||
|
||||
void cCaDescriptors::AddCaId(int CaId)
|
||||
{
|
||||
if (numCaIds < MAXCAIDS) {
|
||||
for (int i = 0; i < numCaIds; i++) {
|
||||
if (caIds[i] == CaId)
|
||||
return;
|
||||
}
|
||||
caIds[numCaIds++] = CaId;
|
||||
caIds[numCaIds] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream)
|
||||
{
|
||||
cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), Stream, d->privateData.getLength(), d->privateData.getData());
|
||||
for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
|
||||
if (*ca == *nca) {
|
||||
delete nca;
|
||||
return;
|
||||
}
|
||||
}
|
||||
AddCaId(nca->CaSystem());
|
||||
caDescriptors.Add(nca);
|
||||
//#define DEBUG_CA_DESCRIPTORS 1
|
||||
#ifdef DEBUG_CA_DESCRIPTORS
|
||||
char buffer[1024];
|
||||
char *q = buffer;
|
||||
q += sprintf(q, "CAM: %04X %5d %5d %04X %d -", source, transponder, serviceId, d->getCaType(), Stream);
|
||||
for (int i = 0; i < nca->Length(); i++)
|
||||
q += sprintf(q, " %02X", nca->Data()[i]);
|
||||
dsyslog(buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
int cCaDescriptors::GetCaDescriptors(const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
|
||||
{
|
||||
if (!CaSystemIds || !*CaSystemIds)
|
||||
return 0;
|
||||
if (BufSize > 0 && Data) {
|
||||
int length = 0;
|
||||
int IsStream = -1;
|
||||
for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
|
||||
const unsigned short *caids = CaSystemIds;
|
||||
do {
|
||||
if (d->CaSystem() == *caids) {
|
||||
if (length + d->Length() <= BufSize) {
|
||||
if (IsStream >= 0 && IsStream != d->Stream())
|
||||
dsyslog("CAM: different stream flag in CA descriptors");
|
||||
IsStream = d->Stream();
|
||||
memcpy(Data + length, d->Data(), d->Length());
|
||||
length += d->Length();
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
} while (*++caids);
|
||||
}
|
||||
StreamFlag = IsStream == 1;
|
||||
return length;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// --- cCaDescriptorHandler --------------------------------------------------
|
||||
|
||||
class cCaDescriptorHandler : public cList<cCaDescriptors> {
|
||||
private:
|
||||
cMutex mutex;
|
||||
public:
|
||||
int AddCaDescriptors(cCaDescriptors *CaDescriptors);
|
||||
// Returns 0 if this is an already known descriptor,
|
||||
// 1 if it is an all new descriptor with actual contents,
|
||||
// and 2 if an existing descriptor was changed.
|
||||
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
|
||||
};
|
||||
|
||||
int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
|
||||
if (ca->Is(CaDescriptors)) {
|
||||
if (*ca == *CaDescriptors) {
|
||||
delete CaDescriptors;
|
||||
return 0;
|
||||
}
|
||||
Del(ca);
|
||||
Add(CaDescriptors);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
Add(CaDescriptors);
|
||||
return CaDescriptors->Empty() ? 0 : 1;
|
||||
}
|
||||
|
||||
int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
|
||||
{
|
||||
cMutexLock MutexLock(&mutex);
|
||||
for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
|
||||
if (ca->Is(Source, Transponder, ServiceId))
|
||||
return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, StreamFlag);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
cCaDescriptorHandler CaDescriptorHandler;
|
||||
|
||||
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
|
||||
{
|
||||
return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, StreamFlag);
|
||||
}
|
||||
|
||||
// --- cPatFilter ------------------------------------------------------------
|
||||
|
||||
cPatFilter::cPatFilter(void)
|
||||
{
|
||||
pmtIndex = 0;
|
||||
pmtPid = 0;
|
||||
lastPmtScan = 0;
|
||||
numPmtEntries = 0;
|
||||
Set(0x00, 0x00); // PAT
|
||||
}
|
||||
|
||||
void cPatFilter::SetStatus(bool On)
|
||||
{
|
||||
cFilter::SetStatus(On);
|
||||
pmtIndex = 0;
|
||||
pmtPid = 0;
|
||||
lastPmtScan = 0;
|
||||
numPmtEntries = 0;
|
||||
}
|
||||
|
||||
void cPatFilter::Trigger(void)
|
||||
{
|
||||
numPmtEntries = 0;
|
||||
}
|
||||
|
||||
bool cPatFilter::PmtVersionChanged(int PmtPid, int Version)
|
||||
{
|
||||
Version <<= 16;
|
||||
for (int i = 0; i < numPmtEntries; i++) {
|
||||
if ((pmtVersion[i] & 0x0000FFFF) == PmtPid) {
|
||||
bool Changed = (pmtVersion[i] & 0x00FF0000) != Version;
|
||||
if (Changed)
|
||||
pmtVersion[i] = PmtPid | Version;
|
||||
return Changed;
|
||||
}
|
||||
}
|
||||
if (numPmtEntries < MAXPMTENTRIES)
|
||||
pmtVersion[numPmtEntries++] = PmtPid | Version;
|
||||
return true;
|
||||
}
|
||||
|
||||
void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
|
||||
{
|
||||
if (Pid == 0x00) {
|
||||
if (Tid == 0x00) {
|
||||
if (pmtPid && time(NULL) - lastPmtScan > PMT_SCAN_TIMEOUT) {
|
||||
Del(pmtPid, 0x02);
|
||||
pmtPid = 0;
|
||||
pmtIndex++;
|
||||
lastPmtScan = time(NULL);
|
||||
}
|
||||
if (!pmtPid) {
|
||||
SI::PAT pat(Data, false);
|
||||
if (!pat.CheckCRCAndParse())
|
||||
return;
|
||||
SI::PAT::Association assoc;
|
||||
int Index = 0;
|
||||
for (SI::Loop::Iterator it; pat.associationLoop.hasNext(it); ) {
|
||||
assoc = pat.associationLoop.getNext(it);
|
||||
if (!assoc.isNITPid()) {
|
||||
if (Index++ == pmtIndex) {
|
||||
pmtPid = assoc.getPid();
|
||||
Add(pmtPid, 0x02);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!pmtPid)
|
||||
pmtIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Pid == pmtPid && Tid == SI::TableIdPMT && Source() && Transponder()) {
|
||||
SI::PMT pmt(Data, false);
|
||||
if (!pmt.CheckCRCAndParse())
|
||||
return;
|
||||
if (!PmtVersionChanged(pmtPid, pmt.getVersionNumber())) {
|
||||
lastPmtScan = 0; // this triggers the next scan
|
||||
return;
|
||||
}
|
||||
if (!Channels.Lock(true, 10)) {
|
||||
numPmtEntries = 0; // to make sure we try again
|
||||
return;
|
||||
}
|
||||
cChannel *Channel = Channels.GetByServiceID(Source(), Transponder(), pmt.getServiceId());
|
||||
if (Channel) {
|
||||
SI::CaDescriptor *d;
|
||||
cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid());
|
||||
// Scan the common loop:
|
||||
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
|
||||
CaDescriptors->AddCaDescriptor(d, false);
|
||||
delete d;
|
||||
}
|
||||
// Scan the stream-specific loop:
|
||||
SI::PMT::Stream stream;
|
||||
int Vpid = 0;
|
||||
int Ppid = pmt.getPCRPid();
|
||||
int Apids[MAXAPIDS] = { 0 };
|
||||
int Dpids[MAXAPIDS] = { 0 };
|
||||
int Tpid = 0;
|
||||
int NumApids = 0;
|
||||
int NumDpids = 0;
|
||||
for (SI::Loop::Iterator it; pmt.streamLoop.hasNext(it); ) {
|
||||
stream = pmt.streamLoop.getNext(it);
|
||||
switch (stream.getStreamType()) {
|
||||
case 1: // STREAMTYPE_11172_VIDEO
|
||||
case 2: // STREAMTYPE_13818_VIDEO
|
||||
Vpid = stream.getPid();
|
||||
break;
|
||||
case 3: // STREAMTYPE_11172_AUDIO
|
||||
case 4: // STREAMTYPE_13818_AUDIO
|
||||
{
|
||||
if (NumApids < MAXAPIDS)
|
||||
Apids[NumApids++] = stream.getPid();
|
||||
}
|
||||
break;
|
||||
case 5: // STREAMTYPE_13818_PRIVATE
|
||||
case 6: // STREAMTYPE_13818_PES_PRIVATE
|
||||
//XXX case 8: // STREAMTYPE_13818_DSMCC
|
||||
{
|
||||
SI::Descriptor *d;
|
||||
for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
|
||||
switch (d->getDescriptorTag()) {
|
||||
case SI::AC3DescriptorTag:
|
||||
if (NumDpids < MAXAPIDS)
|
||||
Dpids[NumDpids++] = stream.getPid();
|
||||
break;
|
||||
case SI::TeletextDescriptorTag:
|
||||
Tpid = stream.getPid();
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
break;
|
||||
//default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
|
||||
}
|
||||
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
|
||||
CaDescriptors->AddCaDescriptor(d, true);
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
Channel->SetPids(Vpid, Ppid, Apids[0], Apids[1], Dpids[0], Dpids[1], Tpid);
|
||||
Channel->SetCaIds(CaDescriptors->CaIds());
|
||||
Channel->SetCaDescriptors(CaDescriptorHandler.AddCaDescriptors(CaDescriptors));
|
||||
}
|
||||
lastPmtScan = 0; // this triggers the next scan
|
||||
Channels.Unlock();
|
||||
}
|
||||
}
|
43
pat.h
Normal file
43
pat.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* pat.h: PAT section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: pat.h 1.3 2004/01/03 13:47:54 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __PAT_H
|
||||
#define __PAT_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
#define MAXPMTENTRIES 64
|
||||
|
||||
class cPatFilter : public cFilter {
|
||||
private:
|
||||
time_t lastPmtScan;
|
||||
int pmtIndex;
|
||||
int pmtPid;
|
||||
int pmtVersion[MAXPMTENTRIES];
|
||||
int numPmtEntries;
|
||||
bool PmtVersionChanged(int PmtPid, int Version);
|
||||
protected:
|
||||
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
|
||||
public:
|
||||
cPatFilter(void);
|
||||
virtual void SetStatus(bool On);
|
||||
void Trigger(void);
|
||||
};
|
||||
|
||||
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
|
||||
///< Gets all CA descriptors for a given channel.
|
||||
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
|
||||
///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
|
||||
///< are copied that match one of the given CA system IDs.
|
||||
///< \return Returns the number of bytes copied into Data (0 if no CA descriptors are
|
||||
///< available), or -1 if BufSize was too small to hold all CA descriptors.
|
||||
///< The return value in StreamFlag tells whether these CA descriptors are to be used
|
||||
///< for the individual streams.
|
||||
|
||||
#endif //__PAT_H
|
5
rcu.c
5
rcu.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: rcu.c 1.5 2003/05/02 14:42:40 kls Exp $
|
||||
* $Id: rcu.c 1.6 2003/10/18 11:34:30 kls Exp $
|
||||
*/
|
||||
|
||||
#include "rcu.h"
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
cRcuRemote::cRcuRemote(char *DeviceName)
|
||||
:cRemote("RCU")
|
||||
,cThread("RCU remote control")
|
||||
{
|
||||
dp = 0;
|
||||
mode = modeB;
|
||||
@ -92,8 +93,6 @@ void cRcuRemote::Action(void)
|
||||
} buffer;
|
||||
#pragma pack()
|
||||
|
||||
dsyslog("RCU remote control thread started (pid=%d)", getpid());
|
||||
|
||||
time_t LastCodeRefresh = 0;
|
||||
int FirstTime = 0;
|
||||
uint64 LastCommand = 0;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: recorder.c 1.7 2003/08/02 13:01:19 kls Exp $
|
||||
* $Id: recorder.c 1.8 2003/10/18 11:35:02 kls Exp $
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
cRecorder::cRecorder(const char *FileName, int Ca, int Priority, int VPid, int APid1, int APid2, int DPid1, int DPid2)
|
||||
:cReceiver(Ca, Priority, 5, VPid, APid1, APid2, DPid1, DPid2)
|
||||
,cThread("recording")
|
||||
{
|
||||
ringBuffer = NULL;
|
||||
remux = NULL;
|
||||
@ -106,8 +107,6 @@ void cRecorder::Receive(uchar *Data, int Length)
|
||||
|
||||
void cRecorder::Action(void)
|
||||
{
|
||||
dsyslog("recording thread started (pid=%d)", getpid());
|
||||
|
||||
time_t t = time(NULL);
|
||||
active = true;
|
||||
while (active) {
|
||||
@ -143,6 +142,4 @@ void cRecorder::Action(void)
|
||||
else
|
||||
usleep(1); // this keeps the CPU load low
|
||||
}
|
||||
|
||||
dsyslog("recording thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
5
remote.c
5
remote.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: remote.c 1.38 2003/05/02 10:49:50 kls Exp $
|
||||
* $Id: remote.c 1.39 2003/10/18 11:35:32 kls Exp $
|
||||
*/
|
||||
|
||||
#include "remote.h"
|
||||
@ -197,6 +197,7 @@ bool cKbdRemote::rawMode = false;
|
||||
|
||||
cKbdRemote::cKbdRemote(void)
|
||||
:cRemote("KBD")
|
||||
,cThread("KBD remote control")
|
||||
{
|
||||
active = false;
|
||||
tcgetattr(STDIN_FILENO, &savedTm);
|
||||
@ -245,7 +246,6 @@ int cKbdRemote::MapCodeToFunc(uint64 Code)
|
||||
|
||||
void cKbdRemote::Action(void)
|
||||
{
|
||||
dsyslog("KBD remote control thread started (pid=%d)", getpid());
|
||||
cPoller Poller(STDIN_FILENO);
|
||||
active = true;
|
||||
while (active) {
|
||||
@ -285,5 +285,4 @@ void cKbdRemote::Action(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
dsyslog("KBD remote control thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
10
ringbuffer.c
10
ringbuffer.c
@ -7,7 +7,7 @@
|
||||
* Parts of this file were inspired by the 'ringbuffy.c' from the
|
||||
* LinuxDVB driver (see linuxtv.org).
|
||||
*
|
||||
* $Id: ringbuffer.c 1.17 2003/05/12 17:38:11 kls Exp $
|
||||
* $Id: ringbuffer.c 1.18 2003/10/12 14:25:09 kls Exp $
|
||||
*/
|
||||
|
||||
#include "ringbuffer.h"
|
||||
@ -75,7 +75,7 @@ cRingBufferLinear::cRingBufferLinear(int Size, int Margin, bool Statistics)
|
||||
{
|
||||
margin = Margin;
|
||||
buffer = NULL;
|
||||
getThreadPid = -1;
|
||||
getThreadTid = 0;
|
||||
if (Size > 1) { // 'Size - 1' must not be 0!
|
||||
buffer = MALLOC(uchar, Size);
|
||||
if (!buffer)
|
||||
@ -125,7 +125,7 @@ int cRingBufferLinear::Put(const uchar *Data, int Count)
|
||||
int percent = maxFill * 100 / (Size() - 1) / 5 * 5;
|
||||
if (abs(lastPercent - percent) >= 5) {
|
||||
if (percent > 75)
|
||||
dsyslog("buffer usage: %d%% (pid=%d)", percent, getThreadPid);
|
||||
dsyslog("buffer usage: %d%% (tid=%ld)", percent, getThreadTid);
|
||||
lastPercent = percent;
|
||||
}
|
||||
}
|
||||
@ -159,8 +159,8 @@ uchar *cRingBufferLinear::Get(int &Count)
|
||||
{
|
||||
uchar *p = NULL;
|
||||
Lock();
|
||||
if (getThreadPid < 0)
|
||||
getThreadPid = getpid();
|
||||
if (getThreadTid <= 0)
|
||||
getThreadTid = pthread_self();
|
||||
int rest = Size() - tail;
|
||||
if (rest < margin && head < tail) {
|
||||
int t = margin - rest;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: ringbuffer.h 1.12 2003/05/12 17:35:10 kls Exp $
|
||||
* $Id: ringbuffer.h 1.13 2003/10/12 13:57:56 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __RINGBUFFER_H
|
||||
@ -46,7 +46,7 @@ private:
|
||||
int margin, head, tail;
|
||||
int lastGet;
|
||||
uchar *buffer;
|
||||
pid_t getThreadPid;
|
||||
pthread_t getThreadTid;
|
||||
public:
|
||||
cRingBufferLinear(int Size, int Margin = 0, bool Statistics = false);
|
||||
///< Creates a linear ring buffer.
|
||||
|
146
sdt.c
Normal file
146
sdt.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* sdt.c: SDT section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: sdt.c 1.1 2004/01/04 11:54:42 kls Exp $
|
||||
*/
|
||||
|
||||
#include "sdt.h"
|
||||
#include "channels.h"
|
||||
#include "libsi/section.h"
|
||||
#include "libsi/descriptor.h"
|
||||
|
||||
// --- cSDT ------------------------------------------------------------------
|
||||
|
||||
class cSDT : public SI::SDT {
|
||||
public:
|
||||
cSDT(int Source, int Transponder, uchar &lastSdtVersion, cPatFilter *PatFilter, const u_char *Data);
|
||||
};
|
||||
|
||||
cSDT::cSDT(int Source, int Transponder, uchar &lastSdtVersion, cPatFilter *PatFilter, const u_char *Data)
|
||||
:SI::SDT(Data, false)
|
||||
{
|
||||
if (!CheckCRCAndParse())
|
||||
return;
|
||||
|
||||
if (getVersionNumber() == lastSdtVersion)
|
||||
return;
|
||||
|
||||
if (!Channels.Lock(true, 10))
|
||||
return;
|
||||
|
||||
lastSdtVersion = getVersionNumber();
|
||||
|
||||
SI::SDT::Service SiSdtService;
|
||||
for (SI::Loop::Iterator it; serviceLoop.hasNext(it); ) {
|
||||
SiSdtService = serviceLoop.getNext(it);
|
||||
|
||||
cChannel *Channel = Channels.GetByChannelID(tChannelID(Source, getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId()));
|
||||
if (!Channel)
|
||||
Channel = Channels.GetByChannelID(tChannelID(Source, 0, Transponder, SiSdtService.getServiceId()));
|
||||
|
||||
SI::Descriptor *d;
|
||||
for (SI::Loop::Iterator it2; (d = SiSdtService.serviceDescriptors.getNext(it2)); ) {
|
||||
switch (d->getDescriptorTag()) {
|
||||
case SI::ServiceDescriptorTag: {
|
||||
SI::ServiceDescriptor *sd = (SI::ServiceDescriptor *)d;
|
||||
switch (sd->getServiceType()) {
|
||||
case 0x01: // digital television service
|
||||
//XXX TODO case 0x02: // digital radio sound service
|
||||
//XXX TODO case 0x04: // NVOD reference service
|
||||
//XXX TODO case 0x05: // NVOD time-shifted service
|
||||
{
|
||||
char buffer[1024];
|
||||
char *p = sd->serviceName.getText(buffer);
|
||||
char NameBuf[1024];
|
||||
char ShortNameBuf[1024];
|
||||
char *pn = NameBuf;
|
||||
char *ps = ShortNameBuf;
|
||||
int IsShortName = 0;
|
||||
while (*p) {
|
||||
if ((uchar)*p == 0x86)
|
||||
IsShortName++;
|
||||
else if ((uchar)*p == 0x87)
|
||||
IsShortName--;
|
||||
else {
|
||||
*pn++ = *p;
|
||||
if (IsShortName)
|
||||
*ps++ = *p;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*pn = *ps = 0;
|
||||
pn = NameBuf;
|
||||
if (*NameBuf && *ShortNameBuf) {
|
||||
*ps++ = ',';
|
||||
strcpy(ps, NameBuf);
|
||||
pn = ShortNameBuf;
|
||||
}
|
||||
if (Channel) {
|
||||
Channel->SetId(getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId());
|
||||
Channel->SetName(pn);
|
||||
// Using SiSdtService.getFreeCaMode() is no good, because some
|
||||
// tv stations set this flag even for non-encrypted channels :-(
|
||||
// The special value 0xFFFF was supposed to mean "unknown encryption"
|
||||
// and would have been overwritten with real CA values later:
|
||||
// Channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
|
||||
}
|
||||
else if (*pn) {
|
||||
Channel = Channels.NewChannel(Source, Transponder, pn, getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId());
|
||||
PatFilter->Trigger();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
// Using the CaIdentifierDescriptor is no good, because some tv stations
|
||||
// just don't use it. The actual CA values are collected in pat.c:
|
||||
/*
|
||||
case SI::CaIdentifierDescriptorTag: {
|
||||
SI::CaIdentifierDescriptor *cid = (SI::CaIdentifierDescriptor *)d;
|
||||
if (Channel) {
|
||||
for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); )
|
||||
Channel->SetCa(cid->identifiers.getNext(it));
|
||||
}
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case SI::NVODReferenceDescriptorTag: {
|
||||
SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d;
|
||||
for (SI::Loop::Iterator it; nrd->serviceLoop.hasNext(it); ) {
|
||||
SI::NVODReferenceDescriptor::Service Service = nrd->serviceLoop.getNext(it);
|
||||
//printf(" %04X-%04X-%04X\n", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());//XXX TODO
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
delete d;
|
||||
}
|
||||
}
|
||||
Channels.Unlock();
|
||||
}
|
||||
|
||||
|
||||
// --- cSdtFilter ------------------------------------------------------------
|
||||
|
||||
cSdtFilter::cSdtFilter(cPatFilter *PatFilter)
|
||||
{
|
||||
lastSdtVersion = 0xFF;
|
||||
patFilter = PatFilter;
|
||||
Set(0x11, 0x42); // SDT
|
||||
}
|
||||
|
||||
void cSdtFilter::SetStatus(bool On)
|
||||
{
|
||||
cFilter::SetStatus(On);
|
||||
lastSdtVersion = 0xFF;
|
||||
}
|
||||
|
||||
void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
|
||||
{
|
||||
if (Source() && Transponder())
|
||||
cSDT SDT(Source(), Transponder(), lastSdtVersion, patFilter, Data);
|
||||
}
|
27
sdt.h
Normal file
27
sdt.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* sdt.h: SDT section filter
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: sdt.h 1.1 2004/01/03 13:49:55 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SDT_H
|
||||
#define __SDT_H
|
||||
|
||||
#include "filter.h"
|
||||
#include "pat.h"
|
||||
|
||||
class cSdtFilter : public cFilter {
|
||||
private:
|
||||
uchar lastSdtVersion;
|
||||
cPatFilter *patFilter;
|
||||
protected:
|
||||
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
|
||||
public:
|
||||
cSdtFilter(cPatFilter *PatFilter);
|
||||
virtual void SetStatus(bool On);
|
||||
};
|
||||
|
||||
#endif //__SDT_H
|
187
sections.c
Normal file
187
sections.c
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* sections.c: Section data handling
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: sections.c 1.2 2004/01/03 12:54:01 kls Exp $
|
||||
*/
|
||||
|
||||
#include "sections.h"
|
||||
#include <unistd.h>
|
||||
#include "device.h"
|
||||
|
||||
// --- cFilterHandle----------------------------------------------------------
|
||||
|
||||
class cFilterHandle : public cListObject {
|
||||
public:
|
||||
cFilterData filterData;
|
||||
int handle;
|
||||
int used;
|
||||
cFilterHandle(const cFilterData &FilterData);
|
||||
};
|
||||
|
||||
cFilterHandle::cFilterHandle(const cFilterData &FilterData)
|
||||
{
|
||||
filterData = FilterData;
|
||||
handle = -1;
|
||||
used = 0;
|
||||
}
|
||||
|
||||
// --- cSectionHandler -------------------------------------------------------
|
||||
|
||||
cSectionHandler::cSectionHandler(cDevice *Device)
|
||||
:cThread("Section handler")
|
||||
{
|
||||
device = Device;
|
||||
active = false;
|
||||
source = 0;
|
||||
transponder = 0;
|
||||
statusCount = 0;
|
||||
on = false;
|
||||
Start();
|
||||
}
|
||||
|
||||
cSectionHandler::~cSectionHandler()
|
||||
{
|
||||
active = false;
|
||||
Cancel(3);
|
||||
cFilter *fi;
|
||||
while ((fi = filters.First()) != NULL)
|
||||
Detach(fi);
|
||||
}
|
||||
|
||||
void cSectionHandler::Add(const cFilterData *FilterData)
|
||||
{
|
||||
Lock();
|
||||
statusCount++;
|
||||
cFilterHandle *fh;
|
||||
for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
|
||||
if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask))
|
||||
break;
|
||||
}
|
||||
if (!fh) {
|
||||
fh = new cFilterHandle(*FilterData);
|
||||
filterHandles.Add(fh);
|
||||
fh->handle = device->OpenFilter(FilterData->pid, FilterData->tid, FilterData->mask);
|
||||
}
|
||||
fh->used++;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void cSectionHandler::Del(const cFilterData *FilterData)
|
||||
{
|
||||
Lock();
|
||||
statusCount++;
|
||||
cFilterHandle *fh;
|
||||
for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
|
||||
if (fh->filterData.Is(FilterData->pid, FilterData->tid, FilterData->mask)) {
|
||||
if (--fh->used <= 0) {
|
||||
close(fh->handle);
|
||||
filterHandles.Del(fh);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void cSectionHandler::Attach(cFilter *Filter)
|
||||
{
|
||||
Lock();
|
||||
statusCount++;
|
||||
filters.Add(Filter);
|
||||
Filter->sectionHandler = this;
|
||||
Filter->SetStatus(true);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void cSectionHandler::Detach(cFilter *Filter)
|
||||
{
|
||||
Lock();
|
||||
statusCount++;
|
||||
Filter->SetStatus(false);
|
||||
Filter->sectionHandler = NULL;
|
||||
filters.Del(Filter, false);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void cSectionHandler::SetSource(int Source, int Transponder)
|
||||
{
|
||||
Lock();
|
||||
source = Source;
|
||||
transponder = Transponder;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void cSectionHandler::SetStatus(bool On)
|
||||
{
|
||||
Lock();
|
||||
if (on != On) {
|
||||
statusCount++;
|
||||
for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
|
||||
fi->SetStatus(false);
|
||||
if (On)
|
||||
fi->SetStatus(true);
|
||||
}
|
||||
on = On;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void cSectionHandler::Action(void)
|
||||
{
|
||||
active = true;
|
||||
while (active) {
|
||||
|
||||
Lock();
|
||||
int NumFilters = filterHandles.Count();
|
||||
pollfd pfd[NumFilters];
|
||||
for (cFilterHandle *fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
|
||||
int i = fh->Index();
|
||||
pfd[i].fd = fh->handle;
|
||||
pfd[i].events = POLLIN;
|
||||
}
|
||||
int oldStatusCount = statusCount;
|
||||
Unlock();
|
||||
|
||||
if (poll(pfd, NumFilters, 1000) != 0) {
|
||||
bool DeviceHasLock = device->HasLock();
|
||||
if (!DeviceHasLock)
|
||||
usleep(100000);
|
||||
for (int i = 0; i < NumFilters; i++) {
|
||||
if (pfd[i].revents & POLLIN) {
|
||||
cFilterHandle *fh = NULL;
|
||||
LOCK_THREAD;
|
||||
if (statusCount != oldStatusCount)
|
||||
break;
|
||||
for (fh = filterHandles.First(); fh; fh = filterHandles.Next(fh)) {
|
||||
if (pfd[i].fd == fh->handle)
|
||||
break;
|
||||
}
|
||||
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));
|
||||
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
|
||||
int len = (((buf[1] & 0x0F) << 8) | (buf[2] & 0xFF)) + 3;
|
||||
if (len == r) {
|
||||
// Distribute data to all attached filters:
|
||||
int pid = fh->filterData.pid;
|
||||
int tid = buf[0];
|
||||
for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
|
||||
if (fi->Matches(pid, tid))
|
||||
fi->Process(pid, tid, buf, len);
|
||||
}
|
||||
}
|
||||
else
|
||||
dsyslog("read incomplete section - len = %d, r = %d", len, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
sections.h
Normal file
45
sections.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* sections.h: Section data handling
|
||||
*
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: sections.h 1.1 2003/12/21 14:37:00 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __SECTIONS_H
|
||||
#define __SECTIONS_H
|
||||
|
||||
#include "filter.h"
|
||||
#include "thread.h"
|
||||
#include "tools.h"
|
||||
|
||||
class cDevice;
|
||||
class cFilterHandle;
|
||||
|
||||
class cSectionHandler : public cThread {
|
||||
friend class cFilter;
|
||||
private:
|
||||
cDevice *device;
|
||||
bool active;
|
||||
int source;
|
||||
int transponder;
|
||||
int statusCount;
|
||||
bool on;
|
||||
cList<cFilter> filters;
|
||||
cList<cFilterHandle> filterHandles;
|
||||
void Add(const cFilterData *FilterData);
|
||||
void Del(const cFilterData *FilterData);
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cSectionHandler(cDevice *Device);
|
||||
virtual ~cSectionHandler();
|
||||
int Source(void) { return source; }
|
||||
int Transponder(void) { return transponder; }
|
||||
void Attach(cFilter *Filter);
|
||||
void Detach(cFilter *Filter);
|
||||
void SetSource(int Source, int Transponder);
|
||||
void SetStatus(bool On);
|
||||
};
|
||||
|
||||
#endif //__SECTIONS_H
|
17
svdrp.c
17
svdrp.c
@ -10,7 +10,7 @@
|
||||
* and interact with the Video Disk Recorder - or write a full featured
|
||||
* graphical interface that sits on top of an SVDRP connection.
|
||||
*
|
||||
* $Id: svdrp.c 1.55 2003/08/31 11:24:47 kls Exp $
|
||||
* $Id: svdrp.c 1.57 2003/12/28 10:09:30 kls Exp $
|
||||
*/
|
||||
|
||||
#include "svdrp.h"
|
||||
@ -155,7 +155,7 @@ bool cPUTEhandler::Process(const char *s)
|
||||
else {
|
||||
rewind(f);
|
||||
if (cSchedules::Read(f)) {
|
||||
cSIProcessor::TriggerDump();
|
||||
cSchedules::Cleanup(true);
|
||||
status = 250;
|
||||
message = "EPG data processed";
|
||||
}
|
||||
@ -458,7 +458,7 @@ void cSVDRP::CmdCHAN(const char *Option)
|
||||
|
||||
void cSVDRP::CmdCLRE(const char *Option)
|
||||
{
|
||||
cSIProcessor::Clear();
|
||||
cSchedules::ClearAll();
|
||||
Reply(250, "EPG data cleared");
|
||||
}
|
||||
|
||||
@ -476,7 +476,7 @@ void cSVDRP::CmdDELC(const char *Option)
|
||||
}
|
||||
Channels.Del(channel);
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
Channels.SetModified();
|
||||
isyslog("channel %s deleted", Option);
|
||||
Reply(250, "Channel \"%s\" deleted", Option);
|
||||
}
|
||||
@ -707,8 +707,8 @@ void cSVDRP::CmdLSTC(const char *Option)
|
||||
|
||||
void cSVDRP::CmdLSTE(const char *Option)
|
||||
{
|
||||
cMutexLock MutexLock;
|
||||
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock);
|
||||
cSchedulesLock SchedulesLock;
|
||||
const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
|
||||
if (Schedules) {
|
||||
FILE *f = fdopen(file, "w");
|
||||
if (f) {
|
||||
@ -810,9 +810,8 @@ void cSVDRP::CmdMODC(const char *Option)
|
||||
if (Channels.HasUniqueChannelID(&ch, channel)) {
|
||||
*channel = ch;
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
Channels.SetModified();
|
||||
isyslog("modifed channel %d %s", channel->Number(), channel->ToText());
|
||||
Timers.Save();
|
||||
Reply(250, "%d %s", channel->Number(), channel->ToText());
|
||||
}
|
||||
else
|
||||
@ -886,7 +885,7 @@ void cSVDRP::CmdNEWC(const char *Option)
|
||||
*channel = ch;
|
||||
Channels.Add(channel);
|
||||
Channels.ReNumber();
|
||||
Channels.Save();
|
||||
Channels.SetModified();
|
||||
isyslog("new channel %d %s", channel->Number(), channel->ToText());
|
||||
Reply(250, "%d %s", channel->Number(), channel->ToText());
|
||||
}
|
||||
|
112
thread.c
112
thread.c
@ -4,12 +4,14 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: thread.c 1.25 2003/05/18 12:45:13 kls Exp $
|
||||
* $Id: thread.c 1.30 2004/01/03 16:59:33 kls Exp $
|
||||
*/
|
||||
|
||||
#include "thread.h"
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
@ -30,7 +32,7 @@ cCondVar::~cCondVar()
|
||||
|
||||
void cCondVar::Wait(cMutex &Mutex)
|
||||
{
|
||||
if (Mutex.locked && Mutex.lockingPid == getpid()) {
|
||||
if (Mutex.locked) {
|
||||
int locked = Mutex.locked;
|
||||
Mutex.locked = 0; // have to clear the locked count here, as pthread_cond_wait
|
||||
// does an implizit unlock of the mutex
|
||||
@ -43,7 +45,7 @@ bool cCondVar::TimedWait(cMutex &Mutex, int TimeoutMs)
|
||||
{
|
||||
bool r = true; // true = condition signaled false = timeout
|
||||
|
||||
if (Mutex.locked && Mutex.lockingPid == getpid()) {
|
||||
if (Mutex.locked) {
|
||||
struct timeval now; // unfortunately timedwait needs the absolute time, not the delta :-(
|
||||
if (gettimeofday(&now, NULL) == 0) { // get current time
|
||||
now.tv_usec += TimeoutMs * 1000; // add the timeout
|
||||
@ -61,7 +63,6 @@ bool cCondVar::TimedWait(cMutex &Mutex, int TimeoutMs)
|
||||
if (pthread_cond_timedwait(&cond, &Mutex.mutex, &abstime) == ETIMEDOUT)
|
||||
r = false;
|
||||
Mutex.locked = locked;
|
||||
Mutex.lockingPid = getpid();
|
||||
}
|
||||
}
|
||||
return r;
|
||||
@ -79,13 +80,46 @@ void cCondVar::Signal(void)
|
||||
}
|
||||
*/
|
||||
|
||||
// --- cRwLock ---------------------------------------------------------------
|
||||
|
||||
cRwLock::cRwLock(bool PreferWriter)
|
||||
{
|
||||
pthread_rwlockattr_t attr = { PreferWriter ? PTHREAD_RWLOCK_PREFER_WRITER_NP : PTHREAD_RWLOCK_PREFER_READER_NP };
|
||||
pthread_rwlock_init(&rwlock, &attr);
|
||||
}
|
||||
|
||||
cRwLock::~cRwLock()
|
||||
{
|
||||
pthread_rwlock_destroy(&rwlock);
|
||||
}
|
||||
|
||||
bool cRwLock::Lock(bool Write, int TimeoutMs)
|
||||
{
|
||||
int Result = 0;
|
||||
struct timespec abstime;
|
||||
if (TimeoutMs) {
|
||||
abstime.tv_sec = TimeoutMs / 1000;
|
||||
abstime.tv_nsec = (TimeoutMs % 1000) * 1000000;
|
||||
}
|
||||
if (Write)
|
||||
Result = TimeoutMs ? pthread_rwlock_timedwrlock(&rwlock, &abstime) : pthread_rwlock_wrlock(&rwlock);
|
||||
else
|
||||
Result = TimeoutMs ? pthread_rwlock_timedrdlock(&rwlock, &abstime) : pthread_rwlock_rdlock(&rwlock);
|
||||
return Result == 0;
|
||||
}
|
||||
|
||||
void cRwLock::Unlock(void)
|
||||
{
|
||||
pthread_rwlock_unlock(&rwlock);
|
||||
}
|
||||
|
||||
// --- cMutex ----------------------------------------------------------------
|
||||
|
||||
cMutex::cMutex(void)
|
||||
{
|
||||
lockingPid = 0;
|
||||
locked = 0;
|
||||
pthread_mutex_init(&mutex, NULL);
|
||||
pthread_mutexattr_t attr = { PTHREAD_MUTEX_ERRORCHECK_NP };
|
||||
pthread_mutex_init(&mutex, &attr);
|
||||
}
|
||||
|
||||
cMutex::~cMutex()
|
||||
@ -95,19 +129,14 @@ cMutex::~cMutex()
|
||||
|
||||
void cMutex::Lock(void)
|
||||
{
|
||||
if (getpid() != lockingPid || !locked) {
|
||||
pthread_mutex_lock(&mutex);
|
||||
lockingPid = getpid();
|
||||
}
|
||||
pthread_mutex_lock(&mutex);
|
||||
locked++;
|
||||
}
|
||||
|
||||
void cMutex::Unlock(void)
|
||||
{
|
||||
if (!--locked) {
|
||||
lockingPid = 0;
|
||||
if (!--locked)
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
}
|
||||
|
||||
// --- cThread ---------------------------------------------------------------
|
||||
@ -118,18 +147,33 @@ void cMutex::Unlock(void)
|
||||
bool cThread::signalHandlerInstalled = false;
|
||||
bool cThread::emergencyExitRequested = false;
|
||||
|
||||
cThread::cThread(void)
|
||||
cThread::cThread(const char *Description)
|
||||
{
|
||||
if (!signalHandlerInstalled) {
|
||||
signal(SIGIO, SignalHandler);
|
||||
signalHandlerInstalled = true;
|
||||
}
|
||||
running = false;
|
||||
parentPid = threadPid = 0;
|
||||
parentTid = childTid = 0;
|
||||
description = NULL;
|
||||
SetDescription(Description);
|
||||
}
|
||||
|
||||
cThread::~cThread()
|
||||
{
|
||||
free(description);
|
||||
}
|
||||
|
||||
void cThread::SetDescription(const char *Description, ...)
|
||||
{
|
||||
free(description);
|
||||
description = NULL;
|
||||
if (Description) {
|
||||
va_list ap;
|
||||
va_start(ap, Description);
|
||||
vasprintf(&description, Description, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void cThread::SignalHandler(int signum)
|
||||
@ -139,8 +183,13 @@ void cThread::SignalHandler(int signum)
|
||||
|
||||
void *cThread::StartThread(cThread *Thread)
|
||||
{
|
||||
Thread->threadPid = getpid();
|
||||
Thread->childTid = pthread_self();
|
||||
if (Thread->description)
|
||||
dsyslog("%s thread started (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
|
||||
Thread->Action();
|
||||
if (Thread->description)
|
||||
dsyslog("%s thread ended (pid=%d, tid=%ld)", Thread->description, getpid(), Thread->childTid);
|
||||
Thread->childTid = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -148,9 +197,9 @@ bool cThread::Start(void)
|
||||
{
|
||||
if (!running) {
|
||||
running = true;
|
||||
parentPid = getpid();
|
||||
pthread_create(&thread, NULL, (void *(*) (void *))&StartThread, (void *)this);
|
||||
pthread_setschedparam(thread, SCHED_RR, 0);
|
||||
parentTid = pthread_self();
|
||||
pthread_create(&childTid, NULL, (void *(*) (void *))&StartThread, (void *)this);
|
||||
pthread_setschedparam(childTid, SCHED_RR, 0);
|
||||
usleep(10000); // otherwise calling Active() immediately after Start() causes a "pure virtual method called" error
|
||||
}
|
||||
return true; //XXX return value of pthread_create()???
|
||||
@ -158,12 +207,21 @@ bool cThread::Start(void)
|
||||
|
||||
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 (childTid) {
|
||||
//
|
||||
// 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(childTid, 0)) != 0) {
|
||||
if (err != ESRCH)
|
||||
LOG_ERROR;
|
||||
childTid = 0;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
@ -180,14 +238,14 @@ void cThread::Cancel(int WaitSeconds)
|
||||
return;
|
||||
usleep(10000);
|
||||
}
|
||||
esyslog("ERROR: thread %d won't end (waited %d seconds) - cancelling it...", threadPid, WaitSeconds);
|
||||
esyslog("ERROR: thread %ld won't end (waited %d seconds) - cancelling it...", childTid, WaitSeconds);
|
||||
}
|
||||
pthread_cancel(thread);
|
||||
pthread_cancel(childTid);
|
||||
}
|
||||
|
||||
void cThread::WakeUp(void)
|
||||
{
|
||||
kill(parentPid, SIGIO); // makes any waiting 'select()' call return immediately
|
||||
pthread_kill(parentTid, SIGIO); // makes any waiting 'select()' call return immediately
|
||||
}
|
||||
|
||||
bool cThread::EmergencyExit(bool Request)
|
||||
|
20
thread.h
20
thread.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: thread.h 1.15 2003/05/03 14:03:36 kls Exp $
|
||||
* $Id: thread.h 1.20 2004/01/03 16:58:50 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __THREAD_H
|
||||
@ -28,11 +28,20 @@ public:
|
||||
//void Signal(void);
|
||||
};
|
||||
|
||||
class cRwLock {
|
||||
private:
|
||||
pthread_rwlock_t rwlock;
|
||||
public:
|
||||
cRwLock(bool PreferWriter = false);
|
||||
~cRwLock();
|
||||
bool Lock(bool Write, int TimeoutMs = 0);
|
||||
void Unlock(void);
|
||||
};
|
||||
|
||||
class cMutex {
|
||||
friend class cCondVar;
|
||||
private:
|
||||
pthread_mutex_t mutex;
|
||||
pid_t lockingPid;
|
||||
int locked;
|
||||
public:
|
||||
cMutex(void);
|
||||
@ -44,10 +53,10 @@ public:
|
||||
class cThread {
|
||||
friend class cThreadLock;
|
||||
private:
|
||||
pthread_t thread;
|
||||
pthread_t parentTid, childTid;
|
||||
cMutex mutex;
|
||||
pid_t parentPid, threadPid;
|
||||
bool running;
|
||||
char *description;
|
||||
static bool emergencyExitRequested;
|
||||
static bool signalHandlerInstalled;
|
||||
static void SignalHandler(int signum);
|
||||
@ -59,8 +68,9 @@ protected:
|
||||
virtual void Action(void) = 0;
|
||||
void Cancel(int WaitSeconds = 0);
|
||||
public:
|
||||
cThread(void);
|
||||
cThread(const char *Description = NULL);
|
||||
virtual ~cThread();
|
||||
void SetDescription(const char *Description, ...);
|
||||
bool Start(void);
|
||||
bool Active(void);
|
||||
static bool EmergencyExit(bool Request = false);
|
||||
|
20
timers.c
20
timers.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.c 1.6 2003/10/12 10:33:09 kls Exp $
|
||||
* $Id: timers.c 1.8 2003/12/27 13:10:04 kls Exp $
|
||||
*/
|
||||
|
||||
#include "timers.h"
|
||||
@ -44,14 +44,14 @@ cTimer::cTimer(bool Instant, bool Pause)
|
||||
snprintf(file, sizeof(file), "%s%s", Setup.MarkInstantRecord ? "@" : "", *Setup.NameInstantRecord ? Setup.NameInstantRecord : channel->Name());
|
||||
}
|
||||
|
||||
cTimer::cTimer(const cEventInfo *EventInfo)
|
||||
cTimer::cTimer(const cEvent *Event)
|
||||
{
|
||||
startTime = stopTime = 0;
|
||||
recording = pending = false;
|
||||
active = true;
|
||||
channel = Channels.GetByChannelID(EventInfo->GetChannelID(), true);
|
||||
time_t tstart = EventInfo->GetTime();
|
||||
time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60;
|
||||
channel = Channels.GetByChannelID(Event->ChannelID(), true);
|
||||
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);
|
||||
@ -64,9 +64,9 @@ cTimer::cTimer(const cEventInfo *EventInfo)
|
||||
priority = Setup.DefaultPriority;
|
||||
lifetime = Setup.DefaultLifetime;
|
||||
*file = 0;
|
||||
const char *Title = EventInfo->GetTitle();
|
||||
const char *Title = Event->Title();
|
||||
if (!isempty(Title))
|
||||
strn0cpy(file, EventInfo->GetTitle(), sizeof(file));
|
||||
strn0cpy(file, Event->Title(), sizeof(file));
|
||||
firstday = 0;
|
||||
summary = NULL;
|
||||
}
|
||||
@ -216,8 +216,10 @@ bool cTimer::Parse(const char *s)
|
||||
strn0cpy(file, filebuffer, MaxFileName);
|
||||
strreplace(file, '|', ':');
|
||||
strreplace(summary, '|', '\n');
|
||||
tChannelID cid = tChannelID::FromString(channelbuffer);
|
||||
channel = cid.Valid() ? Channels.GetByChannelID(cid, true) : Channels.GetByNumber(atoi(channelbuffer));
|
||||
if (isnumber(channelbuffer))
|
||||
channel = Channels.GetByNumber(atoi(channelbuffer));
|
||||
else
|
||||
channel = Channels.GetByChannelID(tChannelID::FromString(channelbuffer), true);
|
||||
if (!channel) {
|
||||
esyslog("ERROR: channel %s not defined", channelbuffer);
|
||||
result = false;
|
||||
|
6
timers.h
6
timers.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: timers.h 1.5 2003/05/11 13:35:53 kls Exp $
|
||||
* $Id: timers.h 1.6 2003/12/13 13:04:21 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __TIMERS_H
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
#include "channels.h"
|
||||
#include "config.h"
|
||||
#include "eit.h"
|
||||
#include "epg.h"
|
||||
#include "tools.h"
|
||||
|
||||
enum eTimerActive { taInactive = 0,
|
||||
@ -39,7 +39,7 @@ private:
|
||||
char *summary;
|
||||
public:
|
||||
cTimer(bool Instant = false, bool Pause = false);
|
||||
cTimer(const cEventInfo *EventInfo);
|
||||
cTimer(const cEvent *Event);
|
||||
virtual ~cTimer();
|
||||
cTimer& operator= (const cTimer &Timer);
|
||||
virtual bool operator< (const cListObject &ListObject);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: transfer.c 1.14 2003/08/31 12:19:16 kls Exp $
|
||||
* $Id: transfer.c 1.15 2003/10/18 11:36:03 kls Exp $
|
||||
*/
|
||||
|
||||
#include "transfer.h"
|
||||
@ -19,6 +19,7 @@
|
||||
|
||||
cTransfer::cTransfer(int VPid, int APid1, int APid2, int DPid1, int DPid2)
|
||||
:cReceiver(0, -1, 5, VPid, APid1, APid2, DPid1, DPid2)
|
||||
,cThread("transfer")
|
||||
{
|
||||
ringBuffer = new cRingBufferLinear(VIDEOBUFSIZE, TS_SIZE * 2, true);
|
||||
remux = new cRemux(VPid, APid1, APid2, DPid1, DPid2);
|
||||
@ -66,8 +67,6 @@ void cTransfer::Receive(uchar *Data, int Length)
|
||||
|
||||
void cTransfer::Action(void)
|
||||
{
|
||||
dsyslog("transfer thread started (pid=%d)", getpid());
|
||||
|
||||
int PollTimeouts = 0;
|
||||
active = true;
|
||||
while (active) {
|
||||
@ -125,8 +124,6 @@ void cTransfer::Action(void)
|
||||
else
|
||||
usleep(1); // this keeps the CPU load low
|
||||
}
|
||||
|
||||
dsyslog("transfer thread ended (pid=%d)", getpid());
|
||||
}
|
||||
|
||||
void cTransfer::StripAudioPackets(uchar *b, int Length, uchar Except)
|
||||
|
43
vdr.5
43
vdr.5
@ -8,7 +8,7 @@
|
||||
.\" License as specified in the file COPYING that comes with the
|
||||
.\" vdr distribution.
|
||||
.\"
|
||||
.\" $Id: vdr.5 1.20 2003/05/29 11:58:57 kls Exp $
|
||||
.\" $Id: vdr.5 1.21 2004/01/02 15:24:21 kls Exp $
|
||||
.\"
|
||||
.TH vdr 5 "1 Jun 2003" "1.2.0" "Video Disk Recorder Files"
|
||||
.SH NAME
|
||||
@ -45,7 +45,7 @@ Such a delimiter will not appear in the Channels menu.
|
||||
A \fBchannel definition\fR is a line with channel data, where the fields
|
||||
are separated by ':' characters. Example:
|
||||
|
||||
\fBRTL:12188:h:S19.2E:27500:163:104:105:0:12003:0:0:0\fR
|
||||
\fBRTL,RTL Television:12188:h:S19.2E:27500:163:104:105:0:12003:1:1089:0\fR
|
||||
|
||||
The line number of a channel definition (not counting group separators,
|
||||
and based on a possible previous '@...' parameter)
|
||||
@ -57,6 +57,13 @@ to right):
|
||||
.B Name
|
||||
The channel's name (if the name originally contains a ':' character
|
||||
it has to be replaced by '|').
|
||||
Some tv stations provide a way of deriving a "short name" from the
|
||||
channel name, which can be used in situations where there is not
|
||||
much space for displaying a long name. If a short name is available
|
||||
for this channel, it preceeds the full name and is delimited by a comma,
|
||||
as in
|
||||
|
||||
\fBRTL,RTL Television:...\fR
|
||||
.TP
|
||||
.B Frequency
|
||||
The transponder frequency (as an integer). For DVB-S this value is in MHz. For DVB-C
|
||||
@ -119,23 +126,33 @@ the audio PIDs, separated by a semicolon, as in
|
||||
The teletext PID.
|
||||
.TP
|
||||
.B Conditional access
|
||||
An integer defining how this channel can be accessed:
|
||||
A hexadecimal integer defining how this channel can be accessed:
|
||||
.TS
|
||||
tab (@);
|
||||
l l.
|
||||
\fB0\fR@Free To Air
|
||||
\fB1...4\fR@explicitly requires the DVB card with the given number
|
||||
\fB>=100\fR@requires a specific decryption method defined in \fIca.conf\fR
|
||||
\fB0000\fR@Free To Air
|
||||
\fB0001...000F\fR@explicitly requires the device with the given number
|
||||
\fB0010...00FF\fR@reserved for user defined assignments defined in \fIca.conf\fR
|
||||
\fB0100...FFFF\fR@specific decryption methods as broadcast in the data stream\fR
|
||||
.TE
|
||||
Values in the range 0001...00FF will not be overwritten, all other values
|
||||
will be automatically replaced by the actual CA system identifiers received
|
||||
from the data stream. If there is more than one CA system id broadcast, they
|
||||
will be separated by commas, as in
|
||||
|
||||
.B ...:1702,1722,1801:...
|
||||
|
||||
The values are in hex because that's the way they are defined in the "ETR 162"
|
||||
document. Leading zeros may be omitted.
|
||||
.TP
|
||||
.B SID
|
||||
The Service ID of this channel.
|
||||
.TP
|
||||
.B NID
|
||||
The Network ID of this channel (for future use, currently always 0).
|
||||
The Network ID of this channel.
|
||||
.TP
|
||||
.B TID
|
||||
The Transport stream ID of this channel (for future use, currently always 0).
|
||||
The Transport stream ID of this channel.
|
||||
.TP
|
||||
.B RID
|
||||
The Radio ID of this channel (typically 0, may be used to distinguish channels where
|
||||
@ -144,12 +161,12 @@ NID, TID and SID are all equal).
|
||||
A particular channel can be uniquely identified by its \fBchannel\ ID\fR,
|
||||
which is a string that looks like this:
|
||||
|
||||
\fBS19.2E-0-12188-12003-0\fR
|
||||
\fBS19.2E-1-1089-12003-0\fR
|
||||
|
||||
The components of this string are the \fBSource\fR (S19.2E), \fBFrequency\fR
|
||||
(12188, MHz) and \fBSID\fR (12003) as defined above. The parts that are currently
|
||||
\fB0\fR are reserved for future use (the last part can be omitted if it is \fB0\fR,
|
||||
so the above example could also be written as \fBS19.2E-0-12188-12003\fR).
|
||||
The components of this string are the \fBSource\fR (S19.2E), \fBNID\fR
|
||||
(1), \fBTID\fR (1089), \fBSID\fR (12003) and \fBRID\fR (0) as defined above.
|
||||
The last part can be omitted if it is \fB0\fR,
|
||||
so the above example could also be written as S19.2E-1-1089-12003).
|
||||
.br
|
||||
The \fBchannel\ ID\fR is used in the \fItimers.conf\fR and \fIepg.data\fR
|
||||
files to properly identify the channels.
|
||||
|
48
vdr.c
48
vdr.c
@ -22,7 +22,7 @@
|
||||
*
|
||||
* The project's page is at http://www.cadsoft.de/vdr
|
||||
*
|
||||
* $Id: vdr.c 1.169 2003/09/14 09:36:54 kls Exp $
|
||||
* $Id: vdr.c 1.172 2004/01/04 11:12:05 kls Exp $
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
@ -39,6 +39,7 @@
|
||||
#include "diseqc.h"
|
||||
#include "dvbdevice.h"
|
||||
#include "eitscan.h"
|
||||
#include "epg.h"
|
||||
#include "i18n.h"
|
||||
#include "interface.h"
|
||||
#include "keys.h"
|
||||
@ -93,10 +94,12 @@ int main(int argc, char *argv[])
|
||||
#define DEFAULTSVDRPPORT 2001
|
||||
#define DEFAULTWATCHDOG 0 // seconds
|
||||
#define DEFAULTPLUGINDIR PLUGINDIR
|
||||
#define DEFAULTEPGDATAFILENAME "epg.data"
|
||||
|
||||
int SVDRPport = DEFAULTSVDRPPORT;
|
||||
const char *AudioCommand = NULL;
|
||||
const char *ConfigDirectory = NULL;
|
||||
const char *EpgDataFileName = DEFAULTEPGDATAFILENAME;
|
||||
bool DisplayHelp = false;
|
||||
bool DisplayVersion = false;
|
||||
bool DaemonMode = false;
|
||||
@ -146,7 +149,7 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr, "vdr: invalid DVB device number: %s\n", optarg);
|
||||
return 2;
|
||||
break;
|
||||
case 'E': cSIProcessor::SetEpgDataFileName(*optarg != '-' ? optarg : NULL);
|
||||
case 'E': EpgDataFileName = (*optarg != '-' ? optarg : NULL);
|
||||
break;
|
||||
case 'h': DisplayHelp = true;
|
||||
break;
|
||||
@ -239,7 +242,8 @@ int main(int argc, char *argv[])
|
||||
" there may be several -D options (default: all DVB\n"
|
||||
" devices will be used)\n"
|
||||
" -E FILE --epgfile=FILE write the EPG data into the given FILE (default is\n"
|
||||
" %s); use '-E-' to disable this\n"
|
||||
" '%s' in the video directory)\n"
|
||||
" '-E-' disables this\n"
|
||||
" if FILE is a directory, the default EPG file will be\n"
|
||||
" created in that directory\n"
|
||||
" -h, --help print this help and exit\n"
|
||||
@ -261,7 +265,7 @@ int main(int argc, char *argv[])
|
||||
" -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
|
||||
" seconds (default: %d); '0' disables the watchdog\n"
|
||||
"\n",
|
||||
cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'",
|
||||
DEFAULTEPGDATAFILENAME,
|
||||
DEFAULTPLUGINDIR,
|
||||
DEFAULTSVDRPPORT,
|
||||
VideoDirectory,
|
||||
@ -358,6 +362,19 @@ int main(int argc, char *argv[])
|
||||
))
|
||||
return 2;
|
||||
|
||||
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
|
||||
|
||||
// EPG data:
|
||||
|
||||
if (EpgDataFileName) {
|
||||
if (DirectoryOk(EpgDataFileName))
|
||||
EpgDataFileName = AddDirectory(EpgDataFileName, DEFAULTEPGDATAFILENAME);
|
||||
else if (*EpgDataFileName != '/' && *EpgDataFileName != '.')
|
||||
EpgDataFileName = AddDirectory(VideoDirectory, EpgDataFileName);
|
||||
}
|
||||
cSchedules::SetEpgDataFileName(EpgDataFileName);
|
||||
cSchedules::Read();
|
||||
|
||||
// DVB interfaces:
|
||||
|
||||
cDvbDevice::Initialize();
|
||||
@ -436,8 +453,6 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
cDevice::PrimaryDevice()->SetVolume(Setup.CurrentVolume, true);
|
||||
|
||||
cSIProcessor::Read();
|
||||
|
||||
// Signal handlers:
|
||||
|
||||
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
|
||||
@ -496,6 +511,25 @@ int main(int argc, char *argv[])
|
||||
dsyslog("max. latency time %d seconds", MaxLatencyTime);
|
||||
}
|
||||
}
|
||||
// Handle channel modifications:
|
||||
if (!Channels.BeingEdited() && Channels.Modified()) {
|
||||
if (Channels.Lock(false, 100)) {
|
||||
Channels.Save(); //XXX only after user changes???
|
||||
Timers.Save();
|
||||
for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
|
||||
if (Channel && Channel->Modification(CHANNELMOD_RETUNE)) {
|
||||
cRecordControls::ChannelDataModified(Channel);
|
||||
if (Channel->Number() == cDevice::CurrentChannel()) {
|
||||
if (!cDevice::PrimaryDevice()->Replaying()) {
|
||||
isyslog("retuning due to modification of channel %d", Channel->Number());
|
||||
Channels.SwitchTo(Channel->Number());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Channels.Unlock();
|
||||
}
|
||||
}
|
||||
// Channel display:
|
||||
if (!EITScanner.Active() && cDevice::CurrentChannel() != LastChannel) {
|
||||
if (!Menu)
|
||||
@ -779,6 +813,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
// Disk housekeeping:
|
||||
RemoveDeletedRecordings();
|
||||
cSchedules::Cleanup();
|
||||
// Plugins housekeeping:
|
||||
PluginManager.Housekeeping();
|
||||
}
|
||||
@ -799,6 +834,7 @@ int main(int argc, char *argv[])
|
||||
Setup.Save();
|
||||
cDevice::Shutdown();
|
||||
PluginManager.Shutdown(true);
|
||||
ReportEpgBugFixStats();
|
||||
if (WatchdogTimeout > 0)
|
||||
dsyslog("max. latency time %d seconds", MaxLatencyTime);
|
||||
isyslog("exiting");
|
||||
|
Loading…
x
Reference in New Issue
Block a user