1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Changed section handling; replaced 'libdtv' with 'libsi'

This commit is contained in:
Klaus Schmidinger 2003-12-22 13:29:24 +01:00
parent 84b99ea810
commit 7ff59171e3
51 changed files with 2118 additions and 9985 deletions

View File

@ -642,6 +642,7 @@ Marcel Wiesweg <marcel.wiesweg@gmx.de>
for reporting a problem with cReceivers that want to receive from PIDs that are for reporting a problem with cReceivers that want to receive from PIDs that are
currently not transmitting currently not transmitting
for fixing volume display in case a plugin has its own OSD open 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> Torsten Herz <torsten.herz@web.de>
for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu for fixing a possible deadlock when using the "Blue" button in the "Schedules" menu

17
HISTORY
View File

@ -2393,7 +2393,7 @@ Video Disk Recorder Revision History
not loaded (suggested by Alexander Wetzel). not loaded (suggested by Alexander Wetzel).
- Fixed checking for VIDEO_STREAM_S in cRemux::SetBrokenLink() (thanks to Oliver - Fixed checking for VIDEO_STREAM_S in cRemux::SetBrokenLink() (thanks to Oliver
Endriss). 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). (suggested by Oliver Endriss).
- Made cOsdMenu::Display() virtual, which allows plugins to do some additional - Made cOsdMenu::Display() virtual, which allows plugins to do some additional
processing after calling the base class function (suggested by Jan Rieger). processing after calling the base class function (suggested by Jan Rieger).
@ -2470,7 +2470,7 @@ Video Disk Recorder Revision History
- Final release of version 1.2.6. - Final release of version 1.2.6.
2003-10-24: Version 1.3.0 2003-12-22: Version 1.3.0
- Changed thread handling to make it work with NPTL ("Native Posix Thread Library"). - Changed thread handling to make it work with NPTL ("Native Posix Thread Library").
Thanks to Jon Burgess, Andreas Schultz, Werner Fink and Stefan Huelswitt. Thanks to Jon Burgess, Andreas Schultz, Werner Fink and Stefan Huelswitt.
@ -2489,3 +2489,16 @@ Video Disk Recorder Revision History
provided by Alessio Sangalli). provided by Alessio Sangalli).
- Greek language texts now use iso8859-7 character set (thanks to Dimitrios - Greek language texts now use iso8859-7 character set (thanks to Dimitrios
Dimitrakos). 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').

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 1.60 2003/10/24 13:13:02 kls Exp $ # $Id: Makefile 1.61 2003/12/21 14:45:27 kls Exp $
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
@ -15,7 +15,7 @@ CXX ?= g++
CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual
DVBDIR = ../DVB DVBDIR = ../DVB
DTVDIR = ./libdtv LSIDIR = ./libsi
MANDIR = /usr/local/man MANDIR = /usr/local/man
BINDIR = /usr/local/bin BINDIR = /usr/local/bin
@ -31,12 +31,12 @@ DOXYFILE = Doxyfile
INCLUDES = -I$(DVBDIR)/include 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\ 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\ 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 player.o plugin.o rcu.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 sources.o\ receiver.o recorder.o recording.o remote.o remux.o ringbuffer.o sections.o sources.o\
spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o spu.o status.o svdrp.o thread.o timers.o tools.o transfer.o vdr.o videodir.o
FIXFONT_ISO8859_1 = -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
@ -89,8 +89,8 @@ $(DEPFILE): Makefile
# The main program: # The main program:
vdr: $(OBJS) $(DTVLIB) vdr: $(OBJS) $(SILIB)
$(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(DTVLIB) -o vdr $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) -ljpeg -lpthread -ldl $(LIBDIRS) $(SILIB) -o vdr
# The font files: # The font files:
@ -112,10 +112,10 @@ fontsml_iso8859_1.c:
genfontfile: genfontfile.c genfontfile: genfontfile.c
$(CC) $(CFLAGS) -o $@ -L/usr/X11R6/lib $< -lX11 $(CC) $(CFLAGS) -o $@ -L/usr/X11R6/lib $< -lX11
# The libdtv library: # The libsi library:
$(DTVLIB) $(DTVDIR)/libdtv.h: $(SILIB):
$(MAKE) -C $(DTVDIR) all $(MAKE) -C $(LSIDIR) all
# The 'include' directory (for plugins): # The 'include' directory (for plugins):
@ -154,7 +154,7 @@ srcdoc:
# Housekeeping: # Housekeeping:
clean: clean:
$(MAKE) -C $(DTVDIR) clean $(MAKE) -C $(LSIDIR) clean
-rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~ -rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~
-rm -rf include -rm -rf include
-rm -rf srcdoc -rm -rf srcdoc

View File

@ -6,7 +6,7 @@
<center><h1>The VDR Plugin System</h1></center> <center><h1>The VDR Plugin System</h1></center>
<center><b>Version 1.2.6</b></center> <center><b>Version 1.3</b></center>
<p> <p>
<center> <center>
Copyright &copy; 2003 Klaus Schmidinger<br> Copyright &copy; 2003 Klaus Schmidinger<br>
@ -14,9 +14,12 @@ Copyright &copy; 2003 Klaus Schmidinger<br>
<a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a> <a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a>
</center> </center>
<p> <p>
<!--X1.1.32--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.2.6--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.2.6 are marked like this. 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>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.3.0 are marked like this.
<!--X1.3.0--></td></tr></table>
<p> <p>
VDR provides an easy to use plugin interface that allows additional functionality 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. 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="#Status monitor">Status monitor</a>
<li><a href="#Players">Players</a> <li><a href="#Players">Players</a>
<li><a href="#Receivers">Receivers</a> <li><a href="#Receivers">Receivers</a>
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</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="#The On Screen Display">The On Screen Display</a>
<li><a href="#Devices">Devices</a> <li><a href="#Devices">Devices</a>
<li><a href="#Dolby Digital">Dolby Digital</a> <li><a href="#Dolby Digital">Dolby Digital</a>
@ -112,7 +118,7 @@ No other characters should be used here.
<p> <p>
A plugin can access its name through the (non virtual) member function 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); const char *Name(void);
</pre></td></tr></table><p> </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 VDR source directory. Inside this directory the following subdirectory structure
is used: is used:
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
VDR/PLUGINS/src VDR/PLUGINS/src
VDR/PLUGINS/src/hello VDR/PLUGINS/src/hello
VDR/PLUGINS/lib 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 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 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 ln -s hello-0.0.1 hello
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -226,7 +232,7 @@ If your plugin shall not be accessible through VDR's main menu, simply remove
<p> <p>
At the end of the plugin's source file you will find a line that looks like this: 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); VDRPLUGINCREATOR(cPluginHello);
</pre></td></tr></table><p> </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 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 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 #ifndef __I18N_H
#define __I18N_H #define __I18N_H
@ -274,7 +280,7 @@ and two replacing the dot).
The constructor and destructor of a plugin are defined as 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); cPlugin(void);
virtual ~cPlugin(); virtual ~cPlugin();
</pre></td></tr></table><p> </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. 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 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; virtual const char *Version(void) = 0;
</pre></td></tr></table><p> </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. be as long as really necessary, and shall not contain the plugin's name itself.
Here's an example: 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"; static const char *VERSION = "0.0.1";
const char *cPluginHello::Version(void) 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 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; virtual const char *Description(void) = 0;
</pre></td></tr></table><p> </pre></td></tr></table><p>
which returns a short, one line description of the plugin's purpose: 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"; static const char *DESCRIPTION = "A friendly greeting";
virtual const char *Description(void) 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 If a plugin wants to react on command line arguments, it needs to implement
the function the function
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
virtual bool ProcessArgs(int argc, char *argv[]); virtual bool ProcessArgs(int argc, char *argv[]);
</pre></td></tr></table><p> </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 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: 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[]) bool cPluginHello::ProcessArgs(int argc, char *argv[])
{ {
// Implement command line argument processing here if applicable. // 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 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); virtual const char *CommandLineHelp(void);
</pre></td></tr></table><p> </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 The returned string should contain the command line help for this plugin, formatted
in the same way as done by VDR itself: 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) const char *cPluginHello::CommandLineHelp(void)
{ {
// Return a string that describes all known command line options. // 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>, thread of its own), or wants to make use of <a href="#Internationalization">internationalization</a>,
it needs to implement one of the functions 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 Initialize(void);
virtual bool Start(void); virtual bool Start(void);
</pre></td></tr></table><p> </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 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 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); virtual const char *MainMenuEntry(void);
</pre></td></tr></table><p> </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 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: 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"; static const char *MAINMENUENTRY = "Hello";
const char *cPluginHello::MainMenuEntry(void) 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 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); virtual cOsdObject *MainMenuAction(void);
</pre></td></tr></table><p> </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 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 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); virtual void Housekeeping(void);
</pre></td></tr></table><p> </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 If a plugin requires its own setup parameters, it needs to implement the following
functions to handle these parameters: 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 cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value); virtual bool SetupParse(const char *Name, const char *Value);
</pre></td></tr></table><p> </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). the log file (and program execution will continue).
A possible implementation of <tt>SetupParse()</tt> could look like this: 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) bool cPluginHello::SetupParse(const char *Name, const char *Value)
{ {
// Parse your own setup parameters and store their values. // Parse your own setup parameters and store their values.
@ -620,7 +626,7 @@ plugins need not worry about this.
<p> <p>
To store its values in the global setup, a plugin has to call the function 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); void SetupStore(const char *Name, <i>type</i> Value);
</pre></td></tr></table><p> </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>cMenuSetupPage</tt> and implement its constructor and the pure virtual
<tt>Store()</tt> member function: <tt>Store()</tt> member function:
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
int GreetingTime = 3; int GreetingTime = 3;
int UseAlternateGreeting = false; 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 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 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); const char *ConfigDirectory(const char *PluginName = NULL);
</pre></td></tr></table><p> </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 the <tt>ConfigDirectory()</tt> function can be given an additional string that will
be appended to the returned directory name, as in 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()); const char *MyConfigDir = ConfigDirectory(Name());
</pre></td></tr></table><p> </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 class. This allows it to be called even from outside any member function of the derived
plugin class, by writing plugin class, by writing
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
const char *MyConfigDir = cPlugin::ConfigDirectory(); const char *MyConfigDir = cPlugin::ConfigDirectory();
</pre></td></tr></table><p> </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 If a plugin displays texts to the user, it should implement internationalized
versions of these texts and call the function 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); void RegisterI18n(const tI18nPhrase * const Phrases);
</pre></td></tr></table><p> </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> 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: 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[] = { const tI18nPhrase Phrases[] = {
{ "Hello world!", { "Hello world!",
"Hallo Welt!", "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 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: 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!"); const char *s = tr("Hello world!");
</pre></td></tr></table><p> </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 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 vdr -Phello
</pre></td></tr></table><p> </pre></td></tr></table><p>
If the plugin accepts command line options, they are given as part of the argument 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: 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" vdr -P"hello -a abc -b"
</pre></td></tr></table><p> </pre></td></tr></table><p>
Any number of plugins can be loaded this way, each with its own <b><tt>-P</tt></b> option: 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 vdr -P"hello -a abc -b" -Pdvd -Pmp3
</pre></td></tr></table><p> </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 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: 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 vdr -L/usr/lib/vdr -Phello
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -879,14 +885,14 @@ provides the target <tt>dist</tt>, which does this for you.
<p> <p>
Simply change into your source directory and execute <tt>make dist</tt>: 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 cd VDR/PLUGINS/src/hello
make dist make dist
</pre></td></tr></table><p> </pre></td></tr></table><p>
After this you should find a file named like 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 vdr-hello-0.0.1.tgz
</pre></td></tr></table><p> </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 If a plugin wants to get informed on various events in VDR, it can derive a class from
<tt>cStatus</tt>, as in <tt>cStatus</tt>, as in
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
#include &lt;vdr/status.h&gt; #include &lt;vdr/status.h&gt;
class cMyStatusMonitor : public cStatus { 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 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: 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 &lt;vdr/plugin.h&gt; #include &lt;vdr/plugin.h&gt;
class cPluginStatus : public cPlugin { class cPluginStatus : public cPlugin {
@ -975,7 +981,7 @@ the functions you actually want to use.
Implementing a player is a two step process. Implementing a player is a two step process.
First you need the actual player class, which is derived from the abstract <tt>cPlayer</tt>: 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 &lt;vdr/player.h&gt; #include &lt;vdr/player.h&gt;
class cMyPlayer : public cPlayer { 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 thread which, e.g., reads data from a file, you can additionally derive your class from
<tt>cThread</tt> and implement the necessary functionality: <tt>cThread</tt> and implement the necessary functionality:
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
#include &lt;vdr/player.h&gt; #include &lt;vdr/player.h&gt;
class cMyPlayer : public cPlayer, cThread { class cMyPlayer : public cPlayer, cThread {
@ -1009,7 +1015,7 @@ its own player for the VDR recordings.
<p> <p>
To play the video data, the player needs to call its member function 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); int PlayVideo(const uchar *Data, int Length);
</pre></td></tr></table><p> </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. DVB device doesn't run out of data.
To avoid busy loops the player should call its member function 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 &amp;Poller, int TimeoutMs = 0); bool DevicePoll(cPoller &amp;Poller, int TimeoutMs = 0);
</pre></td></tr></table><p> </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 If the player can provide more than a single audio track, it can implement the
following functions to make them available: 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 int NumAudioTracks(void) const;
virtual const char **GetAudioTracks(int *CurrentTrack = NULL); virtual const char **GetAudioTracks(int *CurrentTrack = NULL);
virtual void SetAudioTrack(int Index); 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, If there is an additional audio track that has to be replayed with external hardware,
the player shall call its member function 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); void PlayAudio(const uchar *Data, int Length);
</pre></td></tr></table><p> </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 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: 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 &lt;vdr/player.h&gt; #include &lt;vdr/player.h&gt;
class cMyControl : public cControl { 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 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: 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) cMyControl::cMyControl(void)
:cControl(player = new cMyPlayer) :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 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 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); cControl::Launch(new cMyControl);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1104,7 +1110,7 @@ use the primary DVB device, or the user decides to start a different replay).
<p> <p>
The <tt>cPlayer</tt> class has a member function 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); void DeviceStillPicture(const uchar *Data, int Length);
</pre></td></tr></table><p> </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 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: object derived from the <tt>cReceiver</tt> class:
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
#include &lt;vdr/receiver.h&gt; #include &lt;vdr/receiver.h&gt;
class cMyReceiver : public cReceiver, cThread { 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 Once a <tt>cReceiver</tt> has been created, it needs to be <i>attached</i> to
a <tt>cDevice</tt>: a <tt>cDevice</tt>:
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
cMyReceiver *Receiver = new cMyReceiver(123); cMyReceiver *Receiver = new cMyReceiver(123);
cDevice::ActualDevice()-&gt;AttachReceiver(Receiver); cDevice::ActualDevice()-&gt;AttachReceiver(Receiver);
@ -1201,6 +1207,49 @@ Mode</i>).
If the <tt>cReceiver</tt> isn't needed any more, it may simply be <i>deleted</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>. and will automatically detach itself from the <tt>cDevice</tt>.
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</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 &lt;vdr/filter.h&gt;
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()-&gt;AttachFilter(Filter);
</pre></td></tr></table><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> <a name="The On Screen Display"><hr><h2>The On Screen Display</h2>
<center><i><b>Express yourself</b></i></center><p> <center><i><b>Express yourself</b></i></center><p>
@ -1213,7 +1262,7 @@ windows and color depths.
If a plugin needs to have total control over the OSD, it can call the If a plugin needs to have total control over the OSD, it can call the
static function static function
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
#include &lt;vdr/osd.h&gt; #include &lt;vdr/osd.h&gt;
cOsdBase *MyOsd = cOsd::OpenRaw(x, y); cOsdBase *MyOsd = cOsd::OpenRaw(x, y);
@ -1223,7 +1272,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 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 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-&gt;Create(...); MyOsd-&gt;Create(...);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1247,7 +1296,7 @@ stream and displays it, for instance, on an existing graphics adapter.
<p> <p>
To implement an additional device, a plugin must derive a class from cDevice: 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 &lt;vdr/device.h&gt; #include &lt;vdr/device.h&gt;
class cMyDevice : public cDevice { class cMyDevice : public cDevice {
@ -1266,7 +1315,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 If the new device can receive, it most likely needs to provide a way of
selecting which channel it shall tune to: 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 ProvidesSource(int Source) const;
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL); virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL);
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView); virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView);
@ -1281,7 +1330,7 @@ repectively.
If the device can provide more than a single audio track, it can implement the If the device can provide more than a single audio track, it can implement the
following functions to make them available: 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 int NumAudioTracksDevice(void) const;
virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const; virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const;
virtual void SetAudioTrackDevice(int Index); virtual void SetAudioTrackDevice(int Index);
@ -1292,7 +1341,7 @@ virtual void SetAudioTrackDevice(int Index);
<p> <p>
A device that can be used for recording must implement the functions 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 SetPid(cPidHandle *Handle, int Type, bool On);
virtual bool OpenDvr(void); virtual bool OpenDvr(void);
virtual void CloseDvr(void); virtual void CloseDvr(void);
@ -1308,7 +1357,7 @@ must deliver exactly one such packet (if one is currently available).
If this device allows receiving several different data streams, it can If this device allows receiving several different data streams, it can
implement implement
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
virtual bool CanBeReUsed(int Frequency, int Vpid); virtual bool CanBeReUsed(int Frequency, int Vpid);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1318,13 +1367,13 @@ to indicate this to VDR.
<p> <p>
The functions to implement replaying capabilites are 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 HasDecoder(void) const;
virtual bool CanReplay(void) const; virtual bool CanReplay(void) const;
virtual bool SetPlayMode(ePlayMode PlayMode); virtual bool SetPlayMode(ePlayMode PlayMode);
<!--X1.1.32--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.2.6--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
virtual int64_t GetSTC(void); virtual int64_t GetSTC(void);
<!--X1.1.32--></td></tr></table> <!--X1.2.6--></td></tr></table>
virtual void TrickSpeed(int Speed); virtual void TrickSpeed(int Speed);
virtual void Clear(void); virtual void Clear(void);
virtual void Play(void); virtual void Play(void);
@ -1338,12 +1387,39 @@ virtual int PlayVideo(const uchar *Data, int Length);
In addition, the following functions may be implemented to provide further In addition, the following functions may be implemented to provide further
functionality: 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 bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int Si
virtual void SetVideoFormat(bool VideoFormat16_9); virtual void SetVideoFormat(bool VideoFormat16_9);
virtual void SetVolumeDevice(int Volume); virtual void SetVolumeDevice(int Volume);
</pre></td></tr></table><p> </pre></td></tr></table><p>
<!--X1.3.0--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</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> <p>
<b>On Screen Display</b> <b>On Screen Display</b>
<p> <p>
@ -1351,7 +1427,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 that is supposed to be used as a primary device should do), it can implement
the function the function
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
virtual cOsdBase *NewOsd(int x, int y); virtual cOsdBase *NewOsd(int x, int y);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1391,7 +1467,7 @@ audio replay facility.
To implement a new audio output facility, simply derive a class from <tt>cAudio</tt>, To implement a new audio output facility, simply derive a class from <tt>cAudio</tt>,
as in as in
<p><table><tr><td bgcolor=#F0F0F0><pre><br> <p><table><tr><td bgcolor=#F0F0F0><pre>
#include &lt;vdr/audio.h&gt; #include &lt;vdr/audio.h&gt;
#include &lt;vdr/thread.h&gt; #include &lt;vdr/thread.h&gt;
@ -1435,7 +1511,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 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 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); cRemote::Put(kUp);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1447,7 +1523,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 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 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 &lt;vdr/remote.h&gt; #include &lt;vdr/remote.h&gt;
#include &lt;vdr/thread.h&gt; #include &lt;vdr/thread.h&gt;
@ -1472,7 +1548,7 @@ when the program ends).
<p> <p>
The constructor of your remote control class should look like this 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) cMyRemote::cMyRemote(const char *Name)
:cRemote(Name) :cRemote(Name)
{ {
@ -1492,7 +1568,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 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 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); virtual bool Ready(void);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1513,7 +1589,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 readily available next time VDR starts (without having to go through the initialization
procedure again) it can use the <tt>cRemote</tt> member functions 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); void PutSetup(const char *Setup);
const char *GetSetup(void); const char *GetSetup(void);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1527,7 +1603,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 expressed as a character string. So whatever data your remote control provides
needs to be given to the base class by calling 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); Put(const char *Code, bool Repeat = false, bool Release = false);
</pre></td></tr></table><p> </pre></td></tr></table><p>
@ -1538,7 +1614,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, 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: 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); Put(uint64 Code, bool Repeat = false, bool Release = false);
</pre></td></tr></table><p> </pre></td></tr></table><p>

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # 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. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the 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 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): ### The object files (add further files here):

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # 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. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the 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 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): ### The object files (add further files here):

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # 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. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the 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 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): ### The object files (add further files here):

