From 716d3d07b485cadb5e60f40f3b408d533cef190e Mon Sep 17 00:00:00 2001
From: Klaus Schmidinger <vdr@tvdr.de>
Date: Wed, 15 Aug 2001 13:56:11 +0200
Subject: Now using 'libdtv' for getting EIT information

---
 libdtv/COPYING                   |  339 +++++++++++
 libdtv/Makefile                  |   73 +++
 libdtv/README                    |   27 +
 libdtv/liblx/COPYING             |  339 +++++++++++
 libdtv/liblx/Makefile            |   62 ++
 libdtv/liblx/liblx.h             |  448 ++++++++++++++
 libdtv/liblx/xListFuncs.c        |  187 ++++++
 libdtv/liblx/xMemMgt.c           |  621 ++++++++++++++++++++
 libdtv/libsi/COPYING             |  339 +++++++++++
 libdtv/libsi/Makefile            |   83 +++
 libdtv/libsi/README              |    2 +
 libdtv/libsi/include/libsi.h     |  816 ++++++++++++++++++++++++++
 libdtv/libsi/include/si_tables.h | 1205 ++++++++++++++++++++++++++++++++++++++
 libdtv/libsi/si_debug_services.c |  487 +++++++++++++++
 libdtv/libsi/si_debug_services.h |  217 +++++++
 libdtv/libsi/si_parser.c         |  881 ++++++++++++++++++++++++++++
 libdtv/libvdr/COPYING            |  339 +++++++++++
 libdtv/libvdr/Makefile           |   62 ++
 libdtv/libvdr/libvdr.c           |  169 ++++++
 libdtv/libvdr/libvdr.h           |  111 ++++
 20 files changed, 6807 insertions(+)
 create mode 100644 libdtv/COPYING
 create mode 100644 libdtv/Makefile
 create mode 100644 libdtv/README
 create mode 100644 libdtv/liblx/COPYING
 create mode 100644 libdtv/liblx/Makefile
 create mode 100644 libdtv/liblx/liblx.h
 create mode 100644 libdtv/liblx/xListFuncs.c
 create mode 100644 libdtv/liblx/xMemMgt.c
 create mode 100644 libdtv/libsi/COPYING
 create mode 100644 libdtv/libsi/Makefile
 create mode 100644 libdtv/libsi/README
 create mode 100644 libdtv/libsi/include/libsi.h
 create mode 100644 libdtv/libsi/include/si_tables.h
 create mode 100644 libdtv/libsi/si_debug_services.c
 create mode 100644 libdtv/libsi/si_debug_services.h
 create mode 100644 libdtv/libsi/si_parser.c
 create mode 100644 libdtv/libvdr/COPYING
 create mode 100644 libdtv/libvdr/Makefile
 create mode 100644 libdtv/libvdr/libvdr.c
 create mode 100644 libdtv/libvdr/libvdr.h

(limited to 'libdtv')