View File

@ -1,7 +1,7 @@
# #
# Makefile for a Video Disk Recorder plugin # 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. # The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the 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 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): ### The object files (add further files here):

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.c 1.49 2003/11/07 14:15:10 kls Exp $ * $Id: device.c 1.50 2003/12/22 10:53:45 kls Exp $
*/ */
#include "device.h" #include "device.h"
@ -13,7 +13,6 @@
#include <sys/mman.h> #include <sys/mman.h>
#include "audio.h" #include "audio.h"
#include "channels.h" #include "channels.h"
#include "eit.h"
#include "i18n.h" #include "i18n.h"
#include "player.h" #include "player.h"
#include "receiver.h" #include "receiver.h"
@ -45,6 +44,10 @@ cDevice::cDevice(void)
mute = false; mute = false;
volume = Setup.CurrentVolume; volume = Setup.CurrentVolume;
sectionHandler = NULL;
eitFilter = NULL;
patFilter = NULL;
ciHandler = NULL; ciHandler = NULL;
player = NULL; player = NULL;
@ -65,6 +68,9 @@ cDevice::~cDevice()
for (int i = 0; i < MAXRECEIVERS; i++) for (int i = 0; i < MAXRECEIVERS; i++)
Detach(receiver[i]); Detach(receiver[i]);
delete ciHandler; delete ciHandler;
delete eitFilter;
delete patFilter;
delete sectionHandler;
} }
void cDevice::SetUseDevice(int n) void cDevice::SetUseDevice(int n)
@ -313,6 +319,31 @@ bool cDevice::SetPid(cPidHandle *Handle, int Type, bool On)
return false; return false;
} }
void cDevice::StartSectionHandler(void)
{
if (!sectionHandler) {
sectionHandler = new cSectionHandler(this);
AttachFilter(eitFilter = new cEitFilter);
AttachFilter(patFilter = new cPatFilter);
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 bool cDevice::ProvidesSource(int Source) const
{ {
return false; return false;
@ -401,15 +432,25 @@ eSetChannelResult cDevice::SetChannel(const cChannel *Channel, bool LiveView)
} }
else { else {
cStatus::MsgChannelSwitch(this, 0); // only report status if we are actually going to switch the channel 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->Frequency());
sectionHandler->SetStatus(true);
}
}
else
Result = scrFailed; Result = scrFailed;
} }
if (Result == scrOk) { if (Result == scrOk) {
if (LiveView && IsPrimaryDevice()) { if (LiveView && IsPrimaryDevice())
cSIProcessor::SetCurrentChannelID(Channel->GetChannelID());
currentChannel = Channel->Number(); currentChannel = Channel->Number();
}
cStatus::MsgChannelSwitch(this, Channel->Number()); // only report status if channel switch successfull cStatus::MsgChannelSwitch(this, Channel->Number()); // only report status if channel switch successfull
} }