diff --git a/libdtv/COPYING b/libdtv/COPYING
new file mode 100644
index 00000000..a43ea212
--- /dev/null
+++ b/libdtv/COPYING
@@ -0,0 +1,339 @@
+		    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.
diff --git a/libdtv/Makefile b/libdtv/Makefile
new file mode 100644
index 00000000..56cb5330
--- /dev/null
+++ b/libdtv/Makefile
@@ -0,0 +1,73 @@
+##############################################################
+###                                                        ###
+### 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
diff --git a/libdtv/README b/libdtv/README
new file mode 100644
index 00000000..88ee0490
--- /dev/null
+++ b/libdtv/README
@@ -0,0 +1,27 @@
+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.
+
diff --git a/libdtv/liblx/COPYING b/libdtv/liblx/COPYING
new file mode 100644
index 00000000..a43ea212
--- /dev/null
+++ b/libdtv/liblx/COPYING
@@ -0,0 +1,339 @@
+		    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.
diff --git a/libdtv/liblx/Makefile b/libdtv/liblx/Makefile
new file mode 100644
index 00000000..2531708a
--- /dev/null
+++ b/libdtv/liblx/Makefile
@@ -0,0 +1,62 @@
+##############################################################
+###                                                        ###
+### 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
+    
diff --git a/libdtv/liblx/liblx.h b/libdtv/liblx/liblx.h
new file mode 100644
index 00000000..26ea664a
--- /dev/null
+++ b/libdtv/liblx/liblx.h
@@ -0,0 +1,448 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// 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
diff --git a/libdtv/liblx/xListFuncs.c b/libdtv/liblx/xListFuncs.c
new file mode 100644
index 00000000..7457170e
--- /dev/null
+++ b/libdtv/liblx/xListFuncs.c
@@ -0,0 +1,187 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// xListFuncs.c: list handling functions of liblx         ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.1 $
+// $Date: 2001/06/25 12:29:47 $
+// $Author: hakenes $
+//
+//   (C) 1992-2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
+//
+// liblx is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// liblx is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You may have received a copy of the GNU General Public License
+// along with liblx; see the file COPYING.  If not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#include "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);
+}
diff --git a/libdtv/liblx/xMemMgt.c b/libdtv/liblx/xMemMgt.c
new file mode 100644
index 00000000..8f619bc8
--- /dev/null
+++ b/libdtv/liblx/xMemMgt.c
@@ -0,0 +1,621 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// xMemMgt.c: memory management functions of liblx        ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.1 $
+// $Date: 2001/06/25 12:29:47 $
+// $Author: hakenes $
+//
+//   (C) 1992-2001 Rolf Hakenes <hakenes@hippomi.de>, under the GNU GPL.
+//
+// liblx is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// liblx is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You may have received a copy of the GNU General Public License
+// along with liblx; see the file COPYING.  If not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#include <stdio.h>
+#include <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);   
+}
diff --git a/libdtv/libsi/COPYING b/libdtv/libsi/COPYING
new file mode 100644
index 00000000..a43ea212
--- /dev/null
+++ b/libdtv/libsi/COPYING
@@ -0,0 +1,339 @@
+		    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.
diff --git a/libdtv/libsi/Makefile b/libdtv/libsi/Makefile
new file mode 100644
index 00000000..0f2a364a
--- /dev/null
+++ b/libdtv/libsi/Makefile
@@ -0,0 +1,83 @@
+##############################################################
+###                                                        ###
+### Makefile: local makefile for libsi                     ###
+###                                                        ###
+##############################################################
+
+## $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.
+#
+#
+#
+
+.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
diff --git a/libdtv/libsi/README b/libdtv/libsi/README
new file mode 100644
index 00000000..4f1be1ab
--- /dev/null
+++ b/libdtv/libsi/README
@@ -0,0 +1,2 @@
+DVB - System Information Library
+================================
diff --git a/libdtv/libsi/include/libsi.h b/libdtv/libsi/include/libsi.h
new file mode 100644
index 00000000..e527574b
--- /dev/null
+++ b/libdtv/libsi/include/libsi.h
@@ -0,0 +1,816 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// libsi.h: definitions for data structures of libsi      ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.3 $
+// $Date: 2001/06/25 19:39:00 $
+// $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.
+
+#ifndef LIBSI_H
+#define LIBSI_H
+
+#include <time.h>
+#include <sys/types.h>
+#include <asm/types.h>
+
+
+  /* Program Identifier */
+
+#define PID_PAT               0x00           /* Program Association Table */
+#define PID_BAT               0x01           /* Bouquet Association Table */
+#define PID_CAT               0x01           /* Conditional Access Table */
+#define PID_NIT               0x10           /* Network Information Table */
+#define PID_SDT               0x11           /* Service Description Table */
+#define PID_EIT               0x12           /* Event Information Table */
+#define PID_RST               0x13           /* Running Status Table */
+#define PID_TDT               0x14           /* Time Date Table */
+#define PID_TOT               0x14           /* Time Offset Table */
+#define PID_ST                0x14           /* Stuffing Table */
+                           /* 0x15 - 0x1F */ /* Reserved for future use */
+
+  /* Table Identifier */
+
+#define TID_PAT               0x00           /* Program Association Section */
+#define TID_CAT               0x01           /* Conditional Access Section */
+#define TID_PMT               0x02           /* Conditional Access Section */
+                           /* 0x03 - 0x3F */ /* Reserved for future use */
+#define TID_NIT_ACT           0x40           /* Network Information Section -
+                                                   actual */
+#define TID_NIT_OTH           0x41           /* Network Information Section -
+                                                   other */
+#define TID_SDT_ACT           0x42           /* Service Description Section -
+                                                   actual */
+#define TID_SDT_OTH           0x46           /* Service Description Section -
+                                                   other */
+#define TID_EIT_ACT           0x4E           /* Event Information Section -
+                                                   actual */
+#define TID_EIT_OTH           0x4F           /* Event Information Section -
+                                                   other */
+#define TID_EIT_ACT_SCH       0x50           /* Event Information Section -
+                                                   actual, schedule  */
+#define TID_EIT_OTH_SCH       0x60           /* Event Information Section -
+                                                   other, schedule */
+#define TID_TDT               0x70           /* Time Date Section */
+#define TID_TOT               0x73           /* Time Offset Section */
+#define TID_CA_ECM_0          0x80
+#define TID_CA_ECM_1          0x81
+
+#define TID_BAT               0x01           /* Bouquet Association Section */
+
+#define TID_EIT               0x12           /* Event Information Section */
+#define TID_RST               0x13           /* Running Status Section */
+#define TID_ST                0x14           /* Stuffung Section */
+                           /* 0xFF */        /* Reserved for future use */
+
+  /* Descriptor Identifier */
+
+  /* defined by ISO/IEC 13818-1 */
+
+#define DESCR_VIDEO_STREAM                   0x02
+#define DESCR_AUDIO_STREAM                   0x03
+#define DESCR_HIERARCHY                      0x04
+#define DESCR_REGISTRATION                   0x05
+#define DESCR_DATA_STREAM_ALIGN              0x06
+#define DESCR_TARGET_BACKGRID                0x07
+#define DESCR_VIDEO_WINDOW                   0x08
+#define DESCR_CA                             0x09
+#define DESCR_ISO_639_LANGUAGE               0x0A
+#define DESCR_SYSTEM_CLOCK                   0x0B
+#define DESCR_MULTIPLEX_BUFFER_UTIL          0x0C
+#define DESCR_COPYRIGHT                      0x0D
+#define DESCR_MAXIMUM_BITRATE                0x0E
+#define DESCR_PRIVATE_DATA_IND               0x0F
+#define DESCR_SMOOTHING_BUFFER               0x10
+#define DESCR_STD                            0x11
+#define DESCR_IBP                            0x12
+                                          /* 0x13 - 0x3F */ /* Reserved */
+
+  /* defined by ETSI */
+
+#define DESCR_NW_NAME                        0x40
+#define DESCR_SERVICE_LIST                   0x41
+#define DESCR_STUFFING                       0x42
+#define DESCR_SAT_DEL_SYS                    0x43
+#define DESCR_CABLE_DEL_SYS                  0x44
+#define DESCR_VBI_DATA                       0x45
+#define DESCR_VBI_TELETEXT                   0x46
+#define DESCR_BOUQUET_NAME                   0x47
+#define DESCR_SERVICE                        0x48
+#define DESCR_COUNTRY_AVAIL                  0x49
+#define DESCR_LINKAGE                        0x4A
+#define DESCR_NVOD_REF                       0x4B
+#define DESCR_TIME_SHIFTED_SERVICE           0x4C
+#define DESCR_SHORT_EVENT                    0x4D
+#define DESCR_EXTENDED_EVENT                 0x4E
+#define DESCR_TIME_SHIFTED_EVENT             0x4F
+#define DESCR_COMPONENT                      0x50
+#define DESCR_MOSAIC                         0x51
+#define DESCR_STREAM_ID                      0x52
+#define DESCR_CA_IDENT                       0x53
+#define DESCR_CONTENT                        0x54
+#define DESCR_PARENTAL_RATING                0x55
+#define DESCR_TELETEXT                       0x56
+#define DESCR_TELEPHONE                      0x57
+#define DESCR_LOCAL_TIME_OFF                 0x58
+#define DESCR_SUBTITLING                     0x59
+#define DESCR_TERR_DEL_SYS                   0x5A
+#define DESCR_ML_NW_NAME                     0x5B
+#define DESCR_ML_BQ_NAME                     0x5C
+#define DESCR_ML_SERVICE_NAME                0x5D
+#define DESCR_ML_COMPONENT                   0x5E
+#define DESCR_PRIV_DATA_SPEC                 0x5F
+#define DESCR_SERVICE_MOVE                   0x60
+#define DESCR_SHORT_SMOOTH_BUF               0x61
+#define DESCR_FREQUENCY_LIST                 0x62
+#define DESCR_PARTIAL_TP_STREAM              0x63
+#define DESCR_DATA_BROADCAST                 0x64
+#define DESCR_CA_SYSTEM                      0x65
+#define DESCR_DATA_BROADCAST_ID              0x66
+#define DESCR_TRANSPORT_STREAM               0x67
+#define DESCR_DSNG                           0x68
+#define DESCR_PDC                            0x69
+#define DESCR_AC3                            0x6A
+#define DESCR_ANCILLARY_DATA                 0x6B
+#define DESCR_CELL_LIST                      0x6C
+#define DESCR_CELL_FREQ_LINK                 0x6D
+#define DESCR_ANNOUNCEMENT_SUPPORT           0x6E
+
+
+#define MAX_SECTION_BUFFER 4096
+
+
+/* Strukturen zur Aufnahme der SDT und EIT Informationen */
+
+struct Service {
+   struct NODE          Node;
+   int                  ServiceID;
+   int                  TransportStreamID;
+   int                  OriginalNetworkID;
+   int                  SdtVersion;
+   unsigned short       Status;
+   struct LIST         *Descriptors;
+   struct LIST         *Events;
+};
+
+#define EIT_SCHEDULE_FLAG               0x0001
+#define GetScheduleFlag(x)              ((x)&EIT_SCHEDULE_FLAG)
+#define SetScheduleFlag(x)              ((x)|=EIT_SCHEDULE_FLAG)
+#define EIT_PRESENT_FOLLOWING_FLAG      0x0002
+#define GetPresentFollowing(x)          ((x)&EIT_PRESENT_FOLLOWING_FLAG)
+#define SetPresentFollowing(x)          ((x)|=EIT_PRESENT_FOLLOWING_FLAG)
+#define RUNNING_STATUS_NOT_RUNNING      0x0000
+#define RUNNING_STATUS_AWAITING         0x0004
+#define RUNNING_STATUS_PAUSING          0x0008
+#define RUNNING_STATUS_RUNNING          0x000C
+#define GetRunningStatus(x)             ((x)&RUNNING_STATUS_RUNNING)
+#define SetRunningStatus(x,s)           ((x)|=((s)&RUNNING_STATUS_RUNNING))
+#define FREE_TO_AIR                     0x0000
+#define CONDITIONAL_ACCESS              0x0010
+#define GetConditionalAccess(x)         ((x)&CONDITIONAL_ACCESS)
+#define SetConditionalAccess(x)         ((x)|=CONDITIONAL_ACCESS)
+
+#define CreateService(service, svid, tsid, onid, vers, sta) \
+   do \
+   { \
+      xCreateNode (service, NULL); \
+      service->ServiceID = svid; \
+      service->TransportStreamID = tsid; \
+      service->OriginalNetworkID = onid; \
+      service->SdtVersion = vers; \
+      service->Status = sta; \
+      service->Descriptors = xNewList (NULL); \
+      service->Events = xNewList (NULL); \
+   } while (0)
+
+
+struct Event {
+   struct NODE          Node;
+   int                  EventID;
+   int                  ServiceID;
+   int                  EitVersion;
+   int                  TransportStreamID;
+   int                  OriginalNetworkID;
+   time_t               StartTime;
+   time_t               Duration;
+   unsigned short       Status;
+   struct LIST         *Descriptors;
+};
+
+#define CreateEvent(event, evid, svid, tsid, onid, vers, sta) \
+   do \
+   { \
+      xCreateNode (event, NULL); \
+      event->EventID = evid; \
+      event->ServiceID = svid; \
+      event->TransportStreamID = tsid; \
+      event->OriginalNetworkID = onid; \
+      event->EitVersion = vers; \
+      event->Status = sta; \
+      event->Descriptors = xNewList (NULL); \
+   } while (0)
+
+
+/* Strukturen zur Aufnahme der PAT und PMT Informationen */
+
+struct Program {
+   struct NODE          Node;
+   int                  ProgramID;
+   int                  TransportStreamID;
+   int                  NetworkPID;
+   int                  PatVersion;
+   struct LIST         *Pids;
+};
+
+#define CreateProgram(program, pgid, tsid, npid, vers) \
+   do \
+   { \
+      xCreateNode (program, NULL); \
+      program->ProgramID = pgid; \
+      program->TransportStreamID = tsid; \
+      program->NetworkPID = npid; \
+      program->PatVersion = vers; \
+      program->Pids = xNewList (NULL); \
+   } while (0)
+
+struct Pid {
+   struct NODE          Node;
+   int                  ProgramID;
+   int                  PcrPID;
+   int                  PmtVersion;
+   struct LIST         *Descriptors;
+   struct LIST         *InfoList;
+};
+
+#define CreatePid(pid, pgid, pcid, vers) \
+   do \
+   { \
+      xCreateNode (pid, NULL); \
+      pid->ProgramID = pgid; \
+      pid->PcrPID = pcid; \
+      pid->PmtVersion = vers; \
+      pid->Descriptors = xNewList (NULL); \
+      pid->InfoList = xNewList (NULL); \
+   } while (0)
+
+struct PidInfo {
+   struct NODE          Node;
+   int                  StreamType;
+   int                  ElementaryPid;
+   struct LIST         *Descriptors;
+};
+
+#define CreatePidInfo(pidinfo, styp, epid) \
+   do \
+   { \
+      xCreateNode (pidinfo, NULL); \
+      pidinfo->StreamType = styp; \
+      pidinfo->ElementaryPid = epid; \
+      pidinfo->Descriptors = xNewList (NULL); \
+   } while (0)
+
+
+#define STREAMTYPE_ISO_VIDEO                     1
+#define STREAMTYPE_13818_VIDEO                   2
+#define STREAMTYPE_11172_AUDIO                   3
+#define STREAMTYPE_13818_AUDIO                   4
+#define STREAMTYPE_VIDEOTEXT                     6
+#define STREAMTYPE_13522_MPEG                    7
+#define STREAMTYPE_ITU_222                       8
+#define STREAMTYPE_13818_A                       9
+#define STREAMTYPE_13818_B                      10
+#define STREAMTYPE_13818_C                      11
+#define STREAMTYPE_13818_D                      12
+#define STREAMTYPE_13818_AUX                    13
+
+/* Descriptors */
+
+#define DescriptorTag(x) ((struct Descriptor *)(x))->Tag
+
+struct Descriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+};
+
+
+/* Iso639LanguageDescriptor */
+
+struct Iso639LanguageDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   char                 LanguageCode[4];
+};
+
+#define CreateIso639LanguageDescriptor(descr, lc1, lc2, lc3) \
+   do \
+   { \
+      xCreateNode (((struct Iso639LanguageDescriptor *)descr), NULL); \
+      ((struct Iso639LanguageDescriptor *)descr)->Tag = DESCR_ISO_639_LANGUAGE; \
+      ((struct Iso639LanguageDescriptor *)descr)->LanguageCode[0] = lc1; \
+      ((struct Iso639LanguageDescriptor *)descr)->LanguageCode[1] = lc2; \
+      ((struct Iso639LanguageDescriptor *)descr)->LanguageCode[2] = lc3; \
+      ((struct Iso639LanguageDescriptor *)descr)->LanguageCode[3] = '\0'; \
+   } while (0)
+
+
+/* AncillaryDataDescriptor */
+
+struct AncillaryDataDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   unsigned short       Identifier;
+};
+
+#define ANCILLARY_DATA_DVD_VIDEO            0x0001
+#define ANCILLARY_DATA_EXTENDED             0x0002
+#define ANCILLARY_DATA_SWITCHING            0x0004
+#define ANCILLARY_DATA_DAB                  0x0008
+#define ANCILLARY_DATA_SCALE_FACTOR         0x0010
+
+#define CreateAncillaryDataDescriptor(descr, id) \
+   do \
+   { \
+      xCreateNode (((struct AncillaryDataDescriptor *)descr), NULL); \
+      ((struct AncillaryDataDescriptor *)descr)->Tag = DESCR_ANCILLARY_DATA; \
+      ((struct AncillaryDataDescriptor *)descr)->Identifier = id; \
+   } while (0)
+
+
+/* BouquetNameDescriptor */
+
+struct BouquetNameDescriptor {
+   struct NODE          Node;    /* Node enth�lt Namen */
+   unsigned short       Tag;
+};
+
+#define CreateBouquetNameDescriptor(descr, text) \
+   do \
+   { \
+      xCreateNode (((struct BouquetNameDescriptor *)descr), text); \
+      ((struct BouquetNameDescriptor *)descr)->Tag = DESCR_BOUQUET_NAME; \
+   } while (0)
+
+
+/* CountryAvailabilityDescriptor */
+
+struct CountryAvailabilityDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   unsigned short       AvailibilityFlag;
+   unsigned short       Amount;           /* CountryCodes */
+   char                *CountryCodes;
+};
+
+#define COUNTRIES_ARE_AVAILABLE   0x0001
+#define COUNTRIES_ARE_UNAVAILABLE 0x0000
+
+#define CreateCountryAvailabilityDescriptor(descr, ava) \
+   do \
+   { \
+      xCreateNode (((struct CountryAvailabilityDescriptor *)descr), NULL); \
+      ((struct CountryAvailabilityDescriptor *)descr)->Tag = DESCR_COUNTRY_AVAIL; \
+      ((struct CountryAvailabilityDescriptor *)descr)->AvailibilityFlag = ava; \
+      ((struct CountryAvailabilityDescriptor *)descr)->Amount = 0; \
+      ((struct CountryAvailabilityDescriptor *)descr)->CountryCodes = NULL; \
+   } while (0)
+
+#define AddCountryAvailabilityCode(descr, lc1, lc2, lc3) \
+   do \
+   { \
+      char tmpbuf[4], *tmpptr, *ttptr; \
+      \
+      tmpbuf[0] = lc1; tmpbuf[1] = lc2; \
+      tmpbuf[2] = lc3; tmpbuf[3] = '\0'; \
+      xMemAlloc (((struct CountryAvailabilityDescriptor *)descr)->Amount*4 + 8, &tmpptr); \
+      ttptr = tmpptr; \
+      if (((struct CountryAvailabilityDescriptor *)descr)->CountryCodes) { \
+         memcpy (ttptr, ((struct CountryAvailabilityDescriptor *)descr)->CountryCodes, \
+                        ((struct CountryAvailabilityDescriptor *)descr)->Amount*4); \
+         ttptr += ((struct CountryAvailabilityDescriptor *)descr)->Amount*4; \
+      } \
+      memcpy (ttptr, tmpbuf, 4); \
+      ((struct CountryAvailabilityDescriptor *)descr)->CountryCodes = tmpptr; \
+   } while (0)
+
+
+/* CaIdentifierDescriptor */
+
+struct CaIdentifierDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   unsigned short       Amount;           /* SystemIDs */
+   unsigned short      *SystemID;
+};
+
+#define CreateCaIdentifierDescriptor(descr, amo) \
+   do \
+   { \
+      xCreateNode (((struct CaIdentifierDescriptor *)descr), NULL); \
+      ((struct CaIdentifierDescriptor *)descr)->Tag = DESCR_CA_IDENT; \
+      ((struct CaIdentifierDescriptor *)descr)->Amount = amo; \
+      xMemAlloc (amo*2+2, &((struct CaIdentifierDescriptor *)descr)->SystemID); \
+   } while (0)
+
+#define SetCaIdentifierID(descr, num, id) \
+      ((struct CaIdentifierDescriptor *)descr)->SystemID[num] = id
+#define GetCaIdentifierID(descr, num) (((struct CaIdentifierDescriptor *)descr)->SystemID[num])
+
+
+/* StreamIdentifierDescriptor */
+
+struct StreamIdentifierDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   unsigned short       ComponentTag;
+};
+
+#define CreateStreamIdentifierDescriptor(descr, ctag) \
+   do \
+   { \
+      xCreateNode (((struct StreamIdentifierDescriptor *)descr), NULL); \
+      ((struct StreamIdentifierDescriptor *)descr)->Tag = DESCR_STREAM_ID; \
+      ((struct StreamIdentifierDescriptor *)descr)->ComponentTag = (ctag); \
+   } while (0)
+
+
+/* DataBroadcastDescriptor */
+
+struct DataBroadcastDescriptor {
+   struct NODE          Node;          /* Node enth�lt DescriptorText */
+   unsigned short       Tag;
+   unsigned short       DataBroadcastID;
+   unsigned short       ComponentTag;
+   unsigned short       SelectorLength;
+   unsigned char       *SelectorBytes;
+   char                 LanguageCode[4];
+};
+
+struct MosaicDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   /* to be defined */
+};
+
+struct MultiLingualServiceDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   /* to be defined */
+};
+
+
+/* NvodReferenceDescriptor */
+
+struct NvodReferenceDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   struct LIST         *Items;
+};
+
+#define CreateNvodReferenceDescriptor(descr) \
+   do \
+   { \
+      xCreateNode (((struct NvodReferenceDescriptor *)descr), NULL); \
+      ((struct NvodReferenceDescriptor *)descr)->Tag = DESCR_NVOD_REF; \
+      ((struct NvodReferenceDescriptor *)descr)->Items = xNewList (NULL); \
+   } while (0)
+
+struct NvodReferenceItem {
+   struct NODE          Node;
+   int                  TransportStreamID;
+   int                  OriginalNetworkID;
+   int                  ServiceID;
+};
+
+#define CreateNvodReferenceItem(itm, tpid, onid, svid) \
+   do \
+   { \
+      xCreateNode (itm, NULL); \
+      itm->TransportStreamID = tpid; \
+      itm->OriginalNetworkID = onid; \
+      itm->ServiceID = svid; \
+   } while (0)
+
+#define AddNvodReferenceItem(desc, tpid, onid, svid) \
+   do \
+   { \
+      struct NvodReferenceItem *item; \
+      \
+      CreateNvodReferenceItem(item, tpid, onid, svid); \
+      xAddTail (((struct NvodReferenceDescriptor *)desc)->Items, item); \
+   } while (0)
+
+
+/* LinkageDescriptor */
+
+struct LinkageDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   int                  TransportStreamID;
+   int                  OriginalNetworkID;
+   int                  ServiceID;
+   int                  LinkageType;
+   int                  PrivateDataLength;
+   unsigned char       *PrivateData;
+};
+
+#define CreateLinkageDescriptor(descr, tpid, onid, svid, ltyp, pdl, pdp) \
+   do \
+   { \
+      xCreateNode (((struct LinkageDescriptor *)descr), NULL); \
+      ((struct LinkageDescriptor *)descr)->Tag = DESCR_LINKAGE; \
+      ((struct LinkageDescriptor *)descr)->TransportStreamID = tpid; \
+      ((struct LinkageDescriptor *)descr)->OriginalNetworkID = onid; \
+      ((struct LinkageDescriptor *)descr)->ServiceID = svid; \
+      ((struct LinkageDescriptor *)descr)->LinkageType = ltyp; \
+      ((struct LinkageDescriptor *)descr)->PrivateDataLength = pdl; \
+      xMemAlloc ((pdl)+1, &(((struct LinkageDescriptor *) \
+         descr)->PrivateData)); \
+      memcpy ((((struct LinkageDescriptor *)descr)->PrivateData),(pdp),(pdl));\
+   } while (0)
+
+
+/* ServiceDescriptor */
+
+struct ServiceDescriptor {
+   struct NODE          Node;      /* Node enth�lt ServiceName */
+   unsigned short       Tag;
+   unsigned short       ServiceType;
+   char                *ServiceProvider;
+};
+
+#define CreateServiceDescriptor(descr, styp, prov, name) \
+   do \
+   { \
+      xCreateNode (((struct ServiceDescriptor *)descr), name); \
+      ((struct ServiceDescriptor *)descr)->Tag = DESCR_SERVICE; \
+      ((struct ServiceDescriptor *)descr)->ServiceType = styp; \
+      ((struct ServiceDescriptor *)descr)->ServiceProvider = prov; \
+   } while (0)
+
+
+
+struct TelephoneDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   /* to be defined */
+};
+
+
+/* TimeShiftedServiceDescriptor */
+
+struct TimeShiftedServiceDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   int                  ReferenceServiceID;
+};
+
+#define CreateTimeShiftedServiceDescriptor(descr, svid) \
+   do \
+   { \
+      xCreateNode (((struct TimeShiftedServiceDescriptor *)descr), NULL); \
+      ((struct TimeShiftedServiceDescriptor *)descr)->Tag = DESCR_TIME_SHIFTED_SERVICE; \
+      ((struct TimeShiftedServiceDescriptor *)descr)->ReferenceServiceID = svid; \
+   } while (0)
+
+
+/* TimeShiftedEventDescriptor */
+
+struct TimeShiftedEventDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   int                  ReferenceServiceID;
+   int                  ReferenceEventID;
+};
+
+#define CreateTimeShiftedEventDescriptor(descr, svid, evid) \
+   do \
+   { \
+      xCreateNode (((struct TimeShiftedEventDescriptor *)descr), NULL); \
+      ((struct TimeShiftedEventDescriptor *)descr)->Tag = DESCR_TIME_SHIFTED_EVENT; \
+      ((struct TimeShiftedEventDescriptor *)descr)->ReferenceServiceID = svid; \
+      ((struct TimeShiftedEventDescriptor *)descr)->ReferenceEventID = evid; \
+   } while (0)
+
+
+/* ComponentDescriptor */
+
+struct ComponentDescriptor {
+   struct NODE          Node;   /* Node enth�lt ComponentText */
+   unsigned short       Tag;
+   unsigned short       StreamContent;
+   unsigned short       ComponentType;
+   unsigned short       ComponentTag;
+   char                 LanguageCode[4];
+};
+
+#define CreateComponentDescriptor(descr, scnt, ctyp, tag, lc1, lc2, lc3, txt) \
+   do \
+   { \
+      xCreateNode (((struct ComponentDescriptor *)descr), txt); \
+      ((struct ComponentDescriptor *)descr)->Tag = DESCR_COMPONENT; \
+      ((struct ComponentDescriptor *)descr)->StreamContent = scnt; \
+      ((struct ComponentDescriptor *)descr)->ComponentType = ctyp; \
+      ((struct ComponentDescriptor *)descr)->ComponentTag = tag; \
+      ((struct ComponentDescriptor *)descr)->LanguageCode[0] = lc1; \
+      ((struct ComponentDescriptor *)descr)->LanguageCode[1] = lc2; \
+      ((struct ComponentDescriptor *)descr)->LanguageCode[2] = lc3; \
+      ((struct ComponentDescriptor *)descr)->LanguageCode[3] = '\0'; \
+   } while (0)
+
+
+/* ContentDescriptor */
+
+struct ContentDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   unsigned short       Amount;        /* ContentIDs */
+   unsigned short      *ContentID;
+};
+
+#define CreateContentDescriptor(descr, amo) \
+   do \
+   { \
+      xCreateNode (((struct ContentDescriptor *)descr), NULL); \
+      ((struct ContentDescriptor *)descr)->Tag = DESCR_CONTENT; \
+      ((struct ContentDescriptor *)descr)->Amount = amo; \
+      xMemAlloc (amo*2+2, &((struct ContentDescriptor *)descr)->ContentID); \
+   } while (0)
+
+#define SetContentID(descr, num, cnib1, cnib2, unib1, unib2) \
+   do \
+   { \
+      ((struct ContentDescriptor *)descr)->ContentID[num] = \
+         ((cnib1&0xF) << 12) | ((cnib2&0xF) << 8) | \
+         ((unib1&0xF) << 4) | (unib2&0xF); \
+   } while (0)
+#define GetContentContentNibble1(descr, num) ((((struct ContentDescriptor *)descr)->ContentID[num]&0xF000) >> 12)
+#define GetContentContentNibble2(descr, num) ((((struct ContentDescriptor *)descr)->ContentID[num]&0x0F00) >> 8)
+#define GetContentUserNibble1(descr, num) ((((struct ContentDescriptor *)descr)->ContentID[num]&0x00F0) >> 4)
+#define GetContentUserNibble2(descr, num) (((struct ContentDescriptor *)descr)->ContentID[num]&0x000F)
+
+
+/* ExtendedEventDescriptor */
+
+struct ExtendedEventDescriptor {
+   struct NODE          Node;    /* Node enth�lt EventText */
+   unsigned short       Tag;
+   unsigned short       DescriptorNumber;
+   unsigned short       LastDescriptorNumber;
+   char                 LanguageCode[4];
+   struct LIST         *Items;
+};
+
+#define CreateExtendedEventDescriptor(descr, dnum, ldnb, lc1, lc2, lc3, text) \
+   do \
+   { \
+      xCreateNode (((struct ExtendedEventDescriptor *)descr), text); \
+      ((struct ExtendedEventDescriptor *)descr)->Tag = DESCR_EXTENDED_EVENT; \
+      ((struct ExtendedEventDescriptor *)descr)->DescriptorNumber = dnum; \
+      ((struct ExtendedEventDescriptor *)descr)->LastDescriptorNumber = ldnb; \
+      ((struct ExtendedEventDescriptor *)descr)->LanguageCode[0] = lc1; \
+      ((struct ExtendedEventDescriptor *)descr)->LanguageCode[1] = lc2; \
+      ((struct ExtendedEventDescriptor *)descr)->LanguageCode[2] = lc3; \
+      ((struct ExtendedEventDescriptor *)descr)->LanguageCode[3] = '\0'; \
+      ((struct ExtendedEventDescriptor *)descr)->Items = xNewList (NULL); \
+   } while (0)
+
+struct ExtendedEventItem {
+   struct NODE          Node;    /* Node enth�lt ItemDescription Text */
+   char                *Text;
+};
+
+#define CreateExtendedEventItem(itm, dtxt, text) \
+   do \
+   { \
+      xCreateNode (itm, dtxt); \
+      itm->Text = text; \
+   } while (0)
+
+#define AddExtendedEventItem(desc, dtxt, text) \
+   do \
+   { \
+      struct ExtendedEventItem *item; \
+      \
+      CreateExtendedEventItem(item, dtxt, text); \
+      xAddTail (((struct ExtendedEventDescriptor *)desc)->Items, item); \
+   } while (0)
+
+
+/* ParentalRatingDescriptor */
+
+struct ParentalRatingDescriptor {
+   struct NODE          Node;
+   unsigned short       Tag;
+   struct LIST         *Ratings;
+};
+
+#define CreateParentalRatingDescriptor(descr) \
+   do \
+   { \
+      xCreateNode (((struct ParentalRatingDescriptor *)descr), NULL); \
+      ((struct ParentalRatingDescriptor *)descr)->Tag = DESCR_PARENTAL_RATING; \
+      ((struct ParentalRatingDescriptor *)descr)->Ratings = xNewList (NULL); \
+   } while (0)
+
+struct ParentalRating {
+   struct NODE          Node;    /* Node enth�lt ItemDescription Text */
+   char                 LanguageCode[4];
+   char                 Rating;
+};
+
+#define CreateParentalRating(rat, lc1, lc2, lc3, val) \
+   do \
+   { \
+      xCreateNode (rat, NULL); \
+      rat->LanguageCode[0] = lc1; \
+      rat->LanguageCode[1] = lc2; \
+      rat->LanguageCode[2] = lc3; \
+      rat->LanguageCode[3] = '\0'; \
+      rat->Rating = val; \
+   } while (0)
+
+#define AddParentalRating(desc, lc1, lc2, lc3, val) \
+   do \
+   { \
+      struct ParentalRating *item; \
+      \
+      CreateParentalRating(item, lc1, lc2, lc3, val); \
+      xAddTail (((struct ParentalRatingDescriptor *)desc)->Ratings, item); \
+   } while (0)
+
+/* ShortEventDescriptor */
+
+struct ShortEventDescriptor {
+   struct NODE          Node;    /* Node enth�lt EventName */
+   unsigned short       Tag;
+   char                 LanguageCode[4];
+   char                *Text;
+};
+
+#define CreateShortEventDescriptor(descr, name, lc1, lc2, lc3, text) \
+   do \
+   { \
+      xCreateNode (((struct ShortEventDescriptor *)descr), name); \
+      ((struct ShortEventDescriptor *)descr)->Tag = DESCR_SHORT_EVENT; \
+      ((struct ShortEventDescriptor *)descr)->LanguageCode[0] = lc1; \
+      ((struct ShortEventDescriptor *)descr)->LanguageCode[1] = lc2; \
+      ((struct ShortEventDescriptor *)descr)->LanguageCode[2] = lc3; \
+      ((struct ShortEventDescriptor *)descr)->LanguageCode[3] = '\0'; \
+      ((struct ShortEventDescriptor *)descr)->Text = text; \
+   } while (0)
+
+
+
+/* Prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* si_parser.c */
+
+struct LIST *siParsePAT (u_char *);
+struct Pid *siParsePMT (u_char *);
+struct LIST *siParseSDT (u_char *);
+struct LIST *siParseEIT (u_char *);
+time_t siParseTDT (u_char *);
+void siParseDescriptors (struct LIST *, u_char *, u_int, u_char);
+void siParseDescriptor (struct LIST *, u_char *);
+char *siGetDescriptorText (u_char *, u_int);
+u_long crc32 (char *data, int len);
+
+/* si_debug_services.c */
+
+void siDebugServices (struct LIST *);
+void siDebugService (struct Service *);
+void siDebugEvents (char *, struct LIST *);
+void siDebugPrograms (char *, struct LIST *);
+void siDebugProgram (struct Program *);
+void siDebugPids (char *, struct LIST *);
+void siDebugDescriptors (char *, struct LIST *);
+void siDebugEitServices (struct LIST *);
+void siDebugEitEvents (char *, struct LIST *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libdtv/libsi/include/si_tables.h b/libdtv/libsi/include/si_tables.h
new file mode 100644
index 00000000..f10a2980
--- /dev/null
+++ b/libdtv/libsi/include/si_tables.h
@@ -0,0 +1,1205 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// si_tables.h: definitions for data structures of the    ///
+///              incoming SI data stream                   ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.2 $
+// $Date: 2001/08/15 10:00:00 $
+// $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.
+
+#ifndef SI_TABLES_H
+#define SI_TABLES_H
+
+#define HILO(x) (x##_hi << 8 | x##_lo)
+
+#define MjdToEpochTime(x) (((x##_hi << 8 | x##_lo)-40587)*86400)
+#define BcdTimeToSeconds(x) ((3600 * ((10*((x##_h & 0xF0)>>4)) + (x##_h & 0xF))) + \
+                             (60 * ((10*((x##_m & 0xF0)>>4)) + (x##_m & 0xF))) + \
+                             ((10*((x##_s & 0xF0)>>4)) + (x##_s & 0xF)))
+
+#define TableHasMoreSections(x) (((pat_t *)(x))->last_section_number > ((pat_t *)(x))->section_number)
+#define GetTableId(x) ((pat_t *)(x))->table_id
+#define GetSectionNumber(x) ((pat_t *)(x))->section_number
+#define GetLastSectionNumber(x) ((pat_t *)(x))->last_section_number
+#define GetServiceId(x) (((eit_t *)(x))->service_id_hi << 8) | ((eit_t *)(x))->service_id_lo
+
+/*
+ *
+ *    ETSI ISO/IEC 13818-1 specifies SI which is referred to as PSI. The PSI
+ *    data provides information to enable automatic configuration of the
+ *    receiver to demultiplex and decode the various streams of programs
+ *    within the multiplex. The PSI data is structured as four types of table.
+ *    The tables are transmitted in sections.
+ *
+ *    1) Program Association Table (PAT):
+ *
+ *       - for each service in the multiplex, the PAT indicates the location
+ *         (the Packet Identifier (PID) values of the Transport Stream (TS)
+ *         packets) of the corresponding Program Map Table (PMT).
+ *         It also gives the location of the Network Information Table (NIT).
+ *
+ */
+
+#define PAT_LEN 8
+
+typedef struct {
+   u_char table_id                               :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char section_syntax_indicator               :1;
+   u_char dummy                                  :1;        // has to be 0
+   u_char                                        :2;
+   u_char section_length_hi                      :4;
+#else
+   u_char section_length_hi                      :4;
+   u_char                                        :2;
+   u_char dummy                                  :1;        // has to be 0
+   u_char section_syntax_indicator               :1;
+#endif
+   u_char section_length_lo                      :8;
+   u_char transport_stream_id_hi                 :8;
+   u_char transport_stream_id_lo                 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :2;
+   u_char version_number                         :5;
+   u_char current_next_indicator                 :1;
+#else
+   u_char current_next_indicator                 :1;
+   u_char version_number                         :5;
+   u_char                                        :2;
+#endif
+   u_char section_number                         :8;
+   u_char last_section_number                    :8;
+} pat_t;
+
+#define PAT_PROG_LEN 4
+
+typedef struct {
+   u_char program_number_hi                      :8;
+   u_char program_number_lo                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :3;
+   u_char network_pid_hi                         :5;
+#else
+   u_char network_pid_hi                         :5;
+   u_char                                        :3;
+#endif
+   u_char network_pid_lo                         :8; 
+   /* or program_map_pid (if prog_num=0)*/
+} pat_prog_t;
+
+/*
+ *
+ *    2) Conditional Access Table (CAT):
+ *
+ *       - the CAT provides information on the CA systems used in the
+ *         multiplex; the information is private and dependent on the CA
+ *         system, but includes the location of the EMM stream, when
+ *         applicable.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    3) Program Map Table (PMT):
+ *
+ *       - the PMT identifies and indicates the locations of the streams that
+ *         make up each service, and the location of the Program Clock
+ *         Reference fields for a service.
+ *
+ */
+
+#define PMT_LEN 12
+
+typedef struct {
+   u_char table_id                               :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char section_syntax_indicator               :1;
+   u_char dummy                                  :1; // has to be 0
+   u_char                                        :2;
+   u_char section_length_hi                      :4;
+#else
+   u_char section_length_hi                      :4;
+   u_char                                        :2;
+   u_char dummy                                  :1; // has to be 0
+   u_char section_syntax_indicator               :1;
+#endif
+   u_char section_length_lo                      :8;
+   u_char program_number_hi                      :8;
+   u_char program_number_lo                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :2;
+   u_char version_number                         :5;
+   u_char current_next_indicator                 :1;
+#else
+   u_char current_next_indicator                 :1;
+   u_char version_number                         :5;
+   u_char                                        :2;
+#endif
+   u_char section_number                         :8;
+   u_char last_section_number                    :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :3;
+   u_char PCR_PID_hi                             :5;
+#else
+   u_char PCR_PID_hi                             :5;
+   u_char                                        :3;
+#endif
+   u_char PCR_PID_lo                             :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :4;
+   u_char program_info_length_hi                 :4;
+#else
+   u_char program_info_length_hi                 :4;
+   u_char                                        :4;
+#endif
+   u_char program_info_length_lo                 :8;
+   //descriptors
+} pmt_t;
+
+#define PMT_INFO_LEN 5
+
+typedef struct {
+   u_char stream_type                            :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :3;
+   u_char elementary_PID_hi                      :5;
+#else
+   u_char elementary_PID_hi                      :5;
+   u_char                                        :3;
+#endif
+   u_char elementary_PID_lo                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :4;
+   u_char ES_info_length_hi                      :4;
+#else
+   u_char ES_info_length_hi                      :4;
+   u_char                                        :4;
+#endif
+   u_char ES_info_length_lo                      :8;
+   // descriptors
+} pmt_info_t;
+
+/*
+ *
+ *    4) Network Information Table (NIT):
+ *
+ *       - the NIT is intended to provide information about the physical
+ *         network. The syntax and semantics of the NIT are defined in
+ *         ETSI EN 300 468.
+ *
+ */
+
+#define NIT_LEN 10 
+
+typedef struct { 
+   u_char table_id                               :8; 
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char section_syntax_indicator               :1; 
+   u_char                                        :3; 
+   u_char section_length_hi                      :4; 
+#else 
+   u_char section_length_hi                      :4; 
+   u_char                                        :3; 
+   u_char section_syntax_indicator               :1; 
+#endif
+   u_char section_length_lo                      :8; 
+   u_char network_id_hi                          :8; 
+   u_char network_id_lo                          :8; 
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :2; 
+   u_char version_number                         :5; 
+   u_char current_next_indicator                 :1; 
+#else
+   u_char current_next_indicator                 :1; 
+   u_char version_number                         :5; 
+   u_char                                        :2; 
+#endif
+   u_char section_number                         :8; 
+   u_char last_section_number                    :8; 
+#if BYTE_ORDER == BIG_ENDIAN 
+   u_char                                        :4; 
+   u_char network_descriptor_length_hi           :4; 
+#else
+   u_char network_descriptor_length_hi           :4; 
+   u_char                                        :4; 
+#endif
+   u_char network_descriptor_length_lo           :8; 
+  /* descriptors */
+} nit_t; 
+ 
+#define SIZE_NIT_MID 2 
+
+typedef struct {                                 // after descriptors 
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :4; 
+   u_char transport_stream_loop_length_hi        :4; 
+#else
+   u_char transport_stream_loop_length_hi        :4; 
+   u_char                                        :4; 
+#endif
+   u_char transport_stream_loop_length_lo        :8; 
+} nit_mid_t; 
+ 
+#define SIZE_NIT_END 4 
+
+struct nit_end_struct { 
+   long CRC; 
+}; 
+ 
+#define NIT_TS_LEN 6 
+
+typedef struct { 
+   u_char transport_stream_id_hi                 :8; 
+   u_char transport_stream_id_lo                 :8; 
+   u_char original_network_id_hi                 :8; 
+   u_char original_network_id_lo                 :8; 
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :4; 
+   u_char transport_descriptors_length_hi        :4; 
+#else  
+   u_char transport_descriptors_length_hi        :4; 
+   u_char                                        :4; 
+#endif
+   u_char transport_descriptors_length_lo        :8; 
+   /* descriptors  */
+} nit_ts_t;
+
+/*
+ *
+ *    In addition to the PSI, data is needed to provide identification of
+ *    services and events for the user. In contrast with the PAT, CAT, and
+ *    PMT of the PSI, which give information only for the multiplex in which
+ *    they are contained (the actual multiplex), the additional information
+ *    defined within the present document can also provide information on
+ *    services and events carried by different multiplexes, and even on other
+ *    networks. This data is structured as nine tables:
+ *
+ *    1) Bouquet Association Table (BAT):
+ *
+ *       - the BAT provides information regarding bouquets. As well as giving
+ *         the name of the bouquet, it provides a list of services for each
+ *         bouquet.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    2) Service Description Table (SDT):
+ *
+ *       - the SDT contains data describing the services in the system e.g.
+ *         names of services, the service provider, etc.
+ *
+ */
+
+#define SDT_LEN 11
+
+typedef struct {
+   u_char table_id                               :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char section_syntax_indicator               :1;
+   u_char                                        :3;
+   u_char section_length_hi                      :4;
+#else
+   u_char section_length_hi                      :4;
+   u_char                                        :3;
+   u_char section_syntax_indicator               :1;
+#endif
+   u_char section_length_lo                      :8;
+   u_char transport_stream_id_hi                 :8;
+   u_char transport_stream_id_lo                 :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :2;
+   u_char version_number                         :5;
+   u_char current_next_indicator                 :1;
+#else
+   u_char current_next_indicator                 :1;
+   u_char version_number                         :5;
+   u_char                                        :2;
+#endif
+   u_char section_number                         :8;
+   u_char last_section_number                    :8;
+   u_char original_network_id_hi                 :8;
+   u_char original_network_id_lo                 :8;
+   u_char                                        :8;
+} sdt_t;
+
+#define SDT_DESCR_LEN 5
+
+typedef struct {
+   u_char service_id_hi                          :8;
+   u_char service_id_lo                          :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :6;
+   u_char eit_schedule_flag                      :1;
+   u_char eit_present_following_flag             :1;
+   u_char running_status                         :3;
+   u_char free_ca_mode                           :1;
+   u_char descriptors_loop_length_hi             :4;
+#else
+   u_char eit_present_following_flag             :1;
+   u_char eit_schedule_flag                      :1;
+   u_char                                        :6;
+   u_char descriptors_loop_length_hi             :4;
+   u_char free_ca_mode                           :1;
+   u_char running_status                         :3;
+#endif
+   u_char descriptors_loop_length_lo             :8;
+} sdt_descr_t;
+
+/*
+ *
+ *    3) Event Information Table (EIT):
+ * 
+ *       - the EIT contains data concerning events or programmes such as event
+ *         name, start time, duration, etc.; - the use of different descriptors
+ *         allows the transmission of different kinds of event information e.g.
+ *         for different service types.
+ *
+ */
+
+#define EIT_LEN 14
+
+typedef struct {
+   u_char table_id                               :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char section_syntax_indicator               :1;
+   u_char                                        :3;
+   u_char section_length_hi                      :4;
+#else
+   u_char section_length_hi                      :4;
+   u_char                                        :3;
+   u_char section_syntax_indicator               :1;
+#endif
+   u_char section_length_lo                      :8;
+   u_char service_id_hi                          :8;
+   u_char service_id_lo                          :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char                                        :2;
+   u_char version_number                         :5;
+   u_char current_next_indicator                 :1;
+#else
+   u_char current_next_indicator                 :1;
+   u_char version_number                         :5;
+   u_char                                        :2;
+#endif
+   u_char section_number                         :8;
+   u_char last_section_number                    :8;
+   u_char transport_stream_id_hi                 :8;
+   u_char transport_stream_id_lo                 :8;
+   u_char original_network_id_hi                 :8;
+   u_char original_network_id_lo                 :8;
+   u_char segment_last_section_number            :8;
+   u_char segment_last_table_id                  :8;
+} eit_t;
+
+#define EIT_EVENT_LEN 12
+
+typedef struct {
+   u_char event_id_hi                            :8;
+   u_char event_id_lo                            :8;
+   u_char mjd_hi                                 :8;
+   u_char mjd_lo                                 :8;
+   u_char start_time_h                           :8;
+   u_char start_time_m                           :8;
+   u_char start_time_s                           :8;
+   u_char duration_h                             :8;
+   u_char duration_m                             :8;
+   u_char duration_s                             :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char running_status                         :3;
+   u_char free_ca_mode                           :1;
+   u_char descriptors_loop_length_hi             :4;
+#else
+   u_char descriptors_loop_length_hi             :4;
+   u_char free_ca_mode                           :1;
+   u_char running_status                         :3;
+#endif
+   u_char descriptors_loop_length_lo             :8;
+} eit_event_t;
+
+/*
+ *
+ *    4) Running Status Table (RST):
+ *
+ *       - the RST gives the status of an event (running/not running). The RST
+ *         updates this information and allows timely automatic switching to
+ *         events.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    5) Time and Date Table (TDT):
+ *
+ *       - the TDT gives information relating to the present time and date.
+ *         This information is given in a separate table due to the frequent
+ *         updating of this information.
+ *
+ */
+
+#define TDT_LEN 8
+
+typedef struct {
+   u_char table_id                               :8; 
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char section_syntax_indicator               :1;
+   u_char                                        :3;
+   u_char section_length_hi                      :4;
+#else
+   u_char section_length_hi                      :4;
+   u_char                                        :3;
+   u_char section_syntax_indicator               :1;
+#endif
+   u_char section_length_lo                      :8;
+   u_char utc_mjd_hi                             :8;
+   u_char utc_mjd_lo                             :8;
+   u_char utc_time_h                             :8;
+   u_char utc_time_m                             :8;
+   u_char utc_time_s                             :8;
+} tdt_t;
+
+/*
+ *
+ *    6) Time Offset Table (TOT):
+ *
+ *       - the TOT gives information relating to the present time and date and
+ *         local time offset. This information is given in a separate table due
+ *         to the frequent updating of the time information.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    7) Stuffing Table (ST):
+ *
+ *       - the ST is used to invalidate existing sections, for example at
+ *         delivery system boundaries.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    8) Selection Information Table (SIT):
+ *
+ *       - the SIT is used only in "partial" (i.e. recorded) bitstreams. It
+ *         carries a summary of the SI information required to describe the
+ *         streams in the partial bitstream.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    9) Discontinuity Information Table (DIT):
+ *
+ *       - the DIT is used only in "partial" (i.e. recorded) bitstreams.
+ *         It is inserted where the SI information in the partial bitstream may
+ *         be discontinuous. Where applicable the use of descriptors allows a
+ *         flexible approach to the organization of the tables and allows for
+ *         future compatible extensions.
+ *
+ */
+    /* TO BE DONE */
+/*
+ *
+ *    The following describes the different descriptors that can be used within
+ *    the SI.
+ *
+ *    The following semantics apply to all the descriptors defined in this
+ *    subclause:
+ *
+ *    descriptor_tag: The descriptor tag is an 8-bit field which identifies
+ *                    each descriptor. Those values with MPEG-2 normative
+ *                    meaning are described in ISO/IEC 13818-1. The values of
+ *                    descriptor_tag are defined in 'libsi.h'
+ *    descriptor_length: The descriptor length is an 8-bit field specifying the
+ *                       total number of bytes of the data portion of the
+ *                       descriptor following the byte defining the value of
+ *                       this field.
+ *
+ */
+
+#define DESCR_GEN_LEN 2
+typedef struct descr_gen_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+} descr_gen_t;
+#define CastGenericDescriptor(x) ((descr_gen_t *)(x))
+
+#define GetDescriptorTag(x) (((descr_gen_t *) x)->descriptor_tag)
+#define GetDescriptorLength(x) (((descr_gen_t *) x)->descriptor_length+DESCR_GEN_LEN)
+
+
+/* 0x0A iso_639_language_descriptor */
+
+#define DESCR_ISO_639_LANGUAGE_LEN 5
+typedef struct descr_iso_639_language_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char lang_code1                             :8;
+   u_char lang_code2                             :8;
+   u_char lang_code3                             :8;
+} descr_iso_639_language_t;
+#define CastIso639LanguageDescriptor(x) ((descr_iso_639_language_t *)(x))
+
+
+/* 0x40 network_name_descriptor */
+
+#define DESCR_NETWORK_NAME_LEN XX
+typedef struct descr_network_name_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_network_name_t;
+#define CastNetworkNameDescriptor(x) ((descr_network_name_t *)(x))
+
+
+/* 0x41 service_list_descriptor */
+
+#define DESCR_SERVICE_LIST_LEN XX
+typedef struct descr_service_list_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_service_list_t;
+#define CastServiceListDescriptor(x) ((descr_service_list_t *)(x))
+
+
+/* 0x42 stuffing_descriptor */
+
+#define DESCR_STUFFING_LEN XX
+typedef struct descr_stuffing_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_stuffing_t;
+#define CastStuffingDescriptor(x) ((descr_stuffing_t *)(x))
+
+
+/* 0x43 satellite_delivery_system_descriptor */
+
+#define DESCR_SATELLITE_DELIVERY_SYSTEM_LEN 13
+typedef struct descr_satellite_delivery_system_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char frequency1                             :8;
+   u_char frequency2                             :8;
+   u_char frequency3                             :8;
+   u_char frequency4                             :8;
+   u_char orbital_position1                      :8;
+   u_char orbital_position2                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char modulation                             :5;
+   u_char polarization                           :2;
+   u_char west_east_flag                         :1;
+#else
+   u_char west_east_flag                         :1;
+   u_char polarization                           :2;
+   u_char modulation                             :5;
+#endif
+   u_char symbol_rate1                           :8;
+   u_char symbol_rate2                           :8;
+   u_char symbol_rate3                           :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char symbol_rate4                           :4;
+   u_char fec_inner                              :4;
+#else
+   u_char fec_inner                              :4;
+   u_char symbol_rate4                           :4;
+#endif
+} descr_satellite_delivery_system_t;
+#define CastSatelliteDeliverySystemDescriptor(x) ((descr_satellite_delivery_system_t *)(x))
+
+
+/* 0x44 cable_delivery_system_descriptor */
+
+#define DESCR_CABLE_DELIVERY_SYSTEM_LEN 13
+typedef struct descr_cable_delivery_system_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char frequency1                             :8;
+   u_char frequency2                             :8;
+   u_char frequency3                             :8;
+   u_char frequency4                             :8;
+   u_char reserved1                              :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char reserved2                              :4;
+   u_char fec_outer                              :4;
+#else
+   u_char fec_outer                              :4;
+   u_char reserved2                              :4;
+#endif
+   u_char modulation                             :8;
+   u_char symbol_rate1                           :8;
+   u_char symbol_rate2                           :8;
+   u_char symbol_rate3                           :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char symbol_rate4                           :4;
+   u_char fec_inner                              :4;
+#else
+   u_char fec_inner                              :4;
+   u_char symbol_rate4                           :4;
+#endif
+} descr_cable_delivery_system_t;
+#define CastCableDeliverySystemDescriptor(x) ((descr_cable_delivery_system_t *)(x))
+
+
+/* 0x45 vbi_data_descriptor */
+
+#define DESCR_VBI_DATA_LEN XX
+typedef struct descr_vbi_data_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_vbi_data_t;
+#define CastVbiDataDescriptor(x) ((descr_vbi_data_t *)(x))
+
+
+/* 0x46 vbi_teletext_descriptor */
+
+#define DESCR_VBI_TELETEXT_LEN XX
+typedef struct descr_vbi_teletext_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_vbi_teletext_t;
+#define CastVbiDescriptor(x) ((descr_vbi_teletext_t *)(x))
+
+
+/* 0x47 bouquet_name_descriptor */
+
+#define DESCR_BOUQUET_NAME_LEN 2
+typedef struct descr_bouquet_name_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+} descr_bouquet_name_t;
+#define CastBouquetNameDescriptor(x) ((descr_bouquet_name_t *)(x))
+
+
+/* 0x48 service_descriptor */
+
+#define DESCR_SERVICE_LEN  4
+typedef struct descr_service_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char service_type                           :8;
+   u_char provider_name_length                   :8;
+} descr_service_t;
+#define CastServiceDescriptor(x) ((descr_service_t *)(x))
+
+
+/* 0x49 country_availability_descriptor */
+
+#define DESCR_COUNTRY_AVAILABILITY_LEN 3
+typedef struct descr_country_availability_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char country_availability_flag              :1;
+   u_char reserved                               :7;
+#else
+   u_char reserved                               :7;
+   u_char country_availability_flag              :1;
+#endif
+} descr_country_availability_t;
+#define CastCountryAvailabilityDescriptor(x) ((descr_country_availability_t *)(x))
+
+
+/* 0x4A linkage_descriptor */
+
+#define DESCR_LINKAGE_LEN 9
+typedef struct descr_linkage_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char transport_stream_id_hi                 :8;
+   u_char transport_stream_id_lo                 :8;
+   u_char original_network_id_hi                 :8; 
+   u_char original_network_id_lo                 :8; 
+   u_char service_id_hi                          :8;
+   u_char service_id_lo                          :8;
+   u_char linkage_type                           :8;
+} descr_linkage_t;
+#define CastLinkageDescriptor(x) ((descr_linkage_t *)(x))
+
+
+/* 0x4B nvod_reference_descriptor */
+
+#define DESCR_NVOD_REFERENCE_LEN 2
+typedef struct descr_nvod_reference_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+} descr_nvod_reference_t;
+#define CastNvodReferenceDescriptor(x) ((descr_nvod_reference_t *)(x))
+
+#define ITEM_NVOD_REFERENCE_LEN 6
+typedef struct item_nvod_reference_struct {
+   u_char transport_stream_id_hi                 :8;
+   u_char transport_stream_id_lo                 :8;
+   u_char original_network_id_hi                 :8; 
+   u_char original_network_id_lo                 :8; 
+   u_char service_id_hi                          :8;
+   u_char service_id_lo                          :8;
+} item_nvod_reference_t;
+#define CastNvodReferenceItem(x) ((item_nvod_reference_t *)(x))
+
+
+
+/* 0x4C time_shifted_service_descriptor */
+
+#define DESCR_TIME_SHIFTED_SERVICE_LEN 4
+typedef struct descr_time_shifted_service_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char reference_service_id_hi                :8;
+   u_char reference_service_id_lo                :8;
+} descr_time_shifted_service_t;
+#define CastTimeShiftedServiceDescriptor(x) ((descr_time_shifted_service_t *)(x))
+
+
+/* 0x4D short_event_descriptor */
+
+#define DESCR_SHORT_EVENT_LEN 6
+typedef struct descr_short_event_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char lang_code1                             :8;
+   u_char lang_code2                             :8;
+   u_char lang_code3                             :8;
+   u_char event_name_length                      :8;
+} descr_short_event_t;
+#define CastShortEventDescriptor(x) ((descr_short_event_t *)(x))
+
+
+/* 0x4E extended_event_descriptor */
+
+#define DESCR_EXTENDED_EVENT_LEN 7
+typedef struct descr_extended_event_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char descriptor_number                      :4;
+   u_char last_descriptor_number                 :4;
+#else
+   u_char last_descriptor_number                 :4;
+   u_char descriptor_number                      :4;
+#endif
+   u_char lang_code1                             :8;
+   u_char lang_code2                             :8;
+   u_char lang_code3                             :8;
+   u_char length_of_items                        :8;
+} descr_extended_event_t;
+#define CastExtendedEventDescriptor(x) ((descr_extended_event_t *)(x))
+
+#define ITEM_EXTENDED_EVENT_LEN 1
+typedef struct item_extended_event_struct {
+   u_char item_description_length               :8;
+} item_extended_event_t;
+#define CastExtendedEventItem(x) ((item_extended_event_t *)(x))
+
+
+/* 0x4F time_shifted_event_descriptor */
+
+#define DESCR_TIME_SHIFTED_EVENT_LEN 6
+typedef struct descr_time_shifted_event_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char reference_service_id_hi                :8;
+   u_char reference_service_id_lo                :8;
+   u_char reference_event_id_hi                  :8;
+   u_char reference_event_id_lo                  :8;
+} descr_time_shifted_event_t;
+#define CastTimeShiftedEventDescriptor(x) ((descr_time_shifted_event_t *)(x))
+
+
+/* 0x50 component_descriptor */
+
+#define DESCR_COMPONENT_LEN  8
+typedef struct descr_component_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char reserved                               :4;
+   u_char stream_content                         :4;
+#else
+   u_char stream_content                         :4;
+   u_char reserved                               :4;
+#endif
+   u_char component_type                         :8;
+   u_char component_tag                          :8;
+   u_char lang_code1                             :8;
+   u_char lang_code2                             :8;
+   u_char lang_code3                             :8;
+} descr_component_t;
+#define CastComponentDescriptor(x) ((descr_component_t *)(x))
+
+
+/* 0x51 mosaic_descriptor */
+
+#define DESCR_MOSAIC_LEN XX
+typedef struct descr_mosaic_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_mosaic_t;
+#define CastMosaicDescriptor(x) ((descr_mosaic_t *)(x))
+
+
+/* 0x52 stream_identifier_descriptor */
+
+#define DESCR_STREAM_IDENTIFIER_LEN 3
+typedef struct descr_stream_identifier_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char component_tag                          :8;
+} descr_stream_identifier_t;
+#define CastStreamIdentifierDescriptor(x) ((descr_stream_identifier_t *)(x))
+
+
+/* 0x53 ca_identifier_descriptor */
+
+#define DESCR_CA_IDENTIFIER_LEN 2
+typedef struct descr_ca_identifier_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+} descr_ca_identifier_t;
+#define CastCaIdentifierDescriptor(x) ((descr_ca_identifier_t *)(x))
+
+
+/* 0x54 content_descriptor */
+
+#define DESCR_CONTENT_LEN 2
+typedef struct descr_content_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+} descr_content_t;
+#define CastContentDescriptor(x) ((descr_content_t *)(x))
+
+typedef struct nibble_content_struct {
+#if BYTE_ORDER == BIG_ENDIAN
+   u_char content_nibble_level_1                 :4;
+   u_char content_nibble_level_2                 :4;
+   u_char user_nibble_1                          :4;
+   u_char user_nibble_2                          :4;
+#else
+   u_char user_nibble_2                          :4;
+   u_char user_nibble_1                          :4;
+   u_char content_nibble_level_2                 :4;
+   u_char content_nibble_level_1                 :4;
+#endif
+} nibble_content_t;
+#define CastContentNibble(x) ((nibble_content_t *)(x))
+
+
+/* 0x55 parental_rating_descriptor */
+
+#define DESCR_PARENTAL_RATING_LEN 2
+typedef struct descr_parental_rating_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+} descr_parental_rating_t;
+#define CastParentalRatingDescriptor(x) ((descr_parental_rating_t *)(x))
+
+#define PARENTAL_RATING_LEN 4
+typedef struct parental_rating_struct {
+   u_char lang_code1                             :8;
+   u_char lang_code2                             :8;
+   u_char lang_code3                             :8;
+   u_char rating                                 :8;
+} parental_rating_t;
+#define CastParentalRating(x) ((parental_rating_t *)(x))
+
+
+/* 0x56 teletext_descriptor */
+
+#define DESCR_TELETEXT_LEN XX
+typedef struct descr_teletext_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_teletext_t;
+#define CastTeletextDescriptor(x) ((descr_teletext_t *)(x))
+
+
+/* 0x57 telephone_descriptor */
+
+#define DESCR_TELEPHONE_LEN XX
+typedef struct descr_telephone_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_telephone_t;
+#define CastTelephoneDescriptor(x) ((descr_telephone_t *)(x))
+
+
+/* 0x58 local_time_offset_descriptor */
+
+#define DESCR_LOCAL_TIME_OFFSET_LEN XX
+typedef struct descr_local_time_offset_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_local_time_offset_t;
+#define CastLocalTimeOffsetDescriptor(x) ((descr_local_time_offset_t *)(x))
+
+
+/* 0x59 subtitling_descriptor */
+
+#define DESCR_SUBTITLING_LEN XX
+typedef struct descr_subtitling_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_subtitling_t;
+#define CastSubtitlingDescriptor(x) ((descr_subtitling_t *)(x))
+
+
+/* 0x5A terrestrial_delivery_system_descriptor */
+
+#define DESCR_TERRESTRIAL_DELIVERY_SYSTEM_LEN XX
+typedef struct descr_terrestrial_delivery_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_terrestrial_delivery_system_t;
+#define CastTerrestrialDeliverySystemDescriptor(x) ((descr_terrestrial_delivery_system_t *)(x))
+
+
+/* 0x5B multilingual_network_name_descriptor */
+
+#define DESCR_MULTILINGUAL_NETWORK_NAME_LEN XX
+typedef struct descr_multilingual_network_name_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_multilingual_network_name_t;
+#define CastMultilingualNetworkNameDescriptor(x) ((descr_multilingual_network_name_t *)(x))
+
+
+/* 0x5C multilingual_bouquet_name_descriptor */
+
+#define DESCR_MULTILINGUAL_BOUQUET_NAME_LEN XX
+typedef struct descr_multilingual_bouquet_name_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_multilingual_bouquet_name_t;
+#define CastMultilingualBouquetNameDescriptor(x) ((descr_multilingual_bouquet_name_t *)(x))
+
+
+/* 0x5D multilingual_service_name_descriptor */
+
+#define DESCR_MULTILINGUAL_SERVICE_NAME_LEN XX
+typedef struct descr_multilingual_service_name_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_multilingual_service_name_t;
+#define CastMultilingualServiceNameDescriptor(x) ((descr_multilingual_service_name_t *)(x))
+
+
+/* 0x5E multilingual_component_descriptor */
+
+#define DESCR_MULTILINGUAL_COMPONENT_LEN XX
+typedef struct descr_multilingual_component_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_multilingual_component_t;
+#define CastMultilingualComponentDescriptor(x) ((descr_multilingual_component_t *)(x))
+
+
+/* 0x5F private_data_specifier_descriptor */
+
+#define DESCR_PRIVATE_DATA_SPECIFIER_LEN XX
+typedef struct descr_private_data_specifier_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_private_data_specifier_t;
+#define CastPrivateDataSpecifierDescriptor(x) ((descr_private_data_specifier_t *)(x))
+
+
+/* 0x60 service_move_descriptor */
+
+#define DESCR_SERVICE_MOVE_LEN XX
+typedef struct descr_service_move_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_service_move_t;
+#define CastServiceMoveDescriptor(x) ((descr_service_move_t *)(x))
+
+
+/* 0x61 short_smoothing_buffer_descriptor */
+
+#define DESCR_SHORT_SMOOTHING_BUFFER_LEN XX
+typedef struct descr_short_smoothing_buffer_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_short_smoothing_buffer_t;
+#define CastShortSmoothingBufferDescriptor(x) ((descr_short_smoothing_buffer_t *)(x))
+
+
+/* 0x62 frequency_list_descriptor */
+
+#define DESCR_FREQUENCY_LIST_LEN XX
+typedef struct descr_frequency_list_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_frequency_list_t;
+#define CastFrequencyListDescriptor(x) ((descr_frequency_list_t *)(x))
+
+
+/* 0x63 partial_transport_stream_descriptor */
+
+#define DESCR_PARTIAL_TRANSPORT_STREAM_LEN XX
+typedef struct descr_partial_transport_stream_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_partial_transport_stream_t;
+#define CastPartialDescriptor(x) ((descr_partial_transport_stream_t *)(x))
+
+
+/* 0x64 data_broadcast_descriptor */
+
+#define DESCR_DATA_BROADCAST_LEN XX
+typedef struct descr_data_broadcast_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_data_broadcast_t;
+#define CastDataBroadcastDescriptor(x) ((descr_data_broadcast_t *)(x))
+
+
+/* 0x65 ca_system_descriptor */
+
+#define DESCR_CA_SYSTEM_LEN XX
+typedef struct descr_ca_system_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_ca_system_t;
+#define CastCaSystemDescriptor(x) ((descr_ca_system_t *)(x))
+
+
+/* 0x66 data_broadcast_id_descriptor */
+
+#define DESCR_DATA_BROADCAST_ID_LEN XX
+typedef struct descr_data_broadcast_id_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_data_broadcast_id_t;
+#define CastDataBroadcastIdDescriptor(x) ((descr_data_broadcast_id_t *)(x))
+
+
+/* 0x67 transport_stream_descriptor */
+
+#define DESCR_TRANSPORT_STREAM_LEN XX
+typedef struct descr_transport_stream_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_transport_stream_t;
+#define CastTransportStreamDescriptor(x) ((descr_transport_stream_t *)(x))
+
+
+/* 0x68 dsng_descriptor */
+
+#define DESCR_DSNG_LEN XX
+typedef struct descr_dsng_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_dsng_t;
+#define CastDsngDescriptor(x) ((descr_dsng_t *)(x))
+
+
+/* 0x69 pdc_descriptor */
+
+#define DESCR_PDC_LEN XX
+typedef struct descr_pdc_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_pdc_t;
+#define CastPdcDescriptor(x) ((descr_pdc_t *)(x))
+
+
+/* 0x6A ac3_descriptor */
+
+#define DESCR_AC3_LEN XX
+typedef struct descr_ac3_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_ac3_t;
+#define CastAc3Descriptor(x) ((descr_ac3_t *)(x))
+
+
+/* 0x6B ancillary_data_descriptor */
+
+#define DESCR_ANCILLARY_DATA_LEN 3
+typedef struct descr_ancillary_data_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   u_char ancillary_data_identifier              :8;
+} descr_ancillary_data_t;
+#define CastAncillaryDataDescriptor(x) ((descr_ancillary_data_t *)(x))
+
+
+/* 0x6C cell_list_descriptor */
+
+#define DESCR_CELL_LIST_LEN XX
+typedef struct descr_cell_list_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_cell_list_t;
+#define CastCellListDescriptor(x) ((descr_cell_list_t *)(x))
+
+
+/* 0x6D cell_frequency_link_descriptor */
+
+#define DESCR_CELL_FREQUENCY_LINK_LEN XX
+typedef struct descr_cell_frequency_link_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_cell_frequency_link_t;
+#define CastCellFrequencyLinkDescriptor(x) ((descr_cell_frequency_link_t *)(x))
+
+
+/* 0x6E announcement_support_descriptor */
+
+#define DESCR_ANNOUNCEMENT_SUPPORT_LEN XX
+typedef struct descr_announcement_support_struct {
+   u_char descriptor_tag                         :8;
+   u_char descriptor_length                      :8;
+   /* TBD */
+} descr_announcement_support_t;
+#define CastAnnouncementSupportDescriptor(x) ((descr_announcement_support_t *)(x))
+
+#endif
diff --git a/libdtv/libsi/si_debug_services.c b/libdtv/libsi/si_debug_services.c
new file mode 100644
index 00000000..4508d43d
--- /dev/null
+++ b/libdtv/libsi/si_debug_services.c
@@ -0,0 +1,487 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// si_debug_services.c: debugging functions for libsi     ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.2 $
+// $Date: 2001/06/25 19:39:00 $
+// $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.
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "../liblx/liblx.h"
+#include "libsi.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);
+
+      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_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");
+               printf ("%s      Description: %s\n", xName(Item));
+               printf ("%s      Text: %s\n", Item->Text);
+            }
+         }
+         break;
+
+         case DESCR_CA_IDENT:
+            printf ("%sDescriptor: Conditional Access Identity\n", Prepend);
+            {
+               int j;
+               for (j = 0; j < ((struct CaIdentifierDescriptor *)Descriptor)->Amount; j++)
+                  printf ("%s   SystemID: 0x%04x\n", Prepend, GetCaIdentifierID (Descriptor, j));
+            }
+         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_NW_NAME:
+         case DESCR_SERVICE_LIST:
+         case DESCR_STUFFING:
+         case DESCR_SAT_DEL_SYS:
+         case DESCR_CABLE_DEL_SYS:
+         case DESCR_VBI_DATA:
+         case DESCR_VBI_TELETEXT:
+         case DESCR_MOSAIC:
+         case DESCR_TELETEXT:
+         case DESCR_TELEPHONE:
+         case DESCR_LOCAL_TIME_OFF:
+         case DESCR_SUBTITLING:
+         case DESCR_TERR_DEL_SYS:
+         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: (noch nicht unterst�tzt)\n", Prepend);
+         break;
+      }
+   }
+   return;
+}
+
diff --git a/libdtv/libsi/si_debug_services.h b/libdtv/libsi/si_debug_services.h
new file mode 100644
index 00000000..d33b0aa7
--- /dev/null
+++ b/libdtv/libsi/si_debug_services.h
@@ -0,0 +1,217 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// si_debug_services.h: local debugging definitions       ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.1 $
+// $Date: 2001/08/15 10:00:00 $
+// $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[][70] = {
+   "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"
+};
diff --git a/libdtv/libsi/si_parser.c b/libdtv/libsi/si_parser.c
new file mode 100644
index 00000000..e8579511
--- /dev/null
+++ b/libdtv/libsi/si_parser.c
@@ -0,0 +1,881 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// si_parser.c: main parsing functions of libsi           ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.2 $
+// $Date: 2001/06/25 19:39:00 $
+// $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.
+
+#include <stdio.h>
+#include <math.h>
+#include <time.h>
+
+#include "../liblx/liblx.h"
+#include "libsi.h"
+#include "si_tables.h"
+
+
+
+struct LIST *siParsePAT (u_char *Buffer) 
+{
+   pat_t               *Pat;
+   pat_prog_t          *PatProgram;
+   u_char              *Ptr;
+   u_int                SectionLength;
+   int                  TransportStreamID;
+   int                  PatVersion;
+   struct Program      *Program;
+   struct LIST         *ProgramList = NULL;
+
+   if (!Buffer) return NULL;
+
+   Pat = (pat_t *) Buffer; Ptr = Buffer;
+
+   if (Pat->table_id != TID_PAT) {
+//      fprintf (stderr, "PAT: wrong TID %d\n", Pat->table_id);
+      return NULL;
+   }
+
+   SectionLength = HILO (Pat->section_length) + 3 - PAT_LEN - 4;
+
+   if (crc32 (Ptr, HILO (Pat->section_length) + 3)) return (NULL);
+
+   TransportStreamID = HILO (Pat->transport_stream_id);
+   PatVersion = Pat->version_number;
+
+   Ptr += PAT_LEN;
+
+   while (SectionLength > 0)
+   {
+      PatProgram = (pat_prog_t *) Ptr;
+
+      CreateProgram (Program, HILO (PatProgram->program_number),
+         TransportStreamID, HILO (PatProgram->network_pid), PatVersion);
+
+      if (!ProgramList) ProgramList = xNewList (NULL);
+      xAddTail (ProgramList, Program);
+
+      SectionLength -= PAT_PROG_LEN;
+      Ptr += PAT_PROG_LEN;
+   }
+
+   return (ProgramList);
+}
+
+
+struct Pid *siParsePMT (u_char *Buffer) 
+{
+   pmt_t               *Pmt;
+   pmt_info_t          *PmtInfo;
+   u_char              *Ptr;
+   u_int                SectionLength, ProgramInfoLength,
+                        StreamLength, LoopLength;
+   int                  ProgramID;
+   int                  PcrID;
+   int                  PmtVersion;
+   struct Pid          *Pid;
+   struct PidInfo      *PidInfo;
+
+   if (!Buffer) return NULL;
+
+   Pmt = (pmt_t *) Buffer; Ptr = Buffer;
+
+   if (Pmt->table_id != TID_PMT) {
+//      fprintf (stderr, "PMT: wrong TID %d\n", Pmt->table_id);
+      return NULL;
+   }
+
+   SectionLength = HILO (Pmt->section_length) + 3 - 4;
+
+   if (crc32 (Ptr, HILO (Pmt->section_length) + 3)) return (NULL);
+
+   ProgramInfoLength = HILO (Pmt->program_info_length);
+   StreamLength = SectionLength - ProgramInfoLength - PMT_LEN;
+
+   ProgramID = HILO (Pmt->program_number);
+   PmtVersion = Pmt->version_number;
+   PcrID = HILO (Pmt->PCR_PID);
+
+   Ptr += PMT_LEN;
+
+   CreatePid (Pid, ProgramID, PcrID, PmtVersion);
+
+   siParseDescriptors (Pid->Descriptors, Ptr, ProgramInfoLength, Pmt->table_id);
+
+   Ptr += ProgramInfoLength;
+
+   while (StreamLength > 0)
+   {
+      PmtInfo = (pmt_info_t *) Ptr;
+
+      CreatePidInfo (PidInfo, PmtInfo->stream_type,
+                        HILO (PmtInfo->elementary_PID));
+
+      LoopLength = HILO (PmtInfo->ES_info_length);
+      Ptr += PMT_INFO_LEN;
+
+      siParseDescriptors (PidInfo->Descriptors, Ptr, LoopLength, Pmt->table_id);
+
+      xAddTail (Pid->InfoList, PidInfo);
+
+      StreamLength -= LoopLength + PMT_INFO_LEN;
+      Ptr += LoopLength;
+   }
+
+   return (Pid);
+}
+
+
+struct LIST *siParseSDT (u_char *Buffer) 
+{
+   sdt_t               *Sdt;
+   sdt_descr_t         *SdtDescriptor;
+   u_char              *Ptr;
+   u_int                SectionLength, LoopLength;
+   int                  TransportStreamID;
+   int                  SdtVersion;
+   int                  OriginalNetworkID;
+   struct Service      *Service;
+   struct LIST         *ServiceList = NULL;
+
+   if (!Buffer) return NULL;
+
+   Sdt = (sdt_t *) Buffer; Ptr = Buffer;
+
+   if (Sdt->table_id != TID_SDT_ACT && Sdt->table_id != TID_SDT_OTH) {
+//      fprintf (stderr, "SDT: wrong TID %d\n", Sdt->table_id);
+      return NULL;
+   }
+
+   SectionLength = HILO (Sdt->section_length) + 3 - SDT_LEN - 4;
+
+   if (crc32 (Ptr, HILO (Sdt->section_length) + 3)) return (NULL);
+
+   TransportStreamID = HILO (Sdt->transport_stream_id);
+   SdtVersion = Sdt->version_number;
+   OriginalNetworkID = HILO (Sdt->original_network_id);
+
+   Ptr += SDT_LEN;
+
+   while (SectionLength > 0)
+   {
+      SdtDescriptor = (sdt_descr_t *) Ptr;
+
+      CreateService (Service, HILO (SdtDescriptor->service_id),
+         TransportStreamID, OriginalNetworkID, SdtVersion,
+         SdtDescriptor->free_ca_mode ? CONDITIONAL_ACCESS : FREE_TO_AIR);
+
+      switch (SdtDescriptor->running_status)
+      {
+         case 0x01:
+            SetRunningStatus (Service->Status, RUNNING_STATUS_NOT_RUNNING);
+         break;
+
+         case 0x02:
+            SetRunningStatus (Service->Status, RUNNING_STATUS_AWAITING);
+         break;
+
+         case 0x03:
+            SetRunningStatus (Service->Status, RUNNING_STATUS_PAUSING);
+         break;
+
+         case 0x04:
+         default:
+            SetRunningStatus (Service->Status, RUNNING_STATUS_RUNNING);
+         break;
+      }
+      if (SdtDescriptor->eit_schedule_flag)
+         SetScheduleFlag (Service->Status);
+      if (SdtDescriptor->eit_present_following_flag)
+         SetPresentFollowing (Service->Status);
+
+      LoopLength = HILO (SdtDescriptor->descriptors_loop_length);
+      Ptr += SDT_DESCR_LEN;
+
+      siParseDescriptors (Service->Descriptors, Ptr, LoopLength, Sdt->table_id);
+
+      if (!ServiceList) ServiceList = xNewList (NULL);
+      xAddTail (ServiceList, Service);
+
+      SectionLength -= LoopLength + SDT_DESCR_LEN;
+      Ptr += LoopLength;
+   }
+
+   return (ServiceList);
+}
+
+
+struct LIST *siParseEIT (u_char *Buffer) 
+{
+   eit_t               *Eit;
+   eit_event_t         *EitEvent;
+   u_char              *Ptr;
+   u_int                SectionLength, LoopLength;
+   int                  ServiceID;
+   int                  EitVersion;
+   int                  TransportStreamID;
+   int                  OriginalNetworkID;
+   struct Event        *Event;
+   struct LIST         *EventList = NULL;
+
+   if (!Buffer) return NULL;
+
+   Eit = (eit_t *) Buffer; Ptr = Buffer;
+
+   if (Eit->table_id != TID_EIT_ACT && Eit->table_id != TID_EIT_OTH &&
+       !(Eit->table_id >= TID_EIT_ACT_SCH &&
+         Eit->table_id <= TID_EIT_ACT_SCH + 0x0F) &&
+       !(Eit->table_id >= TID_EIT_OTH_SCH &&
+         Eit->table_id <= TID_EIT_OTH_SCH + 0x0F)) {
+//      fprintf (stderr, "EIT: wrong TID %d\n", Eit->table_id);
+      return NULL;
+   }
+
+   SectionLength = HILO (Eit->section_length) + 3 - EIT_LEN - 4;
+
+   if (crc32 (Ptr, HILO (Eit->section_length) + 3)) return (NULL);
+
+   ServiceID = HILO (Eit->service_id);
+   TransportStreamID = HILO (Eit->transport_stream_id);
+   EitVersion = Eit->version_number;
+   OriginalNetworkID = HILO (Eit->original_network_id);
+
+   Ptr += EIT_LEN;
+
+   while (SectionLength > 0)
+   {
+      struct tm thisTime;
+      int year, month, day;
+      double mjd;
+
+      EitEvent = (eit_event_t *) Ptr;
+
+      CreateEvent (Event, HILO (EitEvent->event_id), ServiceID,
+         TransportStreamID, OriginalNetworkID, EitVersion,
+         EitEvent->free_ca_mode ? CONDITIONAL_ACCESS : FREE_TO_AIR);
+
+      switch (EitEvent->running_status)
+      {
+         case 0x01:
+            SetRunningStatus (Event->Status, RUNNING_STATUS_NOT_RUNNING);
+         break;
+
+         case 0x02:
+            SetRunningStatus (Event->Status, RUNNING_STATUS_AWAITING);
+         break;
+
+         case 0x03:
+            SetRunningStatus (Event->Status, RUNNING_STATUS_PAUSING);
+         break;
+
+         case 0x04:
+         default:
+            SetRunningStatus (Event->Status, RUNNING_STATUS_RUNNING);
+         break;
+      }
+      Event->StartTime = MjdToEpochTime (EitEvent->mjd) +
+                         BcdTimeToSeconds (EitEvent->start_time);
+      Event->Duration = BcdTimeToSeconds (EitEvent->duration);
+
+      LoopLength = HILO (EitEvent->descriptors_loop_length);
+      Ptr += EIT_EVENT_LEN;
+
+      siParseDescriptors (Event->Descriptors, Ptr, LoopLength, Eit->table_id);
+
+      if (!EventList) EventList = xNewList (NULL);
+      xAddTail (EventList, Event);
+
+      SectionLength -= LoopLength + EIT_EVENT_LEN;
+      Ptr += LoopLength;
+   }
+
+   return (EventList);
+}
+
+
+time_t siParseTDT (u_char *Buffer) 
+{
+   tdt_t               *Tdt;
+   u_char              *Ptr;
+   u_int                SectionLength;
+   int                  TdtVersion;
+   time_t               CurrentTime;
+
+   if (!Buffer) return 0;
+
+   Tdt = (tdt_t *) Buffer; Ptr = Buffer;
+
+   if (Tdt->table_id != TID_TDT) {
+//      fprintf (stderr, "TDT: wrong TID %d\n", Tdt->table_id);
+      return 0;
+   }
+
+   SectionLength = HILO (Tdt->section_length) + 3;  /* no CRC ?! */
+
+   CurrentTime = MjdToEpochTime (Tdt->utc_mjd) +
+                 BcdTimeToSeconds (Tdt->utc_time);
+
+   return (CurrentTime);
+}
+
+
+void siParseDescriptors (struct LIST *Descriptors, u_char *Buffer,
+                         u_int Length, u_char TableID)
+{
+   u_int        DescriptorLength;
+   u_char      *Ptr;
+
+   DescriptorLength = 0;
+   Ptr = Buffer;
+
+   while (DescriptorLength < Length)
+   {
+      switch (TableID)
+      {
+         case TID_NIT_ACT: case TID_NIT_OTH:
+            switch (GetDescriptorTag(Ptr))
+            {
+               case DESCR_NW_NAME:
+               case DESCR_SERVICE_LIST:
+               case DESCR_STUFFING:
+               case DESCR_SAT_DEL_SYS:
+               case DESCR_CABLE_DEL_SYS:
+               case DESCR_LINKAGE:
+               case DESCR_TERR_DEL_SYS:
+               case DESCR_ML_NW_NAME:
+               case DESCR_PRIV_DATA_SPEC:
+               case DESCR_CELL_LIST:
+               case DESCR_CELL_FREQ_LINK:
+               case DESCR_ANNOUNCEMENT_SUPPORT:
+                  siParseDescriptor (Descriptors, Ptr);
+               break;
+
+               default:
+               /*   fprintf (stderr, "forbidden descriptor 0x%x in NIT\n",
+                              GetDescriptorTag(Ptr));*/
+               break;
+            }
+         break;
+
+         case TID_BAT:
+            switch (GetDescriptorTag(Ptr))
+            {
+               case DESCR_SERVICE_LIST:
+               case DESCR_STUFFING:
+               case DESCR_BOUQUET_NAME:
+               case DESCR_SERVICE:
+               case DESCR_COUNTRY_AVAIL:
+               case DESCR_LINKAGE:
+               case DESCR_CA_IDENT:
+               case DESCR_ML_BQ_NAME:
+               case DESCR_PRIV_DATA_SPEC:
+                  siParseDescriptor (Descriptors, Ptr);
+               break;
+
+               default:
+                  /*fprintf (stderr, "forbidden descriptor 0x%x in BAT\n",
+                              GetDescriptorTag(Ptr));*/
+               break;
+            }
+         break;
+
+         case TID_SDT_ACT: case TID_SDT_OTH:
+            switch (GetDescriptorTag(Ptr))
+            {
+               case DESCR_STUFFING:
+               case DESCR_BOUQUET_NAME:
+               case DESCR_SERVICE: 
+               case DESCR_COUNTRY_AVAIL: 
+               case DESCR_LINKAGE:
+               case DESCR_NVOD_REF:
+               case DESCR_TIME_SHIFTED_SERVICE:
+               case DESCR_MOSAIC:
+               case DESCR_CA_IDENT:
+               case DESCR_TELEPHONE:
+               case DESCR_ML_SERVICE_NAME:
+               case DESCR_PRIV_DATA_SPEC:
+               case DESCR_DATA_BROADCAST:
+                  siParseDescriptor (Descriptors, Ptr);
+               break;
+
+               default:
+                  /* fprintf (stderr, "forbidden descriptor 0x%x in SDT\n",
+                              GetDescriptorTag(Ptr)); */
+               break;
+            }
+         break;
+
+         case TID_EIT_ACT: case TID_EIT_OTH:
+         case TID_EIT_ACT_SCH: case TID_EIT_OTH_SCH:
+         case TID_EIT_ACT_SCH+1: case TID_EIT_OTH_SCH+1:
+         case TID_EIT_ACT_SCH+2: case TID_EIT_OTH_SCH+2:
+         case TID_EIT_ACT_SCH+3: case TID_EIT_OTH_SCH+3:
+         case TID_EIT_ACT_SCH+4: case TID_EIT_OTH_SCH+4:
+         case TID_EIT_ACT_SCH+5: case TID_EIT_OTH_SCH+5:
+         case TID_EIT_ACT_SCH+6: case TID_EIT_OTH_SCH+6:
+         case TID_EIT_ACT_SCH+7: case TID_EIT_OTH_SCH+7:
+         case TID_EIT_ACT_SCH+8: case TID_EIT_OTH_SCH+8:
+         case TID_EIT_ACT_SCH+9: case TID_EIT_OTH_SCH+9:
+         case TID_EIT_ACT_SCH+10: case TID_EIT_OTH_SCH+10:
+         case TID_EIT_ACT_SCH+11: case TID_EIT_OTH_SCH+11:
+         case TID_EIT_ACT_SCH+12: case TID_EIT_OTH_SCH+12:
+         case TID_EIT_ACT_SCH+13: case TID_EIT_OTH_SCH+13:
+         case TID_EIT_ACT_SCH+14: case TID_EIT_OTH_SCH+14:
+         case TID_EIT_ACT_SCH+15: case TID_EIT_OTH_SCH+15:
+            switch (GetDescriptorTag(Ptr))
+            {
+               case DESCR_STUFFING:
+               case DESCR_LINKAGE:
+               case DESCR_SHORT_EVENT:
+               case DESCR_EXTENDED_EVENT:
+               case DESCR_TIME_SHIFTED_EVENT:
+               case DESCR_COMPONENT:
+               case DESCR_CA_IDENT:
+               case DESCR_CONTENT:
+               case DESCR_PARENTAL_RATING:
+               case DESCR_TELEPHONE:
+               case DESCR_ML_COMPONENT:
+               case DESCR_PRIV_DATA_SPEC:
+               case DESCR_SHORT_SMOOTH_BUF:
+               case DESCR_DATA_BROADCAST:
+               case DESCR_PDC:
+                  siParseDescriptor (Descriptors, Ptr);
+               break;
+
+               default:
+                  /*fprintf (stderr, "forbidden descriptor 0x%x in EIT\n",
+                              GetDescriptorTag(Ptr));*/
+               break;
+            }
+         break;
+
+         case TID_TOT:
+            switch (GetDescriptorTag(Ptr))
+            {
+               case DESCR_LOCAL_TIME_OFF:
+                  siParseDescriptor (Descriptors, Ptr);
+               break;
+
+               default:
+                  /*fprintf (stderr, "forbidden descriptor 0x%x in TOT\n",
+                              GetDescriptorTag(Ptr));*/
+               break;
+            }
+         break;
+
+         case TID_PMT:
+            switch (GetDescriptorTag(Ptr))
+            {
+               case DESCR_VBI_DATA:
+               case DESCR_VBI_TELETEXT:
+               case DESCR_MOSAIC:
+               case DESCR_STREAM_ID:
+               case DESCR_TELETEXT:
+               case DESCR_SUBTITLING:
+               case DESCR_PRIV_DATA_SPEC:
+               case DESCR_SERVICE_MOVE:
+               case DESCR_CA_SYSTEM:
+               case DESCR_DATA_BROADCAST_ID:
+               case DESCR_AC3:
+               case DESCR_ANCILLARY_DATA:
+               case DESCR_VIDEO_STREAM:
+               case DESCR_AUDIO_STREAM:
+               case DESCR_HIERARCHY:
+               case DESCR_REGISTRATION:
+               case DESCR_DATA_STREAM_ALIGN:
+               case DESCR_TARGET_BACKGRID:
+               case DESCR_VIDEO_WINDOW:
+               case DESCR_CA:
+               case DESCR_ISO_639_LANGUAGE:
+               case DESCR_SYSTEM_CLOCK:
+               case DESCR_MULTIPLEX_BUFFER_UTIL:
+               case DESCR_COPYRIGHT:
+               case DESCR_MAXIMUM_BITRATE:
+                  siParseDescriptor (Descriptors, Ptr);
+               break;
+
+               default:
+                  /* fprintf (stderr, "forbidden descriptor 0x%x in PMT\n",
+                              GetDescriptorTag(Ptr)); */
+               break;
+            }
+         break;
+
+         default:
+            fprintf (stderr, "descriptor 0x%x in unsupported table 0x%x\n",
+                         GetDescriptorTag(Ptr), TableID);
+         break;
+      }
+      DescriptorLength += GetDescriptorLength (Ptr);
+      Ptr += GetDescriptorLength (Ptr);
+   }
+   return;
+}
+
+
+void siParseDescriptor (struct LIST *Descriptors, u_char *Buffer)
+{
+   struct NODE     *Descriptor = NULL;
+   char            *Text , *Text2;
+   u_char          *Ptr;
+   int              Length, i;
+
+   if (!Descriptors || !Buffer) return;
+
+   Ptr = Buffer;
+
+   switch (GetDescriptorTag(Buffer))
+   {
+      case DESCR_ANCILLARY_DATA:
+         CreateAncillaryDataDescriptor (Descriptor,
+                   CastAncillaryDataDescriptor(Buffer)->ancillary_data_identifier);
+      break;
+
+      case DESCR_BOUQUET_NAME:
+         Text = siGetDescriptorText (Buffer + DESCR_BOUQUET_NAME_LEN,
+                   GetDescriptorLength (Buffer) - DESCR_BOUQUET_NAME_LEN);
+         CreateBouquetNameDescriptor (Descriptor, Text);
+//         xMemFree (Text);
+      break;
+
+      case DESCR_COMPONENT:
+         Text = siGetDescriptorText (Buffer + DESCR_COMPONENT_LEN,
+                   GetDescriptorLength (Buffer) - DESCR_COMPONENT_LEN);
+         CreateComponentDescriptor (Descriptor,
+                   CastComponentDescriptor(Buffer)->stream_content,
+                   CastComponentDescriptor(Buffer)->component_type,
+                   CastComponentDescriptor(Buffer)->component_tag,
+                   CastComponentDescriptor(Buffer)->lang_code1,
+                   CastComponentDescriptor(Buffer)->lang_code2,
+                   CastComponentDescriptor(Buffer)->lang_code3, Text);
+//         xMemFree (Text);
+      break;
+
+      case DESCR_SERVICE:
+         Text = siGetDescriptorText (Buffer + DESCR_SERVICE_LEN,
+                   CastServiceDescriptor(Buffer)->provider_name_length);
+         Text2 = siGetDescriptorText (Buffer + DESCR_SERVICE_LEN +
+                   CastServiceDescriptor(Buffer)->provider_name_length + 1,
+                   *((u_char *)(Buffer + DESCR_SERVICE_LEN +
+                   CastServiceDescriptor(Buffer)->provider_name_length)));
+         CreateServiceDescriptor (Descriptor,
+                   CastServiceDescriptor(Buffer)->service_type, Text, Text2);
+//         xMemFree (Text2);
+      break;
+
+      case DESCR_COUNTRY_AVAIL:
+         CreateCountryAvailabilityDescriptor (Descriptor,
+                   CastCountryAvailabilityDescriptor(Buffer)->country_availability_flag);
+         Length = GetDescriptorLength (Buffer) - DESCR_COUNTRY_AVAILABILITY_LEN;
+         Ptr += DESCR_COUNTRY_AVAILABILITY_LEN;
+         while (Length > 0)
+            { AddCountryAvailabilityCode(Descriptor,
+                      Ptr[0], Ptr[1], Ptr[2]); Ptr += 3; Length -= 3; }
+      break;
+
+      case DESCR_SHORT_EVENT:
+         Text = siGetDescriptorText (Buffer + DESCR_SHORT_EVENT_LEN,
+                   CastShortEventDescriptor(Buffer)->event_name_length);
+         Text2 = siGetDescriptorText (Buffer + DESCR_SHORT_EVENT_LEN +
+                   CastShortEventDescriptor(Buffer)->event_name_length + 1,
+                   *((u_char *)(Buffer + DESCR_SHORT_EVENT_LEN +
+                   CastShortEventDescriptor(Buffer)->event_name_length)));
+         CreateShortEventDescriptor (Descriptor, Text,
+                   CastShortEventDescriptor(Buffer)->lang_code1,
+                   CastShortEventDescriptor(Buffer)->lang_code2,
+                   CastShortEventDescriptor(Buffer)->lang_code3, Text2);
+//         xMemFree (Text);
+      break;
+
+      case DESCR_EXTENDED_EVENT:
+         Text = siGetDescriptorText (Buffer + DESCR_EXTENDED_EVENT_LEN +
+                   CastExtendedEventDescriptor(Buffer)->length_of_items + 1,
+                   *((u_char *)(Buffer + DESCR_EXTENDED_EVENT_LEN +
+                   CastExtendedEventDescriptor(Buffer)->length_of_items)));
+         CreateExtendedEventDescriptor (Descriptor,
+                   CastExtendedEventDescriptor(Buffer)->descriptor_number,
+                   CastExtendedEventDescriptor(Buffer)->last_descriptor_number,
+                   CastExtendedEventDescriptor(Buffer)->lang_code1,
+                   CastExtendedEventDescriptor(Buffer)->lang_code2,
+                   CastExtendedEventDescriptor(Buffer)->lang_code3, Text);
+//         xMemFree (Text);
+         Length = CastExtendedEventDescriptor(Buffer)->length_of_items;
+         Ptr += DESCR_EXTENDED_EVENT_LEN;
+         while (Length > 0)
+         {
+            Text = siGetDescriptorText (Ptr + ITEM_EXTENDED_EVENT_LEN,
+                      CastExtendedEventItem(Ptr)->item_description_length);
+            Text2 = siGetDescriptorText (Ptr + ITEM_EXTENDED_EVENT_LEN +
+                      CastExtendedEventItem(Ptr)->item_description_length + 1,
+                      *((u_char *)(Ptr + ITEM_EXTENDED_EVENT_LEN +
+                      CastExtendedEventItem(Ptr)->item_description_length)));
+            AddExtendedEventItem (Descriptor, Text2, Text);
+//            xMemFree (Text2);
+            Length -= ITEM_EXTENDED_EVENT_LEN + CastExtendedEventItem(Ptr)->item_description_length +
+                      *((u_char *)(Ptr + ITEM_EXTENDED_EVENT_LEN +
+                        CastExtendedEventItem(Ptr)->item_description_length)) + 1;
+            Ptr += ITEM_EXTENDED_EVENT_LEN + CastExtendedEventItem(Ptr)->item_description_length +
+                      *((u_char *)(Ptr + ITEM_EXTENDED_EVENT_LEN +
+                        CastExtendedEventItem(Ptr)->item_description_length)) + 1;
+         }
+      break;
+
+      case DESCR_CA_IDENT:
+         CreateCaIdentifierDescriptor (Descriptor,
+                   (GetDescriptorLength(Buffer) - DESCR_CA_IDENTIFIER_LEN) / 2);
+         Length = GetDescriptorLength (Buffer) - DESCR_CA_IDENTIFIER_LEN;
+         Ptr += DESCR_CA_IDENTIFIER_LEN; i = 0;
+         while (Length > 0)
+            { SetCaIdentifierID(Descriptor, i, *((u_short *) Ptr));
+              Length -= 2; Ptr += 2; i++; }
+      break;
+
+      case DESCR_CONTENT:
+         CreateContentDescriptor (Descriptor,
+                   (GetDescriptorLength(Buffer) - DESCR_CONTENT_LEN) / 2);
+         Length = GetDescriptorLength (Buffer) - DESCR_CONTENT_LEN;
+         Ptr += DESCR_CONTENT_LEN; i = 0;
+         while (Length > 0)
+            { SetContentID(Descriptor, i, CastContentNibble(Ptr)->content_nibble_level_1,
+                              CastContentNibble(Ptr)->content_nibble_level_2,
+                              CastContentNibble(Ptr)->user_nibble_1,
+                              CastContentNibble(Ptr)->user_nibble_2);
+              Length -= 2; Ptr += 2; i++; }
+      break;
+
+      case DESCR_STUFFING:
+         /* intentionally ignored */
+      break;
+
+      case DESCR_PARENTAL_RATING:
+         CreateParentalRatingDescriptor (Descriptor);
+         Length = GetDescriptorLength (Buffer) - DESCR_PARENTAL_RATING_LEN;
+         Ptr += DESCR_PARENTAL_RATING_LEN; i = 0;
+         while (Length > 0)
+            { AddParentalRating (Descriptor, CastParentalRating(Ptr)->lang_code1,
+                 CastParentalRating(Ptr)->lang_code2, CastParentalRating(Ptr)->lang_code3,
+                 CastParentalRating(Ptr)->rating);
+              Length -= PARENTAL_RATING_LEN; Ptr += PARENTAL_RATING_LEN; i++; }
+      break;
+
+      case DESCR_NVOD_REF:
+         CreateNvodReferenceDescriptor (Descriptor);
+         Length = GetDescriptorLength (Buffer) - DESCR_NVOD_REFERENCE_LEN;
+         Ptr += DESCR_NVOD_REFERENCE_LEN;
+         while (Length > 0)
+         {
+            AddNvodReferenceItem (Descriptor,
+               HILO (CastNvodReferenceItem(Ptr)->transport_stream_id),
+               HILO (CastNvodReferenceItem(Ptr)->original_network_id),
+               HILO (CastNvodReferenceItem(Ptr)->service_id));
+            Length -= ITEM_NVOD_REFERENCE_LEN;
+            Ptr += ITEM_NVOD_REFERENCE_LEN;
+         }
+      break;
+
+      case DESCR_TIME_SHIFTED_SERVICE:
+         CreateTimeShiftedServiceDescriptor (Descriptor,
+            HILO (CastTimeShiftedServiceDescriptor(Ptr)->reference_service_id));
+      break;
+
+      case DESCR_TIME_SHIFTED_EVENT:
+         CreateTimeShiftedEventDescriptor (Descriptor,
+            HILO (CastTimeShiftedEventDescriptor(Ptr)->reference_service_id),
+            HILO (CastTimeShiftedEventDescriptor(Ptr)->reference_event_id));
+      break;
+
+      case DESCR_ISO_639_LANGUAGE:
+         CreateIso639LanguageDescriptor (Descriptor,
+                   CastIso639LanguageDescriptor(Buffer)->lang_code1,
+                   CastIso639LanguageDescriptor(Buffer)->lang_code2,
+                   CastIso639LanguageDescriptor(Buffer)->lang_code3);
+      break;
+
+      case DESCR_STREAM_ID:
+         CreateStreamIdentifierDescriptor (Descriptor,
+                   CastStreamIdentifierDescriptor(Ptr)->component_tag);
+      break;
+
+      case DESCR_LINKAGE:
+         CreateLinkageDescriptor (Descriptor,
+                   HILO (CastLinkageDescriptor(Ptr)->transport_stream_id),
+                   HILO (CastLinkageDescriptor(Ptr)->original_network_id),
+                   HILO (CastLinkageDescriptor(Ptr)->service_id),
+                   CastLinkageDescriptor(Ptr)->linkage_type,
+                   GetDescriptorLength (Ptr) - DESCR_LINKAGE_LEN,
+                   Ptr + DESCR_LINKAGE_LEN);
+      break;
+
+      case DESCR_VIDEO_STREAM:
+      case DESCR_AUDIO_STREAM:
+      case DESCR_HIERARCHY:
+      case DESCR_REGISTRATION:
+      case DESCR_DATA_STREAM_ALIGN:
+      case DESCR_TARGET_BACKGRID:
+      case DESCR_VIDEO_WINDOW:
+      case DESCR_CA:
+      case DESCR_SYSTEM_CLOCK:
+      case DESCR_MULTIPLEX_BUFFER_UTIL:
+      case DESCR_COPYRIGHT:
+      case DESCR_MAXIMUM_BITRATE:
+      case DESCR_PRIVATE_DATA_IND:
+      case DESCR_SMOOTHING_BUFFER:
+      case DESCR_STD:
+      case DESCR_IBP:
+      case DESCR_NW_NAME:
+      case DESCR_SERVICE_LIST:
+      case DESCR_SAT_DEL_SYS:
+      case DESCR_CABLE_DEL_SYS:
+      case DESCR_VBI_DATA:
+      case DESCR_VBI_TELETEXT:
+      case DESCR_MOSAIC:
+      case DESCR_TELETEXT:
+      case DESCR_TELEPHONE:
+      case DESCR_LOCAL_TIME_OFF:
+      case DESCR_SUBTITLING:
+      case DESCR_TERR_DEL_SYS:
+      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:
+         /* fprintf (stderr, "unsupported descriptor 0x%x\n",
+                              GetDescriptorTag(Buffer)); */
+      break;
+   }
+   if (Descriptor) xAddTail (Descriptors, Descriptor);
+   return;
+}
+
+
+/*
+ *  ToDo:  ETSI conformal text definition
+ */
+char *siGetDescriptorText (u_char *Buffer, u_int Length)
+{
+   char *tmp, *result;
+   int i;
+
+   if (*Buffer == 0x05 || (*Buffer >= 0x20 && *Buffer <= 0xff))
+   {
+      xMemAlloc (Length+1, &result);
+      tmp = result;
+      for (i = 0; i < Length; i++)
+      {
+         if (*Buffer == 0) break;
+
+         if ((*Buffer >= ' ' && *Buffer <= '~') ||
+             (*Buffer >= 0xa0 && *Buffer <= 0xff)) *tmp++ = *Buffer++;
+         else Buffer++;
+      }
+      *tmp = '\0';
+   }
+   else
+   {
+      switch (*Buffer)
+      {
+         case 0x01: result = xSetText ("Coding according to character table 1"); break;
+         case 0x02: result = xSetText ("Coding according to character table 2"); break;
+         case 0x03: result = xSetText ("Coding according to character table 3"); break;
+         case 0x04: result = xSetText ("Coding according to character table 4"); break;
+         case 0x10: result = xSetText ("Coding according to ISO/IEC 8859"); break;
+         case 0x11: result = xSetText ("Coding according to ISO/IEC 10646"); break;
+         case 0x12: result = xSetText ("Coding according to KSC 5601"); break;
+         default: result = xSetText ("Unknown coding"); break;
+      }
+   }
+
+   return (result);
+}
+
+// CRC32 lookup table for polynomial 0x04c11db7
+
+static u_long crc_table[256] = {
+	0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+	0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+	0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+	0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+	0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+	0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+	0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+	0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+	0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+	0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+	0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+	0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+	0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+	0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+	0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+	0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+	0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+	0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+	0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+	0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+	0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+	0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+	0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+	0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+	0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+	0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+	0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+	0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+	0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+	0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+	0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+	0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+	0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+	0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4};
+
+u_long crc32 (char *data, int len)
+{
+	register int i;
+	u_long crc = 0xffffffff;
+
+	for (i=0; i<len; i++)
+		crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *data++) & 0xff];
+
+	return crc;
+}
diff --git a/libdtv/libvdr/COPYING b/libdtv/libvdr/COPYING
new file mode 100644
index 00000000..a43ea212
--- /dev/null
+++ b/libdtv/libvdr/COPYING
@@ -0,0 +1,339 @@
+		    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.
diff --git a/libdtv/libvdr/Makefile b/libdtv/libvdr/Makefile
new file mode 100644
index 00000000..bf7f37f3
--- /dev/null
+++ b/libdtv/libvdr/Makefile
@@ -0,0 +1,62 @@
+##############################################################
+###                                                        ###
+### Makefile: local makefile for libvdr                    ###
+###                                                        ###
+##############################################################
+
+## $Revision: 1.2 $
+## $Date: 2001/06/25 19:39:00 $
+## $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__ -I../include # -DDEBUG
+
+
+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
+    
diff --git a/libdtv/libvdr/libvdr.c b/libdtv/libvdr/libvdr.c
new file mode 100644
index 00000000..91f96822
--- /dev/null
+++ b/libdtv/libvdr/libvdr.c
@@ -0,0 +1,169 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// libvdr.c: routines to parse the DVB-SI stream          ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.3 $
+// $Date: 2001/06/25 19:39:00 $
+// $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;
+
+   if (!siBuffer) return (NULL);
+
+   if (!(EventList = siParseEIT (siBuffer))) return (NULL);
+
+   Result = xNewList (NULL);
+
+   xForeach (EventList, Event)
+   {
+      VdrProgramInfo = NULL;
+
+      xForeach (Event->Descriptors, Descriptor)
+      {
+         switch (Descriptor->Tag)
+         {
+            case DESCR_SHORT_EVENT:
+            {
+               if (!xName(Descriptor) || !xName(Descriptor)[0])
+                  break;
+
+               if (!VdrProgramInfo)
+               {
+                  CreateVdrProgramInfo(VdrProgramInfo,
+                     Event->EventID, Event->TransportStreamID,
+                     Event->ServiceID, Event->StartTime,
+                     Event->Duration, Event->Status);
+
+                  VdrProgramInfo->ShortName =
+                     xSetText (xName (Descriptor));
+                  VdrProgramInfo->ShortText =
+                     xSetText (((struct ShortEventDescriptor
+                        *)Descriptor)->Text);
+                  memcpy (VdrProgramInfo->LanguageCode, ((struct
+                     ShortEventDescriptor *)Descriptor)->
+                     LanguageCode, 4);
+               }
+            }
+            break;
+
+            case DESCR_TIME_SHIFTED_EVENT:
+            {
+               struct tm *StartTime;
+
+               if (!VdrProgramInfo)
+               {
+                  CreateVdrProgramInfo(VdrProgramInfo,
+                     Event->EventID, Event->TransportStreamID,
+                     Event->ServiceID, Event->StartTime,
+                     Event->Duration, Event->Status);
+
+                  VdrProgramInfo->ReferenceServiceID =
+                     ((struct TimeShiftedEventDescriptor
+                        *)Descriptor)->ReferenceServiceID;
+                  VdrProgramInfo->ReferenceEventID =
+                     ((struct TimeShiftedEventDescriptor
+                        *)Descriptor)->ReferenceEventID;
+               }
+            }
+            break;
+
+            case DESCR_EXTENDED_EVENT:
+            {
+               struct ExtendedEventItem *Item;
+
+               if (VdrProgramInfo)
+               {
+                  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;
+
+               if (VdrProgramInfo)
+               {
+                  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;
+
+               if (VdrProgramInfo)
+               {
+                  xForeach (((struct ParentalRatingDescriptor *)
+                              Descriptor)->Ratings, Rating)
+                     if (!strncmp (VdrProgramInfo->LanguageCode,
+                             Rating->LanguageCode, 3))
+                        VdrProgramInfo->Rating = Rating->Rating;
+               }
+            }
+            break;
+         }
+      }
+      if (VdrProgramInfo) xAddTail (Result, VdrProgramInfo);
+   }
+
+   return (Result);
+}
diff --git a/libdtv/libvdr/libvdr.h b/libdtv/libvdr/libvdr.h
new file mode 100644
index 00000000..c7dd49fa
--- /dev/null
+++ b/libdtv/libvdr/libvdr.h
@@ -0,0 +1,111 @@
+//////////////////////////////////////////////////////////////
+///                                                        ///
+/// libvdr.h: definitions necessary for the libvdr package ///
+///                                                        ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 1.3 $
+// $Date: 2001/06/25 19:39:00 $
+// $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
-- 
cgit v1.2.3