View File

@ -4,13 +4,17 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.h 1.35 2003/11/07 13:15:45 kls Exp $ * $Id: device.h 1.36 2003/12/22 10:52:39 kls Exp $
*/ */
#ifndef __DEVICE_H #ifndef __DEVICE_H
#define __DEVICE_H #define __DEVICE_H
#include "ci.h" #include "ci.h"
#include "eit.h"
#include "filter.h"
#include "pat.h"
#include "sections.h"
#include "thread.h" #include "thread.h"
#include "tools.h" #include "tools.h"
@ -222,6 +226,26 @@ protected:
///< Type indicates some special types of PIDs, which the device may ///< Type indicates some special types of PIDs, which the device may
///< need to set in a specific way. ///< need to set in a specific way.
// Section filter facilities
private:
cSectionHandler *sectionHandler;
cEitFilter *eitFilter;
cPatFilter *patFilter;
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: // Common Interface facilities:
protected: protected:

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 1.72 2003/11/09 11:19:00 kls Exp $ * $Id: dvbdevice.c 1.73 2003/12/22 10:52:24 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -274,7 +274,7 @@ void cDvbTuner::Action(void)
if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed
for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) { for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) {
uchar buffer[2048]; uchar buffer[2048];
int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer); int length = GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer);
if (length > 0) { if (length > 0) {
cCiCaPmt CaPmt(channel.Sid()); cCiCaPmt CaPmt(channel.Sid());
CaPmt.AddCaDescriptor(length, buffer); CaPmt.AddCaDescriptor(length, buffer);
@ -312,7 +312,6 @@ cDvbDevice::cDvbDevice(int n)
{ {
dvbTuner = NULL; dvbTuner = NULL;
frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
siProcessor = NULL;
spuDecoder = NULL; spuDecoder = NULL;
playMode = pmNone; playMode = pmNone;
@ -368,7 +367,6 @@ cDvbDevice::cDvbDevice(int n)
if (fd_frontend >= 0) { if (fd_frontend >= 0) {
dvb_frontend_info feinfo; dvb_frontend_info feinfo;
siProcessor = new cSIProcessor(DvbName(DEV_DVB_DEMUX, n));
if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) { if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) {
frontendType = feinfo.type; frontendType = feinfo.type;
ciHandler = cCiHandler::CreateCiHandler(DvbName(DEV_DVB_CA, n)); ciHandler = cCiHandler::CreateCiHandler(DvbName(DEV_DVB_CA, n));
@ -381,12 +379,13 @@ cDvbDevice::cDvbDevice(int n)
esyslog("ERROR: can't open DVB device %d", n); esyslog("ERROR: can't open DVB device %d", n);
aPid1 = aPid2 = 0; aPid1 = aPid2 = 0;
StartSectionHandler();
} }
cDvbDevice::~cDvbDevice() cDvbDevice::~cDvbDevice()
{ {
delete spuDecoder; delete spuDecoder;
delete siProcessor;
delete dvbTuner; delete dvbTuner;
// We're not explicitly closing any device files here, since this sometimes // We're not explicitly closing any device files here, since this sometimes
// caused segfaults. Besides, the program is about to terminate anyway... // caused segfaults. Besides, the program is about to terminate anyway...
@ -617,6 +616,30 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On)
return true; 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) void cDvbDevice::TurnOffLiveMode(void)
{ {
// Avoid noise while switching: // Avoid noise while switching:
@ -715,13 +738,6 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
TurnOnLivePIDs = false; TurnOnLivePIDs = false;
} }
// Stop SI filtering:
if (siProcessor) {
siProcessor->SetCurrentTransponder(0, 0);
siProcessor->SetStatus(false);
}
// Turn off live PIDs if necessary: // Turn off live PIDs if necessary:
if (TurnOffLivePIDs) if (TurnOffLivePIDs)
@ -746,13 +762,6 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
else if (StartTransferMode) else if (StartTransferMode)
cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), Channel->Apid2(), Channel->Dpid1(), Channel->Dpid2())); 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; return true;
} }
@ -829,16 +838,12 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX)); 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_AV_SYNC, true));
CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
if (siProcessor)
siProcessor->SetStatus(true);
break; break;
case pmAudioVideo: case pmAudioVideo:
if (playMode == pmNone) if (playMode == pmNone)
TurnOffLiveMode(); TurnOffLiveMode();
// continue with next... // continue with next...
case pmAudioOnlyBlack: case pmAudioOnlyBlack:
if (siProcessor)
siProcessor->SetStatus(false);
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo));
@ -847,8 +852,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
CHECK(ioctl(fd_video, VIDEO_PLAY)); CHECK(ioctl(fd_video, VIDEO_PLAY));
break; break;
case pmAudioOnly: case pmAudioOnly:
if (siProcessor)
siProcessor->SetStatus(false);
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
CHECK(ioctl(fd_audio, AUDIO_STOP, true)); CHECK(ioctl(fd_audio, AUDIO_STOP, true));
CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
@ -858,8 +861,6 @@ bool cDvbDevice::SetPlayMode(ePlayMode PlayMode)
CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false));
break; break;
case pmExtern_THIS_SHOULD_BE_AVOIDED: case pmExtern_THIS_SHOULD_BE_AVOIDED:
if (siProcessor)
siProcessor->SetStatus(false);
close(fd_video); close(fd_video);
close(fd_audio); close(fd_audio);
fd_video = fd_audio = -1; fd_video = fd_audio = -1;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.h 1.24 2003/11/07 13:17:13 kls Exp $ * $Id: dvbdevice.h 1.25 2003/12/21 14:04:00 kls Exp $
*/ */
#ifndef __DVBDEVICE_H #ifndef __DVBDEVICE_H
@ -14,7 +14,6 @@
#include <linux/dvb/version.h> #include <linux/dvb/version.h>
#include "device.h" #include "device.h"
#include "dvbspu.h" #include "dvbspu.h"
#include "eit.h"
#if DVB_API_VERSION != 3 #if DVB_API_VERSION != 3
#error VDR requires Linux DVB driver API version 3! #error VDR requires Linux DVB driver API version 3!
@ -71,6 +70,11 @@ protected:
protected: protected:
virtual bool SetPid(cPidHandle *Handle, int Type, bool On); 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 // Image Grab facilities
private: private:
@ -95,11 +99,6 @@ protected:
virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const; virtual const char **GetAudioTracksDevice(int *CurrentTrack = NULL) const;
virtual void SetAudioTrackDevice(int Index); virtual void SetAudioTrackDevice(int Index);
// EIT facilities
private:
cSIProcessor *siProcessor;
// Player facilities // Player facilities
protected: protected:

1544
eit.c

File diff suppressed because it is too large Load Diff

190
eit.h
View File

@ -1,186 +1,22 @@
/*************************************************************************** /*
eit.h - description * eit.h: EIT section filter
------------------- *
begin : Fri Aug 25 2000 * See the main source file 'vdr.c' for copyright information and
copyright : (C) 2000 by Robert Schneider * how to reach the author.
email : Robert.Schneider@web.de *
* $Id: eit.h 1.30 2003/12/21 14:51:50 kls Exp $
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/18 12:51:50 kls Exp $
***************************************************************************/
#ifndef __EIT_H #ifndef __EIT_H
#define __EIT_H #define __EIT_H
#include "channels.h" #include "filter.h"
#include "thread.h"
#include "tools.h"
#define MAXEPGBUGFIXLEVEL 2 class cEitFilter : public cFilter {
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)
protected: protected:
void SetTableID(unsigned char tableid); virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
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);
public: public:
~cEventInfo(); cEitFilter(void);
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);
}; };
class cSchedule : public cListObject { #endif //__EIT_H
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

669
epg.c Normal file
View File

@ -0,0 +1,669 @@
/*
* 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.1 2003/12/22 13:07:32 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;
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::SetTableID(uchar TableID)
{
tableID = TableID;
}
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 (*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) {
// VOX puts too much information into the ShortText and leaves 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
}
}
}
// VOX and VIVA 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());
}
}
}
// VOX and VIVA 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());
}
}
// Pro7 sometimes repeats the Title in the ShortText:
//
// Title
// Title
//
if (shortText && strcmp(title, shortText) == 0) {
free(shortText);
shortText = NULL;
EpgBugFixStat(3, ChannelID());
}
// ZDF.info puts 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;
}

130
epg.h Normal file
View File

@ -0,0 +1,130 @@
/*
* 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.1 2003/12/22 13:03:10 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
//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; }
const uchar TableID(void) const { return tableID; }
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 SetTableID(uchar TableID);
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
View 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
View 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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -1,189 +0,0 @@
/*
*
* xListFuncs.c: list handling functions of liblx
*
*
* $Revision: 1.1 $
* $Date: 2001/08/15 10:00: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.
*
*/
#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);
}

View File

@ -1,624 +0,0 @@
/*
*
* xMemMgt.c: memory management functions of liblx
*
*
* $Revision: 1.1 $
* $Date: 2001/08/15 10:00: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.
*
*/
#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);
}

View File

@ -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.

View File

@ -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

View File

@ -1,2 +0,0 @@
DVB - System Information Library
================================

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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);
}

View File

@ -1,245 +0,0 @@
//////////////////////////////////////////////////////////////
/// ///
/// si_debug_services.h: local debugging definitions ///
/// ///
//////////////////////////////////////////////////////////////
// $Revision: 1.2 $
// $Date: 2003/04/12 11:27:31 $
// $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

View File

@ -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.

View File

@ -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

View File

@ -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);
}

View File

@ -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

184
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.274 2003/10/19 15:13:05 kls Exp $ * $Id: menu.c 1.275 2003/12/22 10:05:14 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -16,7 +16,6 @@
#include "channels.h" #include "channels.h"
#include "config.h" #include "config.h"
#include "cutter.h" #include "cutter.h"
#include "eit.h"
#include "i18n.h" #include "i18n.h"
#include "menuitems.h" #include "menuitems.h"
#include "plugin.h" #include "plugin.h"
@ -1128,29 +1127,29 @@ eOSState cMenuTimers::ProcessKey(eKeys Key)
class cMenuEvent : public cOsdMenu { class cMenuEvent : public cOsdMenu {
private: private:
const cEventInfo *eventInfo; const cEvent *event;
public: public:
cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch = false); cMenuEvent(const cEvent *Event, bool CanSwitch = false);
cMenuEvent(bool Now); cMenuEvent(bool Now);
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
}; };
cMenuEvent::cMenuEvent(const cEventInfo *EventInfo, bool CanSwitch) cMenuEvent::cMenuEvent(const cEvent *Event, bool CanSwitch)
:cOsdMenu(tr("Event")) :cOsdMenu(tr("Event"))
{ {
eventInfo = EventInfo; event = Event;
if (eventInfo) { if (event) {
cChannel *channel = Channels.GetByChannelID(eventInfo->GetChannelID(), true); cChannel *channel = Channels.GetByChannelID(event->ChannelID(), true);
if (channel) { if (channel) {
char *buffer; 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); SetTitle(buffer, false);
free(buffer); free(buffer);
int Line = 2; int Line = 2;
cMenuTextItem *item; cMenuTextItem *item;
const char *Title = eventInfo->GetTitle(); const char *Title = event->Title();
const char *Subtitle = eventInfo->GetSubtitle(); const char *Subtitle = event->ShortText();
const char *ExtendedDescription = eventInfo->GetExtendedDescription(); const char *ExtendedDescription = event->Description();
if (!isempty(Title)) { if (!isempty(Title)) {
Add(item = new cMenuTextItem(Title, 1, Line, Setup.OSDwidth - 2, -1, clrCyan)); Add(item = new cMenuTextItem(Title, 1, Line, Setup.OSDwidth - 2, -1, clrCyan));
Line += item->Height() + 1; Line += item->Height() + 1;
@ -1185,16 +1184,16 @@ eOSState cMenuEvent::ProcessKey(eKeys Key)
class cMenuWhatsOnItem : public cOsdItem { class cMenuWhatsOnItem : public cOsdItem {
public: public:
const cEventInfo *eventInfo; const cEvent *event;
cMenuWhatsOnItem(const cEventInfo *EventInfo); cMenuWhatsOnItem(const cEvent *Event);
}; };
cMenuWhatsOnItem::cMenuWhatsOnItem(const cEventInfo *EventInfo) cMenuWhatsOnItem::cMenuWhatsOnItem(const cEvent *Event)
{ {
eventInfo = EventInfo; event = Event;
char *buffer = NULL; char *buffer = NULL;
cChannel *channel = Channels.GetByNumber(eventInfo->GetChannelNumber()); cChannel *channel = Channels.GetByNumber(event->ChannelNumber());
asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", eventInfo->GetChannelNumber(), 6, channel ? channel->Name() : "???", 5, eventInfo->GetTimeString(), eventInfo->GetTitle()); asprintf(&buffer, "%d\t%.*s\t%.*s\t%s", event->ChannelNumber(), 6, channel ? channel->Name() : "???", 5, event->GetTimeString(), event->Title());
SetText(buffer, false); SetText(buffer, false);
} }
@ -1205,36 +1204,36 @@ private:
eOSState Record(void); eOSState Record(void);
eOSState Switch(void); eOSState Switch(void);
static int currentChannel; static int currentChannel;
static const cEventInfo *scheduleEventInfo; static const cEvent *scheduleEvent;
public: public:
cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr); cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr);
static int CurrentChannel(void) { return currentChannel; } static int CurrentChannel(void) { return currentChannel; }
static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; } static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; }
static const cEventInfo *ScheduleEventInfo(void); static const cEvent *ScheduleEvent(void);
virtual eOSState ProcessKey(eKeys Key); virtual eOSState ProcessKey(eKeys Key);
}; };
int cMenuWhatsOn::currentChannel = 0; int cMenuWhatsOn::currentChannel = 0;
const cEventInfo *cMenuWhatsOn::scheduleEventInfo = NULL; const cEvent *cMenuWhatsOn::scheduleEvent = NULL;
static int CompareEventChannel(const void *p1, const void *p2) 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) cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentChannelNr)
:cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, 7, 6) :cOsdMenu(Now ? tr("What's on now?") : tr("What's on next?"), CHNUMWIDTH, 7, 6)
{ {
const cSchedule *Schedule = Schedules->First(); const cSchedule *Schedule = Schedules->First();
const cEventInfo **pArray = NULL; const cEvent **pArray = NULL;
int num = 0; int num = 0;
while (Schedule) { 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(); pArray[num] = Now ? Schedule->GetPresentEvent() : Schedule->GetFollowingEvent();
if (pArray[num]) { if (pArray[num]) {
cChannel *channel = Channels.GetByChannelID(pArray[num]->GetChannelID(), true); cChannel *channel = Channels.GetByChannelID(pArray[num]->ChannelID(), true);
if (channel) { if (channel) {
pArray[num]->SetChannelNumber(channel->Number()); pArray[num]->SetChannelNumber(channel->Number());
num++; num++;
@ -1243,20 +1242,20 @@ cMenuWhatsOn::cMenuWhatsOn(const cSchedules *Schedules, bool Now, int CurrentCha
Schedule = (const cSchedule *)Schedules->Next(Schedule); 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++) 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; currentChannel = CurrentChannelNr;
free(pArray); free(pArray);
SetHelp(Count() ? tr("Record") : NULL, Now ? tr("Next") : tr("Now"), tr("Button$Schedule"), tr("Switch")); 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; const cEvent *ei = scheduleEvent;
scheduleEventInfo = NULL; scheduleEvent = NULL;
return ei; return ei;
} }
@ -1264,7 +1263,7 @@ eOSState cMenuWhatsOn::Switch(void)
{ {
cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current()); cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current());
if (item) { 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)) if (channel && cDevice::PrimaryDevice()->SwitchChannel(channel, true))
return osEnd; return osEnd;
} }
@ -1276,7 +1275,7 @@ eOSState cMenuWhatsOn::Record(void)
{ {
cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current()); cMenuWhatsOnItem *item = (cMenuWhatsOnItem *)Get(Current());
if (item) { if (item) {
cTimer *timer = new cTimer(item->eventInfo); cTimer *timer = new cTimer(item->event);
cTimer *t = Timers.GetTimer(timer); cTimer *t = Timers.GetTimer(timer);
if (t) { if (t) {
delete timer; delete timer;
@ -1300,14 +1299,14 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key)
case kGreen: { case kGreen: {
cMenuWhatsOnItem *mi = (cMenuWhatsOnItem *)Get(Current()); cMenuWhatsOnItem *mi = (cMenuWhatsOnItem *)Get(Current());
if (mi) { if (mi) {
scheduleEventInfo = mi->eventInfo; scheduleEvent = mi->event;
currentChannel = mi->eventInfo->GetChannelNumber(); currentChannel = mi->event->ChannelNumber();
} }
} }
break; break;
case kBlue: return Switch(); case kBlue: return Switch();
case kOk: if (Count()) case kOk: if (Count())
return AddSubMenu(new cMenuEvent(((cMenuWhatsOnItem *)Get(Current()))->eventInfo, true)); return AddSubMenu(new cMenuEvent(((cMenuWhatsOnItem *)Get(Current()))->event, true));
break; break;
default: break; default: break;
} }
@ -1319,15 +1318,15 @@ eOSState cMenuWhatsOn::ProcessKey(eKeys Key)
class cMenuScheduleItem : public cOsdItem { class cMenuScheduleItem : public cOsdItem {
public: public:
const cEventInfo *eventInfo; const cEvent *event;
cMenuScheduleItem(const cEventInfo *EventInfo); cMenuScheduleItem(const cEvent *Event);
}; };
cMenuScheduleItem::cMenuScheduleItem(const cEventInfo *EventInfo) cMenuScheduleItem::cMenuScheduleItem(const cEvent *Event)
{ {
eventInfo = EventInfo; event = Event;
char *buffer = NULL; 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); SetText(buffer, false);
} }
@ -1335,7 +1334,7 @@ cMenuScheduleItem::cMenuScheduleItem(const cEventInfo *EventInfo)
class cMenuSchedule : public cOsdMenu { class cMenuSchedule : public cOsdMenu {
private: private:
cMutexLock mutexLock; cSchedulesLock schedulesLock;
const cSchedules *schedules; const cSchedules *schedules;
bool now, next; bool now, next;
int otherChannel; int otherChannel;
@ -1356,7 +1355,7 @@ cMenuSchedule::cMenuSchedule(void)
cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel()); cChannel *channel = Channels.GetByNumber(cDevice::CurrentChannel());
if (channel) { if (channel) {
cMenuWhatsOn::SetCurrentChannel(channel->Number()); cMenuWhatsOn::SetCurrentChannel(channel->Number());
schedules = cSIProcessor::Schedules(mutexLock); schedules = cSchedules::Schedules(schedulesLock);
PrepareSchedule(channel); PrepareSchedule(channel);
SetHelp(Count() ? tr("Record") : NULL, tr("Now"), tr("Next")); SetHelp(Count() ? tr("Record") : NULL, tr("Now"), tr("Next"));
} }
@ -1364,12 +1363,12 @@ cMenuSchedule::cMenuSchedule(void)
cMenuSchedule::~cMenuSchedule() 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) 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) void cMenuSchedule::PrepareSchedule(cChannel *Channel)
@ -1382,17 +1381,17 @@ void cMenuSchedule::PrepareSchedule(cChannel *Channel)
if (schedules) { if (schedules) {
const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID()); const cSchedule *Schedule = schedules->GetSchedule(Channel->GetChannelID());
int num = Schedule->NumEvents(); int num = Schedule->NumEvents();
const cEventInfo **pArray = MALLOC(const cEventInfo *, num); const cEvent **pArray = MALLOC(const cEvent *, num);
if (pArray) { if (pArray) {
time_t now = time(NULL); time_t now = time(NULL);
int numreal = 0; int numreal = 0;
for (int a = 0; a < num; a++) { for (int a = 0; a < num; a++) {
const cEventInfo *EventInfo = Schedule->GetEventNumber(a); const cEvent *Event = Schedule->GetEventNumber(a);
if (EventInfo->GetTime() + EventInfo->GetDuration() > now) if (Event->StartTime() + Event->Duration() > now)
pArray[numreal++] = EventInfo; pArray[numreal++] = Event;
} }
qsort(pArray, numreal, sizeof(cEventInfo *), CompareEventTime); qsort(pArray, numreal, sizeof(cEvent *), CompareEventTime);
for (int a = 0; a < numreal; a++) for (int a = 0; a < numreal; a++)
Add(new cMenuScheduleItem(pArray[a])); Add(new cMenuScheduleItem(pArray[a]));
@ -1405,7 +1404,7 @@ eOSState cMenuSchedule::Record(void)
{ {
cMenuScheduleItem *item = (cMenuScheduleItem *)Get(Current()); cMenuScheduleItem *item = (cMenuScheduleItem *)Get(Current());
if (item) { if (item) {
cTimer *timer = new cTimer(item->eventInfo); cTimer *timer = new cTimer(item->event);
cTimer *t = Timers.GetTimer(timer); cTimer *t = Timers.GetTimer(timer);
if (t) { if (t) {
delete timer; delete timer;
@ -1438,7 +1437,7 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
if (!now && !next) { if (!now && !next) {
int ChannelNr = 0; int ChannelNr = 0;
if (Count()) { if (Count()) {
cChannel *channel = Channels.GetByChannelID(((cMenuScheduleItem *)Get(Current()))->eventInfo->GetChannelID(), true); cChannel *channel = Channels.GetByChannelID(((cMenuScheduleItem *)Get(Current()))->event->ChannelID(), true);
if (channel) if (channel)
ChannelNr = channel->Number(); ChannelNr = channel->Number();
} }
@ -1456,16 +1455,16 @@ eOSState cMenuSchedule::ProcessKey(eKeys Key)
return Switch(); return Switch();
break; break;
case kOk: if (Count()) case kOk: if (Count())
return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->eventInfo, otherChannel)); return AddSubMenu(new cMenuEvent(((cMenuScheduleItem *)Get(Current()))->event, otherChannel));
break; break;
default: break; default: break;
} }
} }
else if (!HasSubMenu()) { else if (!HasSubMenu()) {
now = next = false; now = next = false;
const cEventInfo *ei = cMenuWhatsOn::ScheduleEventInfo(); const cEvent *ei = cMenuWhatsOn::ScheduleEvent();
if (ei) { if (ei) {
cChannel *channel = Channels.GetByChannelID(ei->GetChannelID(), true); cChannel *channel = Channels.GetByChannelID(ei->ChannelID(), true);
if (channel) { if (channel) {
PrepareSchedule(channel); PrepareSchedule(channel);
if (channel->Number() != cDevice::CurrentChannel()) { if (channel->Number() != cDevice::CurrentChannel()) {
@ -2633,10 +2632,10 @@ cDisplayChannel::cDisplayChannel(int Number, bool Switched)
int EpgLines = withInfo ? 5 : 1; int EpgLines = withInfo ? 5 : 1;
lines = 0; lines = 0;
number = 0; number = 0;
cChannel *channel = Channels.GetByNumber(Number); channel = Channels.GetByNumber(Number);
Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines); Interface->Open(Setup.OSDwidth, Setup.ChannelInfoPos ? EpgLines : -EpgLines);
if (channel) { if (channel) {
DisplayChannel(channel); DisplayChannel();
DisplayInfo(); DisplayInfo();
} }
lastTime = time_ms(); lastTime = time_ms();
@ -2660,16 +2659,16 @@ cDisplayChannel::~cDisplayChannel()
Interface->Close(); Interface->Close();
} }
void cDisplayChannel::DisplayChannel(const cChannel *Channel) void cDisplayChannel::DisplayChannel(void)
{ {
int BufSize = Width() + 1; int BufSize = Width() + 1;
char buffer[BufSize]; char buffer[BufSize];
*buffer = 0; *buffer = 0;
if (Channel) { if (channel) {
if (Channel->GroupSep()) if (channel->GroupSep())
snprintf(buffer, BufSize, "%s", Channel->Name()); snprintf(buffer, BufSize, "%s", channel->Name());
else 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) else if (number)
snprintf(buffer, BufSize, "%d-", number); snprintf(buffer, BufSize, "%d-", number);
@ -2684,28 +2683,28 @@ void cDisplayChannel::DisplayChannel(const cChannel *Channel)
void cDisplayChannel::DisplayInfo(void) void cDisplayChannel::DisplayInfo(void)
{ {
if (withInfo) { if (withInfo && channel) {
const cEventInfo *Present = NULL, *Following = NULL; const cEvent *Present = NULL, *Following = NULL;
cMutexLock MutexLock; cSchedulesLock SchedulesLock;
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock); const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
if (Schedules) { if (Schedules) {
const cSchedule *Schedule = Schedules->GetSchedule(); const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
if (Schedule) { if (Schedule) {
const char *PresentTitle = NULL, *PresentSubtitle = NULL, *FollowingTitle = NULL, *FollowingSubtitle = NULL; const char *PresentTitle = NULL, *PresentSubtitle = NULL, *FollowingTitle = NULL, *FollowingSubtitle = NULL;
int Lines = 0; int Lines = 0;
if ((Present = Schedule->GetPresentEvent()) != NULL) { if ((Present = Schedule->GetPresentEvent()) != NULL) {
PresentTitle = Present->GetTitle(); PresentTitle = Present->Title();
if (!isempty(PresentTitle)) if (!isempty(PresentTitle))
Lines++; Lines++;
PresentSubtitle = Present->GetSubtitle(); PresentSubtitle = Present->ShortText();
if (!isempty(PresentSubtitle)) if (!isempty(PresentSubtitle))
Lines++; Lines++;
} }
if ((Following = Schedule->GetFollowingEvent()) != NULL) { if ((Following = Schedule->GetFollowingEvent()) != NULL) {
FollowingTitle = Following->GetTitle(); FollowingTitle = Following->Title();
if (!isempty(FollowingTitle)) if (!isempty(FollowingTitle))
Lines++; Lines++;
FollowingSubtitle = Following->GetSubtitle(); FollowingSubtitle = Following->ShortText();
if (!isempty(FollowingSubtitle)) if (!isempty(FollowingSubtitle))
Lines++; Lines++;
} }
@ -2733,7 +2732,7 @@ void cDisplayChannel::DisplayInfo(void)
Interface->Flush(); Interface->Flush();
lines = Lines; lines = Lines;
lastTime = time_ms(); 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);
} }
} }
} }
@ -2743,7 +2742,8 @@ void cDisplayChannel::DisplayInfo(void)
void cDisplayChannel::Refresh(void) void cDisplayChannel::Refresh(void)
{ {
Interface->Clear(); Interface->Clear();
DisplayChannel(Channels.GetByNumber(cDevice::CurrentChannel())); channel = Channels.GetByNumber(cDevice::CurrentChannel());
DisplayChannel();
lastTime = time_ms(); lastTime = time_ms();
lines = 0; lines = 0;
} }
@ -2761,20 +2761,21 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
if (number >= 0) { if (number >= 0) {
number = number * 10 + Key - k0; number = number * 10 + Key - k0;
if (number > 0) { if (number > 0) {
cChannel *channel = Channels.GetByNumber(number); channel = Channels.GetByNumber(number);
Interface->Clear(); Interface->Clear();
withInfo = false; withInfo = false;
DisplayChannel(channel); DisplayChannel();
lastTime = time_ms(); lastTime = time_ms();
// Lets see if there can be any useful further input: // Lets see if there can be any useful further input:
int n = channel ? number * 10 : 0; int n = channel ? number * 10 : 0;
while (channel && (channel = Channels.Next(channel)) != NULL) { cChannel *ch = channel;
if (!channel->GroupSep()) { while (ch && (ch = Channels.Next(ch)) != NULL) {
if (n <= channel->Number() && channel->Number() <= n + 9) { if (!ch->GroupSep()) {
if (n <= ch->Number() && ch->Number() <= n + 9) {
n = 0; n = 0;
break; break;
} }
if (channel->Number() > n) if (ch->Number() > n)
n *= 10; n *= 10;
} }
} }
@ -2805,10 +2806,10 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
group = Channels.GetPrevGroup(group < 1 ? 1 : group); group = Channels.GetPrevGroup(group < 1 ? 1 : group);
if (group < 0) if (group < 0)
group = SaveGroup; group = SaveGroup;
cChannel *channel = Channels.Get(group); channel = Channels.Get(group);
if (channel) { if (channel) {
Interface->Clear(); Interface->Clear();
DisplayChannel(channel); DisplayChannel();
if (!channel->GroupSep()) if (!channel->GroupSep())
group = -1; group = -1;
} }
@ -2835,7 +2836,8 @@ eOSState cDisplayChannel::ProcessKey(eKeys Key)
Channels.SwitchTo(number); Channels.SwitchTo(number);
else { else {
number = 0; number = 0;
DisplayChannel(NULL); channel = NULL;
DisplayChannel();
lastTime = time_ms(); lastTime = time_ms();
return osContinue; return osContinue;
} }
@ -2967,7 +2969,7 @@ eOSState cDisplayVolume::ProcessKey(eKeys Key)
cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause) cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
{ {
eventInfo = NULL; event = NULL;
instantId = NULL; instantId = NULL;
fileName = NULL; fileName = NULL;
recorder = NULL; recorder = NULL;
@ -2986,10 +2988,10 @@ cRecordControl::cRecordControl(cDevice *Device, cTimer *Timer, bool Pause)
const char *Title = NULL; const char *Title = NULL;
const char *Subtitle = NULL; const char *Subtitle = NULL;
const char *Summary = NULL; const char *Summary = NULL;
if (GetEventInfo()) { if (GetEvent()) {
Title = eventInfo->GetTitle(); Title = event->Title();
Subtitle = eventInfo->GetSubtitle(); Subtitle = event->ShortText();
Summary = eventInfo->GetExtendedDescription(); Summary = event->Description();
dsyslog("Title: '%s' Subtitle: '%s'", Title, Subtitle); dsyslog("Title: '%s' Subtitle: '%s'", Title, Subtitle);
} }
cRecording Recording(timer, Title, Subtitle, Summary); cRecording Recording(timer, Title, Subtitle, Summary);
@ -3038,19 +3040,19 @@ cRecordControl::~cRecordControl()
#define INSTANT_REC_EPG_LOOKAHEAD 300 // seconds to look into the EPG data for an instant recording #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(); const cChannel *channel = timer->Channel();
time_t Time = timer->Active() == taActInst ? timer->StartTime() + INSTANT_REC_EPG_LOOKAHEAD : timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2; 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++) { for (int seconds = 0; seconds <= MAXWAIT4EPGINFO; seconds++) {
{ {
cMutexLock MutexLock; cSchedulesLock SchedulesLock;
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock); const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
if (Schedules) { if (Schedules) {
const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID());
if (Schedule) { if (Schedule) {
eventInfo = Schedule->GetEventAround(Time); event = Schedule->GetEventAround(Time);
if (eventInfo) { if (event) {
if (seconds > 0) if (seconds > 0)
dsyslog("got EPG info after %d seconds", seconds); dsyslog("got EPG info after %d seconds", seconds);
return true; return true;

10
menu.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.h 1.57 2003/08/03 09:37:18 kls Exp $ * $Id: menu.h 1.58 2003/12/21 15:27:07 kls Exp $
*/ */
#ifndef __MENU_H #ifndef __MENU_H
@ -12,6 +12,7 @@
#include "ci.h" #include "ci.h"
#include "device.h" #include "device.h"
#include "epg.h"
#include "osd.h" #include "osd.h"
#include "dvbplayer.h" #include "dvbplayer.h"
#include "recorder.h" #include "recorder.h"
@ -36,7 +37,8 @@ private:
int lines; int lines;
int lastTime; int lastTime;
int number; int number;
void DisplayChannel(const cChannel *Channel); cChannel *channel;
void DisplayChannel(void);
void DisplayInfo(void); void DisplayInfo(void);
void Refresh(void); void Refresh(void);
public: public:
@ -113,10 +115,10 @@ private:
cDevice *device; cDevice *device;
cTimer *timer; cTimer *timer;
cRecorder *recorder; cRecorder *recorder;
const cEventInfo *eventInfo; const cEvent *event;
char *instantId; char *instantId;
char *fileName; char *fileName;
bool GetEventInfo(void); bool GetEvent(void);
public: public:
cRecordControl(cDevice *Device, cTimer *Timer = NULL, bool Pause = false); cRecordControl(cDevice *Device, cTimer *Timer = NULL, bool Pause = false);
virtual ~cRecordControl(); virtual ~cRecordControl();

View File

@ -12,7 +12,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # 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"; $PLUGIN_NAME = $ARGV[0] || die "Usage: newplugin <name>\n";
@ -97,7 +97,7 @@ PACKAGE = vdr-\$(ARCHIVE)
INCLUDES += -I\$(VDRDIR)/include -I\$(DVBDIR)/include 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): ### The object files (add further files here):

219
pat.c Normal file
View File

@ -0,0 +1,219 @@
/*
* 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.1 2003/12/21 15:28:28 kls Exp $
*/
#include "pat.h"
#include <malloc.h>
#include "libsi/section.h"
#include "libsi/descriptor.h"
#define PMT_SCAN_TIMEOUT 10 // seconds
// --- cCaDescriptor ---------------------------------------------------------
class cCaDescriptor : public cListObject {
friend class cCaDescriptors;
private:
int source;
int transponder;
int serviceId;
int caSystem;
int providerId;
int caPid;
int length;
uchar *data;
public:
cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int ProviderId, int CaPid, int Length, const uchar *Data);
virtual ~cCaDescriptor();
int Length(void) const { return length; }
const uchar *Data(void) const { return data; }
};
cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int ProviderId, int CaPid, int Length, const uchar *Data)
{
source = Source;
transponder = Transponder;
serviceId = ServiceId;
caSystem = CaSystem;
providerId = ProviderId;
caPid = CaPid;
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);
//#define DEBUG_CA_DESCRIPTORS 1
#ifdef DEBUG_CA_DESCRIPTORS
char buffer[1024];
char *q = buffer;
q += sprintf(q, "CAM: %04X %5d %5d %04X %6X %04X -", source, transponder, serviceId, caSystem, providerId, caPid);
for (int i = 0; i < length; i++)
q += sprintf(q, " %02X", data[i]);
dsyslog(buffer);
#endif
}
cCaDescriptor::~cCaDescriptor()
{
free(data);
}
// --- cCaDescriptors --------------------------------------------------------
class cCaDescriptors : public cList<cCaDescriptor> {
private:
cMutex mutex;
public:
void NewCaDescriptor(int Source, int Transponder, int ServiceId, SI::CaDescriptor *d);
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data);
};
void cCaDescriptors::NewCaDescriptor(int Source, int Transponder, int ServiceId, SI::CaDescriptor *d)
{
// The code for determining the ProviderID was taken from 'libdtv'
// written by Rolf Hakenes <hakenes@hippomi.de>.
const uchar *Data = d->privateData.getData();
int Length = d->privateData.getLength();
int ProviderID = 0;
switch (d->getCaType() >> 8) {
case 0x01: // SECA
ProviderID = (Data[0] << 8) | Data[1];
break;
case 0x05: // Viaccess ? (France Telecom)
for (int i = 0; i < Length; i++) {
if (Data[i] == 0x14 && Data[i + 1] == 0x03) {
ProviderID = (Data[i + 2] << 16) |
(Data[i + 3] << 8) |
(Data[i + 4] & 0xf0);
break;
}
}
break;
}
cMutexLock MutexLock(&mutex);
for (cCaDescriptor *ca = First(); ca; ca = Next(ca)) {
if (ca->source == Source && ca->transponder == Transponder && ca->serviceId == ServiceId && ca->caSystem == d->getCaType() && ca->providerId == ProviderID && ca->caPid == d->getCaPid())
return;
}
Add(new cCaDescriptor(Source, Transponder, ServiceId, d->getCaType(), ProviderID, d->getCaPid(), Length, Data));
//XXX update???
}
int cCaDescriptors::GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data)
{
if (!CaSystemIds || !*CaSystemIds)
return 0;
if (BufSize > 0 && Data) {
cMutexLock MutexLock(&mutex);
int length = 0;
for (cCaDescriptor *d = First(); d; d = Next(d)) {
if (d->source == Source && d->transponder == Transponder && d->serviceId == ServiceId) {
const unsigned short *caids = CaSystemIds;
do {
if (d->caSystem == *caids) {
if (length + d->Length() <= BufSize) {
memcpy(Data + length, d->Data(), d->Length());
length += d->Length();
}
else
return -1;
}
} while (*++caids);
}
}
return length;
}
return -1;
}
cCaDescriptors CaDescriptors;
int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data)
{
return CaDescriptors.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data);
}
// --- cPatFilter ------------------------------------------------------------
cPatFilter::cPatFilter(void)
{
pmtIndex = 0;
pmtPid = 0;
lastPmtScan = 0;
Set(0x00, 0x00); // PAT
}
void cPatFilter::SetStatus(bool On)
{
cFilter::SetStatus(On);
pmtIndex = 0;
pmtPid = 0;
lastPmtScan = 0;
}
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;
SI::CaDescriptor *d;
// Scan the common loop:
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
CaDescriptors.NewCaDescriptor(Source(), Transponder(), pmt.getServiceId(), d);
delete d;
}
// Scan the stream-specific loop:
SI::PMT::Stream stream;
for (SI::Loop::Iterator it; pmt.streamLoop.hasNext(it); ) {
stream = pmt.streamLoop.getNext(it);
for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
CaDescriptors.NewCaDescriptor(Source(), Transponder(), pmt.getServiceId(), d);
delete d;
}
}
lastPmtScan = 0; // this triggers the next scan
}
}

36
pat.h Normal file
View File

@ -0,0 +1,36 @@
/*
* 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.1 2003/12/21 14:56:03 kls Exp $
*/
#ifndef __PAT_H
#define __PAT_H
#include "filter.h"
#include "thread.h"
class cPatFilter : public cFilter {
private:
time_t lastPmtScan;
int pmtIndex;
int pmtPid;
protected:
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length);
public:
cPatFilter(void);
virtual void SetStatus(bool On);
};
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.
#endif //__PAT_H

180
sections.c Normal file
View File

@ -0,0 +1,180 @@
/*
* 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.1 2003/12/22 11:17:38 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)
{
source = Source;
transponder = Transponder;
}
void cSectionHandler::SetStatus(bool On)
{
if (on != On) {
Lock();
statusCount++;
for (cFilter *fi = filters.First(); fi; fi = filters.Next(fi)) {
fi->SetStatus(false);
if (On)
fi->SetStatus(true);
}
Unlock();
on = On;
}
}
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) {
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 (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
View 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

10
svdrp.c
View File

@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured * and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection. * 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.56 2003/12/21 13:37:10 kls Exp $
*/ */
#include "svdrp.h" #include "svdrp.h"
@ -155,7 +155,7 @@ bool cPUTEhandler::Process(const char *s)
else { else {
rewind(f); rewind(f);
if (cSchedules::Read(f)) { if (cSchedules::Read(f)) {
cSIProcessor::TriggerDump(); cSchedules::Cleanup(true);
status = 250; status = 250;
message = "EPG data processed"; message = "EPG data processed";
} }
@ -458,7 +458,7 @@ void cSVDRP::CmdCHAN(const char *Option)
void cSVDRP::CmdCLRE(const char *Option) void cSVDRP::CmdCLRE(const char *Option)
{ {
cSIProcessor::Clear(); cSchedules::ClearAll();
Reply(250, "EPG data cleared"); Reply(250, "EPG data cleared");
} }
@ -707,8 +707,8 @@ void cSVDRP::CmdLSTC(const char *Option)
void cSVDRP::CmdLSTE(const char *Option) void cSVDRP::CmdLSTE(const char *Option)
{ {
cMutexLock MutexLock; cSchedulesLock SchedulesLock;
const cSchedules *Schedules = cSIProcessor::Schedules(MutexLock); const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock);
if (Schedules) { if (Schedules) {
FILE *f = fdopen(file, "w"); FILE *f = fdopen(file, "w");
if (f) { if (f) {

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.c 1.28 2003/10/18 13:00:04 kls Exp $ * $Id: thread.c 1.29 2003/12/21 15:17:24 kls Exp $
*/ */
#include "thread.h" #include "thread.h"
@ -80,6 +80,39 @@ 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::cMutex(void) cMutex::cMutex(void)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: thread.h 1.18 2003/10/18 12:56:20 kls Exp $ * $Id: thread.h 1.19 2003/12/21 15:44:31 kls Exp $
*/ */
#ifndef __THREAD_H #ifndef __THREAD_H
@ -28,6 +28,16 @@ public:
//void Signal(void); //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 { class cMutex {
friend class cCondVar; friend class cCondVar;
private: private:

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: timers.c 1.6 2003/10/12 10:33:09 kls Exp $ * $Id: timers.c 1.7 2003/12/13 13:06:29 kls Exp $
*/ */
#include "timers.h" #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()); 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; startTime = stopTime = 0;
recording = pending = false; recording = pending = false;
active = true; active = true;
channel = Channels.GetByChannelID(EventInfo->GetChannelID(), true); channel = Channels.GetByChannelID(Event->ChannelID(), true);
time_t tstart = EventInfo->GetTime(); time_t tstart = Event->StartTime();
time_t tstop = tstart + EventInfo->GetDuration() + Setup.MarginStop * 60; time_t tstop = tstart + Event->Duration() + Setup.MarginStop * 60;
tstart -= Setup.MarginStart * 60; tstart -= Setup.MarginStart * 60;
struct tm tm_r; struct tm tm_r;
struct tm *time = localtime_r(&tstart, &tm_r); struct tm *time = localtime_r(&tstart, &tm_r);
@ -64,9 +64,9 @@ cTimer::cTimer(const cEventInfo *EventInfo)
priority = Setup.DefaultPriority; priority = Setup.DefaultPriority;
lifetime = Setup.DefaultLifetime; lifetime = Setup.DefaultLifetime;
*file = 0; *file = 0;
const char *Title = EventInfo->GetTitle(); const char *Title = Event->Title();
if (!isempty(Title)) if (!isempty(Title))
strn0cpy(file, EventInfo->GetTitle(), sizeof(file)); strn0cpy(file, Event->Title(), sizeof(file));
firstday = 0; firstday = 0;
summary = NULL; summary = NULL;
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * 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 #ifndef __TIMERS_H
@ -12,7 +12,7 @@
#include "channels.h" #include "channels.h"
#include "config.h" #include "config.h"
#include "eit.h" #include "epg.h"
#include "tools.h" #include "tools.h"
enum eTimerActive { taInactive = 0, enum eTimerActive { taInactive = 0,
@ -39,7 +39,7 @@ private:
char *summary; char *summary;
public: public:
cTimer(bool Instant = false, bool Pause = false); cTimer(bool Instant = false, bool Pause = false);
cTimer(const cEventInfo *EventInfo); cTimer(const cEvent *Event);
virtual ~cTimer(); virtual ~cTimer();
cTimer& operator= (const cTimer &Timer); cTimer& operator= (const cTimer &Timer);
virtual bool operator< (const cListObject &ListObject); virtual bool operator< (const cListObject &ListObject);

27
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/vdr * The project's page is at http://www.cadsoft.de/vdr
* *
* $Id: vdr.c 1.170 2003/10/19 15:14:42 kls Exp $ * $Id: vdr.c 1.171 2003/12/22 13:29:24 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -39,6 +39,7 @@
#include "diseqc.h" #include "diseqc.h"
#include "dvbdevice.h" #include "dvbdevice.h"
#include "eitscan.h" #include "eitscan.h"
#include "epg.h"
#include "i18n.h" #include "i18n.h"
#include "interface.h" #include "interface.h"
#include "keys.h" #include "keys.h"
@ -93,10 +94,12 @@ int main(int argc, char *argv[])
#define DEFAULTSVDRPPORT 2001 #define DEFAULTSVDRPPORT 2001
#define DEFAULTWATCHDOG 0 // seconds #define DEFAULTWATCHDOG 0 // seconds
#define DEFAULTPLUGINDIR PLUGINDIR #define DEFAULTPLUGINDIR PLUGINDIR
#define DEFAULTEPGDATAFILENAME "epg.data"
int SVDRPport = DEFAULTSVDRPPORT; int SVDRPport = DEFAULTSVDRPPORT;
const char *AudioCommand = NULL; const char *AudioCommand = NULL;
const char *ConfigDirectory = NULL; const char *ConfigDirectory = NULL;
const char *EpgDataFileName = DEFAULTEPGDATAFILENAME;
bool DisplayHelp = false; bool DisplayHelp = false;
bool DisplayVersion = false; bool DisplayVersion = false;
bool DaemonMode = false; bool DaemonMode = false;
@ -146,7 +149,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "vdr: invalid DVB device number: %s\n", optarg); fprintf(stderr, "vdr: invalid DVB device number: %s\n", optarg);
return 2; return 2;
break; break;
case 'E': cSIProcessor::SetEpgDataFileName(*optarg != '-' ? optarg : NULL); case 'E': EpgDataFileName = (*optarg != '-' ? optarg : NULL);
break; break;
case 'h': DisplayHelp = true; case 'h': DisplayHelp = true;
break; break;
@ -239,7 +242,8 @@ int main(int argc, char *argv[])
" there may be several -D options (default: all DVB\n" " there may be several -D options (default: all DVB\n"
" devices will be used)\n" " devices will be used)\n"
" -E FILE --epgfile=FILE write the EPG data into the given FILE (default is\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" " if FILE is a directory, the default EPG file will be\n"
" created in that directory\n" " created in that directory\n"
" -h, --help print this help and exit\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" " -w SEC, --watchdog=SEC activate the watchdog timer with a timeout of SEC\n"
" seconds (default: %d); '0' disables the watchdog\n" " seconds (default: %d); '0' disables the watchdog\n"
"\n", "\n",
cSIProcessor::GetEpgDataFileName() ? cSIProcessor::GetEpgDataFileName() : "'-'", DEFAULTEPGDATAFILENAME,
DEFAULTPLUGINDIR, DEFAULTPLUGINDIR,
DEFAULTSVDRPPORT, DEFAULTSVDRPPORT,
VideoDirectory, VideoDirectory,
@ -360,6 +364,17 @@ int main(int argc, char *argv[])
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]); 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: // DVB interfaces:
cDvbDevice::Initialize(); cDvbDevice::Initialize();
@ -438,8 +453,6 @@ int main(int argc, char *argv[])
else else
cDevice::PrimaryDevice()->SetVolume(Setup.CurrentVolume, true); cDevice::PrimaryDevice()->SetVolume(Setup.CurrentVolume, true);
cSIProcessor::Read();
// Signal handlers: // Signal handlers:
if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN); if (signal(SIGHUP, SignalHandler) == SIG_IGN) signal(SIGHUP, SIG_IGN);
@ -781,6 +794,7 @@ int main(int argc, char *argv[])
} }
// Disk housekeeping: // Disk housekeeping:
RemoveDeletedRecordings(); RemoveDeletedRecordings();
cSchedules::Cleanup();
// Plugins housekeeping: // Plugins housekeeping:
PluginManager.Housekeeping(); PluginManager.Housekeeping();
} }
@ -801,6 +815,7 @@ int main(int argc, char *argv[])
Setup.Save(); Setup.Save();
cDevice::Shutdown(); cDevice::Shutdown();
PluginManager.Shutdown(true); PluginManager.Shutdown(true);
ReportEpgBugFixStats();
if (WatchdogTimeout > 0) if (WatchdogTimeout > 0)
dsyslog("max. latency time %d seconds", MaxLatencyTime); dsyslog("max. latency time %d seconds", MaxLatencyTime);
isyslog("exiting"); isyslog("exiting");