summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <root@ubsatserv.(none)>2011-04-24 15:54:07 (GMT)
committerroot <root@ubsatserv.(none)>2011-04-24 15:56:25 (GMT)
commitc59a610f66bb7cfd3cf00df3551a3578d4368d35 (patch)
tree04c4d4df080deacfc80c9cf75e327783d94f697f
downloadvdr-plugin-eepg-c59a610f66bb7cfd3cf00df3551a3578d4368d35.tar.gz
vdr-plugin-eepg-c59a610f66bb7cfd3cf00df3551a3578d4368d35.tar.bz2
Initial eepg git repository with version eepg-0.0.3eepg-0.0.3
-rw-r--r--COPYING340
-rw-r--r--HISTORY24
-rw-r--r--Makefile132
-rw-r--r--README109
-rw-r--r--TODO14
-rw-r--r--eepg.c4222
-rw-r--r--eepg.equiv.IT17
-rw-r--r--eepg.h7149
8 files changed, 12007 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
+
+ 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) <year> <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) year 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/HISTORY b/HISTORY
new file mode 100644
index 0000000..b425237
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,24 @@
+Release 0.0.3:
+-fixed undefined symbol error when not using NO_EPG patch
+-declare Nagra-events that have day-of-the month in the period between today-7days and yesterday as "old events"; some providers keep sending old eepg data that otherways are presented as next months'
+-stopped processing the second title-field that is sent with Nagra, since it is not clear when it is valid
+-make eepg-plugin actually obey the rules defined by the NO_EPG patch, if used
+-fixed all compiler warnings
+
+Release 0.0.2a:
+-fixed problem in NagraGuide, where month of title could get random value
+
+Release 0.0.2:
+-decoded and added NagraGuide
+-tested daylight savings functionality for SKY_UK
+-added daylight savings fucntionality for MHW1 and NAGRA
+-added possiblity to scan more eepg-streams on same transponder (like CanaalDigitaalNL, both MHW1 and Nagra)
+-disabled scan after 1 hour idle time; this was unused functionality, since a) most updates are once/24 hour, and b) most of the time zapping is done within 1 hour
+-added lookup for eventid, so existing events will be updated instead of added. This means less use for the DD_EPG patch, because double EPG entries will be minimized.
+-fixed compile problem when using NO_EPG patch
+-added hexdump routine for debugging
+-improved use of TableId's, so now the plugin can decide whether to overwrite or to preserve the existing EPG data
+-improved several routines, less memory use, less cpu use.
+
+Release 0.0.1:
+First release.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3319320
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,132 @@
+#
+# EEPG plugin to VDR
+#
+# (C) 2008-2009 Dingo35
+#
+# This code 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 code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+
+# The official name of this plugin.
+# This name will be used in the '-P...' option of VDR to load the plugin.
+# By default the main source file also carries this name.
+#
+PLUGIN = eepg
+
+### The version number of this plugin (taken from the main source file):
+
+VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
+
+### The C++ compiler and options:
+
+CXX ?= g++
+CXXFLAGS ?= -O2 -fPIC -Wall -Woverloaded-virtual
+
+### The directory environment:
+
+VDRDIR = ../../..
+LIBDIR = ../../lib
+TMPDIR = /tmp
+
+### Allow user defined options to overwrite defaults:
+
+-include $(VDRDIR)/Make.config
+
+### The version number of VDR (taken from VDR's "config.h"):
+
+VDRVERSION = $(shell sed -ne '/define VDRVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
+APIVERSION = $(shell sed -ne '/define APIVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
+ifeq ($(strip $(APIVERSION)),)
+ APIVERSION = $(VDRVERSION)
+endif
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES += -I$(VDRDIR)/include
+
+DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o
+
+ifdef DBG
+CXXFLAGS += -g
+endif
+
+### Internationalization (I18N):
+
+PODIR = po
+I18Npot = $(PODIR)/$(PLUGIN).pot
+I18Nmsgs = $(addprefix $(LOCALEDIR)/,$(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo,$(notdir $(foreach file, $(wildcard $(PODIR)/*.po), $(basename $(file))))))
+LOCALEDIR = $(VDRDIR)/locale
+
+# Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+ @$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+TARGETS = libvdr-$(PLUGIN).so
+ifneq ($(shell grep -l 'Phrases' $(VDRDIR)/i18n.c),$(VDRDIR)/i18n.c)
+TARGETS += i18n
+endif
+
+all: $(TARGETS)
+.PHONY: i18n
+
+%.o: %.c
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+libvdr-$(PLUGIN).so: $(OBJS)
+ $(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
+ @cp $@ $(LIBDIR)/$@.$(APIVERSION)
+
+$(I18Npot): $(shell grep -rl '\(tr\|trNOOP\)(\".*\")' *.c $(SYSDIR))
+ xgettext -C -cTRANSLATORS --no-wrap -F -k -ktr -ktrNOOP -o $@ $^
+
+%.po: $(I18Npot)
+ msgmerge -U --no-wrap -F --backup=none -q $@ $<
+ @touch $@
+
+%.mo: %.po
+ msgfmt -c -o $@ $<
+
+$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
+ @mkdir -p $(dir $@)
+ cp $< $@
+
+i18n: $(I18Nmsgs)
+
+dist: clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @mkdir $(TMPDIR)/$(ARCHIVE)
+ @cp -a * $(TMPDIR)/$(ARCHIVE)
+ @tar czf $(PACKAGE).tar.gz -C $(TMPDIR) $(ARCHIVE)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @echo Distribution package created as $(PACKAGE).tar.gz
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tar.gz core* *~
+# @-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
diff --git a/README b/README
new file mode 100644
index 0000000..a11b771
--- /dev/null
+++ b/README
@@ -0,0 +1,109 @@
+
+This is the Extended EPG (EEPG) plugin for VDR.
+
+
+See the file COPYING for license information.
+
+----------------------------------------------------------------------
+
+This plugin parses the extended (2 to 10 day) EPG data which is send by
+providers on their portal channels. This EEPG data is transmitted in a
+non-standard format on a non-standard PID.
+
+Currently the following EEPG formats are supported:
+-Mediahighway 1 (CanaalDigitaalNL, CSat, Cyfra+)
+-Mediahighway 2 (Digital+)
+-Sky Italy
+-Sky UK
+-Freesat
+-Premiere
+-NagraGuide (CanaalDigitaalNL, only in test)
+
+INSTALL
+Unpack, make and make plugins like any other plugin. Call like any other
+On the first run, in the vdr-plugins directory a subdirectory eepg is created
+where all necessary files are created.
+One can define equivalent channels in the eepg.equiv file to "copy"
+EEPG data to other channels.
+E.g., CanaalDigitaalNL still sends Dorcel EEPG data on S19.2E, which can be used
+for Dorcel on S13.0E.
+Some sample eepg.equiv files are included.
+
+USE
+The plugin has no mainmenu entry, and only a few settings for Premiere.
+When one of VDR's devices is tuned to a transponder (by tuning, a recording or
+an EPG scan triggered by VDR), the plugin scans all channels on the transponder
+for the supported EEPG formats. When all of the supported formats are detected,
+all available EEPG data is loaded into the schedule of VDR.
+Additionally, the EEPG data is loaded into additional channels if they are specified
+in the eepg.equiv file (not for Premiere or Freesat).
+Everything is done automatically and transparently, all is done concurrently
+with recordings and live viewings.
+Freesat and Premiere are loading their EEPG info continuously.
+
+The plugin is designed to use as less recources as possible: it only uses 1 Pid
+(especially important to users of FF cards, which have a max. of 32 Pids),
+and allocates and frees memory according to its needs.
+
+If one needs to reload EEPG data periodically, it is sufficient to create
+a cron job which tunes to the proper channel through the SVDRP interface.
+In practice, viewing and tuning to your favourite channels reloads the EEPG data daily,
+which is often enough since EEPG data is valid for 2 - 10 days.
+
+New, unknown EEPG transponders will be detected automatically (MHW1, MHW2, Freesat) or
+have to be added (Sky uses different huffman decoding tables for every country).
+
+Currently known transponders that send EEPG data:
+-Sky Italia S13.0E:11881V (OpenTV)
+-Sky UK S28.2E:11778V (OpenTV)
+-Cyfra+ S13.0E:10719V (Mediahighway 1)
+-CSat S19.2E:12363V (Mediahighway 1)
+-Canal DigitaalNL S19.2E:12515H (Mediahighway 1, NagraGuide)
+-Digital+ S19.2E:10847V (Mediahighway 2)
+-Premiere Sport Portal, Premiere Direkt Portal
+-Freesat all freesat channels
+
+Please note that the NagraGuide broadcasts of Canal DigitaalNL are stil in betatest;
+therefore its information is not always reliable. It seems that sometimes, when no summaries
+are available for certain titles, random summaries are chosen by the broadcaster.
+This could, of course, also be a bug, since the protocol of NagraGuide is not published.
+It can be further investigated only when NagraGuide is taken into production, and
+certified receivers will be able to decode Nagra... in the mean time YOU can already
+enjoy the 7-day EEPG schedule!
+The unreliability of Nagra is compensated by having Mediahighway 1 overwrite Nagra-events it
+detects.
+
+For Premiere, the plugin can tag option events i.e. the same event with the same time on
+different channels e.g. F1 sub channels. The tagging format (e.g. before or
+after event name) can be selected in the plugin setup menu.
+In addition there are two switches in the plugin setup menu to control inclusion
+of order and parental rating information into the event description.
+The plugin setup menu is only for Premiere protocol!
+
+
+THANKS
+This code is based on:
+ -Premiere plugin (C) 2005-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
+ -mhwepg program (C) 2002, 2003 Jean-Claude Repetto <mhwepg@repetto.org>
+ -LoadEpg plugin written by Luca De Pieri <dpluca@libero.it>
+ -Freesat patch written by dom /at/ suborbital.org.uk
+
+We wish to thank all authors for the great work they have been doing, decoding
+this EEPG data; this plugin tries to combine the best of all worlds.
+Specific improvement has been done on Mediahigway 1 protocol: all software known
+tries to combine titles and summaries on the basis of the event-id, but several
+channels can use the same event-id at the same time. This leads in practice to
+20-25% erroneous summaries. The plugin uses the same technique as more simple
+satellite receivers, which take into account the order in which titles
+and summaries are sent. This leads to 99-100% accuracy.
+Also, the "number of replays" technique for CSAT is implemented correctly; not all
+software supported this information, which leads to loss of 80-90% of the EEPG
+information.
+
+
+KNOWN BUGS
+-Equivalents file is not used for Freesat, Premiere.
+-On Sky Italy and Sky UK, a lot of "summaries not found" are reported. This is
+ because it is not (yet) known where the "summary available" flag is coded in the
+ OpenTV protocol used, so all titles are assumed to have a summary available.
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..888e3f2
--- /dev/null
+++ b/TODO
@@ -0,0 +1,14 @@
+TODO/WISH:
+-extend equivalents file with transponder SKIP (do not retrieve EEPG info) or
+ transponder ONCE (retrieve once a day, first possiblity after midnight).
+ TUNE (retrieve every time transponder gets tuned to) transponder CONT (retrieve continuously)
+-look at collisions and language problems (eg Cyfra at MTV)
+-check broadcasting frequencys + windows of all providers; report first event seen and last event seen
+-use event-> as database instead of title[] and summary[] , except for MHW1
+-try to minimize resync problems by using sliding window after "lock" on 50 succesfull sequential syncs or so
+-stop premiere after having read all titles (from CONT to ONCE)
+-check version info for all providers
+-decode summary-available bit for OpenTV
+-include DDEPG functionality
+-parallellize when not on FF card
+-NAGRA 2nd textstring is not used right now, find out when it is relevant...
diff --git a/eepg.c b/eepg.c
new file mode 100644
index 0000000..ce42f6c
--- /dev/null
+++ b/eepg.c
@@ -0,0 +1,4222 @@
+/*
+ * Extended Epg plugin to VDR (C++)
+ *
+ * (C) 2008-2009 Dingo35
+ *
+ * This code is based on:
+ * -Premiere plugin (C) 2005-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
+ * -mhwepg program (C) 2002, 2003 Jean-Claude Repetto <mhwepg@repetto.org>
+ * -LoadEpg plugin written by Luca De Pieri <dpluca@libero.it>
+ * -Freesat patch written by dom /at/ suborbital.org.uk
+ *
+ *
+ * This code 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 code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <vdr/plugin.h>
+#include <vdr/filter.h>
+#include <vdr/epg.h>
+#include <vdr/channels.h>
+#include <vdr/dvbdevice.h>
+#include <vdr/i18n.h>
+#include <vdr/config.h>
+#include <libsi/section.h>
+#include <libsi/descriptor.h>
+#include "eepg.h"
+
+#include <map>
+#include "../../../libsi/si.c"
+
+#define VERBOSE 1
+/* 0 = only print errors, 1 = print channels and themes, 2 = print channels, themes, titles, summaries 3 = debug mode */
+/* all is logged into /var/log/syslog */
+
+#if APIVERSNUM < 10401
+#error You need at least VDR API version 1.4.1 for this plugin
+#endif
+#if APIVERSNUM < 10507
+#define trNOOP(s) (s)
+#endif
+
+//#define DEBUG
+//#define DEBUG2
+
+/*#ifdef DEBUG
+#define d(x) { (x); }
+#else
+#define d(x) ;
+#endif
+#ifdef DEBUG2
+#define d2(x) { (x); }
+#else
+#define d2(x) ;
+#endif*/
+
+#define PMT_SCAN_TIMEOUT 10 // seconds
+#define PMT_SCAN_IDLE 3600 // seconds
+
+static const char *VERSION = "0.0.3";
+static const char *DESCRIPTION = trNOOP ("Parses Extended EPG data");
+
+// --- cSetupEEPG -------------------------------------------------------
+
+const char *optPats[] = {
+ "%s",
+ "%s (Option %d)",
+ "%s (O%d)",
+ "#%2$d %1$s",
+ "[%2$d] %1$s"
+};
+
+#define NUM_PATS (sizeof(optPats)/sizeof(char *))
+
+char *cs_hexdump (int m, const uchar * buf, int n)
+{
+ int i;
+ static char dump[1024];
+
+ dump[i = 0] = '\0';
+ m = (m) ? 3 : 2;
+ if (m * n >= (int) sizeof (dump))
+ n = (sizeof (dump) / m) - 1;
+ while (i < n)
+ sprintf (dump + (m * i++), "%02X%s", *buf++, (m > 2) ? " " : "");
+ return (dump);
+}
+
+class cSetupEEPG
+{
+public:
+ int OptPat;
+ int OrderInfo;
+ int RatingInfo;
+ int FixEpg;
+public:
+ cSetupEEPG (void);
+};
+
+cSetupEEPG SetupPE;
+
+cSetupEEPG::cSetupEEPG (void)
+{
+ OptPat = 1;
+ OrderInfo = 1;
+ RatingInfo = 1;
+ FixEpg = 0;
+}
+
+// --- cMenuSetupPremiereEpg ------------------------------------------------------------
+
+class cMenuSetupPremiereEpg:public cMenuSetupPage
+{
+private:
+ cSetupEEPG data;
+ const char *optDisp[NUM_PATS];
+ char buff[NUM_PATS][32];
+protected:
+ virtual void Store (void);
+public:
+ cMenuSetupPremiereEpg (void);
+};
+
+cMenuSetupPremiereEpg::cMenuSetupPremiereEpg (void)
+{
+ data = SetupPE;
+ SetSection (tr ("PremiereEPG"));
+ optDisp[0] = tr ("off");
+ for (unsigned int i = 1; i < NUM_PATS; i++) {
+ snprintf (buff[i], sizeof (buff[i]), optPats[i], "Event", 1);
+ optDisp[i] = buff[i];
+ }
+ Add (new cMenuEditStraItem (tr ("Tag option events"), &data.OptPat, NUM_PATS, optDisp));
+ Add (new cMenuEditBoolItem (tr ("Show order information"), &data.OrderInfo));
+ Add (new cMenuEditBoolItem (tr ("Show rating information"), &data.RatingInfo));
+ Add (new cMenuEditBoolItem (tr ("Fix EPG data"), &data.FixEpg));
+}
+
+void cMenuSetupPremiereEpg::Store (void)
+{
+ SetupPE = data;
+ SetupStore ("OptionPattern", SetupPE.OptPat);
+ SetupStore ("OrderInfo", SetupPE.OrderInfo);
+ SetupStore ("RatingInfo", SetupPE.RatingInfo);
+ SetupStore ("FixEpg", SetupPE.FixEpg);
+}
+
+// --- CRC16 -------------------------------------------------------------------
+
+#define POLY 0xA001 // CRC16
+
+unsigned int crc16 (unsigned int crc, unsigned char const *p, int len)
+{
+ while (len--) {
+ crc ^= *p++;
+ for (int i = 0; i < 8; i++)
+ crc = (crc & 1) ? (crc >> 1) ^ POLY : (crc >> 1);
+ }
+ return crc & 0xFFFF;
+}
+
+// --- cFilterEEPG ------------------------------------------------------
+
+#define STARTTIME_BIAS (20*60)
+
+static int AvailableSources[32];
+static int NumberOfAvailableSources = 0;
+static int LastVersionNagra = -1; //currently only used for Nagra, should be stored per transponder, per system
+
+class cFilterEEPG:public cFilter
+{
+private:
+ int pmtpid, pmtsid, pmtidx, pmtnext;
+ int UnprocessedFormat[HIGHEST_FORMAT + 1]; //stores the pid when a format is detected on this transponder, and that are not processed yet
+ int nEquivChannels, nChannels, nThemes, nTitles, nSummaries, NumberOfTables, Version;
+ int TitleCounter, SummaryCounter, NoSummaryCounter, RejectTableId;
+ bool EndChannels, EndThemes; //only used for ??
+ int MHWStartTime; //only used for MHW1
+ bool ChannelsOk;
+ int Format; //the format that this filter currently is processing
+ std::map < int, int >ChannelSeq; // ChannelSeq[ChannelId] returns the recordnumber of the channel
+
+ Summary_t *Summaries[MAX_TITLES];
+ Title_t *Titles[MAX_TITLES];
+ sChannel sChannels[MAX_CHANNELS];
+ unsigned char Themes[MAX_THEMES][64];
+
+ std::map < unsigned short int, unsigned char *>buffer; //buffer[Table_Extension_Id] returns the pointer to the buffer for this TEI
+ std::map < unsigned short int, int >bufsize; //bufsize[Table_Extension_Id] returns the buffersize of the buffer for this TEI
+ unsigned short int NagraTIE[64]; //at this moment a max of 31 table_ids could be used, so 64 should be enough ....stores the Table_Extension_Id's of summaries received, so they can be processed. Processing while receiving somehow drops sections, the 0x0000 marker will be missed ...
+ unsigned short int NagraCounter;
+
+ unsigned char InitialChannel[8];
+ unsigned char InitialTitle[64];
+ unsigned char InitialSummary[64];
+
+ void NextPmt (void);
+protected:
+#ifdef USE_NOEPG
+ virtual bool allowedEPG(tChannelID kanalID);
+#endif
+ virtual void Process (u_short Pid, u_char Tid, const u_char * Data, int Length);
+ virtual void AddFilter (u_short Pid, u_char Tid);
+ virtual void AddFilter (u_short Pid, u_char Tid, unsigned char Mask);
+ virtual void ProcessNextFormat (bool FirstTime);
+ virtual int GetChannelsSKYBOX (const u_char * Data, int Length);
+ virtual bool GetThemesSKYBOX (void);
+ virtual bool ReadFileDictionary (void); //Reads Huffman tables for SKY
+ virtual int GetTitlesSKYBOX (const u_char * Data, int Length);
+ virtual int GetSummariesSKYBOX (const u_char * Data, int Length);
+ virtual int GetChannelsMHW (const u_char * Data, int Length, int MHW); //TODO replace MHW by Format?
+ virtual int GetThemesMHW1 (const u_char * Data, int Length);
+ virtual int GetNagra (const u_char * Data, int Length);
+ virtual void ProcessNagra (void);
+ virtual void GetTitlesNagra (const u_char * Data, int Length, unsigned short TableIdExtension);
+ virtual char *GetSummaryTextNagra (const u_char * DataStart, long int Offset, unsigned int EventId);
+ virtual int GetChannelsNagra (const u_char * Data, int Length);
+ virtual int GetThemesNagra (const u_char * Data, int Length, unsigned short TableIdExtension);
+ virtual int GetTitlesMHW1 (const u_char * Data, int Length);
+ virtual int GetSummariesMHW1 (const u_char * Data, int Length);
+ virtual int GetThemesMHW2 (const u_char * Data, int Length);
+ virtual int GetTitlesMHW2 (const u_char * Data, int Length);
+ virtual int GetSummariesMHW2 (const u_char * Data, int Length);
+ virtual void FreeSummaries (void);
+ virtual void FreeTitles (void);
+ virtual void PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]); //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
+ virtual void FinishWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]);
+ virtual void WriteToSchedule (cSchedule * ps[MAX_EQUIVALENCES], unsigned short int NumberOfEquivalences,
+ unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text,
+ char *SummText, unsigned short int ThemeId, unsigned short int TableId,
+ unsigned short int Version);
+ virtual void LoadIntoSchedule (void);
+ virtual void LoadEquivalentChannels (void);
+public:
+ cFilterEEPG (void);
+ virtual void SetStatus (bool On);
+ void Trigger (void);
+};
+
+cFilterEEPG::cFilterEEPG (void)
+{
+ Trigger ();
+ //Set (0x00, 0x00);
+}
+
+void cFilterEEPG::Trigger (void)
+{
+ if (VERBOSE >= 3)
+ isyslog ("trigger\n");
+ pmtpid = 0;
+ pmtidx = 0;
+ pmtnext = 0;
+}
+
+void cFilterEEPG::SetStatus (bool On)
+{
+ isyslog ("setstatus %d\n", On);
+ if (!On) {
+ FreeSummaries ();
+ FreeTitles ();
+ Format = 0;
+ ChannelsOk = false;
+ NumberOfTables = 0;
+ }
+ else {
+ //Set(0x00,0x00);
+ for (int i = 0; i <= HIGHEST_FORMAT; i++)
+ UnprocessedFormat[i] = 0; //pid 0 is assumed to be nonvalid for EEPG transfers
+ AddFilter (0, 0);
+ }
+ cFilter::SetStatus (On);
+ Trigger ();
+}
+
+void cFilterEEPG::NextPmt (void)
+{
+ Del (pmtpid, 0x02);
+ pmtpid = 0;
+ pmtidx++;
+ if (VERBOSE >= 3)
+ esyslog ("PMT next\n");
+}
+//TODO next routine is also in cEIT2, make this simpler
+#ifdef USE_NOEPG
+ bool cFilterEEPG::allowedEPG (tChannelID kanalID)
+ {
+ bool rc;
+
+ if (Setup.noEPGMode == 1) {
+ rc = false;
+ if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL)
+ rc = true;
+ }
+ else {
+ rc = true;
+ if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL)
+ rc = false;
+ }
+
+ return rc;
+ }
+#endif /* NOEPG */
+
+
+// ------------------- Freesat -------------------
+
+/* FreeSat Huffman decoder for VDR
+ *
+ * Insert GPL licence
+ */
+
+/* The following features can be controlled:
+ *
+ * FREEVIEW_NO_SYSLOG - Disable use of isyslog
+ */
+
+#ifndef FREEVIEW_NO_SYSLOG
+#include "../tools.h"
+/* Logging via vdr */
+#ifndef isyslog
+#define isyslog(a...) void( (SysLogLevel > 1) ? syslog_with_tid(LOG_INFO, a) : void() )
+#endif
+void syslog_with_tid (int priority, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+#else
+#define isyslog(a...) fprintf(stderr,a)
+#endif
+
+
+
+struct hufftab
+{
+ unsigned int value;
+ short bits;
+ char next;
+};
+
+#define START '\0'
+#define STOP '\0'
+#define ESCAPE '\1'
+
+
+int freesat_decode_error = 0; /* If set an error has occurred during decoding */
+
+static struct hufftab *tables[2][256];
+static int table_size[2][256];
+
+/** \brief Convert a textual character description into a value
+ *
+ * \param str - Encoded (in someway) string
+ *
+ * \return Raw character
+ */
+static unsigned char resolve_char (char *str)
+{
+ int val;
+ if (strcmp (str, "ESCAPE") == 0) {
+ return ESCAPE;
+ }
+ else if (strcmp (str, "STOP") == 0) {
+ return STOP;
+ }
+ else if (strcmp (str, "START") == 0) {
+ return START;
+ }
+ else if (sscanf (str, "0x%02x", &val) == 1) {
+ return val;
+ }
+ return str[0];
+
+
+}
+
+
+/** \brief Decode a binary string into a value
+ *
+ * \param binary - Binary string to decode
+ *
+ * \return Decoded value
+ */
+static unsigned long decode_binary (char *binary)
+{
+ unsigned long mask = 0x80000000;
+ unsigned long maskval = 0;
+ unsigned long val = 0;
+ size_t i;
+
+ for (i = 0; i < strlen (binary); i++) {
+ if (binary[i] == '1') {
+ val |= mask;
+ }
+ maskval |= mask;
+ mask >>= 1;
+ }
+ return val;
+}
+
+/** \brief Load an individual freesat data file
+ *
+ * \param tableid - Table id that should be loaded
+ * \param filename - Filename to load
+ */
+static void load_file (int tableid, char *filename)
+{
+ char buf[1024];
+ char *from, *to, *binary;
+ FILE *fp;
+
+ tableid--;
+ if ((fp = fopen (filename, "r")) != NULL) {
+ isyslog ("Loading table %d Filename <%s>", tableid + 1, filename);
+
+ while (fgets (buf, sizeof (buf), fp) != NULL) {
+ from = binary = to = NULL;
+ int elems = sscanf (buf, "%a[^:]:%a[^:]:%a[^:]:", &from, &binary, &to);
+ if (elems == 3) {
+ int bin_len = strlen (binary);
+ int from_char = resolve_char (from);
+ char to_char = resolve_char (to);
+ unsigned long bin = decode_binary (binary);
+ int i = table_size[tableid][from_char]++;
+
+ tables[tableid][from_char] =
+ (struct hufftab *) realloc (tables[tableid][from_char], (i + 1) * sizeof (tables[tableid][from_char][0]));
+ tables[tableid][from_char][i].value = bin;
+ tables[tableid][from_char][i].next = to_char;
+ tables[tableid][from_char][i].bits = bin_len;
+ free (from);
+ free (to);
+ free (binary);
+ }
+ }
+ fclose (fp);
+ }
+ else {
+ isyslog ("EEPG: Cannot load <%s> for table %d", filename, tableid + 1);
+ }
+}
+
+
+/** \brief Decode an EPG string as necessary
+ *
+ * \param src - Possibly encoded string
+ * \param size - Size of the buffer
+ *
+ * \retval NULL - Can't decode
+ * \return A decoded string
+ */
+char *freesat_huffman_decode (const unsigned char *src, size_t size)
+{
+ int tableid;
+ freesat_decode_error = 0;
+
+ if (src[0] == 0x1f && (src[1] == 1 || src[1] == 2)) {
+ int uncompressed_len = 30;
+ char *uncompressed = (char *) calloc (1, uncompressed_len + 1);
+ unsigned value = 0, byte = 2, bit = 0;
+ int p = 0;
+ int lastch = START;
+
+ tableid = src[1] - 1;
+ while (byte < 6 && byte < size) {
+ value |= src[byte] << ((5 - byte) * 8);
+ byte++;
+ }
+ //freesat_table_load (); /**< Load the tables as necessary */
+
+ do {
+ int found = 0;
+ unsigned bitShift = 0;
+ if (lastch == ESCAPE) {
+ char nextCh = (value >> 24) & 0xff;
+ found = 1;
+ // Encoded in the next 8 bits.
+ // Terminated by the first ASCII character.
+ bitShift = 8;
+ if ((nextCh & 0x80) == 0)
+ lastch = nextCh;
+ if (p >= uncompressed_len) {
+ uncompressed_len += 10;
+ uncompressed = (char *) realloc (uncompressed, uncompressed_len + 1);
+ }
+ uncompressed[p++] = nextCh;
+ uncompressed[p] = 0;
+ }
+ else {
+ int j;
+ for (j = 0; j < table_size[tableid][lastch]; j++) {
+ unsigned mask = 0, maskbit = 0x80000000;
+ short kk;
+ for (kk = 0; kk < tables[tableid][lastch][j].bits; kk++) {
+ mask |= maskbit;
+ maskbit >>= 1;
+ }
+ if ((value & mask) == tables[tableid][lastch][j].value) {
+ char nextCh = tables[tableid][lastch][j].next;
+ bitShift = tables[tableid][lastch][j].bits;
+ if (nextCh != STOP && nextCh != ESCAPE) {
+ if (p >= uncompressed_len) {
+ uncompressed_len += 10;
+ uncompressed = (char *) realloc (uncompressed, uncompressed_len + 1);
+ }
+ uncompressed[p++] = nextCh;
+ uncompressed[p] = 0;
+ }
+ found = 1;
+ lastch = nextCh;
+ break;
+ }
+ }
+ }
+ if (found) {
+ // Shift up by the number of bits.
+ unsigned b;
+ for (b = 0; b < bitShift; b++) {
+ value = (value << 1) & 0xfffffffe;
+ if (byte < size)
+ value |= (src[byte] >> (7 - bit)) & 1;
+ if (bit == 7) {
+ bit = 0;
+ byte++;
+ }
+ else
+ bit++;
+ }
+ }
+ else {
+ isyslog ("Missing table %d entry: <%s>", tableid + 1, uncompressed);
+ // Entry missing in table.
+ return uncompressed;
+ }
+ } while (lastch != STOP && value != 0);
+
+ return uncompressed;
+ }
+ return NULL;
+}
+
+//here all declarations for global variables over all devices
+
+char *ConfDir;
+
+sNodeH *nH, H;
+
+//unsigned char DecodeErrorText[4096]; //TODO only used for debugging?
+
+int Yesterday;
+int YesterdayEpoch;
+int YesterdayEpochUTC;
+
+/*
+ * Convert local time to UTC
+ */
+time_t LocalTime2UTC (time_t t)
+{
+ struct tm *temp;
+
+ temp = gmtime (&t);
+ temp->tm_isdst = -1;
+ return mktime (temp);
+}
+
+/*
+ * Convert UTC to local time
+ */
+time_t UTC2LocalTime (time_t t)
+{
+ return 2 * t - LocalTime2UTC (t);
+}
+
+void GetLocalTimeOffset (void)
+{
+ time_t timeLocal;
+ struct tm *tmCurrent;
+
+ timeLocal = time (NULL);
+ timeLocal -= 86400;
+ tmCurrent = gmtime (&timeLocal);
+ Yesterday = tmCurrent->tm_wday;
+ tmCurrent->tm_hour = 0;
+ tmCurrent->tm_min = 0;
+ tmCurrent->tm_sec = 0;
+ tmCurrent->tm_isdst = -1;
+ YesterdayEpoch = mktime (tmCurrent);
+ YesterdayEpochUTC = UTC2LocalTime (mktime (tmCurrent));
+}
+
+void CleanString (unsigned char *String)
+{
+ unsigned char *Src;
+ unsigned char *Dst;
+ int Spaces;
+ int pC;
+ Src = String;
+ Dst = String;
+ Spaces = 0;
+ pC = 0;
+ while (*Src) {
+ // corrections
+ if (*Src == 0x8c) // iso-8859-2 LATIN CAPITAL LETTER S WITH ACUTE
+ {
+ *Src = 0xa6;
+ }
+ if (*Src == 0x8f) // iso-8859-2 LATIN CAPITAL LETTER Z WITH ACUTE
+ {
+ *Src = 0xac;
+ }
+
+ if (*Src < 0x20) {
+ *Src = 0x20;
+ }
+ if (*Src == 0x20) {
+ Spaces++;
+ if (pC == 0) {
+ Spaces++;
+ }
+ }
+ else {
+ Spaces = 0;
+ }
+ if (Spaces < 2) {
+ *Dst = *Src;
+ *Dst++;
+ pC++;
+ }
+ *Src++;
+ }
+ if (Spaces > 0) {
+ Dst--;
+ *Dst = 0;
+ }
+ else {
+ *Dst = 0;
+ }
+}
+
+bool cFilterEEPG::GetThemesSKYBOX (void) //TODO can't we read this from the DVB stream?
+{
+ char *FileName;
+ FILE *FileThemes;
+ char *Line;
+ char Buffer[256];
+ if (Format == SKY_IT)
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_it.themes");
+ else if (Format == SKY_UK)
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.themes");
+ else {
+ esyslog ("EEPG: Error, wrong format detected in GetThemesSKYBOX. Format = %i.", Format);
+ return false;
+ }
+ //asprintf( &FileName, "%s/%s", ConfDir, ( lProviders + CurrentProvider )->Parm3 );
+ FileThemes = fopen (FileName, "r");
+ if (FileThemes == NULL) {
+ esyslog ("EEPG: Error opening file '%s'. %s", FileName, strerror (errno));
+ free (FileName);
+ return false;
+ }
+ else {
+ //int id = 0;
+ nThemes = 0;
+ char string1[256];
+ char string2[256];
+ //sTheme *T;
+ while ((Line = fgets (Buffer, sizeof (Buffer), FileThemes)) != NULL) {
+ memset (string1, 0, sizeof (string1));
+ memset (string2, 0, sizeof (string2));
+ if (!isempty (Line)) {
+ //T = &Themes[nThemes];
+ if (sscanf (Line, "%[^=] =%[^\n] ", string1, string2) == 2) {
+ snprintf ((char *) Themes[nThemes], 255, "%s", string2);
+ }
+ else {
+ Themes[nThemes][0] = '\0';
+ }
+ //id ++;
+ nThemes++;
+ }
+ }
+ fclose (FileThemes);
+ }
+ free (FileName);
+ return true;
+}
+
+bool cFilterEEPG::ReadFileDictionary (void)
+{
+ char *FileName;
+ FILE *FileDict;
+ char *Line;
+ char Buffer[256];
+ switch (Format) {
+ case SKY_IT:
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_it.dict");
+ break;
+ case SKY_UK:
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.dict");
+ break;
+ case FREEVIEW:
+ asprintf (&FileName, "%s/%s", ConfDir, "freesat.t1");
+ load_file (1, FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "freesat.t2");
+ load_file (2, FileName);
+ break;
+ default:
+ esyslog ("EEPG: Error, wrong format detected in ReadFileDictionary. Format = %i.", Format);
+ return false;
+ }
+ if ((Format == SKY_IT) || (Format == SKY_UK)) { //SKY
+ FileDict = fopen (FileName, "r");
+ if (FileDict == NULL) {
+ esyslog ("EEPG: Error opening file '%s'. %s", FileName, strerror (errno));
+ free (FileName);
+ return false;
+ }
+ else {
+ int i;
+ int LenPrefix;
+ char string1[256];
+ char string2[256];
+ H.Value = NULL;
+ H.P0 = NULL;
+ H.P1 = NULL;
+ while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
+ if (!isempty (Line)) {
+ memset (string1, 0, sizeof (string1));
+ memset (string2, 0, sizeof (string2));
+ if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2) {
+ goto codingstart;
+ }
+ else if (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2) {
+ codingstart:;
+ nH = &H;
+ LenPrefix = strlen (string2);
+ for (i = 0; i < LenPrefix; i++) {
+ switch (string2[i]) {
+ case '0':
+ if (nH->P0 == NULL) {
+ nH->P0 = new sNodeH ();
+ nH = nH->P0;
+ nH->Value = NULL;
+ nH->P0 = NULL;
+ nH->P1 = NULL;
+ if ((LenPrefix - 1) == i) {
+ asprintf (&nH->Value, "%s", string1);
+ }
+ }
+ else {
+ nH = nH->P0;
+ if (nH->Value != NULL || (LenPrefix - 1) == i) {
+ esyslog ("EEPG: Error, huffman prefix code already exists for \"%s\"=%s with '%s'", string1,
+ string2, nH->Value);
+ }
+ }
+ break;
+ case '1':
+ if (nH->P1 == NULL) {
+ nH->P1 = new sNodeH ();
+ nH = nH->P1;
+ nH->Value = NULL;
+ nH->P0 = NULL;
+ nH->P1 = NULL;
+ if ((LenPrefix - 1) == i) {
+ asprintf (&nH->Value, "%s", string1);
+ }
+ }
+ else {
+ nH = nH->P1;
+ if (nH->Value != NULL || (LenPrefix - 1) == i) {
+ esyslog ("EEPG: Error, huffman prefix code already exists for \"%s\"=%s with '%s'", string1,
+ string2, nH->Value);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ fclose (FileDict);
+ }
+
+ // check tree huffman nodes
+ FileDict = fopen (FileName, "r");
+ if (FileDict) {
+ int i;
+ int LenPrefix;
+ char string1[256];
+ char string2[256];
+ while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
+ if (!isempty (Line)) {
+ memset (string1, 0, sizeof (string1));
+ memset (string2, 0, sizeof (string2));
+ if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2) {
+ goto verifystart;
+ }
+ else if (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2) {
+ verifystart:;
+ nH = &H;
+ LenPrefix = strlen (string2);
+ for (i = 0; i < LenPrefix; i++) {
+ switch (string2[i]) {
+ case '0':
+ if (nH->P0 != NULL) {
+ nH = nH->P0;
+ }
+ break;
+ case '1':
+ if (nH->P1 != NULL) {
+ nH = nH->P1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (nH->Value != NULL) {
+ if (memcmp (nH->Value, string1, strlen (nH->Value)) != 0) {
+ esyslog ("EEPG: Error, huffman prefix value '%s' not equal to '%s'", nH->Value, string1);
+ }
+ }
+ else {
+ esyslog ("EEPG: Error, huffman prefix value is not exists for \"%s\"=%s", string1, string2);
+ }
+ }
+ }
+ }
+ fclose (FileDict);
+ }
+ } //if Format == 3 || Format == 4
+ free (FileName);
+ return true;
+}
+
+
+int DecodeHuffmanCode (const u_char * Data, int Length, unsigned char *DecodeText)
+{
+ int i;
+ int p;
+ int q;
+ bool CodeError;
+ bool IsFound;
+ unsigned char Byte;
+ unsigned char lastByte;
+ unsigned char Mask;
+ unsigned char lastMask;
+ nH = &H;
+ p = 0;
+ q = 0;
+ DecodeText[0] = '\0';
+ //DecodeErrorText[0] = '\0';
+ CodeError = false;
+ IsFound = false;
+ lastByte = 0;
+ lastMask = 0;
+ for (i = 0; i < Length; i++) {
+ Byte = Data[i];
+ Mask = 0x80;
+ if (i == 0) {
+ Mask = 0x20;
+ lastByte = i;
+ lastMask = Mask;
+ }
+ loop1:;
+ if (IsFound) {
+ lastByte = i;
+ lastMask = Mask;
+ IsFound = false;
+ }
+ if ((Byte & Mask) == 0) {
+ if (CodeError) {
+ //DecodeErrorText[q] = 0x30;
+ q++;
+ goto nextloop1;
+ }
+ if (nH->P0 != NULL) {
+ nH = nH->P0;
+ if (nH->Value != NULL) {
+ memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
+ p += strlen (nH->Value);
+ nH = &H;
+ IsFound = true;
+ }
+ }
+ else {
+ memcpy (&DecodeText[p], "<...?...>", 9);
+ p += 9;
+ i = lastByte;
+ Byte = Data[lastByte];
+ Mask = lastMask;
+ CodeError = true;
+ goto loop1;
+ }
+ }
+ else {
+ if (CodeError) {
+ //DecodeErrorText[q] = 0x31;
+ q++;
+ goto nextloop1;
+ }
+ if (nH->P1 != NULL) {
+ nH = nH->P1;
+ if (nH->Value != NULL) {
+ memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
+ p += strlen (nH->Value);
+ nH = &H;
+ IsFound = true;
+ }
+ }
+ else {
+ memcpy (&DecodeText[p], "<...?...>", 9);
+ p += 9;
+ i = lastByte;
+ Byte = Data[lastByte];
+ Mask = lastMask;
+ CodeError = true;
+ goto loop1;
+ }
+ }
+ nextloop1:;
+ Mask = Mask >> 1;
+ if (Mask > 0) {
+ goto loop1;
+ }
+ }
+ DecodeText[p] = '\0';
+ //DecodeErrorText[q] = '\0';
+ return p;
+}
+
+
+void cFilterEEPG::LoadEquivalentChannels (void)
+{
+ char Buffer[1024];
+ char *Line;
+ FILE *File;
+ char *FileName;
+
+ asprintf (&FileName, "%s/%s", ConfDir, EEPG_FILE_EQUIV);
+ File = fopen (FileName, "r");
+ if (File) {
+ memset (Buffer, 0, sizeof (Buffer));
+ char string1[256];
+ char string2[256];
+ char string3[256];
+ int int1;
+ int int2;
+ int int3;
+ int int4;
+ while ((Line = fgets (Buffer, sizeof (Buffer), File)) != NULL) {
+ Line = compactspace (skipspace (stripspace (Line)));
+ if (!isempty (Line)) {
+ if (sscanf (Line, "%[^ ] %[^ ] %[^\n]\n", string1, string2, string3) == 3) {
+ if (string1[0] != '#' && string1[0] != ';') {
+ int1 = 0; //TODO: this could be made more readable
+ int2 = 0;
+ int3 = 0;
+ int4 = 0;
+ if (sscanf (string1, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4)
+ if (sscanf (string2, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4) {
+ if (sscanf (string1, "%[^-]-%i -%i -%i -%i ", string3, &int1, &int2, &int3, &int4) != 5) {
+ int4 = 0;
+ }
+ tChannelID OriginalChID = tChannelID (cSource::FromString (string3), int1, int2, int3, int4);
+ bool found = false;
+ int i = 0;
+ sChannel *C;
+ while (i < nChannels && (!found)) {
+ C = &sChannels[i];
+ if (C->Src[0] == cSource::FromString (string3) && C->Nid[0] == int1
+ && C->Tid[0] == int2 && C->Sid[0] == int3)
+ found = true;
+ else
+ i++;
+ }
+ if (!found) {
+ if (VERBOSE >= 2)
+ isyslog
+ ("EEPG Warning: in equivalence file, cannot find original channel %s. Perhaps you are tuned to another transponder right now.",
+ string1);
+ }
+ else {
+ cChannel *OriginalChannel = Channels.GetByChannelID (OriginalChID, false);
+ if (!OriginalChannel && (VERBOSE >= 2))
+ isyslog ("EEPG: warning, not found epg channel \'%s\' in channels.conf. Equivalency is assumed to be valid, but perhaps you should check the entry in the equivalents file", string1); //TODO: skip this warning?
+ if (sscanf (string2, "%[^-]-%i -%i -%i ", string3, &int1, &int2, &int3) == 4) {
+ if (sscanf (string2, "%[^-]-%i -%i -%i -%i ", string3, &int1, &int2, &int3, &int4)
+ != 5) {
+ int4 = 0;
+ }
+ tChannelID EquivChID = tChannelID (cSource::FromString (string3), int1, int2, int3, int4);
+ cChannel *EquivChannel = Channels.GetByChannelID (EquivChID, false); //TODO use valid function?
+ if (EquivChannel) {
+ if (C->NumberOfEquivalences < MAX_EQUIVALENCES) {
+ C->Src[C->NumberOfEquivalences] = EquivChannel->Source ();
+ C->Nid[C->NumberOfEquivalences] = EquivChannel->Nid ();
+ C->Tid[C->NumberOfEquivalences] = EquivChannel->Tid ();
+ C->Sid[C->NumberOfEquivalences] = EquivChannel->Sid ();
+ C->NumberOfEquivalences++;
+ nEquivChannels++;
+ if (VERBOSE >= 3)
+ isyslog
+ ("EEPG: Added equivalent nr %i with Channel Id %s-%i-%i-%i to channel with id %i.",
+ C->NumberOfEquivalences, *cSource::ToString (C->Src[C->NumberOfEquivalences-1]),
+ C->Nid[C->NumberOfEquivalences-1], C->Tid[C->NumberOfEquivalences-1],
+ C->Sid[C->NumberOfEquivalences-1], i);
+ }
+ else
+ esyslog
+ ("EEPG: Error, channel with id %i has more than %i equivalences. Increase MAX_EQUIVALENCES.",
+ i, MAX_EQUIVALENCES);
+ }
+ else
+ isyslog ("EEPG: warning, not found equivalent channel \'%s\' in channels.conf", string2);
+ }
+ } //else !found
+ } //if scanf string1
+ } //if string1
+ } //if scanf
+ } //if isempty
+ } //while
+ fclose (File);
+ } //if file
+ free (FileName);
+} //end of loadequiv
+
+int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ if ((MHW == 1) || (nChannels == 0)) { //prevents MHW2 from reading channels twice while waiting for themes on same filter
+ sChannelMHW1 *Channel;
+ int Size, Off;
+ Size = sizeof (sChannelMHW1);
+ Off = 4;
+ if (MHW == 1) {
+ //Channel = (sChannelMHW1 *) (Data + 4);
+ nChannels = (Length - 4) / sizeof (sChannelMHW1);
+ }
+ if (MHW == 2) {
+ if (Length > 119)
+ nChannels = Data[119];
+ else {
+ esyslog ("EEPG: Error, channels packet too short for MHW2.");
+ return 0;
+ }
+ int pName = ((nChannels * 8) + 120);
+ if (Length > pName) {
+ //Channel = (sChannelMHW1 *) (Data + 120);
+ Size -= 14; //MHW2 is 14 bytes shorter
+ Off = 120; //and offset differs
+ }
+ else {
+ esyslog ("EEPG: Error, channels length does not match pname.");
+ return 0;
+ }
+ }
+
+ if (nChannels > MAX_CHANNELS) {
+ esyslog ("EEPG: Error, channels found more than %i", MAX_CHANNELS);
+ return 0;
+ }
+ else {
+ if (VERBOSE >= 1) {
+ isyslog ("| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+ isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+ "-----------------------------", "--------------------");
+ }
+ int pName = ((nChannels * 8) + 120); //TODO double ...
+ for (int i = 0; i < nChannels; i++) {
+ Channel = (sChannelMHW1 *) (Data + Off);
+ sChannel *C = &sChannels[i];
+ C->ChannelId = i;
+ ChannelSeq[C->ChannelId] = i; //fill lookup table to go from channel-id to sequence nr in table
+ C->SkyNumber = 0;
+ if (MHW == 1)
+ memcpy (C->Name, &Channel->Name, 16); //MHW1
+ else { //MHW2
+ int lenName = Data[pName] & 0x0f;
+ if (lenName < 256) //TODO impossible, after & 0x0f lenName is always < 0x0f !!
+ memcpy (C->Name, &Data[pName + 1], lenName);
+ else
+ memcpy (C->Name, &Data[pName + 1], 256);
+ pName += (lenName + 1);
+ }
+ C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1
+ C->Src[0] = Source (); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!!
+ C->Nid[0] = HILO16 (Channel->NetworkId);
+ C->Tid[0] = HILO16 (Channel->TransportId);
+ C->Sid[0] = HILO16 (Channel->ServiceId);
+ tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]);
+ cChannel *VC = Channels.GetByChannelID (channelID, true);
+ bool IsFound = (VC);
+ if (!IsFound) { //look on other satpositions
+ for (int i = 0; i < NumberOfAvailableSources; i++) {
+ channelID = tChannelID (AvailableSources[i], C->Nid[0], C->Tid[0], C->Sid[0]);
+ VC = Channels.GetByChannelID (channelID, true);
+ IsFound = (VC);
+ if (IsFound) { //found this actually on satellite nextdoor...
+ C->Src[0] = AvailableSources[i];
+ break;
+ }
+ }
+ }
+ CleanString (C->Name);
+
+ if (VERBOSE >= 1) {
+ char *ChID;
+ asprintf (&ChID, "%s-%i-%i-%i-0", *cSource::ToString (C->Src[0]), C->Nid[0], C->Tid[0], C->Sid[0]);
+ char *IsF;
+ if (IsFound)
+ asprintf (&IsF, " %-3.3s |", "YES");
+ else
+ asprintf (&IsF, " %-3.3s |", "NO");
+ isyslog ("|% 5d | %-26.26s | %-22.22s |%s % 6d |\n", C->ChannelId, ChID, C->Name, IsF, C->SkyNumber);
+ free (ChID);
+ free (IsF);
+ }
+ Off += Size;
+ } //for loop
+ } //else nChannels > MAX_CHANNELS
+ LoadEquivalentChannels ();
+ GetLocalTimeOffset (); //reread timing variables, only used for MHW
+ return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
+ } //if nChannels == 0
+ esyslog ("EEPG Warning: Trying to read Channels more than once!");
+//you will only get here when GetChannelsMHW is called, and nChannels !=0, e.g. when multiple citpids cause channels to be read multiple times. Second time, do nothing, give error so that the rest of the chain is not restarted also.
+ return 0;
+}
+
+int cFilterEEPG::GetThemesMHW1 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{ //MHW1 Themes
+ if (Length > 19) {
+ sThemeMHW1 *Theme = (sThemeMHW1 *) (Data + 19);
+ nThemes = (Length - 19) / 15;
+ if (nThemes > MAX_THEMES) {
+ esyslog ("EEPG: Error, themes found more than %i", MAX_THEMES);
+ return 0;
+ }
+ else {
+ if (VERBOSE >= 1)
+ isyslog ("-------------THEMES FOUND--------------");
+ int ThemeId = 0;
+ int Offset = 0;
+ const u_char *ThemesIndex = (Data + 3);
+ for (int i = 0; i < nThemes; i++) {
+ if (ThemesIndex[ThemeId] == i) {
+ Offset = (Offset + 15) & 0xf0; //TODO do not understand this
+ ThemeId++;
+ }
+ memcpy (&Themes[Offset][0], &Theme->Name, 15);
+ Themes[Offset][15] = NULL; //trailing null
+ CleanString (Themes[Offset]);
+ if (VERBOSE >= 1)
+ isyslog ("%.15s", Themes[Offset]);
+ Offset++;
+ Theme++;
+ }
+ if ((nThemes * 15) + 19 != Length) {
+ esyslog ("EEPG: Themes error: buffer is smaller or bigger than sum of entries.");
+ return 0;
+ }
+ else
+ return 2;
+ }
+ }
+ return 1;
+}
+
+int cFilterEEPG::GetThemesMHW2 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ if (!EndThemes) { //only proces if not processed
+ int p1;
+ int p2;
+ int pThemeName = 0;
+ int pSubThemeName = 0;
+ int lenThemeName = 0;
+ int lenSubThemeName = 0;
+ int pThemeId = 0;
+ if (Length > 4) {
+ if (VERBOSE >= 1)
+ isyslog ("-------------THEMES FOUND--------------");
+ for (int i = 0; i < Data[4]; i++) {
+ p1 = ((Data[5 + i * 2] << 8) | Data[6 + i * 2]) + 3;
+ if (Length > p1) {
+ for (int ii = 0; ii <= (Data[p1] & 0x3f); ii++) {
+ p2 = ((Data[p1 + 1 + ii * 2] << 8) | Data[p1 + 2 + ii * 2]) + 3;
+ if (Length > p2) {
+ if (ii == 0) {
+ pThemeName = p2 + 1;
+ lenThemeName = Data[p2] & 0x1f;
+ lenSubThemeName = 0;
+ }
+ else {
+ pSubThemeName = p2 + 1;
+ lenSubThemeName = Data[p2] & 0x1f;
+ }
+ if (Length >= (pThemeName + lenThemeName)) {
+ pThemeId = ((i & 0x3f) << 6) | (ii & 0x3f);
+ if ((lenThemeName + 2) < 256) {
+ memcpy (Themes[pThemeId], &Data[pThemeName], lenThemeName);
+ if (Length >= (pSubThemeName + lenSubThemeName))
+ if (lenSubThemeName > 0)
+ if ((lenThemeName + lenSubThemeName + 2) < 256) {
+ Themes[pThemeId][lenThemeName] = ' ';
+ memcpy (&Themes[pThemeId][lenThemeName + 1], &Data[pSubThemeName], lenSubThemeName);
+ }
+ CleanString (Themes[pThemeId]);
+ if (VERBOSE >= 1)
+ isyslog ("%.*s", lenThemeName + 1 + lenSubThemeName, Themes[pThemeId]);
+ //isyslog ("%.15s", (lThemes + pThemeId)->Name);
+ nThemes++;
+ if (nThemes > MAX_THEMES) {
+ esyslog ("EEPG: Error, themes found more than %i", MAX_THEMES);
+ return 0; //fatal error
+ }
+ }
+ }
+ else
+ return 1; //I assume non fatal error or success
+ }
+ else
+ return 1; //I assume non fatal error or success
+ }
+ }
+ else
+ return 1; //I assume non fatal error or success
+ } //for loop
+ //Del (Pid, Tid);
+ EndThemes = true;
+ return 2; //all themes read
+ } //if length
+ } //if !EndThemes
+ return 1; //non fatal or success
+}
+
+char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offset, unsigned int TitleEventId) //this function returns pointer to reserved part of memory with summary text in it, terminated by NULL
+ //EventId is passed from title, to check it against the eventid of the summary
+{
+ u_char *p = (u_char *) DataStart + Offset;
+ sSummaryDataNagraGuide *SD = (sSummaryDataNagraGuide *) p;
+
+ if (TitleEventId != HILO32 (SD->EventId)) {
+ esyslog ("EEPG: ERROR, Title has EventId %08x and points to Summary with EventId %08x.", TitleEventId,
+ HILO32 (SD->EventId));
+ return 0; //return empty string
+ }
+
+ if (VERBOSE >= 3) {
+ if (SD->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero1 is NOT ZERO:%x.", SD->AlwaysZero1);
+ if (SD->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero2 is NOT ZERO:%x.", SD->AlwaysZero2);
+ if (SD->AlwaysZero3 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero3 is NOT ZERO:%x.", SD->AlwaysZero3);
+ if (SD->AlwaysZero4 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero4 is NOT ZERO:%x.", SD->AlwaysZero4);
+ if (SD->AlwaysZero5 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero5 is NOT ZERO:%x.", SD->AlwaysZero5);
+ if (SD->AlwaysZero6 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero6 is NOT ZERO:%x.", SD->AlwaysZero6);
+ if (SD->AlwaysZero7 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero7 is NOT ZERO:%x.", SD->AlwaysZero7);
+ if (SD->AlwaysZero8 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero8 is NOT ZERO:%x.", SD->AlwaysZero8);
+ if (SD->AlwaysZero9 != 0)
+ isyslog ("EEPGDEBUG: SummAlwaysZero9 is NOT ZERO:%x.", SD->AlwaysZero9);
+
+ if (SD->Always1 != 0x31) //1970
+ isyslog ("EEPGDEBUG: SummAlways1:%02x.", SD->Always1);
+ if (SD->Always9 != 0x39)
+ isyslog ("EEPGDEBUG: SummAlways9:%02x.", SD->Always9);
+ if (SD->Always7 != 0x37)
+ isyslog ("EEPGDEBUG: SummAlways7:%02x.", SD->Always7);
+ if (SD->Always0 != 0x30)
+ isyslog ("EEPGDEBUG: SummAlways0:%02x.", SD->Always0);
+
+ if (SD->Always0x01 != 0x01) // 0x01 byte
+ isyslog ("EEPGDEBUG: Summ0x01 byte:%02x.", SD->Always0x01);
+ }
+ u_char *p2 = (u_char *) DataStart + HILO32 (SD->SummTxtOffset);
+/* esyslog
+ ("EEPGDEBUG: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x.",
+ HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2, SD->Unknown1,
+ SD->Unknown2);
+*/
+ unsigned char *Text = NULL; //makes first realloc work like malloc
+ int TotLength = 0; //and also makes empty summaries if *p2 != 0x4e
+ if (SD->NumberOfBlocks > 1) {
+ switch (*p2) {
+ case 0x4e: //valid summary text follows
+ { //prevents compiler from complaining
+ bool LastTextBlock = false;
+
+ do { //for all text parts
+ sSummaryTextNagraGuide *ST = (sSummaryTextNagraGuide *) p2;
+ p2 += 8; //skip fixed block
+ if (VERBOSE >= 3)
+ if (ST->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: ST AlwaysZero1 is NOT ZERO:%x.", ST->AlwaysZero1);
+ if (ST->Always0x4e != 0x4e) {
+ isyslog ("EEPGDEBUG: ST Always0x4e is NOT 0x4e:%x.", ST->AlwaysZero1);
+ return 0; //fatal error, empty text
+ }
+ //esyslog ("EEPGDEBUG: Textnr %i, Lasttxt %i.", ST->TextNr, ST->LastTextNr);
+ int SummaryLength = ST->Textlength;
+
+ Text = (unsigned char *) realloc (Text, SummaryLength + TotLength);
+ if (Text == NULL) {
+ esyslog ("EEPG: Summaries memory allocation error.");
+ return 0; //empty text
+ }
+ memcpy (Text + TotLength, p2, SummaryLength); //append new textpart
+ TotLength += SummaryLength;
+ p2 += ST->Textlength; //skip text
+
+ LastTextBlock = ((ST->LastTextNr == 0) || (ST->TextNr >= ST->LastTextNr));
+ } while (!LastTextBlock);
+ Text = (unsigned char *) realloc (Text, 1 + TotLength); //allocate 1 extra byte
+ Text[TotLength] = NULL; //terminate string by NULL char
+// isyslog ("EEPGDEBUG: Full Text:%s.", Text);
+
+ break;
+ } //prevents compiler from complaining
+ case 0x8c: //"Geen uitzending" "Geen informatie beschikbaar" e.d.
+ { //prevents compiler from complaining
+ sSummaryGBRNagraGuide *GBR = (sSummaryGBRNagraGuide *) p2;
+
+ p2 += 16; //skip fixed part, point to byte after Nextlength
+ if (VERBOSE >= 3) {
+ if (GBR->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero1 is NOT ZERO:%x.", GBR->AlwaysZero1);
+ if (GBR->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero2 is NOT ZERO:%x.", GBR->AlwaysZero2);
+ if (GBR->AlwaysZero3 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero3 is NOT ZERO:%x.", GBR->AlwaysZero3);
+ if (GBR->AlwaysZero4 != 0)
+ isyslog ("EEPGDEBUG: GBR AlwaysZero4 is NOT ZERO:%x.", GBR->AlwaysZero4);
+
+ isyslog ("EEPGDEBUG: Blocklength: %02x Data %02x %02x %02x %02x %02x %02x %02x %02x %02x", GBR->Blocklength,
+ GBR->Un1, GBR->Un2, GBR->Un3, GBR->Un4, GBR->Un5, GBR->Un6, GBR->Un7, GBR->Un8, GBR->Un9);
+ for (int i = 0; i < GBR->Nextlength; i += 2)
+ isyslog ("GBR Extradata %02x %02x.", *(p2 + i), *(p2 + i + 1));
+ }
+ } //prevents compiler from complaining
+ break;
+ default:
+ esyslog
+ ("EEPG: ERROR *p2 has strange value: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x.",
+ HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2,
+ SD->Unknown1, SD->Unknown2);
+ break;
+ } //end of switch
+ } //NrOfBlocks > 1
+
+ if (TotLength == 0)
+ Text = NULL;
+
+ p += 29; //skip fixed part of block
+ if (SD->NumberOfBlocks == 1)
+ p -= 4; //in this case there is NO summarytext AND no GBR??!!
+ for (int i = 1; i < (SD->NumberOfBlocks - 1); i++) {
+ if (VERBOSE >= 3)
+ isyslog ("EEPGDEBUG: Extra Blockinfo: %02x %02x %02x %02x.", *p, *(p + 1), *(p + 2), *(p + 3));
+ p += 4; //skip this extra blockinfo
+ }
+ return (char *) Text;
+}
+
+void cFilterEEPG::PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]) //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
+{
+ for (int eq = 0; eq < C->NumberOfEquivalences; eq++) {
+ tChannelID channelID = tChannelID (C->Src[eq], C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+#ifdef USE_NOEPG
+ if (allowedEPG (channelID) && (channelID.Valid ()))
+#else
+ if (channelID.Valid ()) //only add channels that are known to vdr
+#endif /* NOEPG */
+ ps[eq] = s->AddSchedule (channelID); //open a a schedule for each equivalent channel
+ else {
+ ps[eq] = NULL;
+ if (VERBOSE >= 5)
+ esyslog
+ ("EEPG ERROR: Titleblock has invalid (equivalent) channel ID: Equivalence: %i, Source:%x, C->Nid:%x,C->Tid:%x,C->Sid:%x.",
+ eq, C->Src[eq], C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+ }
+ }
+}
+
+void cFilterEEPG::FinishWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES])
+{
+ for (int eq = 0; eq < C->NumberOfEquivalences; eq++)
+ if (ps[eq]) {
+ ps[eq]->Sort ();
+ s->SetModified (ps[eq]);
+ }
+}
+
+void cFilterEEPG::WriteToSchedule (cSchedule * ps[MAX_EQUIVALENCES], unsigned short int NumberOfEquivalences, unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text, char *SummText, unsigned short int ThemeId, unsigned short int TableId, unsigned short int Version) //ps points to array of schedules ps[eq], where eq is equivalence number of the channel. If channelId is invalid then ps[eq]=NULL
+ //Duration in minutes
+{
+ bool WrittenTitle = false;
+ bool WrittenSummary = false;
+ for (int eq = 0; eq < NumberOfEquivalences; eq++) {
+ if (ps[eq]) {
+ cEvent *Event = NULL;
+
+ Event = (cEvent *) ps[eq]->GetEvent (EventId); //since Nagra uses consistent EventIds, try this first
+ if (!Event) //if EventId does not match, then try with StartTime
+ Event = (cEvent *) ps[eq]->GetEvent (EventId, StartTime);
+
+ cEvent *newEvent = NULL;
+ if (!Event) { //event is new
+ Event = newEvent = new cEvent (EventId);
+ Event->SetSeen ();
+ }
+ else if (Event->TableID () < TableId) { //existing table may not be overwritten
+ RejectTableId++;
+ //esyslog ("EEPGDEBUG: Rejecting Event, existing TableID:%x, new TableID:%x.", Event->TableID (),
+ // TableId);
+ Event = NULL;
+ }
+
+ if (Event) {
+ Event->SetEventID (EventId); //otherwise the summary cannot be added later
+ Event->SetTableID (TableId); //TableID 0 is reserved for external epg, will not be overwritten; the lower the TableID, the more actual it is
+ Event->SetVersion (Version); //TODO use version and tableID to decide whether to update; TODO add language code
+ Event->SetStartTime (StartTime);
+ Event->SetDuration (Duration * 60);
+ char *tmp;
+ if (Text != 0x00) {
+ WrittenTitle = true;
+ CleanString ((uchar *) Text);
+ Event->SetTitle (Text);
+ }
+ asprintf (&tmp, "%s - %d\'", Themes[ThemeId], Duration);
+ Event->SetShortText (tmp);
+ //strreplace(t, '|', '\n');
+ if (SummText != 0x00) {
+ WrittenSummary = true;
+ CleanString ((uchar *) SummText);
+ Event->SetDescription (SummText);
+ }
+ free (tmp);
+ if (newEvent)
+ ps[eq]->AddEvent (newEvent);
+ //newEvent->FixEpgBugs (); causes segfault
+ }
+/* else
+ esyslog ("EEPG: ERROR, somehow not able to add/update event.");*///at this moment only reports RejectTableId events
+ if (VERBOSE >= 4) {
+ isyslog ("EEPG: Title:%i, Summary:%i I would put into schedule:", TitleCounter, SummaryCounter);
+ //isyslog ("C %s-%i-%i-%i\n", *cSource::ToString (C->Src[eq]), C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+ isyslog ("E %u %u %u 01 FF\n", EventId, StartTime, Duration * 60);
+ isyslog ("T %s\n", Text);
+ isyslog ("S %s - %d\'\n", Themes[ThemeId], Duration);
+ isyslog ("D %s\n", SummText);
+ isyslog ("e\nc\n.\n");
+ }
+ } //if ps[eq]
+ } //for eq
+ if (WrittenTitle)
+ TitleCounter++;
+ if (WrittenSummary)
+ SummaryCounter++;
+}
+
+void cFilterEEPG::GetTitlesNagra (const u_char * Data, int Length, unsigned short TableIdExtension) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{ //TableIdExtension is the TIE from the relevant summary sections!
+ u_char *p = (u_char *) Data;
+ u_char *DataEnd = (u_char *) Data + Length;
+ u_char *next_p;
+ unsigned short int MonthdayTitles = ((TableIdExtension & 0x1ff) >> 4); //Day is coded in day of the month
+ time_t timeLocal;
+ struct tm *tmCurrent;
+
+ timeLocal = time (NULL);
+ tmCurrent = gmtime (&timeLocal); //gmtime gives UTC; only used for getting current year and current day of the month...
+ unsigned short int CurrentMonthday = tmCurrent->tm_mday;
+ unsigned short int CurrentYear = tmCurrent->tm_year;
+ unsigned short int CurrentMonth = tmCurrent->tm_mon;
+ //esyslog("EEPGDEBUG: CurrentMonthday=%i, TableIdExtension:%04x, MonthdayTitles=%i.",CurrentMonthday,TableIdExtension, MonthdayTitles);
+ cSchedulesLock SchedulesLock (true);
+ cSchedules *s = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+ do { //process each block of titles
+ sTitleBlockNagraGuide *TB = (sTitleBlockNagraGuide *) p;
+ int ChannelId = HILO16 (TB->ChannelId);
+ int Blocklength = HILO16 (TB->Blocklength);
+ long int NumberOfTitles = HILO32 (TB->NumberOfTitles);
+
+ if (VERBOSE >= 3)
+ isyslog ("EEPGDEBUG: ChannelId %04x, Blocklength %04x, NumberOfTitles %lu.", ChannelId, Blocklength,
+ NumberOfTitles);
+ p += 4; //skip ChannelId and Blocklength
+ next_p = p + Blocklength;
+ if (next_p > DataEnd) { //only process if block is complete
+ esyslog ("EEPG: ERROR, Block exceeds end of Data. p:%p, Blocklength:%x,DataEnd:%p.", p, Blocklength, DataEnd);
+ return; //fatal error, this should never happen
+ }
+ p += 4; //skip Titlenumber
+
+ sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
+ cSchedule *ps[MAX_EQUIVALENCES];
+ PrepareToWriteToSchedule (C, s, ps);
+
+ for (int i = 0; i < NumberOfTitles; i++) { //process each title within block
+ sTitleNagraGuide *Title = (sTitleNagraGuide *) p;
+ unsigned int EventId = HILO32 (Title->EventId);
+
+ unsigned int StartTime = Title->StartTimeHigh << 5 | Title->StartTimeLow;
+ int Hours = (StartTime / 60);
+ int Minutes = StartTime % 60;
+
+ /*StartTime */
+ tmCurrent->tm_year = CurrentYear;
+ tmCurrent->tm_mon = CurrentMonth;
+ tmCurrent->tm_mday = MonthdayTitles;
+ tmCurrent->tm_hour = 0;
+ tmCurrent->tm_min = StartTime; //if starttime is bigger than 1 hour, mktime will correct this!
+ tmCurrent->tm_sec = 0;
+ tmCurrent->tm_isdst = -1; //now correct with daylight savings
+ if (MonthdayTitles < CurrentMonthday - 7) //the titles that are older than one week are not from the past, but from next month!
+ //at first this was set at -1 day (= yesterday), but sometimes providers send old data which then
+ //end up in next months schedule ...
+ tmCurrent->tm_mon++; //if a year border is passed, mktime will take care of this!
+ StartTime = UTC2LocalTime (mktime (tmCurrent)); //VDR stores its times in UTC, but wants its input in local time...
+
+ char *Text = NULL;
+ u_char *t = (u_char *) Data + HILO32 (Title->OffsetToText);
+ //u_char *t2 = (u_char *) Data + HILO32 (Title->OffsetToText2);
+ asprintf (&Text, "%.*s", *t, t + 1); //FIXME second text string is not processed right now
+ //asprintf (&Text, "%.*s %.*s", *t, t + 1, *t2, t2 + 1);
+
+ //now get summary texts
+ u_char *DataStartSummaries = buffer[TableIdExtension] + 4;
+ char *SummText = GetSummaryTextNagra (DataStartSummaries, HILO32 (Title->SumDataOffset), EventId);
+
+ if (VERBOSE >= 3)
+ isyslog
+ ("EEPGDEBUG: Eventid: %08x ChannelId:%x, Starttime %02i:%02i, Duration %i, OffsetToText:%08x, OffsetToText2:%08x, SumDataOffset:%08x ThemeId:%x Title:%s \n SummaryText:%s",
+ EventId, ChannelId, Hours, Minutes,
+ Title->Duration, HILO32 (Title->OffsetToText), HILO32 (Title->OffsetToText2),
+ HILO32 (Title->SumDataOffset), Title->ThemeId, Text, SummText);
+
+ if (Themes[Title->ThemeId][0] == 0x00) //if detailed themeid is not known, get global themeid
+ Title->ThemeId &= 0xf0;
+ WriteToSchedule (ps, C->NumberOfEquivalences, EventId, StartTime, Title->Duration, Text, SummText, Title->ThemeId,
+ NAGRA_TABLE_ID, Version);
+
+ if (Text != NULL)
+ free (Text);
+ Text = NULL;
+ if (SummText != NULL)
+ free (SummText);
+ SummText = NULL;
+
+ if (VERBOSE >= 3) {
+ if (Title->AlwaysZero16 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero16 (3bits) is NOT ZERO:%x.", Title->AlwaysZero16);
+ if (Title->AlwaysZero17 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero17 is NOT ZERO:%x.", Title->AlwaysZero17);
+ if (Title->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero1 is NOT ZERO:%x.", Title->AlwaysZero1);
+ if (Title->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero2 is NOT ZERO:%x.", Title->AlwaysZero2);
+ if (Title->AlwaysZero3 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero3 is NOT ZERO:%x.", Title->AlwaysZero3);
+ if (Title->AlwaysZero4 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero4 is NOT ZERO:%x.", Title->AlwaysZero4);
+ if (Title->AlwaysZero5 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero5 is NOT ZERO:%x.", Title->AlwaysZero5);
+ if (Title->AlwaysZero8 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero8 is NOT ZERO:%x.", Title->AlwaysZero8);
+ if (Title->AlwaysZero9 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero9 is NOT ZERO:%x.", Title->AlwaysZero9);
+ if (Title->AlwaysZero10 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero10 is NOT ZERO:%x.", Title->AlwaysZero10);
+ if (Title->AlwaysZero11 != 0)
+ isyslog ("EEPGDEBUG: TitleAlwaysZero11 is NOT ZERO:%x.", Title->AlwaysZero11);
+ }
+ p += 30; //next title
+ } //end for titles
+
+ FinishWriteToSchedule (C, s, ps);
+ p = next_p;
+ } while (p < DataEnd); //end of TitleBlock
+}
+
+int cFilterEEPG::GetThemesNagra (const u_char * Data, int Length, unsigned short TableIdExtension) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ u_char *DataStart = (u_char *) Data;
+ u_char *p = DataStart; //TODO Language code terminated by 0 is ignored
+ u_char *DataEnd = DataStart + Length;
+ u_char *DataStartTitles = buffer[TableIdExtension] + 4;
+ if (Length == 0) {
+ if (VERBOSE >= 1)
+ isyslog ("EEPG: NO THEMES FOUND");
+ return 2;
+ }
+
+ int NumberOfThemes = (*p << 24) | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
+ p += 4; //skip number of themes block
+ //isyslog ("EEPG: found %i themes.", NumberOfThemes);
+
+ if ((VERBOSE >= 1) && (nThemes == 0))
+ isyslog ("-------------THEMES FOUND--------------");
+
+ for (int i = 0; i < NumberOfThemes; i++) {
+ int Textlength = *p;
+ p++; //skip textlength byte
+ u_char *Text = p;
+ u_char ThemeId;
+ p += Textlength; //skip text
+ int NrOfBlocks = (*p << 8) | *(p + 1);
+ p += 2; //skip nrofblocks
+ bool AnyDoubt = false;
+ u_char *p2 = p;
+ p += NrOfBlocks * 8;
+ for (int j = 0; j < NrOfBlocks; j++) {
+ sThemesTitlesNagraGuide *TT = (sThemesTitlesNagraGuide *) p2;
+ p2 += 8; //skip block
+ u_char *NewThemeId = DataStartTitles + HILO32 (TT->TitleOffset) + 28;
+ //esyslog("EEPGDEBUG: NewThemeId:%02x, Text:%s.",*NewThemeId, Text);
+ if (Themes[*NewThemeId][0] != 0x00) { //theme is already filled, break off
+ AnyDoubt = true;
+ break; //FIXME enabling this break will cause segfault
+ }
+ if (j == 0) //first block
+ ThemeId = *NewThemeId;
+ else if (ThemeId != *NewThemeId) { //different theme ids in block
+ if ((ThemeId & 0xf0) != (*NewThemeId & 0xf0)) { //major nible of themeid does not correspond
+ if (VERBOSE >= 3)
+ esyslog
+ ("EEPG: ERROR, Theme has multiple indices which differ in major nibble, old index = %x, new index = %x. Ignoring both indices.",
+ ThemeId, *NewThemeId);
+ AnyDoubt = true;
+ break;
+ }
+ else if ((ThemeId & 0x0f) != 0) //ThemeId is like 1a, 2a, not like 10,20. So it is minor in tree-structure, and it should be labeled in major part of tree
+ ThemeId = *NewThemeId; //lets hope new themeid is major, if not, it has not worsened....
+ }
+ if (VERBOSE >= 3) {
+ if (TT->Always1 != 1)
+ isyslog ("EEPGDEBUG: TT Always1 is NOT 1:%x.", TT->Always1);
+ if (TT->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: TT AlwaysZero1 is NOT ZERO:%x.", TT->AlwaysZero1);
+ if (TT->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: TT AlwaysZero2 is NOT ZERO:%x.", TT->AlwaysZero2);
+ }
+ } //for nrofblocks
+ // esyslog("EEPGDEBUG: AnyDoubt:%x.",AnyDoubt);
+ if (!AnyDoubt) {
+ if (Textlength > 63)
+ Textlength = 63; //leave room for trailing NULL
+ if (Themes[ThemeId][0] != 0) {
+ esyslog
+ ("EEPG: Trying to add new theme, but Id already exists. ThemeId = %x, Old theme with this Id:%s, new theme: %s.",
+ ThemeId, Themes[ThemeId], Text);
+ continue;
+ }
+ memcpy (&Themes[ThemeId], Text, Textlength);
+ Themes[ThemeId][Textlength] = NULL; //trailing NULL
+ CleanString (Themes[ThemeId]);
+ nThemes++;
+ if (VERBOSE >= 1)
+ isyslog ("%02x %s", ThemeId, Themes[ThemeId]);
+ }
+ } //for NumberOfThemes
+ if (p != DataEnd) {
+ esyslog ("EEPG: Themes error: buffer is smaller or bigger than sum of entries. p:%p,DataEnd:%p", p, DataEnd);
+ return 0;
+ }
+ else
+ return 2;
+}
+
+int cFilterEEPG::GetChannelsNagra (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ u_char *DataStart = (u_char *) Data;
+ u_char *p = DataStart;
+ u_char *DataEnd = DataStart + Length;
+
+ nChannels = (*p << 24) | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
+ p += 4; //skip numberofchannels
+ if (VERBOSE >= 1) {
+ isyslog ("| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+ isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+ "-----------------------------", "--------------------");
+ }
+
+ for (int j = 0; j < nChannels; j++) {
+ sChannelsNagraGuide *Channel = (sChannelsNagraGuide *) p;
+ sChannel *C = &sChannels[j];
+ C->ChannelId = j + 1; //Nagra starts numbering at 1
+ ChannelSeq[C->ChannelId] = j; //fill lookup table to go from channel-id to sequence nr in table; lookuptable starts with 0
+ C->SkyNumber = 0;
+ C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1
+ C->Src[0] = Source (); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!!
+ C->Nid[0] = HILO16 (Channel->NetworkId);
+ C->Tid[0] = HILO16 (Channel->TransportId);
+ C->Sid[0] = HILO16 (Channel->ServiceId);
+ tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]);
+ cChannel *VC = Channels.GetByChannelID (channelID, true);
+ bool IsFound = (VC);
+
+ if (!IsFound) { //look on other satpositions
+ for (int i = 0; i < NumberOfAvailableSources; i++) {
+ channelID = tChannelID (AvailableSources[i], C->Nid[0], C->Tid[0], C->Sid[0]);
+ VC = Channels.GetByChannelID (channelID, true);
+ IsFound = (VC);
+ if (IsFound) { //found this actually on satellite nextdoor...
+ C->Src[0] = AvailableSources[i];
+ break;
+ }
+ }
+ }
+ if (IsFound)
+ strncpy ((char *) C->Name, VC->Name (), 64);
+ else
+ C->Name[0] = NULL; //empty string
+ CleanString (C->Name);
+
+ if (VERBOSE >= 1) {
+ char *ChID;
+ asprintf (&ChID, "%s-%i-%i-%i-0", *cSource::ToString (C->Src[0]), C->Nid[0], C->Tid[0], C->Sid[0]);
+ char *IsF;
+ if (IsFound)
+ asprintf (&IsF, " %-3.3s |", "YES");
+ else
+ asprintf (&IsF, " %-3.3s |", "NO");
+ isyslog ("|% 5d | %-26.26s | %-22.22s |%s % 6d |\n", C->ChannelId, ChID, C->Name, IsF, C->SkyNumber);
+ free (ChID);
+ free (IsF);
+ }
+ if (VERBOSE >= 4)
+ isyslog ("EEPGDEBUG: start : %s", cs_hexdump (0, p, 9));
+
+ p += 8; //skip to first 0x8c if non-FTA, or 0x00 if FTA
+ for (int i = 0; i < Channel->Nr8cBlocks; i++) {
+ if (*p != 0x8c) {
+ esyslog ("EEPGDEBUG: ERROR in Channel Table, expected value of 0x8c is %02x", *p);
+ return 0; //fatal error
+ }
+ p++; //skip 8c byte
+ if (VERBOSE >= 4)
+ isyslog ("EEPGDEBUG: 8c string: %s", cs_hexdump (0, p + 1, *p));
+ p += *p; //skip 8c block
+ p++; //forgot to skip length byte
+ }
+ //start last non 8c block here
+ if (*p != 0x00) {
+ esyslog ("EEPGDEBUG: ERROR in Channel Table, expected value of 0x00 is %02x", *p);
+ return 0; //fatal error
+ }
+ p++; //skip 0x00 byte
+ if (VERBOSE >= 4)
+ isyslog ("EEPGDEBUG: endstring: %s", cs_hexdump (0, p + 1, *p * 4));
+ p += (*p * 4); //p points to nrofblocks, each block is 4 bytes
+ p++; //forgot to skip nrofblocks byte
+
+/*
+ if (Channel->AlwaysZero1 != 0)
+ isyslog ("EEPGDEBUG: AlwaysZero1 is NOT ZERO:%x.", Channel->AlwaysZero1);
+ if (Channel->AlwaysZero2 != 0)
+ isyslog ("EEPGDEBUG: AlwaysZero2 is NOT ZERO:%x.", Channel->AlwaysZero2);
+ if (Channel->Always0x8c != 0x8c)
+ isyslog ("EEPGDEBUG: Always0x8c is NOT 0x8c:%x.", Channel->Always0x8c);
+ if (Channel->Always0x08 != 0x08)
+ isyslog ("EEPGDEBUG: Always0x08 is NOT 0x08:%x.", Channel->Always0x08);
+ if (Channel->Always0x02 != 0x02)
+ isyslog ("EEPGDEBUG: Always0x02 is NOT 0x02:%x.", Channel->Always0x02);
+ if (Channel->Always0x01 != 0x01)
+ isyslog ("EEPGDEBUG: Always0x01 is NOT 0x01:%x.", Channel->Always0x01);
+ if (Channel->Always0x20 != 0x20)
+ isyslog ("EEPGDEBUG: Always0x20 is NOT 0x20:%x.", Channel->Always0x20);
+ if (Channel->Always0x0a != 0x0a)
+ isyslog ("EEPGDEBUG: Always0x0a is NOT 0x0a:%x.", Channel->Always0x0a);
+ if (Channel->Always0x81 != 0x81)
+ isyslog ("EEPGDEBUG: Always0x81 is NOT 0x81:%x.", Channel->Always0x81);
+ if (Channel->Always0x44 != 0x44)
+ isyslog ("EEPGDEBUG: Always0x44 is NOT 0x44:%x.", Channel->Always0x44);
+*/
+
+ }
+ if (p != DataEnd)
+ esyslog ("EEPG: Warning, possible problem at end of channel table; p = %p, DataEnd = %p", p, DataEnd);
+ LoadEquivalentChannels ();
+ return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
+}
+
+int cFilterEEPG::GetNagra (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ sTitleBlockHeaderNagraGuide *TBH = (sTitleBlockHeaderNagraGuide *) Data;
+ if (InitialTitle[0] == 0x00) { //InitialTitle is empty, so we are waiting for the start marker
+ if (TBH->TableIdExtensionHigh == 0x00 && TBH->TableIdExtensionLow == 0x00) { //this is the start of the data
+ if (TBH->VersionNumber == LastVersionNagra) {
+ isyslog ("EEPG: Nagra EEPG already up-to-date with version %i", LastVersionNagra);
+ return 2;
+ }
+ Version = TBH->VersionNumber;
+ isyslog ("EEPG: initialized Nagraguide, version %i", Version);
+ //u_char *p = (u_char *) Data + 11;
+ u_char *p = (u_char *) Data + 8;
+ if (*p != 0x01) {
+ esyslog
+ ("EEPG: Error, Nagra first byte in table_id_extension 0x0000 is not 0x01 but %02x. Format unknown, exiting.",
+ *p);
+ return 0; //fatal error
+ }
+ p++; //skip 0x01 byte
+ unsigned short int l = ((*p << 8) | *(p + 1));
+ u_char *p_end = p + l - 3; //this ensures a full block of 4 bytes is there to process
+ p += 2; //skip length bytes
+ while (p < p_end) {
+ sSection0000BlockNagraGuide *S = (sSection0000BlockNagraGuide *) p;
+ int TTT = ((S->TableIdExtensionHigh << 10) | (S->TableIdExtensionLow << 3) | (S->TIE200 << 9));
+ if (VERBOSE >= 4)
+ isyslog ("EEPGDEBUG: TableIdExtension %04x, Unknown1 %02x Version %02x Always 0xd6 %02x DayCounter %02x",
+ TTT, S->Unknown1, S->VersionNumber, S->Always0xd6, S->DayCounter);
+ if ((TTT > 0x0400) && (TTT < 0x0600)) //take high byte and compare with summarie tables in 0x0400 and 0x0500 range;
+ NagraTIE[NagraCounter++] = TTT; //only store TIEs of titlessummaries, all others can be derived; they are stored in the order of the 0x0000 index table,
+ //lets hope first entry corresponds with today, next with tomorrow etc.
+ p += 4;
+ }
+ buffer.clear (); //clear buffer maps
+ bufsize.clear (); //clear buffer maps
+ InitialTitle[0] = 0xff; //copy data into initial title
+ }
+ return (1);
+ }
+ unsigned short SectionLength = ((TBH->SectionLengthHigh & 0x0f) << 8) | TBH->SectionLengthLow;
+ unsigned short TableIdExtension = HILO16 (TBH->TableIdExtension);
+ if (TableIdExtension == 0x0000) {
+ LastVersionNagra = Version;
+ return (2); //done
+ }
+/*
+Table_id_extensions:
+(0x0000)
+(0x0010) per channel, nr_of_channels entries, every entry is 8 bytes, first 4 bytes gives nr. of titles in corresponding title table
+(0x0020) per channel info day 2 of the month
+(0x01F0) per channel info day 31 of the month
+(0x0200) leeg; letop op je leest gemakkelijk door naar 0x0210!
+(0x0210) titles day 1 of the month
+(0x0220) titles day 2 of the month
+(0x03F0) titles day 31 of the month
+(0x0400) channel info
+(0x0410) summaries day 1 of the month
+(0x0420) summaries day 2 of the month
+(0x05F0) summaries day 31 of the month
+(0x0610) themes/title reference sunday, correspond to titles 0x0400 lower...
+(0x0620) themes/title reference monday
+... this goes on until 0x07f0
+(0x0810) bouquet info; references to channels within a package, day 1 of the month
+(0x0820) same day 2 of the month
+(0x09f0) same day 31 of the month
+*/
+
+ if (!(TBH->TableIdExtensionHigh >= 0x02 && TBH->TableIdExtensionHigh <= 0x07)) //here we regulate which tables we are testing
+ return (1);
+ if (TableIdExtension == 0x0200) //table 0x0200 only contains language code, because it is for day 0 of the month, and 0x0400 is used for channels
+ return 1;
+ if (TBH->SectionNumber == 0) { //first section, create a table
+ buffer[TableIdExtension] = NULL;
+ bufsize[TableIdExtension] = 0;
+ NumberOfTables++;
+ }
+ //store all sections in core until last section is found; processing incomplete sections is very complex and doesnt save much memory,
+ //since the data has to be stored anyway; summaries do not seem to have channelid included, so storing titles and separately storing summaries will not work...
+ //GetEventId only works for a specific Schedule for a specific ChannelId....
+ buffer[TableIdExtension] =
+ (unsigned char *) realloc (buffer[TableIdExtension], SectionLength - 9 + bufsize[TableIdExtension]);
+ memcpy (buffer[TableIdExtension] + bufsize[TableIdExtension], Data + 8, SectionLength - 9); //append new section
+ bufsize[TableIdExtension] += SectionLength - 9;
+ if (TBH->SectionNumber >= TBH->LastSectionNumber) {
+ if (VERBOSE >= 1)
+ isyslog ("EEPG: found %04x lastsection nr:%i.", TableIdExtension, TBH->SectionNumber);
+ // if (TBH->TableIdExtensionHigh == 0x04 || TBH->TableIdExtensionHigh == 0x05) {
+ if (TableIdExtension == 0x0400) {
+ int Result = GetChannelsNagra (buffer[TableIdExtension] + 4, bufsize[TableIdExtension] - 4); //TODO language code terminated by 0 is ignored
+ free (buffer[TableIdExtension]);
+ buffer[TableIdExtension] = NULL;
+ NumberOfTables--;
+ if (Result == 0)
+ return 0; //fatal error; TODO this exit should also free all other, non-Channel sections that are stored!
+ }
+ } //if lastsection read
+ return (1); //return and continue, nonfatal
+}
+
+void cFilterEEPG::ProcessNagra ()
+{
+ for (int i = 0; i < MAX_THEMES; i++) //clear all themes
+ Themes[i][0] = NULL;
+
+ for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
+ unsigned short int TableIdExtension = NagraTIE[i];
+ int TIE = TableIdExtension + 0x0200; //from 0x0400 to 0x0600 -> themes
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: Processing Theme with TableIdExtension:%04x", TIE);
+ GetThemesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension - 0x0200); //assume theme is completed //TODO Language code terminatd by 0 is ignored
+ free (buffer[TIE]);
+ buffer[TIE] = NULL;
+ NumberOfTables--;
+ }
+
+ for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
+ unsigned short int TableIdExtension = NagraTIE[i];
+ int TIE = TableIdExtension - 0x0200; //from 0x0400 to 0x0200 -> titles
+ isyslog ("EEPG: Processing TableIdExtension:%04x", TableIdExtension);
+ GetTitlesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension); //assume title-reading is completed //TODO Language code terminatd by 0 is ignored
+ free (buffer[TIE]);
+ buffer[TIE] = NULL;
+ NumberOfTables--;
+
+ free (buffer[TableIdExtension]); //summaries
+ buffer[TableIdExtension] = NULL;
+ NumberOfTables--;
+ }
+ if (NumberOfTables != 0)
+ esyslog ("EEPG: ERROR, Not all tables processed and stream is already repeating. NumberOfTables = %i.",
+ NumberOfTables);
+}
+
+int cFilterEEPG::GetTitlesMHW1 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ sTitleMHW1 *Title = (sTitleMHW1 *) Data;
+ if (Length == 46) {
+ if (Title->ChannelId == 0xff) { //FF is separator packet
+ if (memcmp (InitialTitle, Data, 46) == 0) //data is the same as initial title //TODO use easier notation
+ return 2;
+ if (nTitles == 0)
+ memcpy (InitialTitle, Data, 46); //copy data into initial title
+ int Day = Title->Day;
+ int Hours = Title->Hours;
+ if (Hours > 15)
+ Hours -= 4;
+ else if (Hours > 7)
+ Hours -= 2;
+ else
+ Day++;
+ if (Day > 6)
+ Day = Day - 7;
+ Day -= Yesterday;
+ if (Day < 1)
+ Day = 7 + Day;
+ //if (Day == 1 && Hours < 6)
+ if (Day == 0 && Hours < 6)
+ Day = 7;
+ //Day = 8;
+ MHWStartTime = (Day * 86400) + (Hours * 3600) + YesterdayEpochUTC;
+ if (VERBOSE >= 3)
+ isyslog ("EEPG Titles: FF PACKET, seqnr:%02x.", Data[5]);
+ }
+ else if (InitialTitle[0] != 0x00) { //if initialized this should always be 0x90 = tableid!
+ if (nTitles < MAX_TITLES) {
+ Title_t *T;
+ T = (Title_t *) malloc (sizeof (Title_t));
+ Titles[nTitles] = T;
+ int Minutes = Title->Minutes;
+ int StartTime = MHWStartTime + (Minutes * 60);
+ T->ChannelId = Title->ChannelId - 1;
+ T->ThemeId = Title->ThemeId;
+ T->MjdTime = 0; //only used at MHW2 and SKY
+ T->EventId = HILO32 (Title->ProgramId);
+ T->StartTime = LocalTime2UTC (StartTime); //here also Daylight Savings correction is done
+ T->Duration = HILO16 (Title->Duration) * 60;
+ T->SummaryAvailable = Title->SummaryAvailable;
+ T->Text = (unsigned char *) malloc (23 + 1);
+ if (T->Text == NULL) {
+ esyslog ("EEPG: Titles memory allocation error.");
+ return 0;
+ }
+ T->Text[23] = NULL; //end string with NULL character
+ memcpy (T->Text, &Title->Title, 23);
+ CleanString (T->Text);
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: EventId:%04x,ChannelId:%x, Titlenr:%d:, StartTime(epoch):%i, SummAv:%x,Name:%s.", T->EventId,
+ T->ChannelId, nTitles, T->StartTime, T->SummaryAvailable, T->Text);
+ nTitles++;
+ } //nTitles < MaxTitles
+ else {
+ esyslog ("EEPG: Error, titles found more than %i", MAX_TITLES);
+ return 0;
+ }
+ } //else if InitialTitle
+ } //Length==46
+ else {
+ esyslog ("EEPG: Error, length of title package is not 46.");
+ return 1; //non fatal
+ }
+
+ return 1;
+}
+
+int cFilterEEPG::GetTitlesMHW2 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ if (Length > 18) {
+ int Pos = 18;
+ int Len = 0;
+ bool Check = false;
+ while (Pos < Length) {
+ Check = false;
+ Pos += 7;
+ if (Pos < Length) {
+ Pos += 3;
+ if (Pos < Length)
+ if (Data[Pos] > 0xc0) {
+ Pos += (Data[Pos] - 0xc0);
+ Pos += 4;
+ if (Pos < Length) {
+ if (Data[Pos] == 0xff) {
+ Pos += 1;
+ Check = true;
+ }
+ }
+ }
+ }
+ if (Check == false)
+ return 1; // I assume nonfatal error or success
+ }
+ if (memcmp (InitialTitle, Data, 16) == 0) //data is the same as initial title
+ return 2; //last item processed
+ else {
+ if (nTitles == 0)
+ memcpy (InitialTitle, Data, 16); //copy data into initial title
+ Pos = 18;
+ while (Pos < Length) {
+ Title_t *T;
+ T = (Title_t *) malloc (sizeof (Title_t));
+ Titles[nTitles] = T;
+ T->ChannelId = Data[Pos];
+ unsigned int MjdTime = (Data[Pos + 3] << 8) | Data[Pos + 4];
+ T->MjdTime = 0; //not used for matching MHW2
+ T->StartTime = ((MjdTime - 40587) * 86400)
+ + (((((Data[Pos + 5] & 0xf0) >> 4) * 10) + (Data[Pos + 5] & 0x0f)) * 3600)
+ + (((((Data[Pos + 6] & 0xf0) >> 4) * 10) + (Data[Pos + 6] & 0x0f)) * 60);
+ T->Duration = (((Data[Pos + 8] << 8) | Data[Pos + 9]) >> 4) * 60;
+ Len = Data[Pos + 10] & 0x3f;
+ T->Text = (unsigned char *) malloc (Len + 1);
+ if (T->Text == NULL) {
+ esyslog ("EEPG: Titles memory allocation error.");
+ return 0; //fatal error
+ }
+ T->Text[Len] = NULL; //end string with NULL character
+ memcpy (T->Text, &Data[Pos + 11], Len);
+ CleanString (T->Text);
+ Pos += Len + 11;
+ T->ThemeId = ((Data[7] & 0x3f) << 6) | (Data[Pos] & 0x3f);
+ T->EventId = (Data[Pos + 1] << 8) | Data[Pos + 2];
+ T->SummaryAvailable = (T->EventId != 0xFFFF);
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: EventId %04x Titlenr %d:SummAv:%x,Name:%s.", T->EventId, nTitles,
+ T->SummaryAvailable, T->Text);
+ Pos += 4;
+ nTitles++;
+ if (nTitles > MAX_TITLES) {
+ esyslog ("EEPG: Error, titles found more than %i", MAX_TITLES);
+ return 0; //fatal error
+ }
+ }
+ return 1; //success
+ } //else memcmp
+ } //if length
+ return 1; //non fatal error
+}
+
+int cFilterEEPG::GetSummariesMHW1 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ sSummaryMHW1 *Summary = (sSummaryMHW1 *) Data;
+ if (Length > 11) {
+ if (Summary->NumReplays < 10) { //Why limit this at 10?
+ if (Length > (11 + (Summary->NumReplays * 7))) {
+ if (Summary->Byte7 == 0xff && Summary->Byte8 == 0xff && Summary->Byte9 == 0xff) {
+ //if (Summary->Byte7 == 0xff && Summary->Byte8 && Summary->Byte9 == 0xff) {
+ if (memcmp (InitialSummary, Data, 20) == 0) //data is equal to initial buffer
+ return 2;
+ else if (nSummaries < MAX_TITLES) {
+ if (nSummaries == 0)
+ memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
+ int SummaryOffset = 11 + (Summary->NumReplays * 7);
+ int SummaryLength = Length - SummaryOffset;
+ unsigned char *Text = (unsigned char *) malloc (SummaryLength + 1);
+ if (Text == NULL) {
+ esyslog ("EEPG: Summaries memory allocation error.");
+ return 0;
+ }
+ Text[SummaryLength] = NULL; //end string with NULL character
+ memcpy (Text, &Data[SummaryOffset], SummaryLength);
+ CleanString (Text);
+// if (Summary->NumReplays != 0)
+// esyslog ("EEPG: Number of replays:%i.", Summary->NumReplays);
+ int Replays = Summary->NumReplays;
+ int ReplayOffset = 11;
+ do {
+ Summary_t *S;
+ S = (Summary_t *) malloc (sizeof (Summary_t));
+ Summaries[nSummaries] = S;
+ S->NumReplays = Summary->NumReplays;
+ S->MjdTime = 0; //only used for SKY
+ if (Summary->NumReplays == 0) {
+ S->ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
+ S->StartTime = 0;
+ }
+ else {
+ S->ChannelId = Data[ReplayOffset++] - 1;
+ unsigned int Date_hi = Data[ReplayOffset++];
+ unsigned int Date_lo = Data[ReplayOffset++];
+ unsigned short int Hour = Data[ReplayOffset++];
+ unsigned short int Minute = Data[ReplayOffset++];
+ unsigned short int Sec = Data[ReplayOffset++];
+ ReplayOffset++; //makes total of 7 bytes
+
+
+ S->StartTime = MjdToEpochTime (Date) + (((((Hour & 0xf0) >> 4) * 10) + (Hour & 0x0f)) * 3600)
+ + (((((Minute & 0xf0) >> 4) * 10) + (Minute & 0x0f)) * 60)
+ + ((((Sec & 0xf0) >> 4) * 10) + (Sec & 0x0f));
+// summary -> time[i] = ProviderLocalTime2UTC (summary -> time[i]);
+ S->StartTime = LocalTime2UTC (S->StartTime);
+ }
+ S->EventId = HILO32 (Summary->ProgramId);
+ S->Text = Text;
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: Eventid:%04x Channelid:%x, Summnr %d:%.30s.", S->EventId, S->ChannelId,
+ nSummaries, S->Text);
+ nSummaries++;
+ Replays = Replays - 1;
+ } while (Replays > 0);
+ //} while (Replays-- >= 0);
+ }
+ else {
+ esyslog ("EEPG: Error, summaries found more than %i", MAX_TITLES);
+ return 0;
+ }
+ } //0xff
+ else {
+ esyslog ("EEPG: Warning, Summary bytes not as expected.");
+ return 1; //it is not a success, but error is not fatal
+ }
+ } //numreplays length
+ else {
+ esyslog ("EEPG: Warning, number of replays is not conforming to length.");
+ return 1; //nonfatal error
+ }
+ } //numreplays <10
+ else {
+ esyslog ("EEPG: Warning, number of replays 10 or more, cannot process.");
+ return 1; //nonfatal error
+ }
+ } //length >11
+ else {
+ esyslog ("EEPG: Summary length too small.");
+ return 1; //nonfatal error
+ }
+ return 1; //success
+}
+
+int cFilterEEPG::GetSummariesMHW2 (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ if (Length > (Data[14] + 17)) {
+ if (memcmp (InitialSummary, Data, 16) == 0) //data is equal to initial buffer
+ return 2;
+ else {
+ if (nSummaries == 0)
+ memcpy (InitialSummary, Data, 16); //copy this data in initial buffer
+ if (nSummaries < MAX_TITLES) {
+ int lenText = Data[14];
+ int SummaryLength = lenText;
+ int Pos = 15;
+ int Loop = Data[Pos + SummaryLength] & 0x0f;
+ Summary_t *S;
+ S = (Summary_t *) malloc (sizeof (Summary_t));
+ Summaries[nSummaries] = S;
+
+ S->ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
+ S->StartTime = 0; //not used
+ S->MjdTime = 0; //not used
+ S->NumReplays = 0; //not used
+ S->EventId = (Data[3] << 8) | Data[4];
+ unsigned char tmp[4096]; //TODO do this smarter
+ memcpy (tmp, &Data[Pos], lenText);
+ tmp[SummaryLength] = '|';
+ SummaryLength += 1;
+ Pos += (lenText + 1);
+ if (Loop > 0) {
+ while (Loop > 0) {
+ lenText = Data[Pos];
+ Pos += 1;
+ if ((Pos + lenText) < Length) {
+ memcpy (&tmp[SummaryLength], &Data[Pos], lenText);
+ SummaryLength += lenText;
+ if (Loop > 1) {
+ tmp[SummaryLength] = '|';
+ SummaryLength += 1;
+ }
+ }
+ else
+ break;
+ Pos += lenText;
+ Loop--;
+ }
+ }
+ S->Text = (unsigned char *) malloc (SummaryLength + 1);
+ S->Text[SummaryLength] = NULL; //end string with NULL character
+ if (S->Text == NULL) {
+ esyslog ("EEPG: Summaries memory allocation error.");
+ return 0; //fatal error
+ }
+ memcpy (S->Text, tmp, SummaryLength);
+ CleanString (S->Text);
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: EventId %04x Summnr %d:%.30s.", S->EventId, nSummaries, S->Text);
+ nSummaries++;
+ }
+ else {
+ esyslog ("EEPG: Error, summaries found more than %i", MAX_TITLES);
+ return 0; //fatal error
+ }
+ } //else
+ } //if length
+ return 1; //succes or nonfatal error
+}
+
+int cFilterEEPG::GetChannelsSKYBOX (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+
+ if (memcmp (InitialChannel, Data, 8) == 0) { //data is the same as initial title
+ LoadEquivalentChannels ();
+ return 2;
+ }
+ else {
+ if (nChannels == 0)
+ memcpy (InitialChannel, Data, 8); //copy data into initial title
+ if (VERBOSE >= 1 && nChannels == 0) {
+ isyslog ("| ID | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+ isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+ "-----------------------------", "--------------------");
+ }
+// unsigned short int BouquetId = (Data[3] << 8) | Data[4];
+ int BouquetDescriptorsLength = ((Data[8] & 0x0f) << 8) | Data[9];
+ int TransportStreamLoopLength =
+ ((Data[BouquetDescriptorsLength + 10] & 0x0f) << 8) | Data[BouquetDescriptorsLength + 11];
+ int p1 = (BouquetDescriptorsLength + 12);
+ while (TransportStreamLoopLength > 0) {
+ unsigned short int Tid = (Data[p1] << 8) | Data[p1 + 1];
+ unsigned short int Nid = (Data[p1 + 2] << 8) | Data[p1 + 3];
+ int TransportDescriptorsLength = ((Data[p1 + 4] & 0x0f) << 8) | Data[p1 + 5];
+ int p2 = (p1 + 6);
+ p1 += (TransportDescriptorsLength + 6);
+ TransportStreamLoopLength -= (TransportDescriptorsLength + 6);
+ while (TransportDescriptorsLength > 0) {
+ unsigned char DescriptorTag = Data[p2];
+ int DescriptorLength = Data[p2 + 1];
+ int p3 = (p2 + 2);
+ p2 += (DescriptorLength + 2);
+ TransportDescriptorsLength -= (DescriptorLength + 2);
+ switch (DescriptorTag) { //TODO switch with only 1 case??? replace this by template
+ case 0xb1:
+ p3 += 2;
+ DescriptorLength -= 2;
+ while (DescriptorLength > 0) {
+ // 0x01 = Video Channel
+ // 0x02 = Audio Channel
+ // 0x05 = Other Channel
+ //if( Data[p3+2] == 0x01 || Data[p3+2] == 0x02 || Data[p3+2] == 0x05 )
+ //{
+ unsigned short int Sid = (Data[p3] << 8) | Data[p3 + 1];
+ unsigned short int ChannelId = (Data[p3 + 3] << 8) | Data[p3 + 4];
+ unsigned short int SkyNumber = (Data[p3 + 5] << 8) | Data[p3 + 6];
+ if (SkyNumber > 100 && SkyNumber < 1000) {
+ if (ChannelId > 0) {
+ sChannel *C;
+ if (ChannelSeq.count (ChannelId) == 0) //not found
+ {
+ C = &sChannels[nChannels];
+ C->ChannelId = ChannelId;
+ C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1
+ C->Src[0] = Source (); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!!
+ C->Nid[0] = Nid;
+ C->Tid[0] = Tid;
+ C->Sid[0] = Sid;
+ C->SkyNumber = SkyNumber;
+ tChannelID channelID = tChannelID (C->Src[0], C->Nid[0], C->Tid[0], C->Sid[0]);
+ cChannel *VC = Channels.GetByChannelID (channelID, true);
+ bool IsFound = (VC);
+ if (IsFound)
+ strncpy ((char *) C->Name, VC->Name (), 64);
+ else
+ C->Name[0] = NULL; //empty string
+
+ if (VERBOSE >= 1) {
+ char *ChID;
+ asprintf (&ChID, "%s-%i-%i-%i-0", *cSource::ToString (C->Src[0]), C->Nid[0], C->Tid[0], C->Sid[0]);
+ char *IsF;
+ if (IsFound)
+ asprintf (&IsF, " %-3.3s |", "YES");
+ else
+ asprintf (&IsF, " %-3.3s |", "NO");
+ isyslog ("|% 5d | %-26.26s | %-22.22s |%s % 6d |\n", C->ChannelId, ChID, C->Name, IsF,
+ C->SkyNumber);
+ free (ChID);
+ free (IsF);
+ }
+ ChannelSeq[C->ChannelId] = nChannels; //fill lookup table to go from channel-id to sequence nr in table
+ nChannels++;
+ if (nChannels >= MAX_CHANNELS) {
+ esyslog ("EEPG: Error, channels found more than %i", MAX_CHANNELS);
+ return 0;
+ }
+ }
+ }
+ }
+ p3 += 9;
+ DescriptorLength -= 9;
+ }
+ break;
+ default:
+ break;
+ } //switch descriptortag
+ }
+ } //while
+ return 1;
+ } //else part of memcmp
+}
+
+int cFilterEEPG::GetTitlesSKYBOX (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ int p;
+ unsigned short int ChannelId;
+ unsigned short int MjdTime;
+ int Len1;
+ int Len2;
+
+ if (Length < 20)
+ return 1; //nonfatal error
+ if (memcmp (InitialTitle, Data, 20) == 0) //data is the same as initial title
+ return 2;
+ else {
+ if (nTitles == 0)
+ memcpy (InitialTitle, Data, 20); //copy data into initial title
+ ChannelId = (Data[3] << 8) | Data[4];
+ MjdTime = ((Data[8] << 8) | Data[9]);
+ if (ChannelId > 0) {
+ if (MjdTime > 0) {
+ p = 10;
+ do {
+ Title_t *T;
+ T = (Title_t *) malloc (sizeof (Title_t));
+ Titles[nTitles] = T;
+ T->ChannelId = ChannelId;
+ T->MjdTime = MjdTime; //only date, no time. Is used to match titles and summaries, SKYBOX only
+ T->EventId = (Data[p] << 8) | Data[p + 1];
+ Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
+ if (Data[p + 4] != 0xb5) {
+ if (DEBUG) {
+ esyslog ("EEPG: Data error signature for title");
+ }
+ break;
+ }
+ if (Len1 > Length) {
+ if (DEBUG) {
+ esyslog ("EEPG: Data error length for title");
+ }
+ break;
+ }
+ p += 4;
+ Len2 = Data[p + 1] - 7;
+ T->StartTime = ((MjdTime - 40587) * 86400) + ((Data[p + 2] << 9) | (Data[p + 3] << 1));
+ T->Duration = ((Data[p + 4] << 9) | (Data[p + 5] << 1));
+ T->ThemeId = Data[p + 6];
+ T->Unknown1 = Data[p + 4 - 13]; //FIXME
+ T->Unknown2 = Data[p + 4 - 12]; //FIXME
+ T->Unknown3 = Data[p + 4 - 11]; //FIXME
+ unsigned char tmp[4096]; //TODO smarter
+ Len2 = DecodeHuffmanCode (&Data[p + 9], Len2, tmp);
+ if (Len2 == 0) {
+ esyslog ("EEPG: Warning, could not huffman-decode title-text, skipping title.");
+ return 1; //non-fatal error
+ }
+ T->Text = (unsigned char *) malloc (Len2 + 1);
+ if (T->Text == NULL) {
+ esyslog ("EEPG: Titles memory allocation error.");
+ return 0;
+ }
+ T->Text[Len2] = NULL; //end string with NULL character
+ memcpy (T->Text, tmp, Len2);
+ CleanString (T->Text);
+ T->SummaryAvailable = 1; //TODO I assume this is true?
+
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: EventId %04x Titlenr %d,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s.", T->EventId,
+ nTitles, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
+ p += Len1;
+ nTitles++;
+ if (nTitles >= MAX_TITLES) {
+ esyslog ("EEPG: Error, titles found more than %i", MAX_TITLES);
+ return 0; //fatal error
+ }
+ } while (p < Length);
+ }
+ }
+ }
+ return 1; //success
+}
+
+int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length) //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+{
+ int p;
+ unsigned short int ChannelId;
+ unsigned short int MjdTime;
+ int Len1;
+ int Len2;
+
+ if (Length < 20) {
+ return 1; //non fatal error I assume
+ }
+ if (memcmp (InitialSummary, Data, 20) == 0) //data is equal to initial buffer
+ return 2;
+// else if (nSummaries < MAX_SUMMARIES) {
+ else {
+ if (nSummaries == 0)
+ memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
+ ChannelId = (Data[3] << 8) | Data[4];
+ MjdTime = ((Data[8] << 8) | Data[9]);
+ if (ChannelId > 0) {
+ if (MjdTime > 0) {
+ p = 10;
+ do {
+ Summary_t *S;
+ S = (Summary_t *) malloc (sizeof (Summary_t));
+ Summaries[nSummaries] = S;
+ S->ChannelId = ChannelId;
+ S->MjdTime = MjdTime;
+ S->NumReplays = 0; //not used
+ S->EventId = (Data[p] << 8) | Data[p + 1];
+ Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
+ if (Data[p + 4] != 0xb9) {
+ if (DEBUG) {
+ esyslog ("EEPG: Data error signature for summary");
+ }
+ break;
+ }
+ if (Len1 > Length) {
+ if (DEBUG) {
+ esyslog ("EEPG: Data error length for summary");
+ }
+ break;
+ }
+ p += 4;
+ Len2 = Data[p + 1];
+ unsigned char tmp[4096]; //TODO can this be done better?
+ Len2 = DecodeHuffmanCode (&Data[p + 2], Len2, tmp);
+ if (Len2 == 0) {
+ esyslog ("EEPG: Warning, could not huffman-decode text, skipping summary.");
+ return 1; //non-fatal error
+ }
+ S->Text = (unsigned char *) malloc (Len2 + 1);
+ if (S->Text == NULL) {
+ esyslog ("EEPG: Summaries memory allocation error.");
+ return 0;
+ }
+ memcpy (S->Text, tmp, Len2);
+ S->Text[Len2] = NULL; //end string with NULL character
+ CleanString (S->Text);
+ if (VERBOSE >= 3)
+ isyslog ("EEPG: EventId %04x Summnr %d:%.30s.", S->EventId, nSummaries, S->Text);
+ p += Len1;
+ nSummaries++;
+ if (nSummaries >= MAX_TITLES) {
+ esyslog ("EEPG: Error, summaries found more than %i", MAX_TITLES);
+ return 0;
+ }
+ } while (p < Length);
+ }
+ }
+ }
+ return 1;
+}
+
+void cFilterEEPG::FreeSummaries (void)
+{
+ if (Format == MHW1 || Format == MHW2 || Format == SKY_IT || Format == SKY_UK) {
+ Summary_t *S; //TODO do I need this?
+ Summary_t *S2; //TODO do I need this?
+ for (int i = 0; i < nSummaries; i++) {
+ S = Summaries[i];
+ if (i < nSummaries - 1) {
+ S2 = Summaries[i + 1]; //look at next summary
+ if (S->Text != S2->Text && S->Text != 0x00) //this is the last summary that points to this textblock; needed in case NumReplays > 1, multiple pointers to same textblock
+ free (S->Text);
+ }
+ else if (S->Text != 0x00)
+ free (S->Text);
+ free (S);
+ }
+ }
+ nSummaries = 0;
+}
+
+void cFilterEEPG::FreeTitles (void)
+{
+ if (Format == MHW1 || Format == MHW2 || Format == SKY_IT || Format == SKY_UK) {
+ Title_t *T;
+ for (int i = 0; i < nTitles; i++) {
+ T = Titles[i];
+ free (T->Text);
+ free (T);
+ }
+ }
+ nTitles = 0;
+}
+
+void cFilterEEPG::LoadIntoSchedule (void)
+{
+ int i, j, k;
+ i = 0;
+ j = 0;
+ k = 0;
+ bool foundtitle;
+ foundtitle = false;
+ Title_t *T;
+ Summary_t *S;
+ int remembersummary;
+//keep statistics
+ int SummariesNotFound = 0;
+ int NoSummary = 0;
+ int NotMatching = 0;
+ int LostSync = 0;
+ remembersummary = -1;
+
+ cSchedulesLock SchedulesLock (true);
+ cSchedules *s = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+ if (s) {
+
+ while (i < nTitles) {
+ T = Titles[i];
+ S = Summaries[j];
+ foundtitle = false;
+
+ while ((i < nTitles) && (!foundtitle)) { //find next title that has summary
+ T = Titles[i];
+ if (T->SummaryAvailable)
+ foundtitle = true;
+ else {
+ NoSummary++;
+ i++;
+ }
+ }
+//esyslog("foundtitle %x for next title that has a summary:%d",foundtitle,i);
+
+ if (!foundtitle) //no more titles with summaries
+ break; //TODO: does this work???
+ else if ((T->EventId == S->EventId) && (T->MjdTime == S->MjdTime) && ((T->ChannelId == S->ChannelId) || ((Format != SKY_IT) && (Format != SKY_UK)))) { //should always be true, titles and summaries are broadcasted in order...
+ //MjdTime = 0 for all but SKY
+ //S->ChannelId must be equal to T->ChannelId only for SKY; in MHW1 S->ChannelId overrides T->ChannelId when NumReplays > 1
+ remembersummary = -1; //reset summary searcher
+ int Replays = S->NumReplays;
+
+ do {
+ unsigned short int ChannelId;
+ time_t StartTime;
+ if (S->NumReplays == 0) {
+ ChannelId = T->ChannelId;
+ StartTime = T->StartTime;
+ }
+ else {
+ ChannelId = S->ChannelId;
+ StartTime = S->StartTime;
+ }
+
+ //channelids are sequentially numbered and sent in MHW1 and MHW2, but not in SKY, so we need to lookup the table index
+ sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
+ cSchedule *p[MAX_EQUIVALENCES];
+ PrepareToWriteToSchedule (C, s, p);
+
+ WriteToSchedule (p, C->NumberOfEquivalences, T->EventId, StartTime, T->Duration / 60, (char *) T->Text,
+ (char *) S->Text, T->ThemeId, DEFAULT_TABLE_ID, 0);
+
+ FinishWriteToSchedule (C, s, p);
+ Replays--;
+ if ((S->NumReplays != 0) && (Replays > 0)) { //when replays are used, all summaries of the replays are stored consecutively; currently only CSAT
+ j++; //move to next summary
+ if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
+ j = 0;
+ S = Summaries[j]; //next summary within replay range
+ }
+ } //while
+ while (Replays > 0);
+
+//TODO: why load events that have already past, and then run Cleanup
+//end of putting title and summary in schedule
+ i++; //move to next title
+ } //if T->EventId == S->EventId
+ else {
+// esyslog("EEPG ERROR: ProgramIds not matching, title:%d,summary%d, T->EventId:%u, S->Eventid:%u.",i,j,T->EventId,S->EventId);
+ NotMatching++;
+ if (remembersummary == -1) { //I am not in search loop yet
+ remembersummary = j;
+ if (remembersummary == 0)
+ remembersummary = nSummaries; //or next test will never be succesfull for remembersummary = 0
+ LostSync++;
+// esyslog("EEPG Error: lost sync at title %d, summary %d.",i,j);
+ }
+ else if (j == (remembersummary - 1)) { //the last summary to be checked has failed also
+ //esyslog ("EEPG Error: could not find summary for summary-available Title %d.", i);
+ esyslog
+ ("EEPG: Error, summary not found for EventId %04x Titlenr %d:SummAv:%x,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s.",
+ T->EventId, i, T->SummaryAvailable, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
+
+ /* write Title info to schedule */
+ sChannel *C = &sChannels[ChannelSeq[T->ChannelId]]; //find channel
+ cSchedule *p[MAX_EQUIVALENCES];
+ PrepareToWriteToSchedule (C, s, p);
+ WriteToSchedule (p, C->NumberOfEquivalences, T->EventId, T->StartTime, T->Duration / 60, (char *) T->Text,
+ NULL, T->ThemeId, DEFAULT_TABLE_ID, 0);
+ FinishWriteToSchedule (C, s, p);
+
+ SummariesNotFound++;
+ i++; //move to next title, for this one no summary can be found
+ }
+
+// esyslog("Trying again for this title %d, remember summary %d, but advancing one Summary to %d.",i,remembersummary,j);
+ }
+ j++; //move to next summary
+ if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
+ j = 0;
+ } //while title
+ } // if s
+ else
+ esyslog ("EEPG Error: could not lock schedules.");
+
+ cSchedules::Cleanup (true); //deletes all past events
+
+ isyslog ("EEPG: found %i equivalents channels", nEquivChannels);
+ isyslog ("EEPG: found %i themes", nThemes);
+ isyslog ("EEPG: found %i channels", nChannels);
+ isyslog ("EEPG: found %i titles", nTitles);
+ isyslog ("EEPG: of which %i reported to have no summary available; skipping these BIENTOT titles", NoSummary);
+ isyslog ("EEPG: found %i summaries", nSummaries);
+ if (SummariesNotFound != 0)
+ esyslog ("EEPG: %i summaries not found", SummariesNotFound);
+ else if (VERBOSE >= 1)
+ isyslog ("EEPG: %i summaries not found", SummariesNotFound);
+ if (NotMatching > nSummaries)
+ isyslog ("EEPG Warning: lost sync %i times, summary did not match %i times.", LostSync, NotMatching);
+
+ FreeSummaries (); //do NOT free channels, themes and bouquets here because they will be reused in SKY!
+ FreeTitles ();
+ if (!((Format == SKY_IT) || (Format == SKY_UK))) { //everything but SKY; SKY is the only protocol where LoadIntoSchedule is called repeatedly
+ ChannelSeq.clear ();
+ }
+}
+
+void cFilterEEPG::AddFilter (u_short Pid, u_char Tid)
+{
+ if (!Matches (Pid, Tid)) {
+ Add (Pid, Tid);
+ esyslog ("Filter Pid:%x,Tid:%x added.", Pid, Tid);
+ }
+}
+
+void cFilterEEPG::AddFilter (u_short Pid, u_char Tid, unsigned char Mask)
+{
+ if (!Matches (Pid, Tid)) {
+ Add (Pid, Tid, Mask);
+ esyslog ("Filter Pid:%x,Tid:%x,Mask:%x added.", Pid, Tid, Mask);
+ }
+}
+
+namespace SI
+{
+/*extern const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte = NULL);
+extern bool convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode);
+extern bool SystemCharacterTableIsSingleByte;*/
+ class cEIT2:public SI::EIT
+ {
+ public:
+ cEIT2 (cSchedules::cSchedules * Schedules, int Source, u_char Tid, const u_char * Data,
+ bool OnlyRunningStatus = false);
+
+// originally from libdtv, Copyright Rolf Hakenes <hakenes@hippomi.de>
+//void decodeText2(char *from, char *buffer, int size) {
+ void decodeText2 (const unsigned char *from, int len, char *buffer, int size)
+ {
+// const unsigned char *from=data.getData(0);
+ char *to = buffer;
+// int len=getLength();
+ if (len < 0 || len >= size)
+ {
+ strncpy (buffer, "text error", size);
+ buffer[size - 1] = 0;
+ return;
+ }
+ if (len <= 0)
+ {
+ *to = '\0';
+ return;
+ }
+ bool singleByte;
+
+
+ if (from[0] == 0x1f) {
+ char *temp = freesat_huffman_decode (from, len);
+ if (temp) {
+ len = strlen (temp);
+ len = len < size - 1 ? len : size - 1;
+ strncpy (buffer, temp, len);
+ buffer[len] = 0;
+ free (temp);
+ return;
+ }
+ }
+
+
+ const char *cs = getCharacterTable (from, len, &singleByte);
+ // FIXME Need to make this UTF-8 aware (different control codes).
+ // However, there's yet to be found a broadcaster that actually
+ // uses UTF-8 for the SI data... (kls 2007-06-10)
+ for (int i = 0; i < len; i++) {
+ if (*from == 0)
+ break;
+ if (((' ' <= *from) && (*from <= '~'))
+ || (*from == '\n')
+ || (0xA0 <= *from)
+ )
+ *to++ = *from;
+ else if (*from == 0x8A)
+ *to++ = '\n';
+ from++;
+ if (to - buffer >= size - 1)
+ break;
+ }
+ *to = '\0';
+ if (!singleByte || !SystemCharacterTableIsSingleByte) {
+ char convBuffer[size];
+ if (convertCharacterTable (buffer, strlen (buffer), convBuffer, sizeof (convBuffer), cs))
+ strncpy (buffer, convBuffer, strlen (convBuffer) + 1);
+ }
+ }
+
+#ifdef USE_NOEPG
+ private:
+ bool allowedEPG (tChannelID kanalID);
+#endif /* NOEPG */
+ };
+
+#ifdef USE_NOEPG
+ bool cEIT2::allowedEPG (tChannelID kanalID)
+ {
+ bool rc;
+
+ if (Setup.noEPGMode == 1) {
+ rc = false;
+ if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL)
+ rc = true;
+ }
+ else {
+ rc = true;
+ if (strstr (::Setup.noEPGList, kanalID.ToString ()) != NULL)
+ rc = false;
+ }
+
+ return rc;
+ }
+#endif /* NOEPG */
+
+ cEIT2::cEIT2 (cSchedules::cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool OnlyRunningStatus)
+: SI::EIT (Data, false) {
+ if (!CheckCRCAndParse ())
+ return;
+
+ tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ());
+ cChannel *channel = Channels.GetByChannelID (channelID, true);
+ if (!channel)
+ return; // only collect data for known channels
+
+#ifdef USE_NOEPG
+ // only use epg from channels not blocked by noEPG-patch
+ tChannelID kanalID;
+ kanalID = channel->GetChannelID ();
+ if (!allowedEPG (kanalID))
+ return;
+#endif /* NOEPG */
+
+ cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channel, true);
+
+ bool Empty = true;
+ bool Modified = false;
+ bool HasExternalData = false;
+ time_t SegmentStart = 0;
+ time_t SegmentEnd = 0;
+
+ SI::EIT::Event SiEitEvent;
+ for (SI::Loop::Iterator it; eventLoop.getNext (SiEitEvent, it);) {
+ bool ExternalData = false;
+ // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number.
+ if (SiEitEvent.getStartTime () == 0 || SiEitEvent.getStartTime () > 0 && SiEitEvent.getDuration () == 0)
+ continue;
+ Empty = false;
+ if (!SegmentStart)
+ SegmentStart = SiEitEvent.getStartTime ();
+ SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
+ cEvent *newEvent = NULL;
+ cEvent *rEvent = NULL;
+ cEvent *pEvent = (cEvent *) pSchedule->GetEvent (SiEitEvent.getEventId (), SiEitEvent.getStartTime ());
+ if (!pEvent) {
+ if (OnlyRunningStatus)
+ continue;
+ // If we don't have that event yet, we create a new one.
+ // Otherwise we copy the information into the existing event anyway, because the data might have changed.
+ pEvent = newEvent = new cEvent (SiEitEvent.getEventId ());
+ if (!pEvent)
+ continue;
+ }
+ else {
+ // We have found an existing event, either through its event ID or its start time.
+ pEvent->SetSeen ();
+ // If the existing event has a zero table ID it was defined externally and shall
+ // not be overwritten.
+ if (pEvent->TableID () == 0x00) {
+#ifdef USE_DDEPGENTRY
+ if (pEvent->Version () == getVersionNumber ()) {
+ if (Setup.MixEpgAction == 0)
+ continue;
+ //printf("in");
+ //printf("%s", pEvent->GetTimeString());
+ // to use the info of the original epg, update the extern one,
+ // if it has less info
+ SI::Descriptor * d;
+ SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL;
+ //SI::ExtendedEventDescriptor *eed = NULL;
+ SI::ShortEventDescriptor * ShortEventDescriptor = NULL;
+ //SI::ShortEventDescriptor *sed = NULL;
+ //SI::TimeShiftedEventDescriptor *tsed = NULL;
+ //cLinkChannels *LinkChannels = NULL;
+ for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext (it2));) {
+ if (d->getDescriptorTag () == SI::ShortEventDescriptorTag) {
+ int LanguagePreferenceShort = -1;
+ SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+ || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
+ }
+ else if (d->getDescriptorTag () == SI::ExtendedEventDescriptorTag) {
+ int LanguagePreferenceExt = -1;
+ bool UseExtendedEventDescriptor = false;
+ SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+ || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add (eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+ UseExtendedEventDescriptor = false;
+ }
+ delete d;
+ }
+ if (pEvent) {
+ if (ShortEventDescriptor) {
+ char buffer[256];
+ if (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)) && pEvent->ShortText ()
+ && (strlen (ShortEventDescriptor->text.getText (buffer, sizeof (buffer))) >
+ strlen (pEvent->ShortText ()))) {
+ pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
+ pEvent->FixEpgBugs ();
+ }
+ }
+ if (ExtendedEventDescriptors) {
+ char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
+ //pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": "));
+ if (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")
+ && pEvent->Description ()
+ && (strlen (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": ")) >
+ strlen (pEvent->Description ()))) {
+ pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+ pEvent->FixEpgBugs ();
+ }
+ }
+ }
+ delete ExtendedEventDescriptors;
+ delete ShortEventDescriptor;
+ continue;
+ }
+#else
+ if (pEvent->Version () == getVersionNumber ())
+ continue;
+#endif /* DDEPGENTRY */
+ HasExternalData = ExternalData = true;
+ }
+ // If the new event has a higher table ID, let's skip it.
+ // The lower the table ID, the more "current" the information.
+ else if (Tid > pEvent->TableID ())
+ continue;
+ // If the new event comes from the same table and has the same version number
+ // as the existing one, let's skip it to avoid unnecessary work.
+ // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like
+ // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on
+ // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned
+ // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers.
+ else if (Tid == pEvent->TableID () && pEvent->Version () == getVersionNumber ())
+ continue;
+ }
+ if (!ExternalData) {
+ pEvent->SetEventID (SiEitEvent.getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-(
+ pEvent->SetTableID (Tid);
+ pEvent->SetStartTime (SiEitEvent.getStartTime ());
+ pEvent->SetDuration (SiEitEvent.getDuration ());
+ }
+ if (newEvent)
+ pSchedule->AddEvent (newEvent);
+ if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
+#ifdef USE_DDEPGENTRY
+ if (Setup.DisableVPS == 0 && SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
+#else
+ if (SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
+#endif /* DDEPGENTRY */
+ pSchedule->SetRunningStatus (pEvent, SiEitEvent.getRunningStatus (), channel);
+ }
+ if (OnlyRunningStatus)
+ continue; // do this before setting the version, so that the full update can be done later
+ pEvent->SetVersion (getVersionNumber ());
+
+ int LanguagePreferenceShort = -1;
+ int LanguagePreferenceExt = -1;
+ bool UseExtendedEventDescriptor = false;
+ SI::Descriptor * d;
+ SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL;
+ SI::ShortEventDescriptor * ShortEventDescriptor = NULL;
+ cLinkChannels *LinkChannels = NULL;
+ cComponents *Components = NULL;
+ for (SI::Loop::Iterator it2; (d = SiEitEvent.eventDescriptors.getNext (it2));) {
+ if (ExternalData && d->getDescriptorTag () != SI::ComponentDescriptorTag) {
+ delete d;
+ continue;
+ }
+ switch (d->getDescriptorTag ()) {
+ case SI::ExtendedEventDescriptorTag:{
+ SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+ || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add (eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+ UseExtendedEventDescriptor = false;
+ }
+ break;
+ case SI::ShortEventDescriptorTag:{
+ SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+ || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
+ }
+ break;
+ case SI::ContentDescriptorTag:
+ break;
+ case SI::ParentalRatingDescriptorTag:
+ break;
+ case SI::PDCDescriptorTag:{
+ SI::PDCDescriptor * pd = (SI::PDCDescriptor *) d;
+ time_t now = time (NULL);
+ struct tm tm_r;
+ struct tm t = *localtime_r (&now, &tm_r); // this initializes the time zone in 't'
+ t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+ int month = t.tm_mon;
+ t.tm_mon = pd->getMonth () - 1;
+ t.tm_mday = pd->getDay ();
+ t.tm_hour = pd->getHour ();
+ t.tm_min = pd->getMinute ();
+ t.tm_sec = 0;
+ if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan
+ t.tm_year++;
+ else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec
+ t.tm_year--;
+ time_t vps = mktime (&t);
+ pEvent->SetVps (vps);
+ }
+ break;
+ case SI::TimeShiftedEventDescriptorTag:{
+ SI::TimeShiftedEventDescriptor * tsed = (SI::TimeShiftedEventDescriptor *) d;
+ cSchedule *rSchedule =
+ (cSchedule *) Schedules->
+ GetSchedule (tChannelID (Source, channel->Nid (), channel->Tid (), tsed->getReferenceServiceId ()));
+ if (!rSchedule)
+ break;
+ rEvent = (cEvent *) rSchedule->GetEvent (tsed->getReferenceEventId ());
+ if (!rEvent)
+ break;
+ pEvent->SetTitle (rEvent->Title ());
+ pEvent->SetShortText (rEvent->ShortText ());
+ pEvent->SetDescription (rEvent->Description ());
+ }
+ break;
+ case SI::LinkageDescriptorTag:{
+ SI::LinkageDescriptor * ld = (SI::LinkageDescriptor *) d;
+ tChannelID linkID (Source, ld->getOriginalNetworkId (), ld->getTransportStreamId (), ld->getServiceId ());
+ if (ld->getLinkageType () == 0xB0) { // Premiere World
+ time_t now = time (NULL);
+ bool hit = SiEitEvent.getStartTime () <= now
+ && now < SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
+ if (hit) {
+ char linkName[ld->privateData.getLength () + 1];
+ strn0cpy (linkName, (const char *) ld->privateData.getData (), sizeof (linkName));
+ // TODO is there a standard way to determine the character set of this string?
+ cChannel *link = Channels.GetByChannelID (linkID);
+ if (link != channel) { // only link to other channels, not the same one
+ //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX
+ if (link) {
+ if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
+ link->SetName (linkName, "", "");
+ }
+ else if (Setup.UpdateChannels >= 4) {
+ cChannel *transponder = channel;
+ if (channel->Tid () != ld->getTransportStreamId ())
+ transponder = Channels.GetByTransponderID (linkID);
+ link =
+ Channels.NewChannel (transponder, linkName, "", "", ld->getOriginalNetworkId (),
+ ld->getTransportStreamId (), ld->getServiceId ());
+ //XXX patFilter->Trigger();
+ }
+ if (link) {
+ if (!LinkChannels)
+ LinkChannels = new cLinkChannels;
+ LinkChannels->Add (new cLinkChannel (link));
+ }
+ }
+ else
+ channel->SetPortalName (linkName);
+ }
+ }
+ }
+ break;
+ case SI::ComponentDescriptorTag:{
+ SI::ComponentDescriptor * cd = (SI::ComponentDescriptor *) d;
+ uchar Stream = cd->getStreamContent ();
+ uchar Type = cd->getComponentType ();
+ if (1 <= Stream && Stream <= 3 && Type != 0) { // 1=video, 2=audio, 3=subtitles
+ if (!Components)
+ Components = new cComponents;
+ char buffer[Utf8BufSize (256)];
+ Components->SetComponent (Components->NumComponents (), Stream, Type,
+ I18nNormalizeLanguageCode (cd->languageCode),
+ cd->description.getText (buffer, sizeof (buffer)));
+ }
+ }
+ break;
+ default:;
+ }
+ delete d;
+ }
+
+ if (!rEvent) {
+ if (ShortEventDescriptor) {
+ char buffer[Utf8BufSize (256)];
+ unsigned char *f;
+ int l = ShortEventDescriptor->name.getLength ();
+ f = (unsigned char *) ShortEventDescriptor->name.getData ().getData ();
+ decodeText2 (f, l, buffer, sizeof (buffer));
+ pEvent->SetTitle (buffer);
+ l = ShortEventDescriptor->text.getLength ();
+ f = (unsigned char *) ShortEventDescriptor->text.getData ().getData ();
+ decodeText2 (f, l, buffer, sizeof (buffer));
+ pEvent->SetShortText (buffer);
+ }
+ else if (!HasExternalData) {
+ pEvent->SetTitle (NULL);
+ pEvent->SetShortText (NULL);
+ }
+ if (ExtendedEventDescriptors) {
+ char buffer[Utf8BufSize (ExtendedEventDescriptors->getMaximumTextLength (": ")) + 1];
+ pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+ }
+ else if (!HasExternalData)
+ pEvent->SetDescription (NULL);
+ }
+ delete ExtendedEventDescriptors;
+ delete ShortEventDescriptor;
+
+ pEvent->SetComponents (Components);
+
+ if (!HasExternalData)
+ pEvent->FixEpgBugs ();
+ if (LinkChannels)
+ channel->SetLinkChannels (LinkChannels);
+ Modified = true;
+#ifdef USE_DDEPGENTRY
+ //to avoid double epg-entrys from ext and int epg sources :EW
+ if (pEvent && pEvent->TableID () != 0x00) {
+ cEvent *pPreviousEvent = (cEvent *) pSchedule->GetPreviousEvent (pEvent);
+ if (pPreviousEvent) {
+ if (Setup.DoubleEpgAction == 0) {
+ pPreviousEvent->SetStartTime (pEvent->StartTime ());
+ pPreviousEvent->SetDuration (pEvent->Duration ());
+ if (Setup.DisableVPS == 0) {
+ if (channel)
+ pPreviousEvent->SetRunningStatus (pEvent->RunningStatus (), channel);
+ else
+ pPreviousEvent->SetRunningStatus (pEvent->RunningStatus ());
+ }
+ // to use the info of the original epg, update the extern one,
+ // if it has less info
+ char buffer_short_intern[256];
+ char buffer_short_extern[256];
+ int len_short_intern = 0;
+ int len_short_extern = 0;
+ if (pEvent->ShortText ())
+ len_short_intern =
+ snprintf (buffer_short_intern, sizeof (buffer_short_intern) - 1, "%s", pEvent->ShortText ());
+ if (pPreviousEvent->ShortText ())
+ len_short_extern =
+ snprintf (buffer_short_extern, sizeof (buffer_short_extern) - 1, "%s", pPreviousEvent->ShortText ());
+ if (len_short_intern > 0) {
+ if (len_short_extern < 1)
+ pPreviousEvent->SetShortText (buffer_short_intern);
+ else if (len_short_intern > len_short_extern)
+ pPreviousEvent->SetShortText (buffer_short_intern);
+ }
+ if (pEvent->Description ()) {
+ char buffer_title_intern[4096];
+ char buffer_title_extern[4096];
+ int len_title_intern = 0;
+ int len_title_extern = 0;
+ if (pEvent->Description ())
+ len_title_intern =
+ snprintf (buffer_title_intern, sizeof (buffer_title_intern) - 1, "%s", pEvent->Description ());
+ if (pPreviousEvent->Description ())
+ len_title_extern =
+ snprintf (buffer_title_extern, sizeof (buffer_title_extern) - 1, "%s",
+ pPreviousEvent->Description ());
+ if (len_title_intern > 0) {
+ if (len_title_extern < 1)
+ pPreviousEvent->SetDescription (buffer_title_intern);
+ else if (len_title_intern > len_title_extern)
+ pPreviousEvent->SetDescription (buffer_title_intern);
+ }
+ }
+ if (pPreviousEvent->Vps () == 0 && pEvent->Vps () != 0)
+ pPreviousEvent->SetVps (pEvent->Vps ());
+ pSchedule->DelEvent (pEvent);
+ pPreviousEvent->FixEpgBugs ();
+ }
+ else
+ pSchedule->DelEvent (pPreviousEvent);
+ }
+ }
+#endif /* DDEPGENTRY */
+ }
+ if (Empty && Tid == 0x4E && getSectionNumber () == 0)
+ // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
+ pSchedule->ClrRunningStatus (channel);
+ if (Tid == 0x4E)
+ pSchedule->SetPresentSeen ();
+ if (OnlyRunningStatus)
+ return;
+ if (Modified) {
+ pSchedule->Sort ();
+ if (!HasExternalData)
+ pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ());
+ Schedules->SetModified (pSchedule);
+ }
+ }
+//end of cEIT2
+} //end namespace SI
+
+void cFilterEEPG::ProcessNextFormat (bool FirstTime = false)
+{
+/* for (int i = 0; i <= HIGHEST_FORMAT; i++)
+ esyslog ("EEPGDEBUG: Format %i on pid %x", i, UnprocessedFormat[i]); */
+
+ if (!FirstTime) {
+ isyslog ("EEPG: found %i equivalents channels", nEquivChannels);
+ isyslog ("EEPG: found %i themes", nThemes);
+ isyslog ("EEPG: found %i channels", nChannels);
+ isyslog ("EEPG: found %i titles", nTitles);
+ isyslog ("EEPG: found %i summaries", nSummaries);
+ isyslog ("EEPG: written %i titles", TitleCounter);
+ isyslog ("EEPG: written %i summaries", SummaryCounter);
+ isyslog ("EEPG: rejected %i titles/summaries because of higher TableId", RejectTableId);
+ TitleCounter = 0;
+ SummaryCounter = 0;
+ /*if (SummariesNotFound != 0)
+ esyslog ("EEPG: %i summaries not found", SummariesNotFound);
+ else if (VERBOSE >= 1)
+ isyslog ("EEPG: %i summaries not found", SummariesNotFound); */
+ UnprocessedFormat[Format] = 0; //clear previously processed format
+ }
+ TitleCounter = 0;
+ SummaryCounter = 0;
+ RejectTableId = 0;
+ //cleanup mess of last processing
+ ChannelSeq.clear ();
+ FreeTitles ();
+ FreeSummaries ();
+
+ //now start looking for next format to process
+ int pid;
+ Format = -1; //unused value
+ for (int i = 0; i <= HIGHEST_FORMAT; i++) //find first format that is detected
+ if (UnprocessedFormat[i]) {
+ isyslog ("EEPG: %s Extended EPG detected on pid %x.", FormatName[i], UnprocessedFormat[i]);
+ Format = i;
+ } //highest format is processed first this way;; TODO make sure that CONT protocols like Premiere, Freesat are processed AFTER ONCE protocols like MHW, SKY and NAGRA
+
+ if (Format == -1) { //there are no formats left to process
+ isyslog ("EEPG: Ended all processing");
+ return;
+ }
+
+ pid = UnprocessedFormat[Format]; //and reinstall its pid
+
+ memset (&InitialChannel, 0, 8);
+ memset (&InitialTitle, 0, 64);
+ memset (&InitialSummary, 0, 64);
+ NagraCounter = 0;
+ Version = -1; //because 0 can be a valid version number...
+ nEquivChannels = 0;
+ nChannels = 0;
+ nThemes = 0;
+ EndChannels = false;
+ EndThemes = false;
+ switch (Format) {
+ case PREMIERE:
+ if (!Matches (pid, 0xA0))
+ Add (pid, 0xA0);
+ break;
+ case MHW1:
+ AddFilter (0xd3, 0x92); //ThemesMHW1//TODO: all filters are serialized, strictly speaking Themes is non-fatal...
+ break;
+ case MHW2:
+ AddFilter (0x231, 0xc8); //MHW2 Channels & Themes
+ break;
+ case SKY_IT:
+ case SKY_UK:
+ AddFilter (0x11, 0x4a); //Sky Channels
+ break;
+ case FREEVIEW: //Freeview, CONT mode //TODO streamline this for other modes
+ ReadFileDictionary ();
+ AddFilter (pid, 0x4e, 0xfe); //event info, actual(0x4e)/other(0x4f) TS, present/following
+ AddFilter (pid, 0x50, 0xf0); //event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+ AddFilter (pid, 0x60, 0xf0); //event info, other TS, schedule(0x60)/schedule for future days(0x6X)
+ case NAGRA:
+ // isyslog ("EEPG: NagraGuide Extended EPG detected.");
+ AddFilter (pid, 0xb0); //perhaps TID is equal to first data byte?
+ default:
+ break;
+ }
+}
+
+void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Length)
+{
+ int now = time (0);
+ if (Pid == 0 && Tid == SI::TableIdPAT) {
+ if (!pmtnext || now > pmtnext) {
+ if (pmtpid)
+ NextPmt ();
+ if (!pmtpid) {
+ SI::PAT pat (Data, false);
+ if (pat.CheckCRCAndParse ()) {
+ SI::PAT::Association assoc;
+ int idx = 0;
+ for (SI::Loop::Iterator it; pat.associationLoop.getNext (assoc, it);) {
+ if (!assoc.isNITPid ()) {
+ //if (!assoc.isNITPid () && Scanning) {
+ if (idx++ == pmtidx) {
+ pmtpid = assoc.getPid ();
+ pmtsid = assoc.getServiceId ();
+ Add (pmtpid, 0x02);
+ pmtnext = now + PMT_SCAN_TIMEOUT;
+ if (VERBOSE >= 3)
+ esyslog ("PMT pid now 0x%04x (idx=%d)\n", pmtpid, pmtidx);
+ break;
+ }
+ }
+ }
+ if (!pmtpid) {
+ pmtidx = 0;
+ pmtnext = now + PMT_SCAN_IDLE;
+ if (VERBOSE >= 1)
+ esyslog ("PMT scan idle\n");
+
+ Del (0, 0); //this effectively kills the PMT_SCAN_IDLE functionality
+
+ //now after the scan is completed, start processing
+ ProcessNextFormat (true); //FirstTime flag is set
+ }
+ }
+ }
+ }
+ }
+ else if (pmtpid > 0 && Pid == pmtpid && Tid == SI::TableIdPMT && Source () && Transponder ()) {
+ SI::PMT pmt (Data, false);
+ if (pmt.CheckCRCAndParse () && pmt.getServiceId () == pmtsid) {
+ SI::PMT::Stream stream;
+ for (SI::Loop::Iterator it; pmt.streamLoop.getNext (stream, it);) {
+// if(stream.getStreamType()==0x05) {
+ if (stream.getStreamType () == 0x05 || stream.getStreamType () == 0xc1) { //0x05 = Premiere, SKY, Freeview, Nagra 0xc1 = MHW1,MHW2
+ SI::CharArray data = stream.getData ();
+ if ((data[1] & 0xE0) == 0xE0 && (data[3] & 0xF0) == 0xF0) {
+ bool prvData = false, usrData = false;
+ bool prvOTV = false, prvFRV = false;
+ int usrOTV = 0, usrFRV = 0;
+ //Format = 0; // 0 = premiere, 1 = MHW1, 2 = MHW2, 3 = Sky Italy (OpenTV), 4 = Sky UK (OpenTV), 5 = Freesat (Freeview), 6 = Nagraguide
+ SI::Descriptor * d;
+ for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext (it));) {
+ //esyslog ("EEPGDEBUG:d->getDescriptorTAG():%x,SI::PrivateTag:%x\n", d->getDescriptorTag (), SI::PrivateDataSpecifierDescriptorTag);
+ switch (d->getDescriptorTag ()) {
+ case SI::PrivateDataSpecifierDescriptorTag:
+ //esyslog ("prv: %d %08x\n", d->getLength (), d->getData ().FourBytes (2));
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x000000be)
+ prvData = true;
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x4f545600) //OpenTV
+ prvOTV = true;
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x46534154) //Freeview
+ prvFRV = true;
+ break;
+ case 0x52:
+ //if (d->getLength () == 3 && d->getData ().FourBytes (2) == 0xb07ea882) {
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb000))
+ UnprocessedFormat[NAGRA] = stream.getPid ();
+ //int nop; //FIXME
+ break;
+ case 0x90:
+ //esyslog ("usr: %d %08x\n", d->getLength (), d->getData ().FourBytes (2));
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x0000ffff)
+ usrData = true;
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb600)) //SKY IT //TODO ugly!
+ //if (d->getLength () == 3 && (d->getData ().TwoBytes (2) == 0xb6a5)) //SKY IT //TODO ugly!
+ usrOTV = SKY_IT;
+ //Format = SKY_IT;
+
+ //if (d->getLength () == 3 && ((d->getData ().FourBytes (2) & 0xff000000) == 0xc0000000)) //SKY UK
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x9d00)) //SKY UK //TODO ugly!
+ usrOTV = SKY_UK;
+ //Format = SKY_UK;
+ break;
+ case 0xc1: //MHW1, MHW2
+// esyslog("EEPGDEBUG:d->getDescriptorTAG:%d %08x\n",d->getLength(),d->getData().FourBytes(2));
+ if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x50555348) //MHw1 Cyfra
+ UnprocessedFormat[MHW1] = stream.getPid ();
+ break;
+ case 0xc2: //MHW1, MHW2
+ if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x45504700) //MHw1 CanDigNL and CSat
+ UnprocessedFormat[MHW1] = stream.getPid ();
+ //int nop;//FIXME
+ else if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x46494348) { //MHW2
+ UnprocessedFormat[MHW2] = stream.getPid ();
+ }
+ break;
+ case 0xd1: //Freeview
+ if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x0100))
+ usrFRV = 0x01;
+ //01 = EIT pid 3842
+ //03 04 = SDT Service Description Table pid 3841
+ //07 = still undocumented, definition of buch of transport streams pid 3840
+ //02 = ATSC reserved, find out what huffman encoded text is sent here! pid 3843
+ //05 06 = TOT Time Offset Table pid 3844
+ break;
+
+/* case 0xfe: //SKY_IT
+ if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x534b5900) { //SKY_IT
+ Format = SKY_IT;
+ }
+ break;*/
+ default:
+ break;
+ }
+ delete d;
+ }
+ if ((prvOTV) && ((usrOTV == SKY_IT) || (usrOTV == SKY_UK)))
+ UnprocessedFormat[usrOTV] = stream.getPid ();
+ else if (prvFRV)
+ if (usrFRV == 0x01)
+ UnprocessedFormat[FREEVIEW] = stream.getPid ();
+ if (prvData && usrData)
+ UnprocessedFormat[PREMIERE] = stream.getPid ();
+ } //if data[1] && data [3]
+ } //if streamtype
+ /*if (Format != PREMIERE) //any format found
+ break; //break out for loop */
+ } //for loop that walks through streams
+// if (Format == PREMIERE) { //FIXME for Premiere you should also stop scanning when found...
+ NextPmt ();
+ pmtnext = 0;
+/* }
+ else {
+ Del (pmtpid, 0x02);
+ Del (0, 0);
+ pmtidx = 0;
+ pmtnext = now + PMT_SCAN_IDLE;
+ isyslog ("PMT scan forced idle\n");
+ }*/
+ } //checkCRC
+ } //if pmtpid
+ else if (Source ()) {
+ int Result;
+ switch (Tid) {
+ case 0xA0:
+ if ((Pid < 0x30) || (Pid > 0x37)) {
+ SI::PremiereCIT cit (Data, false);
+ if (cit.CheckCRCAndParse ()) {
+ cSchedulesLock SchedulesLock (true, 10);
+ cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+ if (Schedules) {
+ int nCount = 0;
+ SI::ExtendedEventDescriptors * ExtendedEventDescriptors = 0;
+ SI::ShortEventDescriptor * ShortEventDescriptor = 0;
+ char *order = 0, *rating = 0;
+ {
+ time_t firstTime = 0;
+ SI::Descriptor * d;
+ bool UseExtendedEventDescriptor = false;
+ int LanguagePreferenceShort = -1;
+ int LanguagePreferenceExt = -1;
+ for (SI::Loop::Iterator it; (d = cit.eventDescriptors.getNext (it));) {
+ switch (d->getDescriptorTag ()) {
+ case 0xF0: // order information
+ if (SetupPE.OrderInfo) {
+ static const char *text[] = {
+ trNOOP ("Ordernumber"),
+ trNOOP ("Price"),
+ trNOOP ("Ordering"),
+ trNOOP ("SMS"),
+ trNOOP ("WWW")
+ };
+ char buff[512];
+ int p = 0;
+ const unsigned char *data = d->getData ().getData () + 2;
+ for (int i = 0; i < 5; i++) {
+ int l = data[0];
+ if (l > 0)
+ p += snprintf (&buff[p], sizeof (buff) - p, "\n%s: %.*s", tr (text[i]), l, &data[1]);
+ data += l + 1;
+ }
+ if (p > 0)
+ order = strdup (buff);
+ }
+ break;
+ case 0xF1: // parental rating
+ if (SetupPE.RatingInfo) {
+ char buff[512];
+ int p = 0;
+ const unsigned char *data = d->getData ().getData () + 2;
+ p +=
+ snprintf (&buff[p], sizeof (buff) - p, "\n%s: %d %s", tr ("Rating"), data[0] + 3, tr ("years"));
+ data += 7;
+ int l = data[0];
+ if (l > 0)
+ p += snprintf (&buff[p], sizeof (buff) - p, " (%.*s)", l, &data[1]);
+ if (p > 0)
+ rating = strdup (buff);
+ }
+ break;
+ case SI::PremiereContentTransmissionDescriptorTag:
+ if (nCount >= 0) {
+ SI::PremiereContentTransmissionDescriptor * pct = (SI::PremiereContentTransmissionDescriptor *) d;
+ nCount++;
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
+ SI::Loop::Iterator it;
+ if (pct->startDayLoop.getNext (sd, it)) {
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
+ SI::Loop::Iterator it2;
+ if (sd.startTimeLoop.getNext (st, it2)) {
+ time_t StartTime = st.getStartTime (sd.getMJD ());
+ if (nCount == 1)
+ firstTime = StartTime;
+ else if (firstTime < StartTime - 5 * 50 || firstTime > StartTime + 5 * 60)
+ nCount = -1;
+ }
+ }
+ }
+ break;
+ case SI::ExtendedEventDescriptorTag:
+ {
+ SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+ || !ExtendedEventDescriptors) {
+ delete ExtendedEventDescriptors;
+ ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+ UseExtendedEventDescriptor = true;
+ }
+ if (UseExtendedEventDescriptor) {
+ ExtendedEventDescriptors->Add (eed);
+ d = NULL; // so that it is not deleted
+ }
+ if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+ UseExtendedEventDescriptor = false;
+ }
+ break;
+ case SI::ShortEventDescriptorTag:
+ {
+ SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+ if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+ || !ShortEventDescriptor) {
+ delete ShortEventDescriptor;
+ ShortEventDescriptor = sed;
+ d = NULL; // so that it is not deleted
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ delete d;
+ }
+ }
+
+ {
+ bool Modified = false;
+ int optCount = 0;
+ unsigned int crc[3];
+ crc[0] = cit.getContentId ();
+ SI::PremiereContentTransmissionDescriptor * pct;
+ for (SI::Loop::Iterator it;
+ (pct =
+ (SI::PremiereContentTransmissionDescriptor *) cit.eventDescriptors.getNext (it,
+ SI::
+ PremiereContentTransmissionDescriptorTag));)
+ {
+ int nid = pct->getOriginalNetworkId ();
+ int tid = pct->getTransportStreamId ();
+ int sid = pct->getServiceId ();
+ if (SetupPE.FixEpg) {
+ if (nid == 133) {
+ if (tid == 0x03 && sid == 0xf0) {
+ tid = 0x02;
+ sid = 0xe0;
+ }
+ else if (tid == 0x03 && sid == 0xf1) {
+ tid = 0x02;
+ sid = 0xe1;
+ }
+ else if (tid == 0x03 && sid == 0xf5) {
+ tid = 0x03;
+ sid = 0xdc;
+ }
+ else if (tid == 0x04 && sid == 0xd2) {
+ tid = 0x11;
+ sid = 0xe2;
+ }
+ else if (tid == 0x11 && sid == 0xd3) {
+ tid = 0x11;
+ sid = 0xe3;
+ }
+ }
+ }
+ tChannelID channelID (Source (), nid, tid, sid);
+ cChannel *channel = Channels.GetByChannelID (channelID, true);
+#ifdef USE_NOEPG
+ // only use epg from channels not blocked by noEPG-patch
+ if (!allowedEPG (channelID))
+ continue;
+#endif /* NOEPG */
+
+ if (!channel)
+ continue;
+
+ cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channelID);
+ if (!pSchedule) {
+ pSchedule = new cSchedule (channelID);
+ Schedules->Add (pSchedule);
+ }
+
+ optCount++;
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
+ int index = 0;
+ for (SI::Loop::Iterator it; pct->startDayLoop.getNext (sd, it);) {
+ int mjd = sd.getMJD ();
+ SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
+ for (SI::Loop::Iterator it2; sd.startTimeLoop.getNext (st, it2);) {
+ time_t StartTime = st.getStartTime (mjd);
+ time_t EndTime = StartTime + cit.getDuration ();
+ int runningStatus = (StartTime < now
+ && now < EndTime) ? SI::RunningStatusRunning : ((StartTime - 30 < now
+ && now <
+ StartTime) ? SI::
+ RunningStatusStartsInAFewSeconds
+ : SI::RunningStatusNotRunning);
+ bool isOpt = false;
+ if (index++ == 0 && nCount > 1)
+ isOpt = true;
+ crc[1] = isOpt ? optCount : 0;
+ crc[2] = StartTime / STARTTIME_BIAS;
+ tEventID EventId = ((('P' << 8) | 'W') << 16) | crc16 (0, (unsigned char *) crc, sizeof (crc));
+ if (VERBOSE >= 2)
+ isyslog ("%s R%d %04x/%.4x %d %d/%d %s +%d ", *channelID.ToString (), runningStatus,
+ EventId & 0xFFFF, cit.getContentId (), index, isOpt, optCount,
+ stripspace (ctime (&StartTime)), (int) cit.getDuration () / 60);
+ if (EndTime + Setup.EPGLinger * 60 < now) {
+ if (VERBOSE >= 2)
+ isyslog ("(old)\n");
+ continue;
+ }
+
+ bool newEvent = false;
+ cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EventId, -1);
+ if (!pEvent) {
+ if (VERBOSE >= 2)
+ isyslog ("(new)\n");
+ pEvent = new cEvent (EventId);
+ if (!pEvent)
+ continue;
+ newEvent = true;
+ }
+ else {
+ if (VERBOSE >= 2)
+ isyslog ("(upd)\n");
+ pEvent->SetSeen ();
+ if (pEvent->TableID () == 0x00 || pEvent->Version () == cit.getVersionNumber ()) {
+ if (pEvent->RunningStatus () != runningStatus)
+ pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
+ continue;
+ }
+ }
+ pEvent->SetEventID (EventId);
+ pEvent->SetTableID (Tid);
+ pEvent->SetVersion (cit.getVersionNumber ());
+ pEvent->SetStartTime (StartTime);
+ pEvent->SetDuration (cit.getDuration ());
+
+ if (ShortEventDescriptor) {
+ char buffer[256];
+ ShortEventDescriptor->name.getText (buffer, sizeof (buffer));
+ if (isOpt) {
+ char buffer2[sizeof (buffer) + 32];
+ snprintf (buffer2, sizeof (buffer2), optPats[SetupPE.OptPat], buffer, optCount);
+ pEvent->SetTitle (buffer2);
+ }
+ else
+ pEvent->SetTitle (buffer);
+ if (VERBOSE >= 2)
+ isyslog ("title: %s\n", pEvent->Title ());
+ pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
+ }
+ if (ExtendedEventDescriptors) {
+ char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
+ pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+ }
+ if (order || rating) {
+ int len = (pEvent->Description ()? strlen (pEvent->Description ()) : 0) +
+ (order ? strlen (order) : 0) + (rating ? strlen (rating) : 0);
+ char buffer[len + 32];
+ buffer[0] = 0;
+ if (pEvent->Description ())
+ strcat (buffer, pEvent->Description ());
+ if (rating)
+ strcat (buffer, rating);
+ if (order)
+ strcat (buffer, order);
+ pEvent->SetDescription (buffer);
+ }
+
+ if (newEvent)
+ pSchedule->AddEvent (pEvent);
+
+ pEvent->FixEpgBugs ();
+ if (pEvent->RunningStatus () != runningStatus)
+ pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
+ pSchedule->DropOutdated (StartTime, EndTime, Tid, cit.getVersionNumber ());
+ Modified = true;
+ }
+ }
+ if (Modified) {
+ pSchedule->Sort ();
+ Schedules->SetModified (pSchedule);
+ }
+ delete pct;
+ }
+ }
+ delete ExtendedEventDescriptors;
+ delete ShortEventDescriptor;
+ free (order);
+ free (rating);
+ }
+ } //if checkcrcandpars
+ break;
+ } //if citpid == 0xb11 Premiere
+ else //SKY also uses 0xA0 Tid, do NOT break then!!
+ {
+ } //TODO do I need this dummy?
+ case 0xa1:
+ case 0xa2:
+ case 0xa3:
+ Result = GetTitlesSKYBOX (Data, Length - 4);
+ if (Result != 1) //when fatal error or finished
+ Del (Pid, 0xa0, 0xfc); //kill filter
+ if (Result == 0) { //fatal error
+ esyslog ("EEPG: Fatal error reading titles.");
+ ProcessNextFormat (); //and go process other formats
+ }
+ if (Result == 2)
+ AddFilter (Pid + 0x10, 0xa8, 0xfc); //Set filter that processes summaries of this batch
+ break;
+ case 0xa8:
+ case 0xa9:
+ case 0xaa:
+ case 0xab:
+ Result = GetSummariesSKYBOX (Data, Length - 4);
+ if (Result != 1) //when fatal error or finished
+ Del (Pid, 0xa8, 0xfc); //kill filter
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading summaries.");
+ ProcessNextFormat ();
+ }
+ if (Result == 2) {
+ LoadIntoSchedule ();
+ if (Pid < 0x47) //this is not the last batch//FIXME chaining is easy on the PIDs and the CPU, but error when Pid,Tid is not used at the moment...
+ AddFilter (Pid - 0x0F, 0xa0, 0xfc); //next pid, first tid
+ else //last pid was processed
+ ProcessNextFormat ();
+ }
+ break;
+ case 0x90:
+ if (Pid == 0xd2) {
+ Result = GetTitlesMHW1 (Data, Length);
+ if (Result != 1) //fatal error or last processed
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading titles.");
+ ProcessNextFormat ();
+ }
+ if (Result == 2)
+ AddFilter (0xd3, 0x90); //SummariesMHW1
+ }
+ else if (Pid == 0xd3) {
+ Result = GetSummariesMHW1 (Data, Length);
+ if (Result != 1) //fatal error or last processed
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading summaries.");
+ }
+ if (Result == 2) {
+ LoadIntoSchedule ();
+ }
+ if (Result != 1) {
+ ProcessNextFormat ();
+ }
+ }
+ break;
+ case 0xc8: //GetChannelsMHW2 or GetThemesMHW2
+ if (Pid == 0x231) {
+ if (Data[3] == 0x01) { //Themes it will be
+ Result = GetThemesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ //break;
+ if (Result != 1)
+ EndThemes = true; //also set Endthemes on true on fatal error
+ } //if Data
+ else if (Data[3] == 0x00) { //Channels it will be
+ Result = GetChannelsMHW (Data, Length, 2); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ EndChannels = true; //always remove filter, code 1 should never be returned since MHW2 always reads all channels..
+ ChannelsOk = (Result == 2);
+ }
+ if (EndChannels && EndThemes) { //those are only set withing MHW2
+ Del (0x231, 0xc8); //stop reading MHW2 themes and channels
+ if (ChannelsOk) //No channels = fatal, no themes = nonfatal
+ AddFilter (0x234, 0xe6); //start reading MHW2 titles
+ else {
+ esyslog ("EEPG: Fatal error reading channels.");
+ ProcessNextFormat ();
+ }
+ }
+ } //if Pid == 0x231
+ break;
+ case 0x91:
+ Result = GetChannelsMHW (Data, Length, 1); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ Del (Pid, Tid); //always remove filter, code 1 should never be returned since MHW1 always reads all channels...
+ if (Result == 2)
+ AddFilter (0xd2, 0x90); //TitlesMHW1
+ else {
+ esyslog ("EEPG: Fatal error reading channels.");
+ ProcessNextFormat ();
+ }
+ break;
+ case 0x92:
+ Result = GetThemesMHW1 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 2)
+ AddFilter (0xd3, 0x91); //ChannelsMHW1
+ else {
+ esyslog ("EEPG: Fatal error reading themes."); //doesnt have to be fatal...
+ ProcessNextFormat ();
+ }
+ break;
+ case 0xe6: //TitlesMHW2
+ if (Pid == 0x234) {
+ Result = GetTitlesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading titles.");
+ ProcessNextFormat ();
+ }
+ if (Result == 2)
+ AddFilter (0x236, 0x96); //start reading MHW2 summaries....
+ }
+ break;
+ case 0x96: //Summaries MHW2
+ if (Pid == 0x236) {
+ Result = GetSummariesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error reading summaries.");
+ }
+ if (Result == 2)
+ LoadIntoSchedule ();
+ if (Result != 1) {
+ ProcessNextFormat ();
+ }
+ } //if pid
+ break;
+ case 0x4a: //Sky channels
+ if (Pid == 0x11) {
+ Result = GetChannelsSKYBOX (Data, Length - 4);
+ if (Result != 1) //only breakoff on completion or error; do NOT clean up after success, because then not all bouquets will be read
+ Del (Pid, Tid); //Read all channels, clean up filter
+ if (Result == 2) {
+ GetThemesSKYBOX (); //Sky Themes from file; must be called AFTER first channels to have lThemes initialized FIXME
+ if (ReadFileDictionary ())
+ AddFilter (0x30, 0xa0, 0xfc); //SKY Titles batch 0 of 7
+ else {
+ esyslog ("EEPG: Fatal error reading huffman table.");
+ ProcessNextFormat ();
+ }
+ }
+
+ } //if Pid == 0x11
+ break;
+ case 0xb0: //NagraGuide
+ if (Pid == 0xc8) {
+ Result = GetNagra (Data, Length);
+ if (Result != 1)
+ Del (Pid, Tid);
+ if (Result == 0) {
+ esyslog ("EEPG: Fatal error processing NagraGuide. End of processing.");
+ }
+ if (Result == 2) {
+ ProcessNagra ();
+ cSchedules::Cleanup (true); //deletes all past events
+ isyslog ("EEPG: Ended processing Nagra");
+ }
+ if (Result != 1) {
+ ProcessNextFormat ();
+ }
+ }
+ break;
+
+ case 0x4E:
+ case 0x4F:
+ case 0x50:
+ case 0x51:
+ case 0x52:
+ case 0x53:
+ case 0x54:
+ case 0x55:
+ case 0x56:
+ case 0x57:
+ case 0x58:
+ case 0x59:
+ case 0x5A:
+ case 0x5B:
+ case 0x5C:
+ case 0x5D:
+ case 0x5E:
+ case 0x5F:
+ case 0x60:
+ case 0x61:
+ case 0x62:
+ case 0x63:
+ case 0x64:
+ case 0x65:
+ case 0x66:
+ case 0x67:
+ case 0x68:
+ case 0x69:
+ case 0x6A:
+ case 0x6B:
+ case 0x6C:
+ case 0x6D:
+ case 0x6E:
+ case 0x6F:
+ // Freesat:
+ // Set(3842, 0x4E, 0xFE); // event info, actual(0x4E)/other(0x4F) TS, present/following
+ // Set(3842, 0x50, 0xF0); // event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+ // Set(3842, 0x60, 0xF0); // event info, other TS, schedule(0x60)/schedule for future days(0x6X)
+ //
+ // PID found: 3841 (0x0f01) [SECTION: Service Description Table (SDT) - other transport stream]
+ // PID found: 3842 (0x0f02) [SECTION: Event Information Table (EIT) - other transport stream, schedule]
+ // PID found: 3843 (0x0f03) [SECTION: ATSC reserved] TODO find out what compressed text info is here!
+ // PID found: 3844 (0x0f04) [SECTION: Time Offset Table (TOT)]
+
+ if (Pid == 3842) {
+ cSchedulesLock SchedulesLock (true, 10);
+ cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+ if (Schedules)
+ SI::cEIT2 EIT (Schedules, Source (), Tid, Data);
+ //cEIT EIT (Schedules, Source (), Tid, Data);
+ else {
+ // If we don't get a write lock, let's at least get a read lock, so
+ // that we can set the running status and 'seen' timestamp (well, actually
+ // with a read lock we shouldn't be doing that, but it's only integers that
+ // get changed, so it should be ok)
+ cSchedulesLock SchedulesLock;
+ cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+ if (Schedules)
+ SI::cEIT2 EIT (Schedules, Source (), Tid, Data, true);
+ //cEIT EIT (Schedules, Source (), Tid, Data, true);
+ }
+ }
+ break;
+
+ default:
+ break;
+ } //end switch
+ } //closes SOURCE()
+} //end of closing
+
+// --- cPluginEEPG ------------------------------------------------------
+
+class cPluginEEPG:public cPlugin
+{
+private:
+ struct
+ {
+ cFilterEEPG *filter;
+ cDevice *device;
+ } epg[MAXDVBDEVICES];
+public:
+ cPluginEEPG (void);
+ virtual const char *Version (void)
+ {
+ return VERSION;
+ }
+ virtual const char *Description (void)
+ {
+ return tr (DESCRIPTION);
+ }
+ virtual bool Start (void);
+ virtual void Stop (void);
+ virtual cMenuSetupPage *SetupMenu (void);
+ virtual bool SetupParse (const char *Name, const char *Value);
+};
+
+cPluginEEPG::cPluginEEPG (void)
+{
+ memset (epg, 0, sizeof (epg));
+}
+
+bool cPluginEEPG::Start (void)
+{
+#if APIVERSNUM < 10507
+ RegisterI18n (Phrases);
+#endif
+ for (int i = 0; i < MAXDVBDEVICES; i++) {
+ cDevice *dev = cDevice::GetDevice (i);
+ if (dev) {
+ epg[i].device = dev;
+ dev->AttachFilter (epg[i].filter = new cFilterEEPG);
+ isyslog ("Attached EEPG filter to device %d", i);
+ }
+ }
+ ConfDir = NULL;
+ // Initialize any background activities the plugin shall perform.
+ char *FileName;
+ DIR *ConfigDir;
+ FILE *File;
+ if (ConfDir == NULL) {
+ asprintf (&ConfDir, "%s/eepg", cPlugin::ConfigDirectory ());
+ }
+ ConfigDir = opendir (ConfDir);
+ if (ConfigDir == NULL) {
+ esyslog ("EEPG: Error opening directory '%s', %s", ConfDir, strerror (errno));
+ if (mkdir (ConfDir, 0777) < 0) {
+ esyslog ("EEPG: Error creating directory '%s', %s", ConfDir, strerror (errno));
+ }
+ else {
+ isyslog ("EEPG: Success creating directory '%s'", ConfDir);
+ }
+ }
+ asprintf (&FileName, "%s/%s", ConfDir, EEPG_FILE_EQUIV);
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ int i = 0;
+ while (FileEquivalences[i] != NULL) {
+ fprintf (File, "%s\n", FileEquivalences[i]);
+ i++;
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_it.dict");
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ int i = 0;
+ while (SkyItDictionary[i] != NULL) {
+ fprintf (File, "%s\n", SkyItDictionary[i]);
+ i++;
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.dict");
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ int i = 0;
+ while (SkyUkDictionary[i] != NULL) {
+ fprintf (File, "%s\n", SkyUkDictionary[i]);
+ i++;
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_it.themes");
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ for (int i = 0; i < 256; i++) {
+ if (SkyItThemes[i]) {
+ fprintf (File, "0x%02x=%s\n", i, SkyItThemes[i]);
+ }
+ else {
+ fprintf (File, "0x%02x=\n", i);
+ }
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "sky_uk.themes");
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ for (int i = 0; i < 256; i++) {
+ if (SkyUkThemes[i]) {
+ fprintf (File, "0x%02x=%s\n", i, SkyUkThemes[i]);
+ }
+ else {
+ fprintf (File, "0x%02x=\n", i);
+ }
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "freesat.t1");
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ int i = 0;
+ while (FreesatT1[i] != NULL) {
+ fprintf (File, "%s\n", FreesatT1[i]);
+ i++;
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+ asprintf (&FileName, "%s/%s", ConfDir, "freesat.t2");
+ File = fopen (FileName, "r");
+ if (File == NULL) {
+ esyslog ("EEPG: Error opening file '%s', %s", FileName, strerror (errno));
+ File = fopen (FileName, "w");
+ if (File == NULL) {
+ esyslog ("EEPG: Error creating file '%s', %s", FileName, strerror (errno));
+ }
+ else {
+ int i = 0;
+ while (FreesatT2[i] != NULL) {
+ fprintf (File, "%s\n", FreesatT2[i]);
+ i++;
+ }
+ isyslog ("EEPG: Success creating file '%s'", FileName);
+ fclose (File);
+ }
+ }
+ else {
+ fclose (File);
+ }
+ free (FileName);
+
+ //store all available sources, so when a channel is not found on current satellite, we can look for alternate sat positions.
+ //perhaps this can be done smarter through existing VDR function???
+ for (cChannel * Channel = Channels.First (); Channel; Channel = Channels.Next (Channel)) {
+ if (!Channel->GroupSep ()) {
+ bool found = false;
+ for (int i = 0; (i < NumberOfAvailableSources) && (!found); i++)
+ found = (Channel->Source () == AvailableSources[i]);
+ if (!found)
+ AvailableSources[NumberOfAvailableSources++] = Channel->Source ();
+ }
+ }
+ if (VERBOSE >= 3)
+ for (int i = 0; i < NumberOfAvailableSources; i++)
+ isyslog ("EEPG: Available sources:%s.", *cSource::ToString (AvailableSources[i]));
+
+
+ return true;
+}
+
+void cPluginEEPG::Stop (void)
+{
+ for (int i = 0; i < MAXDVBDEVICES; i++) {
+ cDevice *dev = epg[i].device;
+ if (dev)
+ dev->Detach (epg[i].filter);
+ delete epg[i].filter;
+ epg[i].device = 0;
+ epg[i].filter = 0;
+ }
+ // Clean up after yourself!
+ if (ConfDir) {
+ free (ConfDir);
+ }
+}
+
+cMenuSetupPage *cPluginEEPG::SetupMenu (void)
+{
+ return new cMenuSetupPremiereEpg;
+}
+
+bool cPluginEEPG::SetupParse (const char *Name, const char *Value)
+{
+ if (!strcasecmp (Name, "OptionPattern"))
+ SetupPE.OptPat = atoi (Value);
+ else if (!strcasecmp (Name, "OrderInfo"))
+ SetupPE.OrderInfo = atoi (Value);
+ else if (!strcasecmp (Name, "RatingInfo"))
+ SetupPE.RatingInfo = atoi (Value);
+ else if (!strcasecmp (Name, "FixEpg"))
+ SetupPE.FixEpg = atoi (Value);
+ else
+ return false;
+ return true;
+}
+
+VDRPLUGINCREATOR (cPluginEEPG); // Don't touch this!
diff --git a/eepg.equiv.IT b/eepg.equiv.IT
new file mode 100644
index 0000000..6c21282
--- /dev/null
+++ b/eepg.equiv.IT
@@ -0,0 +1,17 @@
+#
+# Simply add a list of the channels in this file with the following format:
+#
+# <OriginalChannelId> <OtherChannelId> <ChannelName>
+#
+
+S13.0E-64511-6700-11517 S13.0E-318-13000-14601 BBC Prime
+S13.0E-318-5200-3401 S19.2E-1-1024-9015 Rai Uno
+S13.0E-318-5200-3401 S13.0E-318-12400-8511 Rai Uno
+S13.0E-318-5200-3402 S13.0E-318-12400-8512 Rai Due
+S13.0E-318-5200-3403 S13.0E-318-12400-8513 Rai Tre
+S13.0E-272-6000-3 T-272-905-143 Rete 4
+S13.0E-272-6000-2 T-272-905-141 Canale 5
+S13.0E-272-6000-1 T-272-905-142 Italia 1
+S13.0E-64511-8600-11733 T-29-514-1 La 7
+S13.0E-64511-6700-11504 S13.0E-318-200-13831 Eurosport
+
diff --git a/eepg.h b/eepg.h
new file mode 100644
index 0000000..5372714
--- /dev/null
+++ b/eepg.h
@@ -0,0 +1,7149 @@
+#define DEBUG false
+//#define DEBUG_STARTTIME false
+
+#define EEPG_FILE_EQUIV "eepg.equiv"
+
+#define MAX_THEMES 256 //this should always be >=256, or Nagra will go wrong!!
+#define MAX_CHANNELS 2048
+#define MAX_TITLES 262144
+
+#define MAX_EQUIVALENCES 8 //the number of equivalences one channel can have
+
+//Formats (need to be consecutively numbered):
+//First all CONTinuous protocols, so they will be processed LAST:
+#define PREMIERE 0
+#define FREEVIEW 1
+//Then all batchmode, load ONCE protocols:
+#define MHW1 2
+#define MHW2 3
+#define SKY_IT 4
+#define SKY_UK 5
+#define NAGRA 6
+#define HIGHEST_FORMAT 6 //the highest number of EPG-formats that is supported by this plugin
+
+#define NAGRA_TABLE_ID 0x60 //the lower the table Id, the more "current" it is; table_id 0x00 never gets overwritten, now/next are at 0x4e or 0x4f!
+#define DEFAULT_TABLE_ID 0x30
+
+const char *FormatName[]= {"Premiere","FreeView","MediaHighWay 1","MediaHighWay 2","Sky Italy","Sky UK","NagraGuide"};
+
+struct sNode
+{
+ char *Value;
+ struct sNode *P0;
+ struct sNode *P1;
+};
+
+typedef struct sNode sNodeH;
+
+typedef struct
+{
+ unsigned short int ChannelId;
+ unsigned short int SkyNumber;
+ unsigned short int NumberOfEquivalences;//original channel sets this value to 1, every equivalent channel adds 1
+ unsigned short int Src[MAX_EQUIVALENCES];
+ unsigned short int Nid[MAX_EQUIVALENCES];
+ unsigned short int Tid[MAX_EQUIVALENCES];
+ unsigned short int Sid[MAX_EQUIVALENCES];
+ unsigned char Name[64];
+} sChannel;
+
+typedef struct {
+ unsigned short int ChannelId;
+ unsigned short int ThemeId;
+ unsigned short int MjdTime;
+ unsigned int EventId;//short is not sufficient for Nagra
+ unsigned int StartTime;
+ unsigned int Duration;
+ unsigned char SummaryAvailable;
+ unsigned char * Text;
+ unsigned char Unknown1;//FIXME
+ unsigned char Unknown2;//FIXME
+ unsigned char Unknown3;//FIXME
+} Title_t;
+
+typedef struct {
+ unsigned short int ChannelId;
+ unsigned int StartTime;
+ unsigned short int MjdTime;
+ unsigned int EventId;//short is not sufficient for Nagra
+ unsigned short int NumReplays;
+ unsigned char * Text;
+} Summary_t;
+
+static const char *FileEquivalences[] = {
+ "#",
+ "# Simply add a list of the channels in this file with the following format:",
+ "#",
+ "# <OriginalChannelId> <OtherChannelId> <ChannelName>",
+ "#",
+ "",
+ "S13.0E-64511-6700-11517 S13.0E-318-13000-14601 BBC Prime",
+ "S13.0E-318-5200-3401 S19.2E-1-1024-9015 Rai Uno",
+ "S13.0E-318-5200-3401 S13.0E-318-12400-8511 Rai Uno",
+ "S13.0E-318-5200-3402 S13.0E-318-12400-8512 Rai Due",
+ "S13.0E-318-5200-3403 S13.0E-318-12400-8513 Rai Tre",
+ "S13.0E-272-6000-3 T-272-905-143 Rete 4",
+ "S13.0E-272-6000-2 T-272-905-141 Canale 5",
+ "S13.0E-272-6000-1 T-272-905-142 Italia 1",
+ "S13.0E-64511-8600-11733 T-29-514-1 La 7",
+ "S13.0E-64511-6700-11504 S13.0E-318-200-13831 Eurosport",
+ "",
+ NULL
+};
+
+static const char *SkyItDictionary[] = {
+ " =00001011010110001111010101010",
+ " =00001011010110001111010101011",
+ " =00001011010110001111010101100",
+ " =00001011010110001111010101101",
+ " =00001011010110001111010101110",
+ " =00001011010110001111010101111",
+ " =00001011010110001111010110000",
+ " =00001011010110001111010110001",
+ " =00001011010110001111010110010",
+ " =00001011010110001111010110011",
+ " =00001011010110001111010110100",
+ " =00001011010110001111010110101",
+ " =00001011010110001111010110110",
+ " =1001110",
+ " =00001011010110001111010110111",
+ " =00001011010110001111010111000",
+ " =00001011010110001111010111001",
+ " =00001011010110001111010111010",
+ " =00001011010110001111010111011",
+ " =00001011010110001111010111100",
+ " =00001011010110001111010111101",
+ " =00001011010110001111010111110",
+ " =00001011010110001111010111111",
+ " =00001011010110001111011000000",
+ " =00001011010110001111011000001",
+ " =00001011010110001111011000010",
+ " =00001011010110001111011000011",
+ " =00001011010110001111011000100",
+ " =00001011010110001111011000101",
+ " =00001011010110001111011000110",
+ " =00001011010110001111011000111",
+ " =00001011010110001111011001000",
+ " =01",
+ "!=1110000011101",
+ "\"=11100010000100011",
+ "#=00001011010110001111011001001",
+ "$=00001011010110001111011001010",
+ "%=00001011010110001111011001011",
+ "&=11100010000101",
+ "'=0000100",
+ "(=0000101101010",
+ ")=110100111111",
+ "*=00001011010110001111011001100",
+ "+=000010110101100011111",
+ ",=110000",
+ "-=10110011",
+ ".=100110",
+ "/=111000100001001",
+ "0=10010011",
+ "1=100100000",
+ "2=1111011001",
+ "3=1110001110",
+ "4=11000100101",
+ "5=111101110100",
+ "6=101100101111",
+ "7=110100011110",
+ "8=11010001110",
+ "9=1111010111",
+ ":=100100011",
+ ";=10000111101",
+ "<=00001011010110001111011001101",
+ "==00001011010110001111011001110",
+ ">=00001011010110001111011001111",
+ "?=1100110110110",
+ "@=1110001000010000",
+ "A=00001010",
+ "B=111101001",
+ "C=10010100",
+ "D=100001010",
+ "E=111000000",
+ "F=1110001100",
+ "G=100101100",
+ "H=1000011111",
+ "I=1111011111",
+ "J=1100010110",
+ "K=11110100011",
+ "L=001111101",
+ "M=100001101",
+ "N=100001011",
+ "O=1100101011",
+ "P=110100000",
+ "Q=00001011000",
+ "R=110010100",
+ "S=10110100",
+ "T=110101100",
+ "U=110100010011",
+ "V=1001000011",
+ "W=1101000110",
+ "X=1110001011001",
+ "Y=1100011110011",
+ "Z=1100010100110",
+ "[=00001011010110001111011010000",
+ "\\=00001011010110001111011010001",
+ "]=00001011010110001111011010010",
+ "^=0000101101011000100",
+ "_=00001011010110001111011010011",
+ "`=00001011010111",
+ "a=11111",
+ "b=11100001",
+ "c=111001",
+ "d=1011000",
+ "e=1010",
+ "f=0011011",
+ "g=000011",
+ "h=10110110",
+ "i=0001",
+ "j=110100010000",
+ "k=110001100",
+ "l=1111001",
+ "m=100010",
+ "n=10111",
+ "o=0010",
+ "p=100011",
+ "q=1110001001",
+ "r=11011",
+ "s=00000",
+ "t=11101",
+ "u=001110",
+ "v=1100111",
+ "w=001100110",
+ "x=11100011110",
+ "y=111101101",
+ "z=0011010",
+ "{=00001011010110001111011010100",
+ "|=00001011010110001111011010101",
+ "}=00001011010110001111011010110",
+ "~=00001011010110001111011010111",
+ " =00001011010110001111011011000",
+ " =000010110101100000",
+ " =00001011010110001111011011001",
+ " =00001011010110001111011011010",
+ " =00001011010110001111011011011",
+ " =00001011010110001111011011100",
+ " =00001011010110001111011011101",
+ " =00001011010110001111011011110",
+ " =00001011010110001111011011111",
+ " =11100010000100010",
+ " =000010110101100001",
+ " =00001011010110001111011100000",
+ " =00001011010110001111011100001",
+ " =00001011010110001111011100010",
+ " =00001011010110001111011100011",
+ " =00001011010110001111011100100",
+ " =00001011010110001111011100101",
+ " =00001011010110001111011100110",
+ " =00001011010110001111011100111",
+ " =00001011010110001110",
+ " =00001011010110001111011101000",
+ " =00001011010110001111011101001",
+ " =00001011010110001111011101010",
+ " =00001011010110001111011101011",
+ " =0000101101011000101",
+ " =00001011010110001111011101100",
+ " =00001011010110001111011101101",
+ " =00001011010110001111011101110",
+ " =00001011010110001111011101111",
+ " =00001011010110001111011110000",
+ " =00001011010110001111011110001",
+ " =00001011010110001111011110010",
+ " =00001011010110001111011110011",
+ " =00001011010110001111011110100",
+ "¡=00001011010110001111011110101",
+ "¢=00001011010110001111011110110",
+ "£=00001011010110001111011110111",
+ "¤=00001011010110001111011111000",
+ "¥=00001011010110001111011111001",
+ "¦=00001011010110001111011111010",
+ "§=00001011010110001111011111011",
+ "¨=00001011010110001111011111100",
+ "©=00001011010110001111011111101",
+ "ª=00001011010110001111011111110",
+ "«=00001011010110001111011111111",
+ "¬=0000101101011000111100000000",
+ "­=0000101101011000111100000001",
+ "®=0000101101011000111100000010",
+ "¯=0000101101011000111100000011",
+ "°=0000101101011000111100000100",
+ "±=0000101101011000111100000101",
+ "²=0000101101011000111100000110",
+ "³=0000101101011000111100000111",
+ "´=0000101101011000111100001000",
+ "µ=0000101101011000111100001001",
+ "¶=0000101101011000111100001010",
+ "·=0000101101011001",
+ "¸=0000101101011000111100001011",
+ "¹=0000101101011000111100001100",
+ "º=0000101101011000111100001101",
+ "»=0000101101011000111100001110",
+ "¼=0000101101011000111100001111",
+ "½=0000101101011000111100010000",
+ "¾=0000101101011000111100010001",
+ "¿=0000101101011000111100010010",
+ "À=0000101101011000111100010011",
+ "Á=0000101101011000111100010100",
+ "Â=0000101101011000111100010101",
+ "Ã=0000101101011000111100010110",
+ "Ä=0000101101011000111100010111",
+ "Å=0000101101011000111100011000",
+ "Æ=000010110101101",
+ "Ç=0000101101011000111100011001",
+ "È=0000101101011000111100011010",
+ "É=0000101101011000111100011011",
+ "Ê=0000101101011000111100011100",
+ "Ë=0000101101011000111100011101",
+ "Ì=0000101101011000111100011110",
+ "Í=0000101101011000111100011111",
+ "Î=0000101101011000111100100000",
+ "Ï=0000101101011000111100100001",
+ "Ð=0000101101011000111100100010",
+ "Ñ=0000101101011000111100100011",
+ "Ò=0000101101011000111100100100",
+ "Ó=0000101101011000111100100101",
+ "Ô=0000101101011000111100100110",
+ "Õ=0000101101011000111100100111",
+ "Ö=0000101101011000111100101000",
+ "×=0000101101011000111100101001",
+ "Ø=0000101101011000111100101010",
+ "Ù=0000101101011000111100101011",
+ "Ú=0000101101011000111100101100",
+ "Û=0000101101011000111100101101",
+ "Ü=0000101101011000111100101110",
+ "Ý=0000101101011000111100101111",
+ "Þ=0000101101011000111100110000",
+ "ß=0000101101011000111100110001",
+ "à=0000101101011000110",
+ "á=0000101101011000111100110010",
+ "â=0000101101011000111100110011",
+ "ã=0000101101011000111100110100",
+ "ä=0000101101011000111100110101",
+ "å=0000101101011000111100110110",
+ "æ=0000101101011000111100110111",
+ "ç=0000101101011000111100111000",
+ "è=0000101101011000111100111001",
+ "é=0000101101011000111100111010",
+ "ê=0000101101011000111100111011",
+ "ë=0000101101011000111100111100",
+ "ì=0000101101011000111100111101",
+ "í=0000101101011000111100111110",
+ "î=0000101101011000111100111111",
+ "ï=0000101101011000111101000000",
+ "ð=0000101101011000111101000001",
+ "ñ=0000101101011000111101000010",
+ "ò=0000101101011000111101000011",
+ "ó=0000101101011000111101000100",
+ "ô=0000101101011000111101000101",
+ "õ=0000101101011000111101000110",
+ "ö=0000101101011000111101000111",
+ "÷=0000101101011000111101001000",
+ "ø=0000101101011000111101001001",
+ "ù=0000101101011000111101001010",
+ "ú=0000101101011000111101001011",
+ "û=0000101101011000111101001100",
+ "ü=0000101101011000111101001101",
+ "ý=0000101101011000111101001110",
+ "þ=0000101101011000111101001111",
+ "ÿ=0000101101011000111101010000",
+ "(dur=100001111000",
+ "2001=001111100",
+ "2002=111000110101",
+ "Adulti=100001111001",
+ "Alle=1100110111",
+ "American=10110101100",
+ "Argentina=110010101011",
+ "Attualita'=110001000001",
+ "Bateman=10010111111",
+ "Bechis=1100010111011",
+ "Campionato=1101001111000",
+ "Carlos=1101000011101",
+ "Cartoon=11110111011",
+ "Club=10000110010",
+ "Commedia=100001100001",
+ "Con=10110101101",
+ "D'Alo'=1100100011111",
+ "Da=1001010111",
+ "Dal=1111010100011",
+ "Dalle=10010111110",
+ "Drammatico=111101111001",
+ "Durante=1101000111110",
+ "Echeverria=1100011100110",
+ "Emmanuelle=1100011100111",
+ "Enzo=1101000100010",
+ "Fares=00001011011",
+ "Figli=1100100011000",
+ "Film=1101011010",
+ "Fine=100001001100",
+ "Fiumi=00001011100",
+ "Francia=10000110001",
+ "Giallo=110001001000",
+ "Giovanni=1100011101000",
+ "Harron=10011110000",
+ "ITV=1101000100100",
+ "Il=0011001110",
+ "In=1001011011",
+ "Informazione=11110100001",
+ "Intrattenimento=1000010000",
+ "Italia=11100010001",
+ "Javier=1100011101001",
+ "Jean=10010101011",
+ "John=1111011100101",
+ "Kassovitz=00110000101",
+ "L'appassionante=00001011101",
+ "La=1001010110",
+ "Le=11000100111",
+ "Ma=1101001110",
+ "Magazine=100001110010",
+ "Mammuccari=1100011101010",
+ "Manhattan=10110010010",
+ "Marco=1110001011110",
+ "Mary=10011110110",
+ "Mathieu=00110000110",
+ "Michael=1101001111011",
+ "Momo=110010001011",
+ "Nadia=00001011110",
+ "News=110100111110",
+ "Notiziario=101100101110",
+ "Orario=1001000100",
+ "Patrick=10110010110",
+ "Paul=000010110011",
+ "Per=11000100110",
+ "Peter=1100101010101",
+ "Programmazione=1110001101001",
+ "Psycho=10011110111",
+ "Regia=110010000",
+ "Reno=00110000111",
+ "Rosa=1100011110101",
+ "Rubrica=1111011100100",
+ "Sandrelli=1100100010001",
+ "Seigner=1100011101011",
+ "Servizi=001100000110",
+ "Snow=100100001000",
+ "Sorvino=1100011110110",
+ "Stefania=1101011011010",
+ "Stream=111101000100",
+ "Street=10110101111",
+ "Streghe=1100011101100",
+ "TRAMA:=1100010111010",
+ "Teo=110001110010",
+ "USA=1101000101",
+ "Un=11110111101",
+ "Una=101100100010",
+ "Veronesi=1100011101101",
+ "Vincent=00110001001",
+ "Wall=11000100001",
+ "World=001100010110",
+ "XXX=10000110011",
+ "ad=1111010110",
+ "affidare=00110000100",
+ "ai=1001011110",
+ "al=0011110",
+ "alla=11010110111",
+ "alle=111101110101",
+ "amici=111000101110",
+ "ammazzare=10011110001",
+ "and=1111010101",
+ "anfiteatro=1100100011001",
+ "anni=10010101010",
+ "as=110011010",
+ "attraverso=1101011011001",
+ "aver=000010110100",
+ "bambina=1101000100011",
+ "banda=1110001011000",
+ "bello=10110101000",
+ "brani=1100100010010",
+ "broker=10011110010",
+ "business=000010110010",
+ "casa=101100100011",
+ "casi=10000111010",
+ "cassel=00001011111",
+ "cerca=11100010100",
+ "che=10010010",
+ "chilometri=00110001111",
+ "citta'=110001000101",
+ "come=110001011100",
+ "compagnia=1100110110001",
+ "con=11010010",
+ "conquista=1101000111111",
+ "contro=110001000100",
+ "crede=1110001111110",
+ "cui=001100111110",
+ "cultura=100001110001",
+ "curiosita'=001100010111",
+ "da=00110010",
+ "dai=1101000100101",
+ "dal=11110110000",
+ "dalla=100101101001",
+ "decidG266 : dedicato=0000101101011000111101010001",
+ "degli=110001000000",
+ "dei=0011000110",
+ "del=111100010",
+ "della=1011001010",
+ "delle=11000111000",
+ "destra=1100101010001",
+ "deve=1111010001011",
+ "di=100000",
+ "diabolici=1100100011010",
+ "dice=1100110110000",
+ "diretta=100100001011",
+ "distanza=00110000000",
+ "divide=10110010011",
+ "divisi=1100011101110",
+ "dolce=1101001111001",
+ "domani=1111010100010",
+ "due=1100011111",
+ "e'=110001101",
+ "ed=101101111",
+ "essere=1110001000000",
+ "esseri=1110001111101",
+ "eventiG=0000101101011000111101010010",
+ "fatti=001100111111",
+ "feste=10110101001",
+ "film=10000100011",
+ "gemelli=1110001000011",
+ "giorno=11110100000",
+ "giovane=11100000110",
+ "giovani=1111011110001",
+ "gli=100101110",
+ "grande=1110001011111",
+ "grandi=1111010001010",
+ "grigi'=1100100011011",
+ "ha=1100010101",
+ "il=11001011",
+ "imbattere=1100100011100",
+ "in=1101010",
+ "incinta=1100101010000",
+ "informazione=110001001001",
+ "inizio=1001010100",
+ "internazionale=100001110111",
+ "interviste=100100001001",
+ "la=11001100",
+ "lavoro=11010000110",
+ "le=11010111",
+ "levatrice=1100011101111",
+ "libro=1100011110100",
+ "lo=111100011",
+ "loro=11000101000",
+ "ma=10011111",
+ "maggiori=100001110110",
+ "malcapitati=10110010000",
+ "maschietto=1100011110000",
+ "mondo=11100010101",
+ "musica=111000001111",
+ "nato=111101110011",
+ "nel=11110111000",
+ "nella=1111010100000",
+ "nello=10000100100",
+ "news=10010110101",
+ "non=00110011110",
+ "nord=1100100011101",
+ "nuovi=001100000111",
+ "of=1011010101",
+ "ogni=100001110011",
+ "ore=1101000010",
+ "parte=1101011011011",
+ "per=00111111",
+ "piccola=1101001111010",
+ "piu'=1001111010",
+ "poliziotti=00110001110",
+ "porpora=00110000001",
+ "prima=1110001111100",
+ "produttore=1100011110111",
+ "programmazione=1110001101000",
+ "proprio=1101011011000",
+ "prossimo=1001000101",
+ "quattro=1111011000110",
+ "regime=1100011110001",
+ "ricco=10110101110",
+ "ricordi=1100101010100",
+ "rovine=1110001000001",
+ "salvare=1110000011100",
+ "scrittore=1100110110111",
+ "scrive=1101000011110",
+ "serie=1111011000111",
+ "servizi=100001110000",
+ "settimanale=1100010100111",
+ "si=11110000",
+ "singolari=00110001000",
+ "solo=110010001010",
+ "sono=11000100011",
+ "stesso=10000100010",
+ "storia=11100011011",
+ "streghe=1100100010000",
+ "su=1110000010",
+ "sua=10000100101",
+ "successo=100101101000",
+ "sui=110011011001",
+ "sulle=100100001010",
+ "suo=10000100111",
+ "suoi=1101000011100",
+ "tale=110010101001",
+ "tempo=111101100010",
+ "the=11110101001",
+ "timida=1100100011110",
+ "torturare=10011110011",
+ "tra=110100110",
+ "trasformarlo=1100011110010",
+ "trecento=00110000010",
+ "trovato=1101000011111",
+ "tutto=110011011010",
+ "ultimi=1100100010011",
+ "un=11001001",
+ "una=101101110",
+ "uno=111000101101",
+ "uomini=1111011110000",
+ "vedono=00110001010",
+ "vengono=100001001101",
+ "verso=100001100000",
+ "viaggio=110001010010",
+ "viene=1111010100001",
+ "vita=11000101111",
+ "vuole=1110001111111",
+ NULL
+};
+
+static const char *SkyUkDictionary[] = {
+ " =101010111000110000101001100",
+ " =101010111000110000101001101",
+ " =101010111000110000101001110",
+ " =101010111000110000101001111",
+ " =101010111000110000101010000",
+ " =101010111000110000101010001",
+ " =101010111000110000101010010",
+ " =101010111000110000101010011",
+ " =101010111000110000101010100",
+ " =0001000",
+ " =1110111",
+ " =101010111000110000101010101",
+ " =101010111000110000101010110",
+ " =101010111000110000101010111",
+ " =101010111000110000101011000",
+ " =101010111000110000101011001",
+ " =101010111000110000101011010",
+ " =101010111000110000101011011",
+ " =101010111000110000101011100",
+ " =101010111000110000101011101",
+ " =101010111000110000101011110",
+ " =101010111000110000101011111",
+ " =101010111000110000101100000",
+ " =101010111000110000101100001",
+ " =101010111000110000101100010",
+ " =101010111000110000101100011",
+ " =101010111000110000101100100",
+ " =101010111000110000101100101",
+ " =101010111000110000101100110",
+ " =101010111000110000101100111",
+ " =101010111000110000101101000",
+ " =101010111000110000101101001",
+ " =110",
+ "!=01000011000",
+ "\"=101010111000110000101101010",
+ "#=101010111000110000101101011",
+ "$=1010101110001101",
+ "%=101010111000110000101101100",
+ "&=10000011101",
+ "'=10000010",
+ "(=11101000101",
+ ")=1010101100",
+ "*=100010101110",
+ "+=101010111000110000101101101",
+ ",=1011000",
+ "-=10001011",
+ ".=1110110",
+ "/=00010100011110",
+ "0=111010010",
+ "1=101100111",
+ "2=1000101000",
+ "3=1000001111",
+ "4=0001010000",
+ "5=1110101000",
+ "6=1000101001",
+ "7=1000100010",
+ "8=10001010110",
+ "9=0100001101",
+ ":=11101000110",
+ ";=00010100010",
+ "<=1110100011111",
+ "==101010111000110000101101110",
+ ">=1110101001100",
+ "?=111010100111",
+ "@=101010111000110001",
+ "A=11100010",
+ "B=01000000",
+ "C=01000010",
+ "D=111000111",
+ "E=1110100000",
+ "F=101010100",
+ "G=100010000",
+ "H=101010101",
+ "I=1110100001",
+ "J=000101001",
+ "K=1110100111",
+ "L=100000110",
+ "M=10001001",
+ "N=111010111",
+ "O=010000010",
+ "P=00010101",
+ "Q=1000101010111",
+ "R=111010110",
+ "S=0001001",
+ "T=0001011",
+ "U=10101011101",
+ "V=11101010101",
+ "W=10110010",
+ "X=1110001101101111",
+ "Y=10101011110",
+ "Z=1110101010000",
+ "[=10101011100011001",
+ "\\=101010111000110000101101111",
+ "]=11100011011011100",
+ "^=101010111000110000101110000",
+ "_=101010111000110000101110001",
+ "`=11101010010",
+ "a=1001",
+ "b=1110000",
+ "c=111001",
+ "d=01001",
+ "e=1111",
+ "f=100001",
+ "g=100011",
+ "h=10111",
+ "i=0101",
+ "j=11100011010",
+ "k=1000000",
+ "l=10100",
+ "m=101011",
+ "n=0111",
+ "o=0011",
+ "p=000111",
+ "q=10101011011",
+ "r=0010",
+ "s=0000",
+ "t=0110",
+ "u=101101",
+ "v=1010100",
+ "w=000110",
+ "x=1110101011",
+ "y=010001",
+ "z=1011001100",
+ "{=101010111000110000101110010",
+ "|=101010111000110000101110011",
+ "}=101010111000110000101110100",
+ "~=101010111000110000101110101",
+ " =101010111000110000101110110",
+ " =101010111000110000101110111",
+ " =101010111000110000101111000",
+ " =101010111000110000101111001",
+ " =101010111000110000101111010",
+ " =101010111000110000101111011",
+ " =101010111000110000101111100",
+ " =101010111000110000101111101",
+ " =101010111000110000101111110",
+ " =101010111000110000101111111",
+ " =101010111000110000110000000",
+ " =101010111000110000110000001",
+ " =101010111000110000110000010",
+ " =101010111000110000110000011",
+ " =101010111000110000110000100",
+ " =101010111000110000110000101",
+ " =101010111000110000110000110",
+ " =101010111000110000110000111",
+ " =101010111000110000110001000",
+ " =101010111000110000110001001",
+ " =101010111000110000110001010",
+ " =101010111000110000110001011",
+ " =101010111000110000110001100",
+ " =101010111000110000110001101",
+ " =101010111000110000110001110",
+ " =101010111000110000110001111",
+ " =101010111000110000110010000",
+ " =101010111000110000110010001",
+ " =101010111000110000110010010",
+ " =11100011011011101",
+ " =101010111000110000110010011",
+ " =101010111000110000110010100",
+ " =101010111000110000110010101",
+ " =101010111000110000110010110",
+ "¡=101010111000110000110010111",
+ "¢=101010111000110000110011000",
+ "£=101010111000110000110011001",
+ "¤=101010111000110000110011010",
+ "¥=101010111000110000110011011",
+ "¦=101010111000110000110011100",
+ "§=101010111000110000110011101",
+ "¨=101010111000110000110011110",
+ "©=101010111000110000110011111",
+ "ª=101010111000110000110100000",
+ "«=101010111000110000110100001",
+ "¬=101010111000110000110100010",
+ "­=101010111000110000110100011",
+ "®=101010111000110000110100100",
+ "¯=101010111000110000110100101",
+ "°=101010111000110000110100110",
+ "±=101010111000110000110100111",
+ "²=101010111000110000110101000",
+ "³=101010111000110000110101001",
+ "´=101010111000110000110101010",
+ "µ=101010111000110000110101011",
+ "¶=101010111000110000110101100",
+ "·=101010111000110000110101101",
+ "¸=101010111000110000110101110",
+ "¹=101010111000110000110101111",
+ "º=101010111000110000110110000",
+ "»=101010111000110000110110001",
+ "¼=101010111000110000110110010",
+ "½=101010111000110000110110011",
+ "¾=101010111000110000110110100",
+ "¿=101010111000110000110110101",
+ "À=101010111000110000110110110",
+ "Á=101010111000110000110110111",
+ "Â=101010111000110000110111000",
+ "Ã=101010111000110000110111001",
+ "Ä=101010111000110000110111010",
+ "Å=101010111000110000110111011",
+ "Æ=101010111000110000110111100",
+ "Ç=101010111000110000110111101",
+ "È=101010111000110000110111110",
+ "É=101010111000110000110111111",
+ "Ê=101010111000110000111000000",
+ "Ë=101010111000110000111000001",
+ "Ì=101010111000110000111000010",
+ "Í=101010111000110000111000011",
+ "Î=101010111000110000111000100",
+ "Ï=101010111000110000111000101",
+ "Ð=101010111000110000111000110",
+ "Ñ=101010111000110000111000111",
+ "Ò=101010111000110000111001000",
+ "Ó=101010111000110000111001001",
+ "Ô=101010111000110000111001010",
+ "Õ=101010111000110000111001011",
+ "Ö=101010111000110000111001100",
+ "×=101010111000110000111001101",
+ "Ø=101010111000110000111001110",
+ "Ù=101010111000110000111001111",
+ "Ú=101010111000110000111010000",
+ "Û=101010111000110000111010001",
+ "Ü=101010111000110000111010010",
+ "Ý=101010111000110000111010011",
+ "Þ=101010111000110000111010100",
+ "ß=101010111000110000111010101",
+ "à=101010111000110000111010110",
+ "á=101010111000110000111010111",
+ "â=101010111000110000111011000",
+ "ã=101010111000110000111011001",
+ "ä=101010111000110000111011010",
+ "å=101010111000110000111011011",
+ "æ=101010111000110000111011100",
+ "ç=101010111000110000111011101",
+ "è=101010111000110000111011110",
+ "é=101010111000110000111011111",
+ "ê=101010111000110000111100000",
+ "ë=101010111000110000111100001",
+ "ì=101010111000110000111100010",
+ "í=101010111000110000111100011",
+ "î=101010111000110000111100100",
+ "ï=101010111000110000111100101",
+ "ð=101010111000110000111100110",
+ "ñ=101010111000110000111100111",
+ "ò=101010111000110000111101000",
+ "ó=101010111000110000111101001",
+ "ô=101010111000110000111101010",
+ "õ=101010111000110000111101011",
+ "ö=101010111000110000111101100",
+ "÷=101010111000110000111101101",
+ "ø=101010111000110000111101110",
+ "ù=101010111000110000111101111",
+ "ú=101010111000110000111110000",
+ "û=101010111000110000111110001",
+ "ü=101010111000110000111110010",
+ "ý=101010111000110000111110011",
+ "þ=101010111000110000111110100",
+ "ÿ=101010111000110000111110101",
+ "(Including =10101011111110",
+ "(New Series)=11101000100010",
+ "(Part =1110100011101",
+ "(Repeat)=1110100110",
+ "(Stereo)=010000111",
+ "(Stereo) (Teletext)=010000011",
+ "(Teletext)=1110001100",
+ "(Widescreen)=100000111001110",
+ "Action=101010111000111",
+ "Adventures=10110011011111",
+ "America=0100001100100",
+ "Animated=111010100110111",
+ "Australia=0100001100101",
+ "Away=11101010100010",
+ "BBC=10101011111111",
+ "Baby=11100011011000",
+ "Best=11101010100011",
+ "Big=10110011011000",
+ "Bill=1000101011111",
+ "Black=1000101010000",
+ "Blue=1011001101110",
+ "Breakfast=000101000110",
+ "Britain=1010101111100",
+ "British=1110100011100",
+ "Business=0100001100110",
+ "Call=1010101111101",
+ "Cartoon=10101011100000",
+ "Channel=10101011100001",
+ "Children=11101010100111",
+ "Clock=11100011011001",
+ "Comedy=11101000100011",
+ "Cook=111010101001010",
+ "Country=111010100110110",
+ "Directed by =101010110100",
+ "Drama=0100001100111",
+ "East=1000101010001",
+ "Education=100000111001111",
+ "English=00010100011111",
+ "Europe=0001010001110",
+ "Extra=10110011011001",
+ "Final=10101011100010",
+ "Financial=111000110110100",
+ "For=111000110111",
+ "French=11101000111101",
+ "From=1000101010010",
+ "George=1010101111110",
+ "Get=1000100011010",
+ "Girls=10001000110110",
+ "Golden=10001000110111",
+ "Golf=111010101001011",
+ "Good=1010101101010",
+ "Great=11101000100100",
+ "Hampshire=111010101001100",
+ "Headlines=1000101010011",
+ "Hear=11101010011010",
+ "Hill=1000001110000",
+ "Hollywood=111000110110101",
+ "Home=1000101010100",
+ "Hour=11101000100101",
+ "House=1000001110010",
+ "How=1010101101011",
+ "ITN=11101010100100",
+ "Important=111010101001101",
+ "Including=1000101011110",
+ "International=11101000100110",
+ "John=10001000111",
+ "Last=11101000100111",
+ "Late=10000011100110",
+ "Learn=10001010101100",
+ "Little=10001010101101",
+ "Live=1110100010000",
+ "London=11101000111100",
+ "Look=10110011011110",
+ "Lunch=111000110110110",
+ "Man=1000101010101",
+ "Mark=1000001110001",
+ "Meridian=101010111001",
+ "Michael=1011001101101",
+ "Minutes=101010111000110000111110110",
+ "More=101010111000110000111110111",
+ "Morning=101010111000110000111111000",
+ "Murder=101010111000110000111111001",
+ "Nation=101010111000110000111111010",
+ "Neighbours=101010111000110000111111011",
+ "New=101010111000110000111111100",
+ "News & Weather=101010111000110000111111101",
+ "News And Weather=101010111000110000111111110",
+ "Paul=101010111000110000111111111",
+ "Plus=10101011100011000000000000",
+ "Prayer=10101011100011000000000001",
+ "Present=10101011100011000000000010",
+ "Presented by=10101011100011000000000011",
+ "Quiz=10101011100011000000000100",
+ "Regional=10101011100011000000000101",
+ "Represent=10101011100011000000000110",
+ "Resource=10101011100011000000000111",
+ "Review=10101011100011000000001000",
+ "Richard=10101011100011000000001001",
+ "School=10101011100011000000001010",
+ "Series=10101011100011000000001011",
+ "Service=10101011100011000000001100",
+ "Show=10101011100011000000001101",
+ "Smith=10101011100011000000001110",
+ "South=10101011100011000000001111",
+ "Sport=10101011100011000000010000",
+ "Star=10101011100011000000010001",
+ "Street=10101011100011000000010010",
+ "TV=10101011100011000000010011",
+ "Teaching=10101011100011000000010100",
+ "The=10101011100011000000010101",
+ "Today=10101011100011000000010110",
+ "Tonight=10101011100011000000010111",
+ "Weather=10101011100011000000011000",
+ "Western=10101011100011000000011001",
+ "Westminster=10101011100011000000011010",
+ "William=10101011100011000000011011",
+ "With=10101011100011000000011100",
+ "World=10101011100011000000011101",
+ "about=10101011100011000000011110",
+ "action-packed=10101011100011000000011111",
+ "adventure=10101011100011000000100000",
+ "afternoon=10101011100011000000100001",
+ "alert=10101011100011000000100010",
+ "all-star cast=10101011100011000000100011",
+ "and=10101011100011000000100100",
+ "anywhere=10101011100011000000100101",
+ "audience=10101011100011000000100110",
+ "based=10101011100011000000100111",
+ "book=10101011100011000000101000",
+ "business=10101011100011000000101001",
+ "but=10101011100011000000101010",
+ "celebrity=10101011100011000000101011",
+ "chance=10101011100011000000101100",
+ "chat=10101011100011000000101101",
+ "child=10101011100011000000101110",
+ "classic=10101011100011000000101111",
+ "consumer=10101011100011000000110000",
+ "contestants=10101011100011000000110001",
+ "continues=10101011100011000000110010",
+ "controversial=10101011100011000000110011",
+ "dealer=10101011100011000000110100",
+ "deliver=10101011100011000000110101",
+ "discuss=10101011100011000000110110",
+ "document=10101011100011000000110111",
+ "drama=10101011100011000000111000",
+ "edition=10101011100011000000111001",
+ "education=10101011100011000000111010",
+ "events=10101011100011000000111011",
+ "every=10101011100011000000111100",
+ "excellent=10101011100011000000111101",
+ "eyed=10101011100011000000111110",
+ "family=10101011100011000000111111",
+ "famous=10101011100011000001000000",
+ "featur=10101011100011000001000001",
+ "film=10101011100011000001000010",
+ "football=10101011100011000001000011",
+ "for=10101011100011000001000100",
+ "from=10101011100011000001000101",
+ "general knowledge=10101011100011000001000110",
+ "get=10101011100011000001000111",
+ "guest=10101011100011000001001000",
+ "guests=10101011100011000001001001",
+ "has=10101011100011000001001010",
+ "have=10101011100011000001001011",
+ "headline=10101011100011000001001100",
+ "her=10101011100011000001001101",
+ "his=10101011100011000001001110",
+ "home and abroad=10101011100011000001001111",
+ "host=10101011100011000001010000",
+ "how=10101011100011000001010001",
+ "in=10101011100011000001010010",
+ "including=10101011100011000001010011",
+ "international=10101011100011000001010100",
+ "interview=10101011100011000001010101",
+ "introduce=10101011100011000001010110",
+ "investigat=10101011100011000001010111",
+ "invites=10101011100011000001011000",
+ "issue=10101011100011000001011001",
+ "knowledge=10101011100011000001011010",
+ "life=10101011100011000001011011",
+ "live=10101011100011000001011100",
+ "look=10101011100011000001011101",
+ "magazine=10101011100011000001011110",
+ "meets =10101011100011000001011111",
+ "morning=10101011100011000001100000",
+ "morning magazine=10101011100011000001100001",
+ "music=10101011100011000001100010",
+ "near=10101011100011000001100011",
+ "network=10101011100011000001100100",
+ "new=10101011100011000001100101",
+ "new series=10101011100011000001100110",
+ "night=10101011100011000001100111",
+ "of=10101011100011000001101000",
+ "on=10101011100011000001101001",
+ "onight=10101011100011000001101010",
+ "out=10101011100011000001101011",
+ "over=10101011100011000001101100",
+ "part=10101011100011000001101101",
+ "people=10101011100011000001101110",
+ "phone=10101011100011000001101111",
+ "poli=10101011100011000001110000",
+ "police=10101011100011000001110001",
+ "political chat show=10101011100011000001110010",
+ "popular=10101011100011000001110011",
+ "presented by =10101011100011000001110100",
+ "programm=10101011100011000001110101",
+ "quiz=10101011100011000001110110",
+ "reconstruction=10101011100011000001110111",
+ "report=10101011100011000001111000",
+ "review=10101011100011000001111001",
+ "school=10101011100011000001111010",
+ "series=10101011100011000001111011",
+ "short =10101011100011000001111100",
+ "show=10101011100011000001111101",
+ "some=10101011100011000001111110",
+ "starring=10101011100011000001111111",
+ "stars=10101011100011000010000000",
+ "stories=10101011100011000010000001",
+ "story=10101011100011000010000010",
+ "studio=10101011100011000010000011",
+ "surprise=10101011100011000010000100",
+ "teller=10101011100011000010000101",
+ "that=10101011100011000010000110",
+ "the=10101011100011000010000111",
+ "their=10101011100011000010001000",
+ "them=10101011100011000010001001",
+ "they=10101011100011000010001010",
+ "this=10101011100011000010001011",
+ "through=10101011100011000010001100",
+ "to=10101011100011000010001101",
+ "top=10101011100011000010001110",
+ "trans=10101011100011000010001111",
+ "under=10101011100011000010010000",
+ "up=10101011100011000010010001",
+ "very=10101011100011000010010010",
+ "video=10101011100011000010010011",
+ "view=10101011100011000010010100",
+ "vintage=10101011100011000010010101",
+ "visit=10101011100011000010010110",
+ "was=10101011100011000010010111",
+ "way=10101011100011000010011000",
+ "week=10101011100011000010011001",
+ "well=10101011100011000010011010",
+ "what=10101011100011000010011011",
+ "when=10101011100011000010011100",
+ "which=10101011100011000010011101",
+ "while=10101011100011000010011110",
+ "who=10101011100011000010011111",
+ "will=10101011100011000010100000",
+ "win=10101011100011000010100001",
+ "with=10101011100011000010100010",
+ "words=10101011100011000010100011",
+ "world=10101011100011000010100100",
+ "written=10101011100011000010100101",
+ "year=100010001100",
+ "you=10110011010",
+ NULL
+};
+
+static const char *SkyItThemes[] = {
+ "Non Definito", // 000 00000
+ NULL, // 000 00001
+ NULL, // 000 00010
+ NULL, // 000 00011
+ NULL, // 000 00100
+ NULL, // 000 00101
+ NULL, // 000 00110
+ NULL, // 000 00111
+ NULL, // 000 01000
+ NULL, // 000 01001
+ NULL, // 000 01010
+ NULL, // 000 01011
+ NULL, // 000 01100
+ NULL, // 000 01101
+ NULL, // 000 01110
+ NULL, // 000 01111
+ NULL, // 000 10000
+ NULL, // 000 10001
+ NULL, // 000 10010
+ NULL, // 000 10011
+ NULL, // 000 10100
+ NULL, // 000 10101
+ NULL, // 000 10110
+ NULL, // 000 10111
+ NULL, // 000 11000
+ NULL, // 000 11001
+ NULL, // 000 11010
+ NULL, // 000 11011
+ NULL, // 000 11100
+ NULL, // 000 11101
+ NULL, // 000 11110
+ NULL, // 000 11111
+ "Intrattenimento", // 001 00000
+ "Intrattenimento - Fiction", // 001 00001
+ "Intrattenimento - Sit Com", // 001 00010
+ "Intrattenimento - Show", // 001 00011
+ "Intrattenimento - Telefilm", // 001 00100
+ "Intrattenimento - Soap Opera", // 001 00101
+ "Intrattenimento - Telenovela", // 001 00110
+ "Intrattenimento - Fantascienza", // 001 00111
+ "Intrattenimento - Animazione", // 001 01000
+ "Intrattenimento - Giallo", // 001 01001
+ "Intrattenimento - Drammatico", // 001 01010
+ "Intrattenimento - Romantico", // 001 01011
+ "Intrattenimento - Miniserie", // 001 01100
+ "Intrattenimento - Spettacolo", // 001 01101
+ "Intrattenimento - Quiz", // 001 01110
+ "Intrattenimento - Talk Show", // 001 01111
+ "Intrattenimento - Varietà", // 001 10000
+ "Intrattenimento - Festival", // 001 10001
+ "Intrattenimento - Teatro", // 001 10010
+ "Intrattenimento - Gioco", // 001 10011
+ NULL, // 001 10100
+ NULL, // 001 10101
+ NULL, // 001 10110
+ NULL, // 001 10111
+ NULL, // 001 11000
+ NULL, // 001 11001
+ NULL, // 001 11010
+ NULL, // 001 11011
+ NULL, // 001 11100
+ NULL, // 001 11101
+ NULL, // 001 11110
+ NULL, // 001 11111
+ "Sport", // 010 00000
+ "Sport - Calcio", // 010 00001
+ "Sport - Tennis", // 010 00010
+ "Sport - Motori", // 010 00011
+ "Sport - Altri", // 010 00100
+ "Sport - Baseball", // 010 00101
+ "Sport - Ciclismo", // 010 00110
+ "Sport - Rugby", // 010 00111
+ "Sport - Basket", // 010 01000
+ "Sport - Boxe", // 010 01001
+ "Sport - Atletica", // 010 01010
+ "Sport - Football USA", // 010 01011
+ "Sport - Hockey", // 010 01100
+ "Sport - Sci", // 010 01101
+ "Sport - Equestri", // 010 01110
+ "Sport - Golf", // 010 01111
+ "Sport - Nuoto", // 010 10000
+ "Sport - Wrestling", // 010 10001
+ NULL, // 010 10010
+ NULL, // 010 10011
+ NULL, // 010 10100
+ NULL, // 010 10101
+ NULL, // 010 10110
+ NULL, // 010 10111
+ NULL, // 010 11000
+ NULL, // 010 11001
+ NULL, // 010 11010
+ NULL, // 010 11011
+ NULL, // 010 11100
+ NULL, // 010 11101
+ NULL, // 010 11110
+ NULL, // 010 11111
+ "Film", // 011 00000
+ "Film - Drammatico", // 011 00001
+ "Film - Commedia", // 011 00010
+ "Film - Romantico", // 011 00011
+ "Film - Azione", // 011 00100
+ "Film - Fantascienza", // 011 00101
+ "Film - Western", // 011 00110
+ "Film - Comico", // 011 00111
+ "Film - Fantastico", // 011 01000
+ "Film - Avventura", // 011 01001
+ "Film - Poliziesco", // 011 01010
+ "Film - Guerra", // 011 01011
+ "Film - Horror", // 011 01100
+ "Film - Animazione", // 011 01101
+ "Film - Thriller", // 011 01110
+ "Film - Musicale", // 011 01111
+ "Film - Corto", // 011 10000
+ "Film - Cortometraggio", // 011 10001
+ NULL, // 011 10010
+ NULL, // 011 10011
+ NULL, // 011 10100
+ NULL, // 011 10101
+ NULL, // 011 10110
+ NULL, // 011 10111
+ NULL, // 011 11000
+ NULL, // 011 11001
+ NULL, // 011 11010
+ NULL, // 011 11011
+ NULL, // 011 11100
+ NULL, // 011 11101
+ NULL, // 011 11110
+ NULL, // 011 11111
+ "Mondo e Tendenze", // 100 00000
+ "Mondo e Tendenze - Natura", // 100 00001
+ "Mondo e Tendenze - Arte e Cultura", // 100 00010
+ "Mondo e Tendenze - Lifestyle", // 100 00011
+ "Mondo e Tendenze - Viaggi", // 100 00100
+ "Mondo e Tendenze - Documentario", // 100 00101
+ "Mondo e Tendenze - Società", // 100 00110
+ "Mondo e Tendenze - Scienza", // 100 00111
+ "Mondo e Tendenze - Storia", // 100 01000
+ "Mondo e Tendenze - Sport", // 100 01001
+ "Mondo e Tendenze - Pesca", // 100 01010
+ "Mondo e Tendenze - Popoli", // 100 01011
+ "Mondo e Tendenze - Cinema", // 100 01100
+ "Mondo e Tendenze - Musica", // 100 01101
+ "Mondo e Tendenze - Hobby", // 100 01110
+ "Mondo e Tendenze - Caccia", // 100 01111
+ "Mondo e Tendenze - Reportage", // 100 10000
+ "Mondo e Tendenze - Magazine", // 100 10001
+ "Mondo e Tendenze - Magazine Cultura", // 100 10010
+ "Mondo e Tendenze - Magazine Scienza", // 100 10011
+ "Mondo e Tendenze - Politica", // 100 10100
+ "Mondo e Tendenze - Magazine Cinema", // 100 10101
+ "Mondo e Tendenze - Magazine Sport", // 100 10110
+ "Mondo e Tendenze - Attualità", // 100 10111
+ "Mondo e Tendenze - Moda", // 100 11000
+ "Mondo e Tendenze - Economia", // 100 11001
+ "Mondo e Tendenze - Magazine Caccia e Pesca", // 100 11010
+ "Mondo e Tendenze - Magazine Viaggi", // 100 11011
+ "Mondo e Tendenze - Magazine Natura", // 100 11100
+ "Mondo e Tendenze - Magazine Musica", // 100 11101
+ "Mondo e Tendenze - Religione", // 100 11110
+ "Mondo e Tendenze - Televendita", // 100 11111
+ "Informazione", // 101 00000
+ "Informazione - Notiziario", // 101 00001
+ "Informazione - Sport", // 101 00010
+ "Informazione - Economia", // 101 00011
+ NULL, // 101 00100
+ NULL, // 101 00101
+ NULL, // 101 00110
+ NULL, // 101 00111
+ NULL, // 101 01000
+ NULL, // 101 01001
+ NULL, // 101 01010
+ NULL, // 101 01011
+ NULL, // 101 01100
+ NULL, // 101 01101
+ NULL, // 101 01110
+ NULL, // 101 01111
+ NULL, // 101 10000
+ NULL, // 101 10001
+ NULL, // 101 10010
+ NULL, // 101 10011
+ NULL, // 101 10100
+ NULL, // 101 10101
+ NULL, // 101 10110
+ NULL, // 101 10111
+ NULL, // 101 11000
+ NULL, // 101 11001
+ NULL, // 101 11010
+ NULL, // 101 11011
+ NULL, // 101 11100
+ NULL, // 101 11101
+ NULL, // 101 11110
+ NULL, // 101 11111
+ "Ragazzi e Musica", // 110 00000
+ "Ragazzi e Musica - Bambini", // 110 00001
+ "Ragazzi e Musica - Ragazzi", // 110 00010
+ "Ragazzi e Musica - Cartoni Animati", // 110 00011
+ "Ragazzi e Musica - Musica", // 110 00100
+ "Ragazzi e Musica - Film Animazione", // 110 00101
+ "Ragazzi e Musica - Film", // 110 00110
+ "Ragazzi e Musica - Telefilm", // 110 00111
+ "Ragazzi e Musica - Magazine", // 110 01000
+ NULL, // 110 01001
+ NULL, // 110 01010
+ NULL, // 110 01011
+ NULL, // 110 01100
+ NULL, // 110 01101
+ NULL, // 110 01110
+ NULL, // 110 01111
+ NULL, // 110 10000
+ NULL, // 110 10001
+ NULL, // 110 10010
+ NULL, // 110 10011
+ "Ragazzi e Musica - Danza", // 110 10100
+ NULL, // 110 10101
+ NULL, // 110 10110
+ NULL, // 110 10111
+ NULL, // 110 11000
+ NULL, // 110 11001
+ NULL, // 110 11010
+ NULL, // 110 11011
+ NULL, // 110 11100
+ NULL, // 110 11101
+ NULL, // 110 11110
+ NULL, // 110 11111
+ "Altri Programmi", // 111 00000
+ "Altri Programmi - Educational", // 111 00001
+ "Altri Programmi - Regionale", // 111 00010
+ "Altri Programmi - Shopping", // 111 00011
+ NULL, // 111 00100
+ "Altri Programmi - Inizio e Fine Trasmissioni", // 111 00101
+ "Altri Programmi - Eventi Speciali", // 111 00110
+ "Altri Programmi - Film per Adulti", // 111 00111
+ NULL, // 111 01000
+ NULL, // 111 01001
+ NULL, // 111 01010
+ NULL, // 111 01011
+ NULL, // 111 01100
+ NULL, // 111 01101
+ NULL, // 111 01110
+ NULL, // 111 01111
+ NULL, // 111 10000
+ NULL, // 111 10001
+ NULL, // 111 10010
+ NULL, // 111 10011
+ NULL, // 111 10100
+ NULL, // 111 10101
+ NULL, // 111 10110
+ NULL, // 111 10111
+ NULL, // 111 11000
+ NULL, // 111 11001
+ NULL, // 111 11010
+ NULL, // 111 11011
+ NULL, // 111 11100
+ NULL, // 111 11101
+ NULL, // 111 11110
+ NULL, // 111 11111
+};
+
+static const char *SkyUkThemes[] = {
+ "No Category", // 000 00000
+ NULL, // 000 00001
+ NULL, // 000 00010
+ NULL, // 000 00011
+ NULL, // 000 00100
+ NULL, // 000 00101
+ NULL, // 000 00110
+ NULL, // 000 00111
+ NULL, // 000 01000
+ NULL, // 000 01001
+ NULL, // 000 01010
+ NULL, // 000 01011
+ NULL, // 000 01100
+ NULL, // 000 01101
+ NULL, // 000 01110
+ NULL, // 000 01111
+ NULL, // 000 10000
+ NULL, // 000 10001
+ NULL, // 000 10010
+ NULL, // 000 10011
+ NULL, // 000 10100
+ NULL, // 000 10101
+ NULL, // 000 10110
+ NULL, // 000 10111
+ NULL, // 000 11000
+ NULL, // 000 11001
+ NULL, // 000 11010
+ NULL, // 000 11011
+ NULL, // 000 11100
+ NULL, // 000 11101
+ NULL, // 000 11110
+ NULL, // 000 11111
+ NULL, // 001 00000
+ NULL, // 001 00001
+ NULL, // 001 00010
+ "Shopping", // 001 00011
+ NULL, // 001 00100
+ NULL, // 001 00101
+ NULL, // 001 00110
+ NULL, // 001 00111
+ NULL, // 001 01000
+ NULL, // 001 01001
+ NULL, // 001 01010
+ NULL, // 001 01011
+ NULL, // 001 01100
+ NULL, // 001 01101
+ NULL, // 001 01110
+ NULL, // 001 01111
+ NULL, // 001 10000
+ NULL, // 001 10001
+ NULL, // 001 10010
+ NULL, // 001 10011
+ NULL, // 001 10100
+ NULL, // 001 10101
+ NULL, // 001 10110
+ NULL, // 001 10111
+ NULL, // 001 11000
+ NULL, // 001 11001
+ NULL, // 001 11010
+ NULL, // 001 11011
+ NULL, // 001 11100
+ NULL, // 001 11101
+ NULL, // 001 11110
+ NULL, // 001 11111
+ "Children", // 010 00000
+ "Children - Cartoons", // 010 00001
+ "Children - Comedy", // 010 00010
+ "Children - Drama", // 010 00011
+ "Children - Educational", // 010 00100
+ "Children - Under 5", // 010 00101
+ "Children - Factual", // 010 00110
+ "Children - Magazine", // 010 00111
+ NULL, // 010 01000
+ NULL, // 010 01001
+ NULL, // 010 01010
+ NULL, // 010 01011
+ NULL, // 010 01100
+ NULL, // 010 01101
+ NULL, // 010 01110
+ NULL, // 010 01111
+ NULL, // 010 10000
+ NULL, // 010 10001
+ NULL, // 010 10010
+ NULL, // 010 10011
+ NULL, // 010 10100
+ NULL, // 010 10101
+ NULL, // 010 10110
+ NULL, // 010 10111
+ NULL, // 010 11000
+ NULL, // 010 11001
+ NULL, // 010 11010
+ NULL, // 010 11011
+ NULL, // 010 11100
+ NULL, // 010 11101
+ NULL, // 010 11110
+ NULL, // 010 11111
+ "Entertainment", // 011 00000
+ "Entertainment - Action", // 011 00001
+ "Entertainment - Comedy", // 011 00010
+ "Entertainment - Detective", // 011 00011
+ "Entertainment - Drama", // 011 00100
+ "Entertainment - Game Show", // 011 00101
+ "Entertainment - Sci-FI", // 011 00110
+ "Entertainment - Soap", // 011 00111
+ "Entertainment - Animation", // 011 01000
+ "Entertainment - Chat Show", // 011 01001
+ "Entertainment - Cooking", // 011 01010
+ "Entertainment - Factual", // 011 01011
+ "Entertainment - Fashion", // 011 01100
+ "Entertainment - Gardening", // 011 01101
+ "Entertainment - Travel", // 011 01110
+ "Entertainment - Technology", // 011 01111
+ "Entertainment - Arts", // 011 10000
+ "Entertainment - Lifestyle", // 011 10001
+ "Entertainment - Home", // 011 10010
+ "Entertainment - Magazine", // 011 10011
+ "Entertainment - Medical", // 011 10100
+ "Entertainment - Review", // 011 10101
+ "Entertainment - Antiques", // 011 10110
+ "Entertainment - Motors", // 011 10111
+ "Entertainment - Art&Lit", // 011 11000
+ "Entertainment - Ballet", // 011 11001
+ "Entertainment - Opera", // 011 11010
+ NULL, // 011 11011
+ NULL, // 011 11100
+ NULL, // 011 11101
+ NULL, // 011 11110
+ NULL, // 011 11111
+ "Music", // 100 00000
+ "Music - Classical ", // 100 00001
+ "Music - Folk and Country", // 100 00010
+ "Music - National Music", // 100 00011
+ "Music - Jazz", // 100 00100
+ "Music - Opera", // 100 00101
+ "Music - Rock&Pop", // 100 00110
+ "Music - Alternative Music", // 100 00111
+ "Music - Events", // 100 01000
+ "Music - Club and Dance", // 100 01001
+ "Music - Hip Hop", // 100 01010
+ "Music - Soul/R&B", // 100 01011
+ "Music - Dance", // 100 01100
+ NULL, // 100 01101
+ NULL, // 100 01110
+ NULL, // 100 01111
+ "Music - Features", // 100 10000
+ NULL, // 100 10001
+ NULL, // 100 10010
+ NULL, // 100 10011
+ NULL, // 100 10100
+ "Music - Lifestyle", // 100 10101
+ "Music - News and Weather", // 100 10110
+ "Music - Easy Listening", // 100 10111
+ "Music - Discussion", // 100 11000
+ "Music - Entertainment", // 100 11001
+ "Music - Religious", // 100 11010
+ NULL, // 100 11011
+ NULL, // 100 11100
+ NULL, // 100 11101
+ NULL, // 100 11110
+ NULL, // 100 11111
+ "News & Documentaries", // 101 00000
+ "News & Documentaries - Business", // 101 00001
+ "News & Documentaries - World Cultures", // 101 00010
+ "News & Documentaries - Adventure", // 101 00011
+ "News & Documentaries - Biography", // 101 00100
+ "News & Documentaries - Educational", // 101 00101
+ "News & Documentaries - Feature", // 101 00110
+ "News & Documentaries - Politics", // 101 00111
+ "News & Documentaries - News", // 101 01000
+ "News & Documentaries - Nature", // 101 01001
+ "News & Documentaries - Religious", // 101 01010
+ "News & Documentaries - Science", // 101 01011
+ "News & Documentaries - Showbiz", // 101 01100
+ "News & Documentaries - War Documentary", // 101 01101
+ "News & Documentaries - Historical", // 101 01110
+ "News & Documentaries - Ancient", // 101 01111
+ "News & Documentaries - Transport", // 101 10000
+ "News & Documentaries - Docudrama", // 101 10001
+ "News & Documentaries - World Affairs", // 101 10010
+ NULL, // 101 10011
+ NULL, // 101 10100
+ NULL, // 101 10101
+ NULL, // 101 10110
+ NULL, // 101 10111
+ NULL, // 101 11000
+ NULL, // 101 11001
+ NULL, // 101 11010
+ NULL, // 101 11011
+ NULL, // 101 11100
+ NULL, // 101 11101
+ NULL, // 101 11110
+ NULL, // 101 11111
+ "Movie", // 110 00000
+ "Movie - Action", // 110 00001
+ "Movie - Animation", // 110 00010
+ NULL, // 110 00011
+ "Movie - Comedy", // 110 00100
+ "Movie - Family", // 110 00101
+ "Movie - Drama", // 110 00110
+ NULL, // 110 00111
+ "Movie - Sci-Fi", // 110 01000
+ "Movie - Thriller", // 110 01001
+ "Movie - Horror", // 110 01010
+ "Movie - Romance", // 110 01011
+ "Movie - Musical", // 110 01100
+ "Movie - Mystery", // 110 01101
+ "Movie - Western", // 110 01110
+ "Movie - Factual", // 110 01111
+ "Movie - Fantasy", // 110 10000
+ "Movie - Erotic", // 110 10001
+ "Movie - Adventure", // 110 10010
+ NULL, // 110 10011
+ NULL, // 110 10100
+ NULL, // 110 10101
+ NULL, // 110 10110
+ NULL, // 110 10111
+ NULL, // 110 11000
+ NULL, // 110 11001
+ NULL, // 110 11010
+ NULL, // 110 11011
+ NULL, // 110 11100
+ NULL, // 110 11101
+ NULL, // 110 11110
+ NULL, // 110 11111
+ "Sports - Other", // 111 00000
+ "Sports - American Football", // 111 00001
+ "Sports - Athletics", // 111 00010
+ "Sports - Baseball", // 111 00011
+ "Sports - Basketball", // 111 00100
+ "Sports - Boxing", // 111 00101
+ "Sports - Cricket", // 111 00110
+ "Sports - Fishing", // 111 00111
+ "Sports - Football", // 111 01000
+ "Sports - Golf", // 111 01001
+ "Sports - Ice Hockey", // 111 01010
+ "Sports - Motor Sport", // 111 01011
+ "Sports - Racing", // 111 01100
+ "Sports - Rugby", // 111 01101
+ "Sports - Equestrian", // 111 01110
+ "Sports - Winter Sports", // 111 01111
+ "Sports - Snooker / Pool", // 111 10000
+ "Sports - Tennis", // 111 10001
+ "Sports - Wrestling", // 111 10010
+ "Sports - Darts", // 111 10011
+ "Sports - Watersports", // 111 10100
+ "Sports - Extreme", // 111 10101
+ NULL, // 111 10110
+ NULL, // 111 10111
+ NULL, // 111 11000
+ NULL, // 111 11001
+ NULL, // 111 11010
+ NULL, // 111 11011
+ NULL, // 111 11100
+ NULL, // 111 11101
+ NULL, // 111 11110
+ NULL, // 111 11111
+};
+
+static const char *FreesatT1[] = {
+ "START:00:T:",
+ "START:010:B:",
+ "START:1000:C:",
+ "START:1001:I:",
+ "START:1101:S:",
+ "START:01100:L:",
+ "START:01110:D:",
+ "START:01111:H:",
+ "START:10100:R:",
+ "START:10101:N:",
+ "START:10110:E:",
+ "START:11000:F:",
+ "START:11001:A:",
+ "START:11100:M:",
+ "START:11101:P:",
+ "START:11110:W:",
+ "START:011011:Q:",
+ "START:101111:G:",
+ "START:111110:J:",
+ "START:0110100:K:",
+ "START:1011101:U:",
+ "START:1111110:O:",
+ "START:01101010:6:",
+ "START:01101011:.:",
+ "START:10111000:V:",
+ "START:11111110:Y:",
+ "START:101110011:2:",
+ "START:111111111:X:",
+ "START:1011100100:Z:",
+ "START:1111111100:8:",
+ "START:10111001010:1:",
+ "START:10111001011:3:",
+ "START:111111110100:4:",
+ "START:111111110101:':",
+ "START:111111110111: :",
+ "START:11111111011000:5:",
+ "START:11111111011011:0:",
+ "START:111111110110011:m:",
+ "START:1111111101100100:c:",
+ "START:1111111101101000:9:",
+ "START:1111111101101010:a:",
+ "START:1111111101101011:d:",
+ "START:11111111011001010:s:",
+ "START:11111111011001011:p:",
+ "START:11111111011010010:(:",
+ "START:111111110110100110:t:",
+ "START:1111111101101001110:7:",
+ "START:11111111011010011110:ESCAPE:",
+ "START:11111111011010011111:l:",
+ "ESCAPE:0:ESCAPE:",
+ "ESCAPE:1:ESCAPE:",
+ "STOP:0:ESCAPE:",
+ "STOP:1:ESCAPE:",
+ "0x03:0:ESCAPE:",
+ "0x03:1:ESCAPE:",
+ "0x04:0:ESCAPE:",
+ "0x04:1:ESCAPE:",
+ "0x05:0:ESCAPE:",
+ "0x05:1:ESCAPE:",
+ "0x06:0:ESCAPE:",
+ "0x06:1:ESCAPE:",
+ "0x07:0:ESCAPE:",
+ "0x07:1:ESCAPE:",
+ "0x08:0:ESCAPE:",
+ "0x08:1:ESCAPE:",
+ "0x09:0:ESCAPE:",
+ "0x09:1:ESCAPE:",
+ "0x0a:0:ESCAPE:",
+ "0x0a:1:ESCAPE:",
+ "0x0b:0:ESCAPE:",
+ "0x0b:1:ESCAPE:",
+ "0x0c:0:ESCAPE:",
+ "0x0c:1:ESCAPE:",
+ "0x0d:0:ESCAPE:",
+ "0x0d:1:ESCAPE:",
+ "0x0e:0:ESCAPE:",
+ "0x0e:1:ESCAPE:",
+ "0x0f:0:ESCAPE:",
+ "0x0f:1:ESCAPE:",
+ "0x10:0:ESCAPE:",
+ "0x10:1:ESCAPE:",
+ "0x11:0:ESCAPE:",
+ "0x11:1:ESCAPE:",
+ "0x12:0:ESCAPE:",
+ "0x12:1:ESCAPE:",
+ "0x13:0:ESCAPE:",
+ "0x13:1:ESCAPE:",
+ "0x14:0:ESCAPE:",
+ "0x14:1:ESCAPE:",
+ "0x15:0:ESCAPE:",
+ "0x15:1:ESCAPE:",
+ "0x16:0:ESCAPE:",
+ "0x16:1:ESCAPE:",
+ "0x17:0:ESCAPE:",
+ "0x17:1:ESCAPE:",
+ "0x18:0:ESCAPE:",
+ "0x18:1:ESCAPE:",
+ "0x19:0:ESCAPE:",
+ "0x19:1:ESCAPE:",
+ "0x1a:0:ESCAPE:",
+ "0x1a:1:ESCAPE:",
+ "0x1b:0:ESCAPE:",
+ "0x1b:1:ESCAPE:",
+ "0x1c:0:ESCAPE:",
+ "0x1c:1:ESCAPE:",
+ "0x1d:0:ESCAPE:",
+ "0x1d:1:ESCAPE:",
+ "0x1e:0:ESCAPE:",
+ "0x1e:1:ESCAPE:",
+ "0x1f:0:ESCAPE:",
+ "0x1f:1:ESCAPE:",
+ " :0000:W:",
+ " :0011:M:",
+ " :0100:C:",
+ " :0101:B:",
+ " :0111:P:",
+ " :1001:T:",
+ " :1100:N:",
+ " :1111:S:",
+ " :00011:I:",
+ " :00100:G:",
+ " :01100:H:",
+ " :01101:D:",
+ " :10000:o:",
+ " :10001:A:",
+ " :10100:t:",
+ " :10110:a:",
+ " :10111:F:",
+ " :11010:L:",
+ " :11011:R:",
+ " :001011:U:",
+ " :101011:O:",
+ " :111001:J:",
+ " :111010:E:",
+ " :0001000:f:",
+ " :0001001:Q:",
+ " :0001011:V:",
+ " :0010100:STOP:",
+ " :0010101:w:",
+ " :1110000:2:",
+ " :1110001:K:",
+ " :1110110:Y:",
+ " :1110111:i:",
+ " :00010100:-:",
+ " :10101001:1:",
+ " :101010000:&:",
+ " :101010101:X:",
+ " :0001010101:r:",
+ " :1010100010:5:",
+ " :1010100011:Z:",
+ " :1010101001:9:",
+ " :1010101101:s:",
+ " :1010101110:4:",
+ " :1010101111:3:",
+ " :00010101000:7:",
+ " :00010101100:b:",
+ " :00010101110:y:",
+ " :10101010000:':",
+ " :10101011000:6:",
+ " :000101011010:v:",
+ " :000101011011:d:",
+ " :000101011110:(:",
+ " :101010100010: :",
+ " :101010100011:0:",
+ " :101010110010:n:",
+ " :101010110011:8:",
+ " :0001010100110:g:",
+ " :0001010111110:u:",
+ " :00010101001000:+:",
+ " :00010101001001:.:",
+ " :00010101001010:ESCAPE:",
+ " :00010101001011:l:",
+ " :00010101001111:m:",
+ " :00010101111110:p:",
+ " :000101010011100:\\:",
+ " :000101010011101:/:",
+ " :000101011111111:e:",
+ " :0001010111111101:\":",
+ " :00010101111111001:c:",
+ " :000101011111110000:k:",
+ " :000101011111110001:h:",
+ "!:1:STOP:",
+ "!:01: :",
+ "!:001:.:",
+ "!:0001:!:",
+ "!:00001:\":",
+ "!:000000:ESCAPE:",
+ "!:000001:0x3a:",
+ "\":0: :",
+ "\":10:ESCAPE:",
+ "\":11:I:",
+ "#:0:ESCAPE:",
+ "#:1:ESCAPE:",
+ "$:0:ESCAPE:",
+ "$:1:ESCAPE:",
+ "%:1: :",
+ "%:00:ESCAPE:",
+ "%:01:STOP:",
+ "&:1: :",
+ "&:01:B:",
+ "&:000:ESCAPE:",
+ "&:001:.:",
+ "':1:s:",
+ "':000:m:",
+ "':010:C:",
+ "':0010:t:",
+ "':0011: :",
+ "':01100:d:",
+ "':01110:v:",
+ "':011011:r:",
+ "':011111:A:",
+ "':0110101:n:",
+ "':01101000:G:",
+ "':01111001:l:",
+ "':011010011:D:",
+ "':011110000:B:",
+ "':011110001:e:",
+ "':011110101:i:",
+ "':011110110:6:",
+ "':0110100100:L:",
+ "':0111101001:STOP:",
+ "':0111101111:w:",
+ "':01101001010:O:",
+ "':01111010000:S:",
+ "':01111010001:E:",
+ "':01111011101:N:",
+ "':011110111001:R:",
+ "':0110100101100:a:",
+ "':0110100101101:M:",
+ "':0110100101110:K:",
+ "':0110100101111:F:",
+ "':0111101110000:0:",
+ "':01111011100010:ESCAPE:",
+ "':01111011100011:c:",
+ "(:1:c:",
+ "(:000:1:",
+ "(:0010:M:",
+ "(:0011:U:",
+ "(:0100:R:",
+ "(:0101:D:",
+ "(:0110:H:",
+ "(:01110:S:",
+ "(:011110:F:",
+ "(:0111110:G:",
+ "(:01111110:ESCAPE:",
+ "(:01111111:Y:",
+ "):1:STOP:",
+ "):00:ESCAPE:",
+ "):01: :",
+ "*:0:*:",
+ "*:101: :",
+ "*:1000:d:",
+ "*:1100:m:",
+ "*:1101:t:",
+ "*:1111:s:",
+ "*:10010:e:",
+ "*:11100:g:",
+ "*:11101:k:",
+ "*:100110:ESCAPE:",
+ "*:100111:y:",
+ "+:0:ESCAPE:",
+ "+:1: :",
+ ",:1: :",
+ ",:01:0:",
+ ",:000:ESCAPE:",
+ ",:001:.:",
+ "-:11: :",
+ "-:011:S:",
+ "-:100:G:",
+ "-:101:O:",
+ "-:0011:T:",
+ "-:0100:U:",
+ "-:00000:E:",
+ "-:00010:D:",
+ "-:000010:m:",
+ "-:000110:0:",
+ "-:000111:I:",
+ "-:001010:6:",
+ "-:010100:F:",
+ "-:010101:o:",
+ "-:0000110:L:",
+ "-:0000111:C:",
+ "-:0010001:A:",
+ "-:0010010:t:",
+ "-:0010011:Y:",
+ "-:0010111:2:",
+ "-:0101100:B:",
+ "-:0101101:.:",
+ "-:00100000:P:",
+ "-:00100001:Z:",
+ "-:01011100:8:",
+ "-:01011101:i:",
+ "-:01011110:d:",
+ "-:01011111:H:",
+ "-:001011001:N:",
+ "-:001011011:R:",
+ "-:0010110000:1:",
+ "-:0010110001:W:",
+ "-:00101101001:c:",
+ "-:00101101010:a:",
+ "-:00101101011:M:",
+ "-:001011010000:ESCAPE:",
+ "-:001011010001:Q:",
+ ".:1:.:",
+ ".:01:STOP:",
+ ".:0010: :",
+ ".:00000:I:",
+ ".:00001:T:",
+ ".:00010:C:",
+ ".:00110:p:",
+ ".:00111:0:",
+ ".:000111:H:",
+ ".:00011010:W:",
+ ".:000110001:S:",
+ ".:000110110:3:",
+ ".:000110111:B:",
+ ".:0001100000:1:",
+ ".:0001100001:M:",
+ ".:0001100110:c:",
+ ".:00011001000:t:",
+ ".:00011001001:R:",
+ ".:00011001010:F:",
+ ".:00011001110:E:",
+ ".:00011001111:A:",
+ ".:0001100101100:ESCAPE:",
+ ".:0001100101101:l:",
+ ".:0001100101110:d:",
+ ".:0001100101111:U:",
+ "/:00:1:",
+ "/:10:7:",
+ "/:010:4:",
+ "/:011:2:",
+ "/:110:3:",
+ "/:1110:5:",
+ "/:111100:6:",
+ "/:111110:C:",
+ "/:1111010:9:",
+ "/:1111011: :",
+ "/:1111110:8:",
+ "/:11111111:U:",
+ "/:1111111000:G:",
+ "/:1111111010:0:",
+ "/:11111110010:ESCAPE:",
+ "/:11111110011:W:",
+ "/:11111110110:V:",
+ "/:11111110111:S:",
+ "0:00:6:",
+ "0:01: :",
+ "0:11:0:",
+ "0:1001:p:",
+ "0:1010:STOP:",
+ "0:10000:1:",
+ "0:10001:a:",
+ "0:10111:7:",
+ "0:1011000:-:",
+ "0:1011010:s:",
+ "0:10110011:4:",
+ "0:10110110:t:",
+ "0:101101111:%:",
+ "0:1011001000:8:",
+ "0:1011001001:0x3a:",
+ "0:1011001010:5:",
+ "0:1011001011:2:",
+ "0:1011011100:/:",
+ "0:10110111011:U:",
+ "0:101101110101:,:",
+ "0:1011011101000:.:",
+ "0:10110111010010:ESCAPE:",
+ "0:10110111010011:l:",
+ "1:01:STOP:",
+ "1:000:.:",
+ "1:101:0:",
+ "1:111:1:",
+ "1:0010:2:",
+ "1:0011: :",
+ "1:1101:/:",
+ "1:10010:8:",
+ "1:11000:3:",
+ "1:100000:5:",
+ "1:100001:s:",
+ "1:100010:6:",
+ "1:100011:0x3a:",
+ "1:100110:':",
+ "1:110010:X:",
+ "1:110011:9:",
+ "1:1001111:4:",
+ "1:10011101:-:",
+ "1:100111001:7:",
+ "1:1001110000:):",
+ "1:10011100010:ESCAPE:",
+ "1:10011100011:,:",
+ "2:0:0:",
+ "2:11:4:",
+ "2:101:STOP:",
+ "2:1001: :",
+ "2:10000:0x3a:",
+ "2:1000101:5:",
+ "2:1000111:/:",
+ "2:10001000:.:",
+ "2:10001001:1:",
+ "2:10001100:W:",
+ "2:100011011:7:",
+ "2:10001101001:3:",
+ "2:10001101011:Z:",
+ "2:100011010000:n:",
+ "2:100011010001:6:",
+ "2:100011010101:':",
+ "2:1000110101000:ESCAPE:",
+ "2:1000110101001:s:",
+ "3:0: :",
+ "3:10:STOP:",
+ "3:1100:r:",
+ "3:1101:/:",
+ "3:1111:B:",
+ "3:11100:0:",
+ "3:1110100:0x3a:",
+ "3:1110110:-:",
+ "3:11101010:1:",
+ "3:11101011:8:",
+ "3:11101111:4:",
+ "3:1110111000:6:",
+ "3:1110111011:9:",
+ "3:11101110011:t:",
+ "3:11101110100:3:",
+ "3:111011100100:ESCAPE:",
+ "3:111011100101:e:",
+ "3:111011101010:7:",
+ "3:111011101011:5:",
+ "4:0:STOP:",
+ "4:11: :",
+ "4:1001:0x3a:",
+ "4:1011:/:",
+ "4:10001:8:",
+ "4:10101:.:",
+ "4:100000:9:",
+ "4:101000:0:",
+ "4:1010010:M:",
+ "4:10000101:I:",
+ "4:10000110:):",
+ "4:10100110:R:",
+ "4:10100111:-:",
+ "4:100001000:W:",
+ "4:100001110:P:",
+ "4:100001111:5:",
+ "4:1000010011:2:",
+ "4:10000100100:ESCAPE:",
+ "4:10000100101:':",
+ "5:0:STOP:",
+ "5:11: :",
+ "5:101:0:",
+ "5:1001:/:",
+ "5:100001:-:",
+ "5:100011:0x3a:",
+ "5:1000001:t:",
+ "5:1000100:3:",
+ "5:1000101:1:",
+ "5:10000000:ESCAPE:",
+ "5:10000001:a:",
+ "6:00:STOP:",
+ "6:01: :",
+ "6:10:0:",
+ "6:111:0x3a:",
+ "6:11001:.:",
+ "6:11011:i:",
+ "6:110000:-:",
+ "6:110101:a:",
+ "6:1100011:4:",
+ "6:1101000:8:",
+ "6:1101001:/:",
+ "6:11000100:6:",
+ "6:110001011:9:",
+ "6:1100010100:3:",
+ "6:11000101010:ESCAPE:",
+ "6:11000101011:t:",
+ "7:1:STOP:",
+ "7:01: :",
+ "7:000:0:",
+ "7:0011:.:",
+ "7:00101:/:",
+ "7:0010000:1:",
+ "7:0010010:5:",
+ "7:00100010:ESCAPE:",
+ "7:00100011:4:",
+ "7:00100110:3:",
+ "7:00100111:2:",
+ "8:1: :",
+ "8:00:0:",
+ "8:010:0x3a:",
+ "8:01101:STOP:",
+ "8:011000:t:",
+ "8:011001:p:",
+ "8:011101:8:",
+ "8:011110:.:",
+ "8:011111:6:",
+ "8:0111000:5:",
+ "8:01110010:9:",
+ "8:011100110:M:",
+ "8:0111001110:F:",
+ "8:01110011110:ESCAPE:",
+ "8:01110011111:c:",
+ "9:0:1:",
+ "9:11:STOP:",
+ "9:1000:9:",
+ "9:1010:.:",
+ "9:10011:0:",
+ "9:100100: :",
+ "9:100101:8:",
+ "9:101100:7:",
+ "9:101101:/:",
+ "9:101110:6:",
+ "9:1011111:0x3a:",
+ "9:10111101:4:",
+ "9:101111000:ESCAPE:",
+ "9:101111001:3:",
+ "0x3a:1: :",
+ "0x3a:00:0:",
+ "0x3a:011:.:",
+ "0x3a:0100:2:",
+ "0x3a:01010:1:",
+ "0x3a:010111:3:",
+ "0x3a:0101101:C:",
+ "0x3a:01011000:ESCAPE:",
+ "0x3a:01011001:T:",
+ ";:1: :",
+ ";:00:ESCAPE:",
+ ";:01:.:",
+ "<:0:ESCAPE:",
+ "<:1:ESCAPE:",
+ "=:0:ESCAPE:",
+ "=:1:ESCAPE:",
+ ">:0:ESCAPE:",
+ ">:1:ESCAPE:",
+ "?:1:STOP:",
+ "?:01: :",
+ "?:001:0x3a:",
+ "?:0000:ESCAPE:",
+ "?:0001:.:",
+ "@:0:ESCAPE:",
+ "@:1:H:",
+ "A:001:r:",
+ "A:010: :",
+ "A:100:l:",
+ "A:110:n:",
+ "A:0000:m:",
+ "A:0111:g:",
+ "A:1111:d:",
+ "A:00010:w:",
+ "A:01100:T:",
+ "A:01101:c:",
+ "A:10101:t:",
+ "A:10110:f:",
+ "A:10111:i:",
+ "A:11100:s:",
+ "A:000110:u:",
+ "A:000111:STOP:",
+ "A:101001:R:",
+ "A:111010:b:",
+ "A:1010001:v:",
+ "A:1110110:p:",
+ "A:10100000:S:",
+ "A:11101110:M:",
+ "A:101000011:P:",
+ "A:111011111:.:",
+ "A:10100001000:e:",
+ "A:10100001001:B:",
+ "A:10100001010:1:",
+ "A:11101111011:-:",
+ "A:101000010110:k:",
+ "A:101000010111:h:",
+ "A:111011110000:a:",
+ "A:111011110100:y:",
+ "A:111011110101:*:",
+ "A:1110111100010:x:",
+ "A:1110111100011:':",
+ "A:1110111100100:N:",
+ "A:1110111100110:2:",
+ "A:11101111001010:0x3a:",
+ "A:11101111001111:z:",
+ "A:111011110010110:L:",
+ "A:111011110010111:F:",
+ "A:111011110011100:D:",
+ "A:1110111100111010:ESCAPE:",
+ "A:1110111100111011:q:",
+ "B:00:C:",
+ "B:01:B:",
+ "B:101:r:",
+ "B:1001:i:",
+ "B:1100:o:",
+ "B:1101:u:",
+ "B:1110:a:",
+ "B:1111:e:",
+ "B:10001:l:",
+ "B:1000000:STOP:",
+ "B:1000010:y:",
+ "B:10000010:O:",
+ "B:10000110:3:",
+ "B:100000111:A:",
+ "B:100001110:S:",
+ "B:1000001101:0x3a:",
+ "B:10000011000:.:",
+ "B:10000011001:w:",
+ "B:10000111101:h:",
+ "B:10000111110:*:",
+ "B:10000111111: :",
+ "B:100001111001:R:",
+ "B:1000011110000:':",
+ "B:10000111100011:T:",
+ "B:100001111000100:ESCAPE:",
+ "B:100001111000101:4:",
+ "C:00:o:",
+ "C:01: :",
+ "C:100:l:",
+ "C:110:h:",
+ "C:1010:r:",
+ "C:1110:a:",
+ "C:10110:i:",
+ "C:10111:e:",
+ "C:111100:u:",
+ "C:111101:B:",
+ "C:1111100:y:",
+ "C:1111110:!:",
+ "C:11111011:.:",
+ "C:111110100:w:",
+ "C:111111100:STOP:",
+ "C:111111110:S:",
+ "C:111111111:T:",
+ "C:1111101011:2:",
+ "C:1111111011:I:",
+ "C:11111010100:4:",
+ "C:11111010101:*:",
+ "C:11111110101:D:",
+ "C:111111101000:U:",
+ "C:1111111010010:':",
+ "C:11111110100110:n:",
+ "C:111111101001110:z:",
+ "C:11111110100111100:O:",
+ "C:11111110100111101:E:",
+ "C:11111110100111110:A:",
+ "C:111111101001111110:ESCAPE:",
+ "C:111111101001111111:s:",
+ "D:01:o:",
+ "D:10:a:",
+ "D:000:r:",
+ "D:110:e:",
+ "D:111:i:",
+ "D:00100:t:",
+ "D:00111:u:",
+ "D:001011: :",
+ "D:0010101:J:",
+ "D:0011000:y:",
+ "D:0011010:STOP:",
+ "D:0011011:I:",
+ "D:00110011:0x3a:",
+ "D:001010001:*:",
+ "D:001010010:-:",
+ "D:001010011:&:",
+ "D:001100100:':",
+ "D:0010100000:A:",
+ "D:0010100001:h:",
+ "D:00110010101:N:",
+ "D:00110010110:V:",
+ "D:001100101110:D:",
+ "D:001100101111:w:",
+ "D:0011001010000:O:",
+ "D:0011001010001:E:",
+ "D:0011001010011:d:",
+ "D:00110010100100:ESCAPE:",
+ "D:00110010100101:T:",
+ "E:00:m:",
+ "E:011:v:",
+ "E:101:n:",
+ "E:111:a:",
+ "E:0100:E:",
+ "E:1000:STOP:",
+ "E:1101:x:",
+ "E:10011:d:",
+ "E:11001:l:",
+ "E:010100:4:",
+ "E:010101:y:",
+ "E:010110:u:",
+ "E:100100:r:",
+ "E:110000:i:",
+ "E:0101111:s:",
+ "E:1001010:F:",
+ "E:1100010:X:",
+ "E:10010110:R:",
+ "E:11000111: :",
+ "E:010111010:g:",
+ "E:100101111:0x3a:",
+ "E:110001100:T:",
+ "E:110001101:':",
+ "E:0101110001:c:",
+ "E:0101110011:q:",
+ "E:0101110110:e:",
+ "E:0101110111:C:",
+ "E:1001011100:p:",
+ "E:01011100000:-:",
+ "E:01011100101:Z:",
+ "E:10010111011:t:",
+ "E:010111000010:S:",
+ "E:010111000011:.:",
+ "E:100101110101:W:",
+ "E:0101110010000:!:",
+ "E:1001011101000:o:",
+ "E:01011100100010:f:",
+ "E:01011100100011:U:",
+ "E:01011100100100:N:",
+ "E:01011100100101:M:",
+ "E:01011100100110:L:",
+ "E:01011100100111:A:",
+ "E:10010111010011:D:",
+ "E:100101110100100:ESCAPE:",
+ "E:100101110100101:w:",
+ "F:00:i:",
+ "F:10:a:",
+ "F:011:r:",
+ "F:110:u:",
+ "F:111:o:",
+ "F:0100:e:",
+ "F:01011:l:",
+ "F:0101000:A:",
+ "F:0101010:O:",
+ "F:01010010: :",
+ "F:010100110:h:",
+ "F:010100111:t:",
+ "F:010101101:f:",
+ "F:010101111:L:",
+ "F:0101011001:STOP:",
+ "F:01010111000:j:",
+ "F:01010111001:I:",
+ "F:01010111010:.:",
+ "F:01010111011:1:",
+ "F:010101100000:M:",
+ "F:010101100010:*:",
+ "F:010101100011:K:",
+ "F:0101011000010:y:",
+ "F:01010110000111:H:",
+ "F:010101100001100:ESCAPE:",
+ "F:010101100001101:!:",
+ "G:10:r:",
+ "G:001:M:",
+ "G:010:a:",
+ "G:011:o:",
+ "G:110:i:",
+ "G:111:e:",
+ "G:00001:u:",
+ "G:00010:X:",
+ "G:000001:h:",
+ "G:000111:l:",
+ "G:0000001:y:",
+ "G:0001100:w:",
+ "G:00000000:0x3a:",
+ "G:00011011:C:",
+ "G:000000011:STOP:",
+ "G:000110100:-:",
+ "G:0001101010:P:",
+ "G:0001101011: :",
+ "G:00000001000:':",
+ "G:00000001010:A:",
+ "G:000000010010:U:",
+ "G:000000010110:T:",
+ "G:000000010111:4:",
+ "G:0000000100110:ESCAPE:",
+ "G:0000000100111:Y:",
+ "H:0:o:",
+ "H:100:a:",
+ "H:101:i:",
+ "H:110:e:",
+ "H:1110:u:",
+ "H:11110:R:",
+ "H:111110:A:",
+ "H:1111110:.:",
+ "H:111111101:y:",
+ "H:111111110:S:",
+ "H:1111111110:E:",
+ "H:1111111111:r:",
+ "H:11111110000:STOP:",
+ "H:11111110010:L:",
+ "H:11111110011:M:",
+ "H:111111100011:w:",
+ "H:1111111000101:D:",
+ "H:11111110001000:ESCAPE:",
+ "H:11111110001001:I:",
+ "I:0:T:",
+ "I:100:s:",
+ "I:101:n:",
+ "I:1101:t:",
+ "I:11001: :",
+ "I:11101:':",
+ "I:11111:r:",
+ "I:110000:I:",
+ "I:110001:STOP:",
+ "I:111001:m:",
+ "I:1110000:d:",
+ "I:1110001:N:",
+ "I:1111001:z:",
+ "I:1111010:.:",
+ "I:11110000:a:",
+ "I:11110001:Y:",
+ "I:111101100:S:",
+ "I:111101110:c:",
+ "I:11110110101:D:",
+ "I:11110110110:f:",
+ "I:11110111100:l:",
+ "I:11110111111:y:",
+ "I:111101101000:V:",
+ "I:111101101110:o:",
+ "I:111101111011:F:",
+ "I:1111011010010:,:",
+ "I:1111011010011:A:",
+ "I:1111011011110:O:",
+ "I:1111011110101:g:",
+ "I:1111011111000:C:",
+ "I:1111011111001:0x3a:",
+ "I:1111011111011:v:",
+ "I:11110110111110:p:",
+ "I:11110110111111:E:",
+ "I:11110111101000:B:",
+ "I:11110111110100:k:",
+ "I:11110111110101:b:",
+ "I:1111011110100100:ESCAPE:",
+ "I:1111011110100101:R:",
+ "I:1111011110100110:L:",
+ "I:1111011110100111:G:",
+ "J:00:a:",
+ "J:01:u:",
+ "J:11:e:",
+ "J:101:o:",
+ "J:1001:i:",
+ "J:10000: :",
+ "J:100010:K:",
+ "J:1000111:STOP:",
+ "J:100011001:s:",
+ "J:100011010:F:",
+ "J:1000110000:V:",
+ "J:1000110001:':",
+ "J:1000110111:f:",
+ "J:10001101101:G:",
+ "J:100011011000:ESCAPE:",
+ "J:100011011001:D:",
+ "K:01:i:",
+ "K:11:y:",
+ "K:001:e:",
+ "K:101: :",
+ "K:0000:a:",
+ "K:1000:o:",
+ "K:00010:STOP:",
+ "K:00011:r:",
+ "K:100101:t:",
+ "K:100110:n:",
+ "K:100111:S:",
+ "K:10010011:G:",
+ "K:100100000:-:",
+ "K:100100011:O:",
+ "K:100100100:h:",
+ "K:100100101:w:",
+ "K:1001000010:1:",
+ "K:1001000011:':",
+ "K:10010001011:u:",
+ "K:100100010000:T:",
+ "K:100100010001:N:",
+ "K:100100010010:0x3a:",
+ "K:100100010011:.:",
+ "K:100100010100:,:",
+ "K:1001000101010:ESCAPE:",
+ "K:1001000101011:l:",
+ "L:00:a:",
+ "L:10:o:",
+ "L:11:i:",
+ "L:010:e:",
+ "L:0111:u:",
+ "L:01101:K:",
+ "L:0110000:l:",
+ "L:0110010:A:",
+ "L:0110011: :",
+ "L:01100011:y:",
+ "L:0110001000:L:",
+ "L:0110001001:I:",
+ "L:01100010100:C:",
+ "L:01100010101:.:",
+ "L:01100010111:STOP:",
+ "L:011000101101:':",
+ "L:0110001011000:E:",
+ "L:01100010110010:ESCAPE:",
+ "L:01100010110011:Y:",
+ "M:01:a:",
+ "M:10:o:",
+ "M:000:e:",
+ "M:111:i:",
+ "M:0010:T:",
+ "M:1100:y:",
+ "M:1101:u:",
+ "M:00110:STOP:",
+ "M:001111:c:",
+ "M:00111001:r:",
+ "M:00111010:E:",
+ "M:001110111:F:",
+ "M:0011100001:Z:",
+ "M:0011100011: :",
+ "M:0011101100:1:",
+ "M:0011101101:I:",
+ "M:00111000001:h:",
+ "M:00111000100:C:",
+ "M:001110000001:Q:",
+ "M:001110001010:K:",
+ "M:0011100010110:P:",
+ "M:00111000000000:0x3a:",
+ "M:00111000000001:.:",
+ "M:00111000000010:':",
+ "M:00111000101110:M:",
+ "M:001110000000110:ESCAPE:",
+ "M:001110000000111:w:",
+ "M:001110001011110:S:",
+ "M:001110001011111:R:",
+ "N:1:e:",
+ "N:00:o:",
+ "N:011:i:",
+ "N:0101:a:",
+ "N:01001:u:",
+ "N:010000:C:",
+ "N:01000100:E:",
+ "N:01000110:F:",
+ "N:010001110:B:",
+ "N:010001111:H:",
+ "N:0100010110:Y:",
+ "N:01000101000:G:",
+ "N:01000101001:':",
+ "N:01000101011:I:",
+ "N:01000101110:A:",
+ "N:010001010100:M:",
+ "N:010001011110: :",
+ "N:010001011111:STOP:",
+ "N:0100010101010:T:",
+ "N:01000101010110:.:",
+ "N:010001010101110:ESCAPE:",
+ "N:010001010101111:Z:",
+ "O:000:':",
+ "O:010:f:",
+ "O:110:u:",
+ "O:111:n:",
+ "O:0010:M:",
+ "O:0011:l:",
+ "O:1001:m:",
+ "O:01101:r:",
+ "O:01110:d:",
+ "O:10000:p:",
+ "O:10100:h:",
+ "O:10110:STOP:",
+ "O:011001:S:",
+ "O:011110:z:",
+ "O:011111:b:",
+ "O:100011:v:",
+ "O:101010:w:",
+ "O:101011:U:",
+ "O:1011100:T:",
+ "O:1011101:O:",
+ "O:1011110:K:",
+ "O:01100001:C:",
+ "O:01100010:x:",
+ "O:01100011:.:",
+ "O:10001001:t:",
+ "O:10001011: :",
+ "O:10111110:s:",
+ "O:10111111:N:",
+ "O:011000001:g:",
+ "O:100010000:-:",
+ "O:100010101:a:",
+ "O:1000100010:i:",
+ "O:1000100011:e:",
+ "O:1000101001:o:",
+ "O:01100000000:A:",
+ "O:01100000001:j:",
+ "O:01100000010:c:",
+ "O:10001010000:2:",
+ "O:011000000111:R:",
+ "O:100010100010:P:",
+ "O:100010100011:0x3a:",
+ "O:0110000001100:E:",
+ "O:01100000011010:ESCAPE:",
+ "O:01100000011011:L:",
+ "P:01:r:",
+ "P:10:l:",
+ "P:000:e:",
+ "P:001:a:",
+ "P:111:o:",
+ "P:1101:i:",
+ "P:110000:D:",
+ "P:110001:u:",
+ "P:110011:h:",
+ "P:11001000: :",
+ "P:11001010:2:",
+ "P:110010010:H:",
+ "P:110010011:M:",
+ "P:110010110:S:",
+ "P:11001011100:0x3a:",
+ "P:11001011101:*:",
+ "P:110010111101:s:",
+ "P:1100101111001:I:",
+ "P:1100101111100:STOP:",
+ "P:1100101111101:G:",
+ "P:1100101111110:':",
+ "P:11001011111110:y:",
+ "P:110010111100000:Y:",
+ "P:110010111100001:L:",
+ "P:110010111100010:C:",
+ "P:110010111100011:ESCAPE:",
+ "P:110010111111110:O:",
+ "P:110010111111111:.:",
+ "Q:1:u:",
+ "Q:000:I:",
+ "Q:001:STOP:",
+ "Q:010:V:",
+ "Q:0111: :",
+ "Q:01101:C:",
+ "Q:011000:ESCAPE:",
+ "Q:011001:':",
+ "R:00:a:",
+ "R:01:o:",
+ "R:11:e:",
+ "R:100:i:",
+ "R:1011:u:",
+ "R:10101:E:",
+ "R:101000:D:",
+ "R:1010011:STOP:",
+ "R:10100101:h:",
+ "R:1010010000:I:",
+ "R:1010010010:y:",
+ "R:1010010011:n:",
+ "R:101001000110: :",
+ "R:1010010001000:':",
+ "R:1010010001011:S:",
+ "R:1010010001110:N:",
+ "R:10100100010010:B:",
+ "R:10100100010011:.:",
+ "R:10100100010100:&:",
+ "R:10100100011110:T:",
+ "R:10100100011111:1:",
+ "R:101001000101010:ESCAPE:",
+ "R:101001000101011:C:",
+ "S:001:o:",
+ "S:010:p:",
+ "S:011:u:",
+ "S:110:h:",
+ "S:111:t:",
+ "S:0001:a:",
+ "S:1001:e:",
+ "S:1011:c:",
+ "S:00000:n:",
+ "S:10001:i:",
+ "S:10101:k:",
+ "S:000011:w:",
+ "S:101000:m:",
+ "S:0000101:A:",
+ "S:1000010:l:",
+ "S:1010010:q:",
+ "S:1010011:M:",
+ "S:00001000:2:",
+ "S:00001001:P:",
+ "S:10000000:O:",
+ "S:10000010:I:",
+ "S:10000011: :",
+ "S:10000111:STOP:",
+ "S:100000010:y:",
+ "S:100001100:E:",
+ "S:1000000111:?:",
+ "S:1000011011:H:",
+ "S:10000001100:B:",
+ "S:10000110100:g:",
+ "S:100000011011:r:",
+ "S:100001101010:*:",
+ "S:1000011010110:3:",
+ "S:1000011010111:.:",
+ "S:10000001101000:5:",
+ "S:10000001101010:0x3a:",
+ "S:10000001101011:1:",
+ "S:100000011010010:C:",
+ "S:1000000110100110:ESCAPE:",
+ "S:1000000110100111:Y:",
+ "T:0:h:",
+ "T:101:o:",
+ "T:111:V:",
+ "T:1000:e:",
+ "T:1001:r:",
+ "T:11000:a:",
+ "T:11010:w:",
+ "T:110011:i:",
+ "T:1101101:O:",
+ "T:1101111:H:",
+ "T:11001001:y:",
+ "T:11001010:M:",
+ "T:11011000:.:",
+ "T:11011100:u:",
+ "T:11011101:W:",
+ "T:110010001:P:",
+ "T:110010110:0x3a:",
+ "T:110010111:4:",
+ "T:110110011:I:",
+ "T:1101100100: :",
+ "T:1101100101:STOP:",
+ "T:11001000010:X:",
+ "T:11001000011:s:",
+ "T:110010000000:T:",
+ "T:110010000001:S:",
+ "T:110010000010:B:",
+ "T:1100100000110:U:",
+ "T:11001000001110:A:",
+ "T:1100100000111100:C:",
+ "T:1100100000111101:*:",
+ "T:1100100000111111:N:",
+ "T:11001000001111100:ESCAPE:",
+ "T:11001000001111101:Y:",
+ "U:0:n:",
+ "U:10:p:",
+ "U:1101:K:",
+ "U:1111:l:",
+ "U:11000:R:",
+ "U:11100:S:",
+ "U:110011:E:",
+ "U:111011:s:",
+ "U:1100101:g:",
+ "U:1110101:T:",
+ "U:11001001: :",
+ "U:110010000:-:",
+ "U:110010001:r:",
+ "U:111010000:2:",
+ "U:111010001:m:",
+ "U:111010011:STOP:",
+ "U:1110100100:.:",
+ "U:11101001010:c:",
+ "U:111010010110:k:",
+ "U:11101001011100:ESCAPE:",
+ "U:11101001011101:z:",
+ "U:11101001011110:t:",
+ "U:11101001011111:B:",
+ "V:1: :",
+ "V:000:0x3a:",
+ "V:011:i:",
+ "V:0010:e:",
+ "V:0011:a:",
+ "V:0100:3:",
+ "V:010101:C:",
+ "V:010111:STOP:",
+ "V:0101000:':",
+ "V:0101001:4:",
+ "V:0101101:o:",
+ "V:01011001:I:",
+ "V:0101100000:s:",
+ "V:0101100001:D:",
+ "V:0101100010:.:",
+ "V:01011000110:8:",
+ "V:0101100011101:u:",
+ "V:0101100011110:r:",
+ "V:0101100011111:B:",
+ "V:01011000111000:ESCAPE:",
+ "V:01011000111001:E:",
+ "W:01:o:",
+ "W:11:e:",
+ "W:001:h:",
+ "W:100:a:",
+ "W:101:i:",
+ "W:00000:.:",
+ "W:00010:O:",
+ "W:00011:r:",
+ "W:000011:y:",
+ "W:0000100:u:",
+ "W:00001010:STOP:",
+ "W:000010111:A:",
+ "W:00001011001:Y:",
+ "W:00001011010:T:",
+ "W:00001011011: :",
+ "W:000010110000:I:",
+ "W:0000101100010:ESCAPE:",
+ "W:0000101100011:l:",
+ "X:00:STOP:",
+ "X:10: :",
+ "X:11:t:",
+ "X:010:T:",
+ "X:0111:c:",
+ "X:01101:m:",
+ "X:011001:U:",
+ "X:01100000:a:",
+ "X:01100001:X:",
+ "X:01100010:-:",
+ "X:011000110:x:",
+ "X:0110001111:9:",
+ "X:01100011100:ESCAPE:",
+ "X:01100011101:i:",
+ "Y:1:o:",
+ "Y:01:e:",
+ "Y:000:u:",
+ "Y:0011: :",
+ "Y:00100:v:",
+ "Y:001010:a:",
+ "Y:00101110:P:",
+ "Y:00101111:':",
+ "Y:001011000:n:",
+ "Y:001011011:r:",
+ "Y:0010110010:D:",
+ "Y:00101100110:w:",
+ "Y:00101100111:s:",
+ "Y:00101101000:R:",
+ "Y:00101101001:L:",
+ "Y:00101101010:STOP:",
+ "Y:001011010110:C:",
+ "Y:0010110101110:ESCAPE:",
+ "Y:0010110101111:N:",
+ "Z:1:o:",
+ "Z:00:a:",
+ "Z:010:i:",
+ "Z:01100:O:",
+ "Z:01101:u:",
+ "Z:01110:e:",
+ "Z:011110: :",
+ "Z:0111111:STOP:",
+ "Z:01111101:0x3a:",
+ "Z:011111000:ESCAPE:",
+ "Z:011111001:-:",
+ "[:0:ESCAPE:",
+ "[:1:ESCAPE:",
+ "\\:0:ESCAPE:",
+ "\\:1:x:",
+ "]:0:ESCAPE:",
+ "]:1:ESCAPE:",
+ "^:0:ESCAPE:",
+ "^:1:ESCAPE:",
+ "_:0:ESCAPE:",
+ "_:1:ESCAPE:",
+ "`:0:ESCAPE:",
+ "`:1:ESCAPE:",
+ "a:001:r:",
+ "a:011:t:",
+ "a:100:l:",
+ "a:110:n:",
+ "a:0001:m:",
+ "a:0100:c:",
+ "a:1010:s:",
+ "a:1110:y:",
+ "a:10110: :",
+ "a:10111:d:",
+ "a:11110:i:",
+ "a:11111:k:",
+ "a:000010:b:",
+ "a:000011:STOP:",
+ "a:010110:p:",
+ "a:010111:g:",
+ "a:0000000:e:",
+ "a:0000001:':",
+ "a:0000011:w:",
+ "a:0101001:u:",
+ "a:0101010:z:",
+ "a:0101011:v:",
+ "a:00000101:f:",
+ "a:01010001:h:",
+ "a:000001001:0x3a:",
+ "a:0000010000:!:",
+ "a:0101000000:o:",
+ "a:0101000001:x:",
+ "a:00000100010:-:",
+ "a:00000100011:a:",
+ "a:01010000101:.:",
+ "a:01010000110:N:",
+ "a:01010000111:,:",
+ "a:010100001000:q:",
+ "a:0101000010010:j:",
+ "a:01010000100111:?:",
+ "a:010100001001101:J:",
+ "a:0101000010011000:ESCAPE:",
+ "a:0101000010011001:U:",
+ "b:000:r:",
+ "b:001:o:",
+ "b:010:e:",
+ "b:011:a:",
+ "b:100:i:",
+ "b:1011:u:",
+ "b:1100:y:",
+ "b:1101:l:",
+ "b:1111: :",
+ "b:10101:s:",
+ "b:11100:b:",
+ "b:11101:STOP:",
+ "b:101000:h:",
+ "b:1010010:3:",
+ "b:10100111:':",
+ "b:1010011001:t:",
+ "b:1010011010:j:",
+ "b:10100110000:n:",
+ "b:10100110001:d:",
+ "b:10100110111:w:",
+ "b:101001101101:m:",
+ "b:1010011011001:.:",
+ "b:10100110110000:ESCAPE:",
+ "b:10100110110001:0x3a:",
+ "c:00:k:",
+ "c:010:o:",
+ "c:100:h:",
+ "c:110:t:",
+ "c:111:e:",
+ "c:0111:r:",
+ "c:10100: :",
+ "c:10110:i:",
+ "c:10111:a:",
+ "c:011000:l:",
+ "c:011001:y:",
+ "c:011010:s:",
+ "c:011011:STOP:",
+ "c:1010100:c:",
+ "c:1010111:u:",
+ "c:10101010:0x3a:",
+ "c:10101011:P:",
+ "c:101011001:D:",
+ "c:1010110100:G:",
+ "c:1010110110:b:",
+ "c:10101100000:L:",
+ "c:10101100001:K:",
+ "c:10101100011:A:",
+ "c:10101101010:q:",
+ "c:10101101110:.:",
+ "c:10101101111:C:",
+ "c:101011000100:n:",
+ "c:101011000101:':",
+ "c:1010110101100:B:",
+ "c:1010110101101:I:",
+ "c:10101101011101:f:",
+ "c:10101101011110:8:",
+ "c:101011010111000:M:",
+ "c:101011010111001:ESCAPE:",
+ "c:101011010111111:F:",
+ "c:1010110101111100:w:",
+ "c:1010110101111101:Q:",
+ "d:11: :",
+ "d:001:e:",
+ "d:100:STOP:",
+ "d:101:a:",
+ "d:0001:y:",
+ "d:0100:i:",
+ "d:0110:s:",
+ "d:00000:o:",
+ "d:01010:d:",
+ "d:000011:u:",
+ "d:010110:r:",
+ "d:010111:l:",
+ "d:011101:v:",
+ "d:011110:g:",
+ "d:0000100:':",
+ "d:0111111:.:",
+ "d:00001010:0x3a:",
+ "d:00001011:h:",
+ "d:01110000:c:",
+ "d:01110010:n:",
+ "d:01110011:w:",
+ "d:011100010:?:",
+ "d:011111000:!:",
+ "d:011111001:-:",
+ "d:011111010:f:",
+ "d:0111000111:m:",
+ "d:0111110110:,:",
+ "d:01111101110:t:",
+ "d:01111101111:b:",
+ "d:011100011001:):",
+ "d:011100011010:/:",
+ "d:011100011011:k:",
+ "d:0111000110001:p:",
+ "d:01110001100001:z:",
+ "d:011100011000000:ESCAPE:",
+ "d:011100011000001:4:",
+ "e:01: :",
+ "e:000:s:",
+ "e:101:r:",
+ "e:0010:t:",
+ "e:1001:n:",
+ "e:1100:STOP:",
+ "e:1110:a:",
+ "e:1111:w:",
+ "e:10000:l:",
+ "e:11011:e:",
+ "e:001110:m:",
+ "e:100010:c:",
+ "e:100011:d:",
+ "e:0011010:i:",
+ "e:0011011:p:",
+ "e:0011110:b:",
+ "e:1101000:v:",
+ "e:1101011:y:",
+ "e:00110000:g:",
+ "e:00110001:f:",
+ "e:00110010:x:",
+ "e:00111110:k:",
+ "e:00111111:0x3a:",
+ "e:11010011:o:",
+ "e:11010100:':",
+ "e:001100111:h:",
+ "e:110100101:.:",
+ "e:0011001100:P:",
+ "e:0011001101:B:",
+ "e:1101001000:,:",
+ "e:1101010100:V:",
+ "e:1101010101:z:",
+ "e:1101010111:j:",
+ "e:11010010010:4:",
+ "e:11010010011:?:",
+ "e:11010101101:u:",
+ "e:110101011001:-:",
+ "e:1101010110001:!:",
+ "e:11010101100001:q:",
+ "e:110101011000001:G:",
+ "e:1101010110000000:ESCAPE:",
+ "e:1101010110000001:S:",
+ "f:0: :",
+ "f:101:o:",
+ "f:1001:t:",
+ "f:1100:a:",
+ "f:1101:i:",
+ "f:1111:e:",
+ "f:10000:.:",
+ "f:11100:r:",
+ "f:11101:f:",
+ "f:100010:STOP:",
+ "f:10001101:y:",
+ "f:10001111:u:",
+ "f:100011000:':",
+ "f:100011101:l:",
+ "f:1000110011:n:",
+ "f:1000111000:g:",
+ "f:10001100100:c:",
+ "f:10001110010:-:",
+ "f:100011001010:,:",
+ "f:100011001011:s:",
+ "f:100011100111:0x3a:",
+ "f:1000111001101:k:",
+ "f:10001110011000:ESCAPE:",
+ "f:10001110011001:b:",
+ "g:00:h:",
+ "g:10: :",
+ "g:010:STOP:",
+ "g:011:e:",
+ "g:1100:i:",
+ "g:11100:0x3a:",
+ "g:11101:r:",
+ "g:11111:a:",
+ "g:110100:s:",
+ "g:110111:l:",
+ "g:111101:u:",
+ "g:1101011:b:",
+ "g:1101100:g:",
+ "g:1101101:o:",
+ "g:1111001:n:",
+ "g:11010100:2:",
+ "g:11110000:!:",
+ "g:111100011:d:",
+ "g:1101010100:.:",
+ "g:1101010101:,:",
+ "g:1101010110:':",
+ "g:1101010111:t:",
+ "g:1111000101:y:",
+ "g:11110001000:w:",
+ "g:111100010011:m:",
+ "g:11110001001011:?:",
+ "g:111100010010000:p:",
+ "g:111100010010001:f:",
+ "g:111100010010010:@:",
+ "g:111100010010011:-:",
+ "g:111100010010101:;:",
+ "g:1111000100101000:ESCAPE:",
+ "g:1111000100101001:z:",
+ "h:0:e:",
+ "h:101:o:",
+ "h:1001:i:",
+ "h:1100:a:",
+ "h:1110: :",
+ "h:1111:t:",
+ "h:11010:r:",
+ "h:11011:STOP:",
+ "h:100000:b:",
+ "h:100001:u:",
+ "h:10001000:w:",
+ "h:10001001:d:",
+ "h:10001010:n:",
+ "h:10001011:y:",
+ "h:10001100:!:",
+ "h:10001101:l:",
+ "h:10001111:.:",
+ "h:100011100:':",
+ "h:1000111010:s:",
+ "h:10001110110:m:",
+ "h:100011101111:0x3a:",
+ "h:10001110111000:f:",
+ "h:10001110111001:?:",
+ "h:10001110111010:c:",
+ "h:1000111011101100:v:",
+ "h:1000111011101101:q:",
+ "h:1000111011101110:g:",
+ "h:100011101110111100:h:",
+ "h:100011101110111101:ESCAPE:",
+ "h:100011101110111110:,:",
+ "h:100011101110111111:*:",
+ "i:01:n:",
+ "i:000:c:",
+ "i:1001:o:",
+ "i:1010:l:",
+ "i:1100:g:",
+ "i:1101:s:",
+ "i:1110:t:",
+ "i:1111:e:",
+ "i:00101:a:",
+ "i:00110:v:",
+ "i:10000:r:",
+ "i:10001:d:",
+ "i:10110:m:",
+ "i:001000:p:",
+ "i:001110: :",
+ "i:101111:f:",
+ "i:0011110:z:",
+ "i:0011111:STOP:",
+ "i:1011100:b:",
+ "i:1011101:k:",
+ "i:00100101:-:",
+ "i:00100110:x:",
+ "i:001001001:':",
+ "i:001001111:q:",
+ "i:0010011100:u:",
+ "i:0010011101:i:",
+ "i:00100100001:h:",
+ "i:00100100010:0x3a:",
+ "i:00100100011:w:",
+ "i:0010010000001:,:",
+ "i:0010010000010:y:",
+ "i:0010010000011:/:",
+ "i:00100100000000:.:",
+ "i:001001000000010:ESCAPE:",
+ "i:001001000000011:j:",
+ "j:0:y:",
+ "j:11:o:",
+ "j:101:e:",
+ "j:1001:a:",
+ "j:10001:u:",
+ "j:100001:i:",
+ "j:1000000:STOP:",
+ "j:10000010:ESCAPE:",
+ "j:10000011: :",
+ "k:00: :",
+ "k:10:e:",
+ "k:010:i:",
+ "k:110:STOP:",
+ "k:0110:y:",
+ "k:0111:s:",
+ "k:1111:f:",
+ "k:111001:a:",
+ "k:111010:l:",
+ "k:1110001:0x3a:",
+ "k:1110110:k:",
+ "k:11100000:':",
+ "k:11101111:.:",
+ "k:111000011:w:",
+ "k:111011100:o:",
+ "k:1110000101:h:",
+ "k:11100001000:b:",
+ "k:11100001001:,:",
+ "k:11101110111:n:",
+ "k:111011101010:?:",
+ "k:111011101100:m:",
+ "k:111011101101:!:",
+ "k:1110111010010:u:",
+ "k:1110111010011:c:",
+ "k:1110111010110:d:",
+ "k:1110111010111:t:",
+ "k:11101110100001:j:",
+ "k:11101110100010:-:",
+ "k:111011101000000:p:",
+ "k:111011101000001:/:",
+ "k:111011101000111:S:",
+ "k:1110111010001100:ESCAPE:",
+ "k:1110111010001101:r:",
+ "l:01:e:",
+ "l:000:l:",
+ "l:101:a:",
+ "l:0011:y:",
+ "l:1000:STOP:",
+ "l:1001:d:",
+ "l:1100:o:",
+ "l:1110:i:",
+ "l:1111: :",
+ "l:00100:u:",
+ "l:11010:s:",
+ "l:001010:t:",
+ "l:001011:m:",
+ "l:1101101:k:",
+ "l:11011000:f:",
+ "l:11011100:b:",
+ "l:11011110:':",
+ "l:11011111:c:",
+ "l:110110011:v:",
+ "l:110111010:0x3a:",
+ "l:1101100101:.:",
+ "l:1101110110:w:",
+ "l:11011001000:z:",
+ "l:11011101111:p:",
+ "l:110110010010:h:",
+ "l:110110010011:*:",
+ "l:1101110111000:g:",
+ "l:1101110111001:,:",
+ "l:11011101110100:r:",
+ "l:11011101110101:n:",
+ "l:11011101110111:-:",
+ "l:110111011101100:!:",
+ "l:1101110111011011:?:",
+ "l:11011101110110101:C:",
+ "l:110111011101101000:ESCAPE:",
+ "l:110111011101101001:j:",
+ "m:10:e:",
+ "m:001:m:",
+ "m:011: :",
+ "m:111:a:",
+ "m:0000:i:",
+ "m:0001:STOP:",
+ "m:0100:y:",
+ "m:1101:p:",
+ "m:01010:b:",
+ "m:11000:o:",
+ "m:110010:n:",
+ "m:110011:s:",
+ "m:0101100:l:",
+ "m:0101110:f:",
+ "m:01011010:0x3a:",
+ "m:01011110:4:",
+ "m:010110110:h:",
+ "m:010111110:w:",
+ "m:0101101111:':",
+ "m:0101111110:r:",
+ "m:0101111111:u:",
+ "m:01011011101:.:",
+ "m:010110111001:k:",
+ "m:0101101110000:ESCAPE:",
+ "m:0101101110001:d:",
+ "n:000:i:",
+ "n:100:g:",
+ "n:101: :",
+ "n:110:d:",
+ "n:0011:a:",
+ "n:0100:s:",
+ "n:0110:e:",
+ "n:1110:STOP:",
+ "n:1111:t:",
+ "n:01110:c:",
+ "n:01111:n:",
+ "n:001010:y:",
+ "n:010100:':",
+ "n:010101:k:",
+ "n:010111:o:",
+ "n:0010000:r:",
+ "n:0010011:f:",
+ "n:0010110:u:",
+ "n:0010111:j:",
+ "n:00100010:v:",
+ "n:00100100:-:",
+ "n:00100101:.:",
+ "n:01011000:l:",
+ "n:01011010:x:",
+ "n:01011011:0x3a:",
+ "n:001000111:,:",
+ "n:010110011:m:",
+ "n:0010001100:!:",
+ "n:00100011010:z:",
+ "n:01011001001:?:",
+ "n:01011001010:h:",
+ "n:01011001011:b:",
+ "n:001000110110:B:",
+ "n:001000110111:*:",
+ "n:010110010000:w:",
+ "n:0101100100011:q:",
+ "n:01011001000101:p:",
+ "n:010110010001000:;:",
+ "n:0101100100010010:/:",
+ "n:0101100100010011:ESCAPE:",
+ "o:00:r:",
+ "o:110:n:",
+ "o:0100:f:",
+ "o:0101: :",
+ "o:0110:w:",
+ "o:1000:o:",
+ "o:1011:u:",
+ "o:01111:t:",
+ "o:10010:c:",
+ "o:10100:p:",
+ "o:10101:d:",
+ "o:11100:m:",
+ "o:11110:l:",
+ "o:011100:a:",
+ "o:011101:b:",
+ "o:100110:y:",
+ "o:100111:STOP:",
+ "o:111010:s:",
+ "o:111011:k:",
+ "o:1111101:v:",
+ "o:1111110:g:",
+ "o:11111111:i:",
+ "o:111110001:h:",
+ "o:111110010:!:",
+ "o:111111100:e:",
+ "o:111111101:j:",
+ "o:1111100110:':",
+ "o:11111000001:?:",
+ "o:11111000010:0x3a:",
+ "o:11111001110:z:",
+ "o:11111001111:x:",
+ "o:111110000000:J:",
+ "o:111110000110:.:",
+ "o:111110000111:-:",
+ "o:11111000000100:4:",
+ "o:11111000000110:,:",
+ "o:11111000000111:G:",
+ "o:111110000001011:):",
+ "o:1111100000010100:S:",
+ "o:11111000000101010:D:",
+ "o:111110000001010110:ESCAPE:",
+ "o:111110000001010111:q:",
+ "p:00:e:",
+ "p:010:STOP:",
+ "p:100:i:",
+ "p:110:o:",
+ "p:0110:s:",
+ "p:1010: :",
+ "p:1110:p:",
+ "p:01110:l:",
+ "p:01111:r:",
+ "p:10110:h:",
+ "p:11110:a:",
+ "p:101110:t:",
+ "p:101111:':",
+ "p:1111100:d:",
+ "p:1111101:m:",
+ "p:1111110:y:",
+ "p:111111101:0x3a:",
+ "p:111111111:!:",
+ "p:1111111100:w:",
+ "p:1111111101:u:",
+ "p:11111110000:b:",
+ "p:11111110010:-:",
+ "p:11111110011:.:",
+ "p:111111100011:n:",
+ "p:1111111000101:k:",
+ "p:11111110001001:,:",
+ "p:111111100010000:ESCAPE:",
+ "p:111111100010001:c:",
+ "q:1:u:",
+ "q:01:STOP:",
+ "q:001:0x3a:",
+ "q:0000:ESCAPE:",
+ "q:0001:':",
+ "r:000: :",
+ "r:011:i:",
+ "r:101:e:",
+ "r:0011:y:",
+ "r:0100:d:",
+ "r:1000:s:",
+ "r:1001:t:",
+ "r:1100:a:",
+ "r:1101:STOP:",
+ "r:1111:o:",
+ "r:01011:n:",
+ "r:11101:l:",
+ "r:001001:k:",
+ "r:001010:r:",
+ "r:001011:m:",
+ "r:010101:u:",
+ "r:111001:g:",
+ "r:0010000:':",
+ "r:0101001:c:",
+ "r:1110001:0x3a:",
+ "r:00100010:f:",
+ "r:00100011:.:",
+ "r:01010001:b:",
+ "r:11100000:v:",
+ "r:010100000:,:",
+ "r:010100001:p:",
+ "r:111000010:w:",
+ "r:1110000111:j:",
+ "r:11100001100:-:",
+ "r:111000011010:h:",
+ "r:1110000110110:G:",
+ "r:11100001101110:q:",
+ "r:111000011011111:S:",
+ "r:1110000110111100:!:",
+ "r:111000011011110100:*:",
+ "r:111000011011110110:T:",
+ "r:1110000110111101010:ESCAPE:",
+ "r:1110000110111101011:E:",
+ "r:1110000110111101110:1:",
+ "r:1110000110111101111:/:",
+ "s:10: :",
+ "s:11:STOP:",
+ "s:011:t:",
+ "s:0000:s:",
+ "s:0010:i:",
+ "s:0011:h:",
+ "s:00011:;:",
+ "s:01010:e:",
+ "s:010001:o:",
+ "s:010011:c:",
+ "s:010110:0x3a:",
+ "s:0001000:.:",
+ "s:0001001:!:",
+ "s:0001011:y:",
+ "s:0100000:p:",
+ "s:0100100:a:",
+ "s:0101111:u:",
+ "s:00010100:,:",
+ "s:00010101:f:",
+ "s:01000011:':",
+ "s:01001011:n:",
+ "s:01011100:l:",
+ "s:01011101:r:",
+ "s:010000101:k:",
+ "s:010010100:d:",
+ "s:0100001001:m:",
+ "s:0100101011:b:",
+ "s:01000010000:?:",
+ "s:01000010001:w:",
+ "s:01001010100:g:",
+ "s:010010101010:q:",
+ "s:01001010101101:E:",
+ "s:01001010101110:-:",
+ "s:010010101011000:ESCAPE:",
+ "s:010010101011001:):",
+ "s:010010101011110:W:",
+ "s:010010101011111:1:",
+ "t:000:i:",
+ "t:011:STOP:",
+ "t:100: :",
+ "t:111:h:",
+ "t:0010:a:",
+ "t:0100:r:",
+ "t:1010:s:",
+ "t:1011:o:",
+ "t:1101:e:",
+ "t:00111:t:",
+ "t:01010:y:",
+ "t:11000:u:",
+ "t:010110:m:",
+ "t:110010:c:",
+ "t:110011:l:",
+ "t:0011000:':",
+ "t:0011010:0x3a:",
+ "t:00110010:w:",
+ "t:00110110:!:",
+ "t:01011100:.:",
+ "t:01011101:b:",
+ "t:01011110:E:",
+ "t:01011111:f:",
+ "t:001100110:?:",
+ "t:001101110:n:",
+ "t:0011001110:z:",
+ "t:0011011110:d:",
+ "t:00110011111:,:",
+ "t:00110111110:P:",
+ "t:001100111100:v:",
+ "t:001100111101:-:",
+ "t:001101111110:):",
+ "t:0011011111110:g:",
+ "t:00110111111110:ESCAPE:",
+ "t:001101111111110:S:",
+ "t:0011011111111111:4:",
+ "t:00110111111111100:k:",
+ "t:001101111111111010:j:",
+ "t:001101111111111011:p:",
+ "u:00:r:",
+ "u:100:s:",
+ "u:111:n:",
+ "u:0100:e:",
+ "u:0101:m:",
+ "u:1100:t:",
+ "u:01100:c:",
+ "u:01101:g:",
+ "u:01110:b:",
+ "u:10100:p:",
+ "u:10101:i:",
+ "u:10110:l:",
+ "u:11010:d:",
+ "u:11011:a:",
+ "u:011110:STOP:",
+ "u:101110:y:",
+ "u:0111110:z:",
+ "u:1011110: :",
+ "u:01111111:':",
+ "u:10111110:-:",
+ "u:011111100:k:",
+ "u:101111111:0x3a:",
+ "u:0111111010:f:",
+ "u:0111111011:,:",
+ "u:1011111100:w:",
+ "u:101111110100:v:",
+ "u:101111110101:x:",
+ "u:101111110111:o:",
+ "u:1011111101100:j:",
+ "u:10111111011010:u:",
+ "u:101111110110110:.:",
+ "u:1011111101101111:h:",
+ "u:10111111011011100:?:",
+ "u:10111111011011101:ESCAPE:",
+ "v:1:e:",
+ "v:01:i:",
+ "v:001:a:",
+ "v:0001:o:",
+ "v:00000: :",
+ "v:000011:STOP:",
+ "v:0000100:y:",
+ "v:00001011:s:",
+ "v:000010101:r:",
+ "v:0000101000:ESCAPE:",
+ "v:0000101001:.:",
+ "w:0:s:",
+ "w:100: :",
+ "w:110:STOP:",
+ "w:1011:i:",
+ "w:1110:o:",
+ "w:10100:a:",
+ "w:11110:n:",
+ "w:11111:e:",
+ "w:1010111:y:",
+ "w:10101000:m:",
+ "w:10101011:d:",
+ "w:10101101:l:",
+ "w:101010011:b:",
+ "w:101010100:k:",
+ "w:101010101:r:",
+ "w:1010100100:j:",
+ "w:1010110001:,:",
+ "w:1010110011:h:",
+ "w:10101001011:-:",
+ "w:10101100000:c:",
+ "w:10101100001:f:",
+ "w:10101100101:p:",
+ "w:101010010100:g:",
+ "w:101011001000:t:",
+ "w:1010100101010:.:",
+ "w:1010100101011:0x3a:",
+ "w:1010110010011:q:",
+ "w:10101100100101:':",
+ "w:101011001001001:?:",
+ "w:1010110010010000:ESCAPE:",
+ "w:1010110010010001:B:",
+ "x:00:p:",
+ "x:10: :",
+ "x:11:t:",
+ "x:0110:STOP:",
+ "x:01000:o:",
+ "x:01010:c:",
+ "x:01110:i:",
+ "x:01111:m:",
+ "x:010010:e:",
+ "x:010110:y:",
+ "x:0100110:u:",
+ "x:0100111:f:",
+ "x:0101111:,:",
+ "x:010111000:g:",
+ "x:010111001:a:",
+ "x:010111011:9:",
+ "x:0101110101:':",
+ "x:01011101001:x:",
+ "x:010111010000:ESCAPE:",
+ "x:010111010001:s:",
+ "y:0: :",
+ "y:11:STOP:",
+ "y:10001:o:",
+ "y:10010:s:",
+ "y:10100:a:",
+ "y:10110:l:",
+ "y:10111:0x3a:",
+ "y:100110:d:",
+ "y:1000001:n:",
+ "y:1000010:t:",
+ "y:1010100:':",
+ "y:1010101:b:",
+ "y:1010111:.:",
+ "y:10000000:i:",
+ "y:10000110:,:",
+ "y:10000111:p:",
+ "y:10011100:m:",
+ "y:10011110:c:",
+ "y:10101100:w:",
+ "y:10101101:e:",
+ "y:100000010:?:",
+ "y:100000011:f:",
+ "y:100111010:r:",
+ "y:100111011:g:",
+ "y:1001111100:z:",
+ "y:1001111110:-:",
+ "y:1001111111:T:",
+ "y:100111110100:2:",
+ "y:100111110110:!:",
+ "y:100111110111:k:",
+ "y:1001111101010:v:",
+ "y:10011111010110:y:",
+ "y:100111110101110:h:",
+ "y:1001111101011111:j:",
+ "y:10011111010111100:ESCAPE:",
+ "y:10011111010111101:):",
+ "z:00:z:",
+ "z:01:STOP:",
+ "z:101:i:",
+ "z:1000:y:",
+ "z:1001:e:",
+ "z:1100:w:",
+ "z:1101: :",
+ "z:1110:l:",
+ "z:11110:a:",
+ "z:111110:o:",
+ "z:11111100:m:",
+ "z:11111101:0x3a:",
+ "z:11111111:c:",
+ "z:111111100:,:",
+ "z:1111111011:b:",
+ "z:11111110100:u:",
+ "z:111111101011:!:",
+ "z:11111110101000:ESCAPE:",
+ "z:11111110101001:t:",
+ "z:11111110101010:h:",
+ "z:11111110101011:?:",
+ "{:0:ESCAPE:",
+ "{:1:ESCAPE:",
+ "|:0:ESCAPE:",
+ "|:1:ESCAPE:",
+ "}:0:ESCAPE:",
+ "}:1:ESCAPE:",
+ "~:0:ESCAPE:",
+ "~:1:ESCAPE:",
+ "0x7f:0:ESCAPE:",
+ "0x7f:1:ESCAPE:",
+ NULL
+};
+
+static const char *FreesatT2[] = {
+ "START:010:A:",
+ "START:100:C:",
+ "START:111:T:",
+ "START:0001:J:",
+ "START:0011:D:",
+ "START:1010:S:",
+ "START:00000:H:",
+ "START:00100:I:",
+ "START:00101:R:",
+ "START:01101:F:",
+ "START:01110:.:",
+ "START:01111:W:",
+ "START:10111:M:",
+ "START:11000:B:",
+ "START:11001:P:",
+ "START:11011:N:",
+ "START:000010:O:",
+ "START:011001:[:",
+ "START:101101:L:",
+ "START:110101:E:",
+ "START:0000110:K:",
+ "START:1101000:Y:",
+ "START:1101001:G:",
+ "START:00001110:2:",
+ "START:01100000:p:",
+ "START:01100001:b:",
+ "START:01100010:U:",
+ "START:01100011:(:",
+ "START:10110000:1:",
+ "START:10110011:V:",
+ "START:000011110:Q:",
+ "START:101100010:3:",
+ "START:0000111110:9:",
+ "START:0000111111:8:",
+ "START:1011000110:6:",
+ "START:1011000111:5:",
+ "START:1011001000:Z:",
+ "START:1011001001:7:",
+ "START:1011001010:4:",
+ "START:101100101110:X:",
+ "START:101100101111: :",
+ "START:1011001011001:w:",
+ "START:1011001011010:':",
+ "START:1011001011011:\":",
+ "START:10110010110000:t:",
+ "START:101100101100010:a:",
+ "START:1011001011000110:`:",
+ "START:10110010110001110:ESCAPE:",
+ "START:10110010110001111:m:",
+ "ESCAPE:0:ESCAPE:",
+ "ESCAPE:1:ESCAPE:",
+ "STOP:0:ESCAPE:",
+ "STOP:1:ESCAPE:",
+ "0x03:0:ESCAPE:",
+ "0x03:1:ESCAPE:",
+ "0x04:0:ESCAPE:",
+ "0x04:1:ESCAPE:",
+ "0x05:0:ESCAPE:",
+ "0x05:1:ESCAPE:",
+ "0x06:0:ESCAPE:",
+ "0x06:1:ESCAPE:",
+ "0x07:0:ESCAPE:",
+ "0x07:1:ESCAPE:",
+ "0x08:0:ESCAPE:",
+ "0x08:1:ESCAPE:",
+ "0x09:0:ESCAPE:",
+ "0x09:1:ESCAPE:",
+ "0x0a:0:ESCAPE:",
+ "0x0a:1:ESCAPE:",
+ "0x0b:0:ESCAPE:",
+ "0x0b:1:ESCAPE:",
+ "0x0c:0:ESCAPE:",
+ "0x0c:1:ESCAPE:",
+ "0x0d:0:ESCAPE:",
+ "0x0d:1:ESCAPE:",
+ "0x0e:0:ESCAPE:",
+ "0x0e:1:ESCAPE:",
+ "0x0f:0:ESCAPE:",
+ "0x0f:1:ESCAPE:",
+ "0x10:0:ESCAPE:",
+ "0x10:1:ESCAPE:",
+ "0x11:0:ESCAPE:",
+ "0x11:1:ESCAPE:",
+ "0x12:0:ESCAPE:",
+ "0x12:1:ESCAPE:",
+ "0x13:0:ESCAPE:",
+ "0x13:1:ESCAPE:",
+ "0x14:0:ESCAPE:",
+ "0x14:1:ESCAPE:",
+ "0x15:0:ESCAPE:",
+ "0x15:1:ESCAPE:",
+ "0x16:0:ESCAPE:",
+ "0x16:1:ESCAPE:",
+ "0x17:0:ESCAPE:",
+ "0x17:1:ESCAPE:",
+ "0x18:0:ESCAPE:",
+ "0x18:1:ESCAPE:",
+ "0x19:0:ESCAPE:",
+ "0x19:1:ESCAPE:",
+ "0x1a:0:ESCAPE:",
+ "0x1a:1:ESCAPE:",
+ "0x1b:0:ESCAPE:",
+ "0x1b:1:ESCAPE:",
+ "0x1c:0:ESCAPE:",
+ "0x1c:1:ESCAPE:",
+ "0x1d:0:ESCAPE:",
+ "0x1d:1:ESCAPE:",
+ "0x1e:0:ESCAPE:",
+ "0x1e:1:ESCAPE:",
+ "0x1f:0:ESCAPE:",
+ "0x1f:1:ESCAPE:",
+ " :010:a:",
+ " :100:t:",
+ " :0001:o:",
+ " :0010:s:",
+ " :00110:d:",
+ " :01100:[:",
+ " :01111:p:",
+ " :10101:b:",
+ " :11001:c:",
+ " :11010:h:",
+ " :11100:w:",
+ " :11101:i:",
+ " :11111:f:",
+ " :000000:A:",
+ " :000011:M:",
+ " :001111:e:",
+ " :011100:B:",
+ " :011101:C:",
+ " :101000:T:",
+ " :101101:S:",
+ " :101110:g:",
+ " :110000:r:",
+ " :110110:n:",
+ " :110111:l:",
+ " :111101:m:",
+ " :0000011:v:",
+ " :0000100:G:",
+ " :0000101:N:",
+ " :0011101:y:",
+ " :0110101:H:",
+ " :0110111:L:",
+ " :1010010:J:",
+ " :1010011:F:",
+ " :1011001:R:",
+ " :1011110:u:",
+ " :1100010:D:",
+ " :1100011:W:",
+ " :1111001:P:",
+ " :00000100:k:",
+ " :00000101:O:",
+ " :01101000:-:",
+ " :01101101:1:",
+ " :10110001:K:",
+ " :10111110:j:",
+ " :11110000:I:",
+ " :11110001:E:",
+ " :001110010:q:",
+ " :001110011:U:",
+ " :011010010:V:",
+ " :011011000:Y:",
+ " :011011001: :",
+ " :101100001:2:",
+ " :101111110:STOP:",
+ " :0011100000:3:",
+ " :0011100001:8:",
+ " :0011100010:6:",
+ " :0110100111:5:",
+ " :1011000000:(:",
+ " :1011111110:7:",
+ " :00111000110:0:",
+ " :01101001100:':",
+ " :01101001101:9:",
+ " :10110000010:Z:",
+ " :10111111110:4:",
+ " :10111111111:Q:",
+ " :001110001111:X:",
+ " :1011000001100:ESCAPE:",
+ " :1011000001101:.:",
+ " :1011000001110:&:",
+ " :00111000111000:\\:",
+ " :00111000111010:@:",
+ " :00111000111011:`:",
+ " :10110000011110:\":",
+ " :10110000011111:z:",
+ " :001110001110011:$:",
+ " :0011100011100100:+:",
+ " :00111000111001011:x:",
+ " :001110001110010101:]:",
+ " :0011100011100101000:/:",
+ " :0011100011100101001:?:",
+ "!:1: :",
+ "!:01:STOP:",
+ "!:001:.:",
+ "!:0000:0x3a:",
+ "!:00011:[:",
+ "!:0001001:\":",
+ "!:0001010:/:",
+ "!:0001011:!:",
+ "!:00010000:):",
+ "!:000100010:':",
+ "!:0001000111:?:",
+ "!:00010001100:ESCAPE:",
+ "!:00010001101:]:",
+ "\":11: :",
+ "\":001:.:",
+ "\":0000:p:",
+ "\":0101:B:",
+ "\":0111:T:",
+ "\":1000:i:",
+ "\":00010:f:",
+ "\":00011:W:",
+ "\":01000:S:",
+ "\":01100:t:",
+ "\":01101:C:",
+ "\":10100:STOP:",
+ "\":10111:,:",
+ "\":010010:J:",
+ "\":100100:m:",
+ "\":101010:n:",
+ "\":101011:I:",
+ "\":0100110:E:",
+ "\":0100111:D:",
+ "\":1001010:w:",
+ "\":1001011:g:",
+ "\":1001100:b:",
+ "\":1001101:L:",
+ "\":1001110:-:",
+ "\":1011000:c:",
+ "\":1011001:H:",
+ "\":10011110:P:",
+ "\":10110100:r:",
+ "\":10110111:K:",
+ "\":100111111:l:",
+ "\":101101010:Y:",
+ "\":101101011:Q:",
+ "\":101101100:G:",
+ "\":101101101:A:",
+ "\":1001111100:ESCAPE:",
+ "\":1001111101:a:",
+ "#:0:ESCAPE:",
+ "#:1:ESCAPE:",
+ "$:0:1:",
+ "$:11:3:",
+ "$:100:4:",
+ "$:1011:2:",
+ "$:10101:7:",
+ "$:101001:5:",
+ "$:1010000:ESCAPE:",
+ "$:1010001:9:",
+ "%:1: :",
+ "%:00:ESCAPE:",
+ "%:01:,:",
+ "&:1: :",
+ "&:01:w:",
+ "&:001:B:",
+ "&:0000:E:",
+ "&:000100:2:",
+ "&:000110:A:",
+ "&:000111:R:",
+ "&:00010100:O:",
+ "&:00010101:4:",
+ "&:00010111:J:",
+ "&:000101100:ESCAPE:",
+ "&:000101101:P:",
+ "':1:s:",
+ "':001:t:",
+ "':010: :",
+ "':0000:l:",
+ "':01101:r:",
+ "':000100:n:",
+ "':000101:.:",
+ "':000110:C:",
+ "':011000:B:",
+ "':011101:A:",
+ "':0111000:d:",
+ "':0111100:v:",
+ "':00011100:S:",
+ "':00011111:p:",
+ "':01100101:D:",
+ "':01111011:i:",
+ "':01111100:c:",
+ "':01111101:m:",
+ "':01111111:,:",
+ "':000111010:f:",
+ "':000111011:g:",
+ "':011001000:F:",
+ "':011001001:h:",
+ "':011001101:H:",
+ "':011001110:N:",
+ "':011100101:R:",
+ "':011100110:STOP:",
+ "':011100111:T:",
+ "':011110101:G:",
+ "':011111101:L:",
+ "':0001111000:o:",
+ "':0001111001:K:",
+ "':0001111011:a:",
+ "':0110011001:u:",
+ "':0110011111:O:",
+ "':0111001001:I:",
+ "':0111101000:w:",
+ "':0111101001:b:",
+ "':0111111001:e:",
+ "':00011110101:?:",
+ "':01100110000:E:",
+ "':01100110001:7:",
+ "':01110010000:P:",
+ "':000111101001:W:",
+ "':011001111001:0x3a:",
+ "':011001111010:!:",
+ "':011100100011:J:",
+ "':011111100001:q:",
+ "':011111100011:M:",
+ "':0001111010001:V:",
+ "':0110011110001:9:",
+ "':0110011110111:y:",
+ "':0111001000100:8:",
+ "':0111001000101:5:",
+ "':0111111000000:6:",
+ "':0111111000101:k:",
+ "':00011110100000:2:",
+ "':00011110100001:0:",
+ "':01100111100001:Y:",
+ "':01100111101100:):",
+ "':01111110000010:j:",
+ "':01111110000011:Q:",
+ "':011001111000000:-:",
+ "':011001111000001:':",
+ "':011001111011011:z:",
+ "':011111100010000:X:",
+ "':011111100010001:U:",
+ "':011111100010010:4:",
+ "':011111100010011:3:",
+ "':0110011110110100:ESCAPE:",
+ "':0110011110110101:1:",
+ "(:01:1:",
+ "(:000:P:",
+ "(:101:t:",
+ "(:1000:2:",
+ "(:1101:5:",
+ "(:1110:N:",
+ "(:00111:T:",
+ "(:10010:p:",
+ "(:11111:c:",
+ "(:001001:a:",
+ "(:001010:S:",
+ "(:001100:R:",
+ "(:100111:e:",
+ "(:111100:J:",
+ "(:111101:A:",
+ "(:0010110:D:",
+ "(:0011011:K:",
+ "(:1001100:v:",
+ "(:1001101:s:",
+ "(:1100000:b:",
+ "(:1100010:G:",
+ "(:1100011:8:",
+ "(:1100100:M:",
+ "(:1100101:H:",
+ "(:1100110:C:",
+ "(:00100000:m:",
+ "(:00100010:o:",
+ "(:00100011:E:",
+ "(:00101110:W:",
+ "(:11000011:g:",
+ "(:11001110:L:",
+ "(:001000010:d:",
+ "(:001011111:U:",
+ "(:001101000:F:",
+ "(:001101010:f:",
+ "(:110000100:w:",
+ "(:110000101:B:",
+ "(:110011111:n:",
+ "(:0010000110:l:",
+ "(:0010000111:9:",
+ "(:0010111100:4:",
+ "(:0010111101:I:",
+ "(:0011010010:3:",
+ "(:0011010111:h:",
+ "(:1100111101:i:",
+ "(:00110100110:Z:",
+ "(:00110100111:V:",
+ "(:00110101100: :",
+ "(:11001111000:k:",
+ "(:001101011011:O:",
+ "(:110011110010:':",
+ "(:0011010110100:ESCAPE:",
+ "(:0011010110101:u:",
+ "(:1100111100110:X:",
+ "(:1100111100111:7:",
+ "):0: :",
+ "):11:.:",
+ "):101:STOP:",
+ "):1001:,:",
+ "):10000:0x3a:",
+ "):100011:;:",
+ "):1000101:!:",
+ "):10001001:(:",
+ "):1000100000:ESCAPE:",
+ "):1000100001:o:",
+ "):1000100010:?:",
+ "):1000100011:):",
+ "*:0:*:",
+ "*:100:s:",
+ "*:101: :",
+ "*:1100:m:",
+ "*:1110:t:",
+ "*:11010:g:",
+ "*:11011:k:",
+ "*:11111:d:",
+ "*:111101:y:",
+ "*:1111001:e:",
+ "*:11110000:i:",
+ "*:111100010:ESCAPE:",
+ "*:111100011:n:",
+ "+:1:n:",
+ "+:00:ESCAPE:",
+ "+:01: :",
+ ",:1: :",
+ ",:01:S:",
+ ",:001:0:",
+ ",:0001:A:",
+ ",:00000:5:",
+ ",:0000110:b:",
+ ",:0000111:3:",
+ ",:00001000:2:",
+ ",:00001001:\":",
+ ",:00001011:1:",
+ ",:0000101000:Q:",
+ ",:0000101010:':",
+ ",:00001010111:4:",
+ ",:000010100100:T:",
+ ",:000010100101:B:",
+ ",:000010100110:7:",
+ ",:000010100111:6:",
+ ",:000010101100:STOP:",
+ ",:0000101011010:ESCAPE:",
+ ",:0000101011011:i:",
+ "-:00: :",
+ "-:0100:t:",
+ "-:0101:b:",
+ "-:0110:w:",
+ "-:0111:u:",
+ "-:1001:o:",
+ "-:1010:s:",
+ "-:1011:f:",
+ "-:10000:c:",
+ "-:11011:l:",
+ "-:11101:d:",
+ "-:100010:9:",
+ "-:110000:h:",
+ "-:110010:1:",
+ "-:110011:y:",
+ "-:110101:r:",
+ "-:111000:a:",
+ "-:111100:m:",
+ "-:111110:p:",
+ "-:1000110:S:",
+ "-:1101000:e:",
+ "-:1101001:i:",
+ "-:1111011:n:",
+ "-:10001110:C:",
+ "-:11000101:W:",
+ "-:11000111:g:",
+ "-:11100101:J:",
+ "-:11100110:D:",
+ "-:11110101:2:",
+ "-:11111100:7:",
+ "-:11111110:G:",
+ "-:11111111:O:",
+ "-:100011111:H:",
+ "-:110001000:A:",
+ "-:110001100:6:",
+ "-:110001101:B:",
+ "-:111001111:M:",
+ "-:111101000:E:",
+ "-:111101001:L:",
+ "-:111111010:U:",
+ "-:111111011:k:",
+ "-:1000111100:F:",
+ "-:1100010010:j:",
+ "-:1100010011:P:",
+ "-:1110010001:q:",
+ "-:1110010010:5:",
+ "-:1110010011:T:",
+ "-:1110011101:I:",
+ "-:10001111011:K:",
+ "-:11100100000:v:",
+ "-:11100100001:Z:",
+ "-:11100111001:N:",
+ "-:100011110101:R:",
+ "-:111001110001:Y:",
+ "-:1000111101001:0:",
+ "-:10001111010000:4:",
+ "-:10001111010001:z:",
+ "-:11100111000001:V:",
+ "-:11100111000010:3:",
+ "-:11100111000011:8:",
+ "-:111001110000001:Q:",
+ "-:1110011100000000:':",
+ "-:11100111000000010:ESCAPE:",
+ "-:11100111000000011:x:",
+ ".:1: :",
+ ".:01:STOP:",
+ ".:0011:.:",
+ ".:00010:i:",
+ ".:00100:0:",
+ ".:00101:c:",
+ ".:000001:u:",
+ ".:0000000:a:",
+ ".:0000001:[:",
+ ".:0001101:3:",
+ ".:00001000:4:",
+ ".:00001110:H:",
+ ".:00011000:S:",
+ ".:00011001:W:",
+ ".:00011100:o:",
+ ".:00011110:1:",
+ ".:000010100:5:",
+ ".:000010101:L:",
+ ".:000010111:p:",
+ ".:000011000:T:",
+ ".:000011001:A:",
+ ".:000011010:M:",
+ ".:000011110:C:",
+ ".:000011111:2:",
+ ".:000111011:D:",
+ ".:000111110:B:",
+ ".:0000100100:N:",
+ ".:0000100110:t:",
+ ".:0000100111:J:",
+ ".:0000101101:R:",
+ ".:0000110111:P:",
+ ".:0001110101:s:",
+ ".:0001111111:I:",
+ ".:00001011000:r:",
+ ".:00001101100:V:",
+ ".:00011101000:w:",
+ ".:00011101001:F:",
+ ".:00011111101:G:",
+ ".:000010010100:E:",
+ ".:000010010101:0x3a:",
+ ".:000010110010:h:",
+ ".:000011011010:,:",
+ ".:000111111000:':",
+ ".:0000100101101:b:",
+ ".:0000100101110:K:",
+ ".:0000100101111:Y:",
+ ".:0000101100111:O:",
+ ".:0000110110110:-:",
+ ".:0001111110010:f:",
+ ".:0001111110011:(:",
+ ".:00001011001100:\":",
+ ".:00001101101110:y:",
+ ".:000010010110000:?:",
+ ".:000010010110001:m:",
+ ".:000010010110010:Q:",
+ ".:000011011011110:*:",
+ ".:000011011011111:&:",
+ ".:0000100101100110:U:",
+ ".:0000100101100111:;:",
+ ".:0000101100110100:8:",
+ ".:0000101100110101:6:",
+ ".:0000101100110111:k:",
+ ".:00001011001101100:d:",
+ ".:000010110011011010:ESCAPE:",
+ ".:000010110011011011:n:",
+ "/:01:c:",
+ "/:110:1:",
+ "/:111:e:",
+ "/:0000:5:",
+ "/:0010:8:",
+ "/:00010:T:",
+ "/:00011:f:",
+ "/:00110:B:",
+ "/:00111:2:",
+ "/:10001:3:",
+ "/:10010:7:",
+ "/:10100:6:",
+ "/:10110:a:",
+ "/:101111:4:",
+ "/:1000000:F:",
+ "/:1000010:s:",
+ "/:1000011:M:",
+ "/:1001100:H:",
+ "/:1001110:D:",
+ "/:1001111:A:",
+ "/:1010101:S:",
+ "/:10000011:m:",
+ "/:10011010:W:",
+ "/:10101000:G:",
+ "/:10101001:U:",
+ "/:10101100:d:",
+ "/:10101101:O:",
+ "/:10101110:N:",
+ "/:10111001:C:",
+ "/:10111011:P:",
+ "/:100110110:L:",
+ "/:101011110: :",
+ "/:101011111:I:",
+ "/:101110000:E:",
+ "/:101110001:R:",
+ "/:101110100:K:",
+ "/:101110101:t:",
+ "/:1000001001:J:",
+ "/:1000001011:9:",
+ "/:10000010000:v:",
+ "/:10000010001:p:",
+ "/:10000010100:h:",
+ "/:10011011101:o:",
+ "/:10011011110:Q:",
+ "/:10011011111:0:",
+ "/:100000101010:l:",
+ "/:100000101011:i:",
+ "/:100110111000:V:",
+ "/:1001101110011:y:",
+ "/:10011011100100:ESCAPE:",
+ "/:10011011100101:g:",
+ "0:0:0:",
+ "0:111: :",
+ "0:1001:a:",
+ "0:1011:p:",
+ "0:10001:s:",
+ "0:11000:.:",
+ "0:11001:8:",
+ "0:11011:,:",
+ "0:100000:4:",
+ "0:100001:t:",
+ "0:101001:5:",
+ "0:110100:6:",
+ "0:1010000:3:",
+ "0:1010001:7:",
+ "0:1010101:]:",
+ "0:1010110:-:",
+ "0:1010111:1:",
+ "0:10101000:):",
+ "0:10101001:/:",
+ "0:11010100:STOP:",
+ "0:11010101:9:",
+ "0:11010111:2:",
+ "0:110101100:%:",
+ "0:1101011010:0x3a:",
+ "0:110101101101:f:",
+ "0:110101101111:m:",
+ "0:1101011011100:y:",
+ "0:11010110110001:l:",
+ "0:11010110110010:;:",
+ "0:11010110110011:':",
+ "0:11010110111010:k:",
+ "0:11010110111011:!:",
+ "0:110101101100000:C:",
+ "0:1101011011000010:ESCAPE:",
+ "0:1101011011000011:J:",
+ "1:00:9:",
+ "1:100:1:",
+ "1:111:0:",
+ "1:0101: :",
+ "1:0111:2:",
+ "1:1011:.:",
+ "1:1100:5:",
+ "1:01000:6:",
+ "1:01001:8:",
+ "1:01101:/:",
+ "1:10100:]:",
+ "1:11010:3:",
+ "1:011001:7:",
+ "1:110110:4:",
+ "1:0110000:STOP:",
+ "1:0110001:-:",
+ "1:1010100:):",
+ "1:1010110:0x3a:",
+ "1:1010111:s:",
+ "1:1101110:,:",
+ "1:1101111:x:",
+ "1:10101010:':",
+ "1:101010110:X:",
+ "1:10101011110:t:",
+ "1:10101011111:R:",
+ "1:101010111011:;:",
+ "1:1010101110000:p:",
+ "1:1010101110001:m:",
+ "1:1010101110010:!:",
+ "1:1010101110101:&:",
+ "1:10101011100110:e:",
+ "1:101010111001110:b:",
+ "1:101010111001111:a:",
+ "1:101010111010000:D:",
+ "1:101010111010001:C:",
+ "1:101010111010010:%:",
+ "1:1010101110100110:ESCAPE:",
+ "1:1010101110100111:o:",
+ "2:11:0:",
+ "2:000: :",
+ "2:010:.:",
+ "2:100:5:",
+ "2:0011:/:",
+ "2:1011:,:",
+ "2:00100:]:",
+ "2:00101:p:",
+ "2:01101:1:",
+ "2:10101:4:",
+ "2:011000:6:",
+ "2:011001:2:",
+ "2:011100:0x3a:",
+ "2:011101:-:",
+ "2:011111:):",
+ "2:1010000:STOP:",
+ "2:1010010:8:",
+ "2:1010011:9:",
+ "2:01111000:D:",
+ "2:01111001:3:",
+ "2:01111010:t:",
+ "2:01111011:7:",
+ "2:10100010:n:",
+ "2:101000110:a:",
+ "2:1010001110:':",
+ "2:10100011111:;:",
+ "2:101000111100:s:",
+ "2:1010001111010:\":",
+ "2:101000111101100:ESCAPE:",
+ "2:101000111101101:i:",
+ "2:101000111101110:W:",
+ "2:101000111101111:L:",
+ "3:00: :",
+ "3:10:0:",
+ "3:110:.:",
+ "3:1110:/:",
+ "3:01000:2:",
+ "3:01001:1:",
+ "3:01010:):",
+ "3:01100:0x3a:",
+ "3:01110:-:",
+ "3:11111:]:",
+ "3:010110:D:",
+ "3:011010:4:",
+ "3:011011:STOP:",
+ "3:011111:5:",
+ "3:111100:,:",
+ "3:0101110:7:",
+ "3:0101111:3:",
+ "3:0111101:6:",
+ "3:1111011:t:",
+ "3:01111001:B:",
+ "3:11110100:8:",
+ "3:111101010:9:",
+ "3:0111100001:;:",
+ "3:1111010110:r:",
+ "3:1111010111:s:",
+ "3:01111000000:n:",
+ "3:01111000101:b:",
+ "3:01111000110:':",
+ "3:01111000111:A:",
+ "3:011110000010:p:",
+ "3:011110000011:e:",
+ "3:0111100010000:a:",
+ "3:0111100010001:&:",
+ "3:0111100010010:%:",
+ "3:01111000100110:ESCAPE:",
+ "3:01111000100111:k:",
+ "4:01: :",
+ "4:000:4:",
+ "4:100:.:",
+ "4:110:0:",
+ "4:0010:/:",
+ "4:1010:5:",
+ "4:1011:-:",
+ "4:00110:1:",
+ "4:11101:]:",
+ "4:11110:,:",
+ "4:001110:2:",
+ "4:111001:8:",
+ "4:111110:):",
+ "4:0011110:0x3a:",
+ "4:0011111:':",
+ "4:1110000:t:",
+ "4:1110001:3:",
+ "4:1111111:STOP:",
+ "4:11111101:6:",
+ "4:1111110000:9:",
+ "4:1111110010:7:",
+ "4:11111100011:C:",
+ "4:11111100110:;:",
+ "4:111111000101:x:",
+ "4:1111110011101:m:",
+ "4:1111110011110:I:",
+ "4:11111100010000:f:",
+ "4:11111100010001:e:",
+ "4:11111100010010:b:",
+ "4:11111100010011:L:",
+ "4:11111100111000:%:",
+ "4:11111100111110:p:",
+ "4:11111100111111:c:",
+ "4:111111001110010:ESCAPE:",
+ "4:111111001110011:i:",
+ "5:00:0:",
+ "5:10: :",
+ "5:010:.:",
+ "5:0111:p:",
+ "5:1100:5:",
+ "5:01100:/:",
+ "5:11010:a:",
+ "5:11011:-:",
+ "5:11101:6:",
+ "5:011010:3:",
+ "5:111100:2:",
+ "5:111110:8:",
+ "5:111111:]:",
+ "5:0110110:0x3a:",
+ "5:1110000:):",
+ "5:1110001:s:",
+ "5:1110011:,:",
+ "5:1111010:7:",
+ "5:1111011:9:",
+ "5:01101110:4:",
+ "5:11100100:STOP:",
+ "5:11100101:t:",
+ "5:0110111110:c:",
+ "5:0110111111:1:",
+ "5:01101111001:;:",
+ "5:01101111011:m:",
+ "5:011011110000:e:",
+ "5:011011110001:':",
+ "5:011011110101:k:",
+ "5:0110111101001:l:",
+ "5:01101111010000:ESCAPE:",
+ "5:01101111010001:f:",
+ "6:00: :",
+ "6:10:.:",
+ "6:111:0:",
+ "6:0101:]:",
+ "6:01001:1:",
+ "6:01100:7:",
+ "6:01110:):",
+ "6:11000:,:",
+ "6:11001:0x3a:",
+ "6:11010:/:",
+ "6:010001:-:",
+ "6:011010:5:",
+ "6:011011:4:",
+ "6:011111:8:",
+ "6:110111:t:",
+ "6:0100000:6:",
+ "6:0111100:3:",
+ "6:0111101:2:",
+ "6:1101101:9:",
+ "6:01000010:STOP:",
+ "6:01000011:+:",
+ "6:11011000:':",
+ "6:1101100101:a:",
+ "6:1101100110:?:",
+ "6:11011001000:m:",
+ "6:11011001001:e:",
+ "6:11011001110:;:",
+ "6:1101100111100:f:",
+ "6:1101100111101:b:",
+ "6:1101100111110:M:",
+ "6:11011001111110:\":",
+ "6:110110011111110:ESCAPE:",
+ "6:110110011111111:i:",
+ "7:11:.:",
+ "7:001: :",
+ "7:011:0:",
+ "7:101:-:",
+ "7:0000:8:",
+ "7:0100:7:",
+ "7:1001:]:",
+ "7:01010:/:",
+ "7:000101:6:",
+ "7:000110:2:",
+ "7:000111:1:",
+ "7:010111:t:",
+ "7:100000:9:",
+ "7:100010:):",
+ "7:100011:5:",
+ "7:0001001:3:",
+ "7:0101101:,:",
+ "7:1000010:a:",
+ "7:1000011:4:",
+ "7:00010000:STOP:",
+ "7:01011000:0x3a:",
+ "7:01011001:p:",
+ "7:0001000101:R:",
+ "7:0001000110:;:",
+ "7:00010001000:':",
+ "7:00010001111:m:",
+ "7:000100010011:f:",
+ "7:000100011100:A:",
+ "7:000100011101:?:",
+ "7:0001000100100:ESCAPE:",
+ "7:0001000100101:s:",
+ "8:01: :",
+ "8:000:4:",
+ "8:110:.:",
+ "8:0011:0:",
+ "8:1000:9:",
+ "8:1001:7:",
+ "8:1011:8:",
+ "8:1110:1:",
+ "8:00100:/:",
+ "8:10100:3:",
+ "8:11110:5:",
+ "8:101010:):",
+ "8:111110:6:",
+ "8:111111:]:",
+ "8:0010100:0x3a:",
+ "8:0010101:,:",
+ "8:1010111:t:",
+ "8:00101100:p:",
+ "8:00101101:-:",
+ "8:00101111:a:",
+ "8:10101100:c:",
+ "8:10101101:2:",
+ "8:001011101:STOP:",
+ "8:0010111001:;:",
+ "8:001011100000:l:",
+ "8:001011100001:':",
+ "8:0010111000100:f:",
+ "8:0010111000101:D:",
+ "8:0010111000110:A:",
+ "8:00101110001110:ESCAPE:",
+ "8:00101110001111:i:",
+ "9:000:5:",
+ "9:001:]:",
+ "9:111:9:",
+ "9:0101:0:",
+ "9:0110:.:",
+ "9:0111:-:",
+ "9:1000:4:",
+ "9:1001:8:",
+ "9:1011:6:",
+ "9:1100: :",
+ "9:1101:7:",
+ "9:01000:2:",
+ "9:10100:3:",
+ "9:010010:1:",
+ "9:010011:/:",
+ "9:101010:t:",
+ "9:1010111:):",
+ "9:10101100:0x3a:",
+ "9:101011010:,:",
+ "9:10101101100:p:",
+ "9:10101101101:;:",
+ "9:10101101111:STOP:",
+ "9:1010110111000:n:",
+ "9:1010110111001:m:",
+ "9:1010110111010:a:",
+ "9:10101101110111:e:",
+ "9:101011011101100:ESCAPE:",
+ "9:101011011101101:k:",
+ "0x3a:1: :",
+ "0x3a:01:0:",
+ "0x3a:001:3:",
+ "0x3a:00001:1:",
+ "0x3a:00010:T:",
+ "0x3a:00011:C:",
+ "0x3a:000001:4:",
+ "0x3a:0000000:ESCAPE:",
+ "0x3a:0000001:5:",
+ ";:0:ESCAPE:",
+ ";:1: :",
+ "<:0:ESCAPE:",
+ "<:1:ESCAPE:",
+ "=:0:ESCAPE:",
+ "=:1:ESCAPE:",
+ ">:0:ESCAPE:",
+ ">:1:ESCAPE:",
+ "?:1: :",
+ "?:01:STOP:",
+ "?:000:0x3a:",
+ "?:00100:!:",
+ "?:00110:[:",
+ "?:00111:.:",
+ "?:001010:;:",
+ "?:0010110:':",
+ "?:00101111:,:",
+ "?:001011101:/:",
+ "?:0010111000:ESCAPE:",
+ "?:0010111001:Q:",
+ "@:0:k:",
+ "@:10: :",
+ "@:111:T:",
+ "@:1101:b:",
+ "@:11000:ESCAPE:",
+ "@:11001:H:",
+ "A:01: :",
+ "A:110:D:",
+ "A:111:n:",
+ "A:0000:s:",
+ "A:0001:m:",
+ "A:0010:d:",
+ "A:1000:r:",
+ "A:1011:l:",
+ "A:00110:c:",
+ "A:10010:u:",
+ "A:10100:g:",
+ "A:001111:b:",
+ "A:100111:t:",
+ "A:101011:f:",
+ "A:1010100:w:",
+ "A:1010101:i:",
+ "A:10011001:v:",
+ "A:10011011:p:",
+ "A:001110010:h:",
+ "A:001110100:.:",
+ "A:001110111:B:",
+ "A:100110100:q:",
+ "A:0011100000:C:",
+ "A:0011100010:,:",
+ "A:0011100110:y:",
+ "A:0011101010:S:",
+ "A:0011101100:k:",
+ "A:0011101101:T:",
+ "A:1001100001:R:",
+ "A:1001100010:F:",
+ "A:1001100011:z:",
+ "A:1001101011:a:",
+ "A:00111000010:P:",
+ "A:00111000110:-:",
+ "A:00111010110:A:",
+ "A:00111010111:I:",
+ "A:10011000001:e:",
+ "A:10011010100:N:",
+ "A:10011010101:x:",
+ "A:001110000110:X:",
+ "A:001110000111:K:",
+ "A:001110001110:3:",
+ "A:001110001111:&:",
+ "A:001110011101:M:",
+ "A:001110011111:Y:",
+ "A:0011100111000:L:",
+ "A:0011100111001:W:",
+ "A:0011100111100:*:",
+ "A:1001100000000:o:",
+ "A:1001100000001:1:",
+ "A:1001100000010:':",
+ "A:1001100000011:0x3a:",
+ "A:00111001111010:j:",
+ "A:001110011110110:G:",
+ "A:0011100111101110:O:",
+ "A:00111001111011110:4:",
+ "A:001110011110111110:ESCAPE:",
+ "A:001110011110111111:E:",
+ "B:00:C:",
+ "B:010:a:",
+ "B:101:r:",
+ "B:110:e:",
+ "B:111:B:",
+ "B:0111:i:",
+ "B:1000:u:",
+ "B:1001:o:",
+ "B:01101:l:",
+ "B:01100000:T:",
+ "B:01100001:.:",
+ "B:01100011:y:",
+ "B:01100100:I:",
+ "B:01100110:h:",
+ "B:01100111: :",
+ "B:011000100:A:",
+ "B:0110001010:O:",
+ "B:01100010110:0x3a:",
+ "B:01100101000:&:",
+ "B:01100101001:3:",
+ "B:01100101010:j:",
+ "B:01100101011:M:",
+ "B:01100101110:D:",
+ "B:011000101111:W:",
+ "B:011001011000:*:",
+ "B:011001011010:,:",
+ "B:011001011011:1:",
+ "B:011001011110:ESCAPE:",
+ "B:011001011111:P:",
+ "B:0110001011100:E:",
+ "B:0110010110011:R:",
+ "B:01100010111011:w:",
+ "B:011000101110100:-:",
+ "B:011001011001001:U:",
+ "B:011001011001010:S:",
+ "B:011001011001011:F:",
+ "B:0110001011101010:X:",
+ "B:0110001011101011:V:",
+ "B:0110010110010000:Q:",
+ "B:0110010110010001:4:",
+ "C:00:h:",
+ "C:011:B:",
+ "C:100:a:",
+ "C:110:o:",
+ "C:0101:r:",
+ "C:1010:.:",
+ "C:1110: :",
+ "C:1111:l:",
+ "C:01000:':",
+ "C:10111:i:",
+ "C:010011:e:",
+ "C:101101:u:",
+ "C:0100101:y:",
+ "C:1011001:,:",
+ "C:01001001:I:",
+ "C:010010000:A:",
+ "C:1011000000:C:",
+ "C:1011000001:D:",
+ "C:1011000011:STOP:",
+ "C:1011000100:S:",
+ "C:1011000101:T:",
+ "C:1011000111:G:",
+ "C:01001000100:*:",
+ "C:01001000111:w:",
+ "C:10110001101:J:",
+ "C:010010001010:R:",
+ "C:010010001100:2:",
+ "C:010010001101:U:",
+ "C:101100001000:?:",
+ "C:101100001010:O:",
+ "C:101100001011:H:",
+ "C:101100011000:E:",
+ "C:0100100010110:z:",
+ "C:1011000010011:-:",
+ "C:1011000110011:s:",
+ "C:01001000101111:1:",
+ "C:10110000100101:!:",
+ "C:10110001100100:P:",
+ "C:010010001011101:n:",
+ "C:101100001001000:K:",
+ "C:101100001001001:7:",
+ "C:101100011001011:4:",
+ "C:0100100010111000:0x3a:",
+ "C:1011000110010100:F:",
+ "C:1011000110010101:):",
+ "C:01001000101110010:ESCAPE:",
+ "C:01001000101110011:b:",
+ "D:00:a:",
+ "D:01:,:",
+ "D:100:r:",
+ "D:101:o:",
+ "D:110:e:",
+ "D:1110:i:",
+ "D:111111:u:",
+ "D:1111001: :",
+ "D:1111011:':",
+ "D:11110000:.:",
+ "D:11110001:]:",
+ "D:11111010:y:",
+ "D:111101010:w:",
+ "D:111101011:W:",
+ "D:111110001:N:",
+ "D:111110010:C:",
+ "D:111110111:J:",
+ "D:1111010010:h:",
+ "D:1111100000:t:",
+ "D:1111100111:I:",
+ "D:1111101101:0x3a:",
+ "D:11110100001:M:",
+ "D:11110100010:&:",
+ "D:11110100011:V:",
+ "D:11111000010:-:",
+ "D:11111000011:G:",
+ "D:11111001100:O:",
+ "D:11111001101:A:",
+ "D:11111011001:S:",
+ "D:111101000000:F:",
+ "D:111101001100:*:",
+ "D:111101001101:s:",
+ "D:111101001111:d:",
+ "D:111110110000:v:",
+ "D:1111010011100:m:",
+ "D:1111010011101:j:",
+ "D:1111101100010:ESCAPE:",
+ "D:1111101100011:T:",
+ "D:11110100000110:9:",
+ "D:111101000001000:):",
+ "D:111101000001011:E:",
+ "D:111101000001110:8:",
+ "D:111101000001111:7:",
+ "D:1111010000010010:U:",
+ "D:1111010000010011:R:",
+ "D:1111010000010100:B:",
+ "D:1111010000010101:4:",
+ "E:000:p:",
+ "E:010:a:",
+ "E:011:n:",
+ "E:110:l:",
+ "E:1001:m:",
+ "E:1010:x:",
+ "E:1110:v:",
+ "E:1111:d:",
+ "E:00100:s:",
+ "E:00110:r:",
+ "E:00111:u:",
+ "E:10000:E:",
+ "E:10001: :",
+ "E:001010:.:",
+ "E:001011:i:",
+ "E:101101:0x3a:",
+ "E:1011000:y:",
+ "E:1011001:t:",
+ "E:1011100:g:",
+ "E:1011110:4:",
+ "E:101110110:w:",
+ "E:101111100:c:",
+ "E:101111110:b:",
+ "E:1011101010:R:",
+ "E:1011101011:F:",
+ "E:1011101111:C:",
+ "E:10111010001:k:",
+ "E:10111010010:f:",
+ "E:10111010011:o:",
+ "E:10111011100:U:",
+ "E:10111011101:L:",
+ "E:10111110101:e:",
+ "E:10111110110:N:",
+ "E:10111111100:h:",
+ "E:10111111101:I:",
+ "E:10111111111:D:",
+ "E:101111101000:M:",
+ "E:101111101111:':",
+ "E:101111111100:2:",
+ "E:101111111101:-:",
+ "E:1011101000011:q:",
+ "E:1011111010010:O:",
+ "E:1011111010011:A:",
+ "E:1011111011101:Z:",
+ "E:10111010000000:W:",
+ "E:10111010000001:S:",
+ "E:10111010000010:H:",
+ "E:10111010000011:9:",
+ "E:10111010000100:):",
+ "E:10111110111000:T:",
+ "E:10111110111001:,:",
+ "E:101110100001010:P:",
+ "E:1011101000010110:ESCAPE:",
+ "E:1011101000010111:z:",
+ "F:00:o:",
+ "F:10:r:",
+ "F:010:e:",
+ "F:110:i:",
+ "F:111:a:",
+ "F:0110:l:",
+ "F:01110:u:",
+ "F:0111100: :",
+ "F:0111101:O:",
+ "F:01111101:A:",
+ "F:01111111:B:",
+ "F:011111100:f:",
+ "F:0111110000:.:",
+ "F:0111110011:L:",
+ "F:01111100010:M:",
+ "F:01111100011:E:",
+ "F:01111100101:T:",
+ "F:01111110101:C:",
+ "F:01111110110:W:",
+ "F:011111001000:0x3a:",
+ "F:011111101000:U:",
+ "F:011111101001:':",
+ "F:011111101111:1:",
+ "F:0111110010010:y:",
+ "F:0111110010011:,:",
+ "F:01111110111000:-:",
+ "F:01111110111010:I:",
+ "F:011111101110011:h:",
+ "F:0111111011100100:*:",
+ "F:0111111011100101:K:",
+ "F:0111111011101100:F:",
+ "F:0111111011101101:ESCAPE:",
+ "F:01111110111011100:X:",
+ "F:01111110111011101:R:",
+ "F:01111110111011110:;:",
+ "F:01111110111011111:4:",
+ "G:00:r:",
+ "G:01:a:",
+ "G:101:o:",
+ "G:110:e:",
+ "G:1001:u:",
+ "G:1111:i:",
+ "G:10001:n:",
+ "G:11101:l:",
+ "G:100000:X:",
+ "G:1110000:y:",
+ "G:1110001: :",
+ "G:1110011:w:",
+ "G:10000101:4:",
+ "G:10000111:P:",
+ "G:11100101:h:",
+ "G:100001000:-:",
+ "G:100001100:C:",
+ "G:111001001:M:",
+ "G:1000011010:B:",
+ "G:1110010000:.:",
+ "G:1110010001:I:",
+ "G:10000100100:;:",
+ "G:10000100101:,:",
+ "G:10000100110:A:",
+ "G:10000100111:N:",
+ "G:10000110111:0x3a:",
+ "G:1000011011000:O:",
+ "G:1000011011001:L:",
+ "G:10000110110110:b:",
+ "G:100001101101000:K:",
+ "G:100001101101001:2:",
+ "G:100001101101010:1:",
+ "G:100001101101011:':",
+ "G:1000011011011100:ESCAPE:",
+ "G:1000011011011101:m:",
+ "G:1000011011011110:T:",
+ "G:1000011011011111:S:",
+ "H:00:e:",
+ "H:01:a:",
+ "H:10:o:",
+ "H:110:i:",
+ "H:1111:u:",
+ "H:11100:R:",
+ "H:1110100:P:",
+ "H:1110110:y:",
+ "H:11101011:I:",
+ "H:111011100:Q:",
+ "H:111011101:M:",
+ "H:111011110:A:",
+ "H:111011111: :",
+ "H:1110101000:S:",
+ "H:1110101001:.:",
+ "H:11101010101:G:",
+ "H:11101010110:):",
+ "H:111010101001:E:",
+ "H:1110101011100:O:",
+ "H:1110101011101:L:",
+ "H:11101010100000:1:",
+ "H:11101010100001:&:",
+ "H:11101010111100:H:",
+ "H:11101010111101:w:",
+ "H:11101010111110:v:",
+ "H:111010101000100:X:",
+ "H:111010101000101:W:",
+ "H:111010101000110:D:",
+ "H:111010101111110:s:",
+ "H:111010101111111:F:",
+ "H:1110101010001110:ESCAPE:",
+ "H:1110101010001111:r:",
+ "I:0:n:",
+ "I:110:t:",
+ "I:1001:s:",
+ "I:1111:r:",
+ "I:10000:T:",
+ "I:10101:a:",
+ "I:11100: :",
+ "I:100010:c:",
+ "I:101001:m:",
+ "I:101100:z:",
+ "I:101101:.:",
+ "I:101111:d:",
+ "I:111011:I:",
+ "I:1000111:':",
+ "I:1011101:l:",
+ "I:10100000:A:",
+ "I:10100001:v:",
+ "I:10111001:V:",
+ "I:11101001:f:",
+ "I:11101011:o:",
+ "I:100011001:C:",
+ "I:100011010:P:",
+ "I:101000100:w:",
+ "I:101000110:0x3a:",
+ "I:101110000:p:",
+ "I:111010000:R:",
+ "I:111010001:,:",
+ "I:111010101:Y:",
+ "I:1000110000:E:",
+ "I:1000110001:6:",
+ "I:1000110111:q:",
+ "I:1010001011:y:",
+ "I:1010001110:M:",
+ "I:1110101000:g:",
+ "I:1110101001:D:",
+ "I:10001101100:e:",
+ "I:10001101101:5:",
+ "I:10100010100:S:",
+ "I:10100010101:9:",
+ "I:10100011111:F:",
+ "I:10111000100:b:",
+ "I:10111000110:-:",
+ "I:10111000111:L:",
+ "I:101000111100:B:",
+ "I:101000111101:):",
+ "I:1011100010100:N:",
+ "I:1011100010101:Q:",
+ "I:1011100010110:k:",
+ "I:10111000101111:O:",
+ "I:101110001011101:?:",
+ "I:1011100010111000:ESCAPE:",
+ "I:1011100010111001:h:",
+ "J:00:e:",
+ "J:10:a:",
+ "J:11:o:",
+ "J:011:u:",
+ "J:0101:i:",
+ "J:01000: :",
+ "J:0100110:D:",
+ "J:0100111:.:",
+ "J:01001001:r:",
+ "J:010010110:s:",
+ "J:0100100000:M:",
+ "J:0100100010:J:",
+ "J:0100100011:,:",
+ "J:0100101000:B:",
+ "J:0100101001:-:",
+ "J:0100101010:V:",
+ "J:0100101110:K:",
+ "J:0100101111:T:",
+ "J:01001000010:C:",
+ "J:01001010110:n:",
+ "J:010010000110:!:",
+ "J:0100100001110:w:",
+ "J:0100100001111:R:",
+ "J:0100101011100:F:",
+ "J:0100101011110:7:",
+ "J:0100101011111:':",
+ "J:01001010111010:G:",
+ "J:010010101110110:ESCAPE:",
+ "J:010010101110111:L:",
+ "K:00:i:",
+ "K:01:a:",
+ "K:10:e:",
+ "K:1111:y:",
+ "K:11000:n:",
+ "K:11001:o:",
+ "K:11011:r:",
+ "K:11101: :",
+ "K:110100:':",
+ "K:111000:u:",
+ "K:1101011:.:",
+ "K:1110011:l:",
+ "K:11100101:h:",
+ "K:110101000:T:",
+ "K:110101011:G:",
+ "K:111001001:,:",
+ "K:1101010100:w:",
+ "K:11010100100:5:",
+ "K:11010100101:4:",
+ "K:11010100110:A:",
+ "K:11010101010:3:",
+ "K:11100100000:2:",
+ "K:11100100011:M:",
+ "K:110101001110:-:",
+ "K:110101010110:0x3a:",
+ "K:110101010111:!:",
+ "K:111001000010:):",
+ "K:111001000101:S:",
+ "K:1101010011110:V:",
+ "K:1110010000110:6:",
+ "K:1110010000111:1:",
+ "K:11010100111111:L:",
+ "K:11100100010000:I:",
+ "K:11100100010001:?:",
+ "K:110101001111100:ESCAPE:",
+ "K:110101001111101:v:",
+ "K:111001000100100:k:",
+ "K:111001000100101:Y:",
+ "K:111001000100110:N:",
+ "K:111001000100111:E:",
+ "L:00:i:",
+ "L:10:o:",
+ "L:011:]:",
+ "L:110:e:",
+ "L:111:a:",
+ "L:0100:u:",
+ "L:010100:l:",
+ "L:010101:A:",
+ "L:010111:y:",
+ "L:01011011: :",
+ "L:010110000:I:",
+ "L:010110001:R:",
+ "L:010110101:,:",
+ "L:0101100100:O:",
+ "L:0101100101:':",
+ "L:01011001101:.:",
+ "L:01011001110:C:",
+ "L:01011001111:Y:",
+ "L:01011010001:F:",
+ "L:01011010010:L:",
+ "L:010110011001:t:",
+ "L:010110100001:G:",
+ "L:010110100111:S:",
+ "L:0101100110001:h:",
+ "L:0101101000001:W:",
+ "L:0101101001100:J:",
+ "L:01011001100000:E:",
+ "L:01011010000001:\":",
+ "L:01011010011011:STOP:",
+ "L:010110011000010:T:",
+ "L:010110011000011:P:",
+ "L:010110100000000:D:",
+ "L:010110100000001:7:",
+ "L:010110100110101:j:",
+ "L:0101101001101000:ESCAPE:",
+ "L:0101101001101001:U:",
+ "M:00:o:",
+ "M:11:a:",
+ "M:011:e:",
+ "M:101:i:",
+ "M:0101:c:",
+ "M:1001:u:",
+ "M:01001:y:",
+ "M:10001:r:",
+ "M:100000:S:",
+ "M:100001:P:",
+ "M:0100001: :",
+ "M:01000001:C:",
+ "M:01000110:F:",
+ "M:010000000:1:",
+ "M:010001000:h:",
+ "M:010001010:I:",
+ "M:010001110:T:",
+ "M:010001111:X:",
+ "M:0100000010:A:",
+ "M:0100010010:z:",
+ "M:01000100110:f:",
+ "M:01000101110:.:",
+ "M:010000001100:Z:",
+ "M:010000001101:K:",
+ "M:010000001110:B:",
+ "M:010001001111:s:",
+ "M:010001011000:R:",
+ "M:010001011001:W:",
+ "M:010001011010:O:",
+ "M:0100000011110:,:",
+ "M:0100000011111:':",
+ "M:0100010110111:D:",
+ "M:0100010111100:4:",
+ "M:0100010111110:E:",
+ "M:01000100111000:m:",
+ "M:01000100111001:J:",
+ "M:01000100111010:ESCAPE:",
+ "M:01000101111010:l:",
+ "M:01000101111011:-:",
+ "M:01000101111110:):",
+ "M:01000101111111:w:",
+ "M:010001001110110:t:",
+ "M:010001001110111:V:",
+ "M:010001011011000:Q:",
+ "M:010001011011001:N:",
+ "M:010001011011010:6:",
+ "M:010001011011011:2:",
+ "N:00:a:",
+ "N:10:o:",
+ "N:11:e:",
+ "N:011:i:",
+ "N:01010:u:",
+ "N:01011:E:",
+ "N:010010:A:",
+ "N:0100010:y:",
+ "N:0100110:g:",
+ "N:01000001:B:",
+ "N:01000010:I:",
+ "N:01000110:F:",
+ "N:01000111: :",
+ "N:010000000:):",
+ "N:010000001:':",
+ "N:010000111:Y:",
+ "N:010011100:L:",
+ "N:010011101:H:",
+ "N:0100001100:C:",
+ "N:0100111100:W:",
+ "N:0100111110:N:",
+ "N:0100111111:T:",
+ "N:010000110101:M:",
+ "N:010000110111:O:",
+ "N:010011110100:,:",
+ "N:010011110101:J:",
+ "N:010011110111:h:",
+ "N:0100001101000:D:",
+ "N:0100001101001:.:",
+ "N:0100111101100:X:",
+ "N:0100111101101:ESCAPE:",
+ "N:01000011011000:k:",
+ "N:01000011011001:Z:",
+ "N:01000011011010:Q:",
+ "N:01000011011011:G:",
+ "O:111:n:",
+ "O:0000:s:",
+ "O:0001:N:",
+ "O:0011:z:",
+ "O:0100:r:",
+ "O:1000:u:",
+ "O:1010:p:",
+ "O:1011:l:",
+ "O:1101:':",
+ "O:00101:U:",
+ "O:01011:h:",
+ "O:01110:f:",
+ "O:01111:w:",
+ "O:10010:.:",
+ "O:11000: :",
+ "O:001000:o:",
+ "O:001001:J:",
+ "O:010100:b:",
+ "O:010101:m:",
+ "O:011001:H:",
+ "O:011010:O:",
+ "O:011011:v:",
+ "O:100111:c:",
+ "O:110011:x:",
+ "O:1001101:d:",
+ "O:1100100:a:",
+ "O:01100001:t:",
+ "O:01100010:k:",
+ "O:10011000:g:",
+ "O:11001010:R:",
+ "O:011000000:K:",
+ "O:100110010:i:",
+ "O:110010111:V:",
+ "O:0110000011:2:",
+ "O:0110001101:S:",
+ "O:0110001110:B:",
+ "O:1001100110:W:",
+ "O:1001100111:-:",
+ "O:01100000100:,:",
+ "O:01100011000:j:",
+ "O:01100011001:L:",
+ "O:01100011111:I:",
+ "O:11001011001:A:",
+ "O:11001011011:C:",
+ "O:011000001010:0x3a:",
+ "O:011000111100:e:",
+ "O:110010110000:y:",
+ "O:110010110001:/:",
+ "O:110010110100:M:",
+ "O:0110000010110:!:",
+ "O:0110001111011:P:",
+ "O:1100101101011:F:",
+ "O:01100000101110:E:",
+ "O:01100000101111:D:",
+ "O:01100011110100:8:",
+ "O:01100011110101:4:",
+ "O:11001011010101:T:",
+ "O:110010110101000:ESCAPE:",
+ "O:110010110101001:q:",
+ "P:11:a:",
+ "P:000:i:",
+ "P:010:e:",
+ "P:011:l:",
+ "P:100:o:",
+ "P:101:r:",
+ "P:0010:h:",
+ "P:001111:u:",
+ "P:0011010:C:",
+ "P:0011100:.:",
+ "P:0011101: :",
+ "P:00110000:B:",
+ "P:00110010:D:",
+ "P:00110111:s:",
+ "P:001100011:O:",
+ "P:001100111:,:",
+ "P:0011000101:y:",
+ "P:0011001100:M:",
+ "P:0011011000:E:",
+ "P:0011011001:':",
+ "P:0011011011:3:",
+ "P:00110001001:T:",
+ "P:001100010000:L:",
+ "P:001100010001:G:",
+ "P:001100110100:*:",
+ "P:001100110110:A:",
+ "P:001100110111:S:",
+ "P:001101101000:w:",
+ "P:001101101001:F:",
+ "P:0011001101011:J:",
+ "P:0011011010100:f:",
+ "P:0011011010101:R:",
+ "P:0011011010111:t:",
+ "P:00110011010100:V:",
+ "P:00110110101100:Y:",
+ "P:00110110101101:I:",
+ "P:001100110101011:&:",
+ "P:0011001101010100:ESCAPE:",
+ "P:0011001101010101:):",
+ "Q:1:u:",
+ "Q:00:V:",
+ "Q:011: :",
+ "Q:0101:.:",
+ "Q:01000:a:",
+ "Q:0100100:w:",
+ "Q:0100110:E:",
+ "Q:0100111:C:",
+ "Q:01001011:&:",
+ "Q:010010101:':",
+ "Q:0100101000:T:",
+ "Q:01001010010:ESCAPE:",
+ "Q:01001010011:s:",
+ "R:01:a:",
+ "R:11:o:",
+ "R:100:i:",
+ "R:101:e:",
+ "R:0000:p:",
+ "R:0011:u:",
+ "R:00011:E:",
+ "R:00100:h:",
+ "R:000100: :",
+ "R:001010:y:",
+ "R:00010100:D:",
+ "R:00010110:.:",
+ "R:00101100:T:",
+ "R:00101110:S:",
+ "R:000101010:F:",
+ "R:001011010:B:",
+ "R:001011011:n:",
+ "R:001011111:A:",
+ "R:0001010110:w:",
+ "R:0001011100:N:",
+ "R:0001011101:&:",
+ "R:0001011110:V:",
+ "R:0001011111:H:",
+ "R:0010111101:':",
+ "R:00010101110:t:",
+ "R:00010101111:I:",
+ "R:001011110000:C:",
+ "R:001011110010:O:",
+ "R:00101111000100:,:",
+ "R:00101111000101:s:",
+ "R:00101111000110:U:",
+ "R:00101111000111:M:",
+ "R:00101111001100:-:",
+ "R:00101111001101:ESCAPE:",
+ "R:00101111001111:0x3a:",
+ "R:001011110011100:2:",
+ "R:001011110011101:R:",
+ "S:1:]:",
+ "S:0000:a:",
+ "S:0010:h:",
+ "S:0111:t:",
+ "S:00010:p:",
+ "S:00011:,:",
+ "S:00110:L:",
+ "S:01000:i:",
+ "S:01001:u:",
+ "S:01010:o:",
+ "S:01011:c:",
+ "S:01100:e:",
+ "S:001111:k:",
+ "S:0011100:w:",
+ "S:0110101: :",
+ "S:0110111:m:",
+ "S:00111010:q:",
+ "S:01101000:M:",
+ "S:01101001:n:",
+ "S:01101100:l:",
+ "S:001110110:P:",
+ "S:011011011:y:",
+ "S:0011101110:A:",
+ "S:01101101001:.:",
+ "S:001110111101:r:",
+ "S:001110111110:S:",
+ "S:001110111111:W:",
+ "S:011011010000:C:",
+ "S:011011010101:E:",
+ "S:011011010110:v:",
+ "S:0110110100011:ESCAPE:",
+ "S:0110110101000:I:",
+ "S:0110110101111:g:",
+ "S:00111011110000:*:",
+ "S:00111011110010:4:",
+ "S:00111011110011:1:",
+ "S:01101101000100:O:",
+ "S:01101101010010:STOP:",
+ "S:01101101011100:z:",
+ "S:011011010001011:B:",
+ "S:011011010111010:H:",
+ "S:011011010111011:T:",
+ "S:0011101111000100:G:",
+ "S:0011101111000110:}:",
+ "S:0011101111000111:D:",
+ "S:0110110100010100:-:",
+ "S:0110110101001100:3:",
+ "S:0110110101001101:2:",
+ "S:00111011110001010:':",
+ "S:00111011110001011:?:",
+ "S:01101101010011101:s:",
+ "S:01101101010011110:j:",
+ "S:01101101010011111:b:",
+ "S:011011010001010100:R:",
+ "S:011011010001010101:K:",
+ "S:011011010001010110:J:",
+ "S:011011010001010111:F:",
+ "S:011011010100111000:0x3a:",
+ "S:011011010100111001:):",
+ "T:0:h:",
+ "T:100:o:",
+ "T:1010:V:",
+ "T:1011:w:",
+ "T:1100:r:",
+ "T:1111:e:",
+ "T:11010:a:",
+ "T:11011:i:",
+ "T:11100:u:",
+ "T:1110100:H:",
+ "T:1110110:W:",
+ "T:11101010: :",
+ "T:11101011:y:",
+ "T:111011101:M:",
+ "T:111011111:x:",
+ "T:1110111000:S:",
+ "T:11101110010:A:",
+ "T:11101111001:s:",
+ "T:11101111011:J:",
+ "T:111011100111:X:",
+ "T:111011110000:.:",
+ "T:1110111001101:-:",
+ "T:1110111100011:L:",
+ "T:1110111101000:C:",
+ "T:1110111101011:c:",
+ "T:11101110011000:T:",
+ "T:11101110011001:U:",
+ "T:11101111000101:4:",
+ "T:11101111010010:O:",
+ "T:111011110001001:G:",
+ "T:111011110100110:E:",
+ "T:111011110100111:,:",
+ "T:111011110101010:':",
+ "T:1110111100010001:;:",
+ "T:1110111101010000:P:",
+ "T:1110111101010001:1:",
+ "T:1110111101010010:ESCAPE:",
+ "T:1110111101010111:D:",
+ "T:11101111000100000:0x3a:",
+ "T:11101111000100001:*:",
+ "T:11101111010100110:R:",
+ "T:11101111010100111:N:",
+ "T:11101111010101100:I:",
+ "T:11101111010101101:B:",
+ "U:00:K:",
+ "U:10:n:",
+ "U:011:S:",
+ "U:110:p:",
+ "U:1111:l:",
+ "U:01010:s:",
+ "U:01011:r:",
+ "U:11101:R:",
+ "U:010000:g:",
+ "U:111000: :",
+ "U:0100111:.:",
+ "U:1110010:m:",
+ "U:01000100:k:",
+ "U:01000101:t:",
+ "U:01000110:E:",
+ "U:01000111:-:",
+ "U:01001000:F:",
+ "U:01001100:2:",
+ "U:11100110:c:",
+ "U:11100111:N:",
+ "U:010010010:f:",
+ "U:010010011:8:",
+ "U:010010100:,:",
+ "U:010010111:Z:",
+ "U:0100101010:h:",
+ "U:0100110100:i:",
+ "U:0100110101:w:",
+ "U:0100110110:a:",
+ "U:01001010110:b:",
+ "U:01001010111:D:",
+ "U:01001101110:!:",
+ "U:010010110000:e:",
+ "U:010010110001:V:",
+ "U:010010110010:P:",
+ "U:010010110011:I:",
+ "U:010010110100:B:",
+ "U:010010110101:A:",
+ "U:010011011111:d:",
+ "U:0100101101100:H:",
+ "U:0100101101101:C:",
+ "U:0100101101110:0x3a:",
+ "U:0100101101111:):",
+ "U:0100110111101:z:",
+ "U:01001101111000:ESCAPE:",
+ "U:01001101111001:T:",
+ "V:01: :",
+ "V:11:i:",
+ "V:000:.:",
+ "V:001:a:",
+ "V:101:e:",
+ "V:10001:C:",
+ "V:10011:o:",
+ "V:1000001:F:",
+ "V:1000011:I:",
+ "V:10000001:1:",
+ "V:10000101:4:",
+ "V:10010000:r:",
+ "V:10010010:E:",
+ "V:10010011:s:",
+ "V:10010101:':",
+ "V:10010110:0x3a:",
+ "V:10010111:l:",
+ "V:100000001:/:",
+ "V:100001001:-:",
+ "V:100100010:D:",
+ "V:100100011:u:",
+ "V:100101001:,:",
+ "V:1000000000:6:",
+ "V:1000000001:2:",
+ "V:1000010000:5:",
+ "V:1001010000:;:",
+ "V:10010100010:ESCAPE:",
+ "V:100001000100:7:",
+ "V:100101000110:3:",
+ "V:1000010001010:9:",
+ "V:1000010001011:y:",
+ "V:1000010001100:P:",
+ "V:1000010001101:H:",
+ "V:1000010001110:A:",
+ "V:1000010001111:8:",
+ "V:1001010001111:W:",
+ "V:10010100011100:f:",
+ "V:10010100011101:B:",
+ "W:00:h:",
+ "W:10:i:",
+ "W:011:a:",
+ "W:110:o:",
+ "W:111:e:",
+ "W:0100:r:",
+ "W:01011:O:",
+ "W:0101001: :",
+ "W:0101010:y:",
+ "W:010100000:B:",
+ "W:010100001:.:",
+ "W:010101100:I:",
+ "W:010101110:W:",
+ "W:010101111:A:",
+ "W:0101000100:':",
+ "W:0101000101:M:",
+ "W:0101000111:T:",
+ "W:01010001100:2:",
+ "W:01010001101:0x3a:",
+ "W:01010110100:H:",
+ "W:01010110110:V:",
+ "W:010101101010:l:",
+ "W:010101101110:s:",
+ "W:010101101111:,:",
+ "W:0101011010111:u:",
+ "W:010101101011000:5:",
+ "W:010101101011001:):",
+ "W:010101101011011:E:",
+ "W:0101011010110100:ESCAPE:",
+ "W:0101011010110101:m:",
+ "X:1: :",
+ "X:000:a:",
+ "X:0010:z:",
+ "X:0011:m:",
+ "X:0111:t:",
+ "X:01001:U:",
+ "X:01010:-:",
+ "X:01011:e:",
+ "X:011000:u:",
+ "X:011001:I:",
+ "X:011011:,:",
+ "X:0100010:V:",
+ "X:0110100:5:",
+ "X:0110101:.:",
+ "X:01000000:S:",
+ "X:01000010:0x3a:",
+ "X:01000110:c:",
+ "X:01000111:i:",
+ "X:010000010:9:",
+ "X:010000011:':",
+ "X:010000111:X:",
+ "X:0100001100:):",
+ "X:01000011010:ESCAPE:",
+ "X:01000011011:y:",
+ "Y:1:o:",
+ "Y:00:e:",
+ "Y:010:u:",
+ "Y:01100:a:",
+ "Y:01110:v:",
+ "Y:01111: :",
+ "Y:0110100:n:",
+ "Y:01101010:r:",
+ "Y:01101101:O:",
+ "Y:01101111:i:",
+ "Y:011010111:N:",
+ "Y:011011000:L:",
+ "Y:011011001:s:",
+ "Y:011011101:m:",
+ "Y:0110101100:.:",
+ "Y:0110101101:M:",
+ "Y:0110111001:P:",
+ "Y:011011100001:R:",
+ "Y:011011100010:2:",
+ "Y:0110111000000:-:",
+ "Y:0110111000110:C:",
+ "Y:0110111000111:,:",
+ "Y:01101110000010:ESCAPE:",
+ "Y:01101110000011:d:",
+ "Z:01:a:",
+ "Z:10:e:",
+ "Z:11:o:",
+ "Z:0010:z:",
+ "Z:0011:i:",
+ "Z:00001:Z:",
+ "Z:00010: :",
+ "Z:00011:u:",
+ "Z:0000010:O:",
+ "Z:0000011:.:",
+ "Z:00000000:y:",
+ "Z:00000001:4:",
+ "Z:00000010:,:",
+ "Z:0000001100:f:",
+ "Z:0000001101:-:",
+ "Z:0000001110:STOP:",
+ "Z:00000011110:ESCAPE:",
+ "Z:00000011111:l:",
+ "[:1:S:",
+ "[:01:A:",
+ "[:0000:2:",
+ "[:0010:R:",
+ "[:0011:1:",
+ "[:000101:n:",
+ "[:000110:m:",
+ "[:0001111:l:",
+ "[:00010011:r:",
+ "[:00011101:b:",
+ "[:000100001:C:",
+ "[:000100010:f:",
+ "[:000100101:M:",
+ "[:000111001:c:",
+ "[:0001000001:STOP:",
+ "[:0001000111:K:",
+ "[:0001001000:H:",
+ "[:0001110001:T:",
+ "[:00010000000:J:",
+ "[:00010000001:B:",
+ "[:00010001101:Z:",
+ "[:00010010011:P:",
+ "[:00011100000:L:",
+ "[:000100011000:F:",
+ "[:000100100101:I:",
+ "[:000111000011:N:",
+ "[:0001000110010:s:",
+ "[:0001000110011:V:",
+ "[:0001001001000:U:",
+ "[:0001001001001:G:",
+ "[:0001110000101:D:",
+ "[:00011100001000:O:",
+ "[:000111000010010:ESCAPE:",
+ "[:000111000010011:W:",
+ "\\:0:ESCAPE:",
+ "\\:1:x:",
+ "]:1:STOP:",
+ "]:01: :",
+ "]:001:.:",
+ "]:0001:[:",
+ "]:00001:0x3a:",
+ "]:000001:,:",
+ "]:0000001:;:",
+ "]:00000000:ESCAPE:",
+ "]:00000001:]:",
+ "^:0:ESCAPE:",
+ "^:1:ESCAPE:",
+ "_:0:ESCAPE:",
+ "_:1:ESCAPE:",
+ "`:001:w:",
+ "`:011:H:",
+ "`:110:P:",
+ "`:111:F:",
+ "`:0101:n:",
+ "`:1011:D:",
+ "`:00001:s:",
+ "`:00010:A:",
+ "`:01001:t:",
+ "`:10000:g:",
+ "`:10011:c:",
+ "`:000000:W:",
+ "`:000001:r:",
+ "`:000110:e:",
+ "`:000111:C:",
+ "`:100011:l:",
+ "`:100100:h:",
+ "`:100101:G:",
+ "`:101001:B:",
+ "`:101010:T:",
+ "`:101011:S:",
+ "`:0100000:o:",
+ "`:0100001:d:",
+ "`:0100010:b:",
+ "`:0100011:R:",
+ "`:1000100:O:",
+ "`:1000101:L:",
+ "`:1010001:f:",
+ "`:10100000:J:",
+ "`:101000010:ESCAPE:",
+ "`:101000011:M:",
+ "a:01:n:",
+ "a:001:r:",
+ "a:101:t:",
+ "a:0000:m:",
+ "a:1001:s:",
+ "a:1110: :",
+ "a:1111:l:",
+ "a:00011:d:",
+ "a:10000:i:",
+ "a:11000:y:",
+ "a:11010:c:",
+ "a:000100:p:",
+ "a:100010:u:",
+ "a:100011:v:",
+ "a:110011:g:",
+ "a:110110:b:",
+ "a:110111:k:",
+ "a:0001010:w:",
+ "a:00010111:z:",
+ "a:11001000:.:",
+ "a:11001011:f:",
+ "a:000101100:,:",
+ "a:000101101:':",
+ "a:110010011:e:",
+ "a:110010101:h:",
+ "a:1100101001:x:",
+ "a:11001001000:a:",
+ "a:11001001001:-:",
+ "a:11001001011:j:",
+ "a:11001010000:0x3a:",
+ "a:11001010001:o:",
+ "a:110010010100:q:",
+ "a:11001001010100:!:",
+ "a:11001001010111:?:",
+ "a:1100100101010100:ESCAPE:",
+ "a:1100100101010110:;:",
+ "a:1100100101010111:):",
+ "a:1100100101011001:/:",
+ "a:1100100101011011:@:",
+ "a:11001001010101010:J:",
+ "a:11001001010101011:]:",
+ "a:11001001010110100:N:",
+ "a:11001001010110101:L:",
+ "a:110010010101100000:R:",
+ "a:110010010101100001:S:",
+ "a:110010010101100010:V:",
+ "a:11001001010110001100:[:",
+ "a:11001001010110001110:P:",
+ "a:11001001010110001111:STOP:",
+ "a:110010010101100011010:W:",
+ "a:110010010101100011011:1:",
+ "b:00:e:",
+ "b:010:u:",
+ "b:011:a:",
+ "b:100:y:",
+ "b:101:o:",
+ "b:1100:l:",
+ "b:1110:r:",
+ "b:1111:i:",
+ "b:110100:s:",
+ "b:110110: :",
+ "b:110111:b:",
+ "b:11010101:c:",
+ "b:110101000:j:",
+ "b:110101100:,:",
+ "b:110101101:.:",
+ "b:1101010011:':",
+ "b:1101011111:t:",
+ "b:11010100101:0x3a:",
+ "b:11010111000:w:",
+ "b:11010111001:d:",
+ "b:11010111010:h:",
+ "b:11010111011:&:",
+ "b:11010111101:-:",
+ "b:110101111000:m:",
+ "b:110101111001:n:",
+ "b:1101010010000:?:",
+ "b:1101010010010:v:",
+ "b:11010100100010:f:",
+ "b:11010100100111:p:",
+ "b:110101001000111:;:",
+ "b:110101001001101:D:",
+ "b:1101010010001100:/:",
+ "b:1101010010011001:@:",
+ "b:11010100100011010:X:",
+ "b:11010100100011011:\":",
+ "b:11010100100110001:k:",
+ "b:110101001001100000:STOP:",
+ "b:1101010010011000010:ESCAPE:",
+ "b:1101010010011000011:!:",
+ "c:00:o:",
+ "c:011:a:",
+ "c:100:e:",
+ "c:110:h:",
+ "c:0100:i:",
+ "c:0101:l:",
+ "c:1011:k:",
+ "c:1111:t:",
+ "c:10100:u:",
+ "c:10101:r:",
+ "c:11100: :",
+ "c:1110100:y:",
+ "c:1110101:c:",
+ "c:11101101:s:",
+ "c:11101110:.:",
+ "c:111011111:,:",
+ "c:1110110001:G:",
+ "c:11101100001:n:",
+ "c:11101100110:D:",
+ "c:11101111000:K:",
+ "c:11101111011:C:",
+ "c:111011000000:0x3a:",
+ "c:111011001001:-:",
+ "c:111011001010:A:",
+ "c:111011001110:L:",
+ "c:111011001111:':",
+ "c:111011110010:d:",
+ "c:111011110100:q:",
+ "c:111011110101:I:",
+ "c:1110110010000:N:",
+ "c:1110110010001:z:",
+ "c:1110111100111:F:",
+ "c:11101100000101:w:",
+ "c:11101100000111:E:",
+ "c:11101100101100:?:",
+ "c:11101111001100:M:",
+ "c:11101111001101:S:",
+ "c:111011000001000:b:",
+ "c:111011000001001:ESCAPE:",
+ "c:111011000001100:!:",
+ "c:111011001011010:Q:",
+ "c:111011001011011:P:",
+ "c:111011001011100:;:",
+ "c:111011001011110:B:",
+ "c:1110110000011011:V:",
+ "c:1110110010111011:m:",
+ "c:1110110010111110:/:",
+ "c:11101100000110101:):",
+ "c:11101100101110100:U:",
+ "c:11101100101111110:W:",
+ "c:111011000001101000:p:",
+ "c:111011000001101001:H:",
+ "c:111011001011101010:STOP:",
+ "c:111011001011111110:R:",
+ "c:111011001011111111:T:",
+ "c:1110110010111010110:]:",
+ "c:1110110010111010111:[:",
+ "d:0: :",
+ "d:101:e:",
+ "d:1100:a:",
+ "d:1110:i:",
+ "d:10001:.:",
+ "d:10011:o:",
+ "d:11011:r:",
+ "d:11111:s:",
+ "d:100001:d:",
+ "d:100101:l:",
+ "d:110100:u:",
+ "d:111101:y:",
+ "d:1001001:-:",
+ "d:1101011:v:",
+ "d:1111000:g:",
+ "d:1111001:,:",
+ "d:10000000:h:",
+ "d:10000001:0x3a:",
+ "d:10000010:m:",
+ "d:10010000:w:",
+ "d:10010001:n:",
+ "d:11010101:':",
+ "d:100000111:f:",
+ "d:1101010001:?:",
+ "d:1101010010:b:",
+ "d:1101010011:c:",
+ "d:10000011000:!:",
+ "d:11010100000:p:",
+ "d:11010100001:t:",
+ "d:100000110010:STOP:",
+ "d:100000110011:):",
+ "d:100000110100:k:",
+ "d:100000110101:;:",
+ "d:100000110111:/:",
+ "d:10000011011010:\":",
+ "d:10000011011011:j:",
+ "d:100000110110000:z:",
+ "d:100000110110011:q:",
+ "d:1000001101100011:@:",
+ "d:1000001101100100:ESCAPE:",
+ "d:10000011011000101:C:",
+ "d:10000011011001010:]:",
+ "d:100000110110001000:Z:",
+ "d:100000110110001001:[:",
+ "d:100000110110010110:T:",
+ "d:100000110110010111:`:",
+ "e:10: :",
+ "e:010:s:",
+ "e:110:r:",
+ "e:0000:d:",
+ "e:0011:a:",
+ "e:1111:n:",
+ "e:00010:c:",
+ "e:01100:e:",
+ "e:01101:w:",
+ "e:01111:t:",
+ "e:11100:l:",
+ "e:000110:x:",
+ "e:001000:v:",
+ "e:001001:i:",
+ "e:001010:y:",
+ "e:011100:m:",
+ "e:111010:.:",
+ "e:0001110:f:",
+ "e:0010111:b:",
+ "e:0111010:,:",
+ "e:1110110:p:",
+ "e:00011110:-:",
+ "e:00011111:h:",
+ "e:00101100:k:",
+ "e:01110110:':",
+ "e:11101110:g:",
+ "e:11101111:o:",
+ "e:001011011:0x3a:",
+ "e:0010110100:):",
+ "e:0010110101:q:",
+ "e:0111011101:?:",
+ "e:0111011110:u:",
+ "e:01110111000:z:",
+ "e:01110111110:!:",
+ "e:011101111110:STOP:",
+ "e:011101111111:j:",
+ "e:0111011100110:/:",
+ "e:01110111001001:4:",
+ "e:01110111001010:B:",
+ "e:01110111001110:]:",
+ "e:01110111001111:;:",
+ "e:011101110010000:\":",
+ "e:0111011100100011:D:",
+ "e:0111011100101100:ESCAPE:",
+ "e:0111011100101110:@:",
+ "e:01110111001000100:T:",
+ "e:01110111001000101:C:",
+ "e:01110111001011011:[:",
+ "e:01110111001011111:L:",
+ "e:011101110010110100:V:",
+ "e:011101110010110101:G:",
+ "e:011101110010111100:1:",
+ "e:01110111001011110101:E:",
+ "e:011101110010111101000:2:",
+ "e:011101110010111101001:N:",
+ "e:011101110010111101100:F:",
+ "e:011101110010111101101:A:",
+ "e:0111011100101111011100:\\:",
+ "e:0111011100101111011101:P:",
+ "e:0111011100101111011110:M:",
+ "e:0111011100101111011111:H:",
+ "f:00:o:",
+ "f:10: :",
+ "f:010:i:",
+ "f:110:r:",
+ "f:0111:a:",
+ "f:1110:e:",
+ "f:01100:t:",
+ "f:11110:u:",
+ "f:11111:f:",
+ "f:011011:l:",
+ "f:01101000:s:",
+ "f:01101001:y:",
+ "f:011010110:.:",
+ "f:0110101000:?:",
+ "f:0110101011:,:",
+ "f:0110101111:-:",
+ "f:01101010011:0x3a:",
+ "f:01101010100:':",
+ "f:01101010101:g:",
+ "f:011010100100:m:",
+ "f:011010111000:ESCAPE:",
+ "f:011010111010:b:",
+ "f:011010111011:n:",
+ "f:0110101001011:c:",
+ "f:0110101110010:!:",
+ "f:01101011100110:):",
+ "f:01101011100111:w:",
+ "f:011010100101001:p:",
+ "f:011010100101010:/:",
+ "f:0110101001010000:h:",
+ "f:0110101001010110:;:",
+ "f:01101010010100010:STOP:",
+ "f:01101010010100011:d:",
+ "f:01101010010101110:k:",
+ "f:01101010010101111:v:",
+ "g:11: :",
+ "g:000:a:",
+ "g:010:h:",
+ "g:101:e:",
+ "g:0011:u:",
+ "g:0110:r:",
+ "g:1000:i:",
+ "g:01110:l:",
+ "g:10010:s:",
+ "g:10011:o:",
+ "g:001001:,:",
+ "g:001010:n:",
+ "g:011110:g:",
+ "g:011111:.:",
+ "g:0010110:y:",
+ "g:00100001:':",
+ "g:00100010:-:",
+ "g:00100011:0x3a:",
+ "g:001000000:d:",
+ "g:001011101:b:",
+ "g:001011110:t:",
+ "g:001011111:w:",
+ "g:0010000010:?:",
+ "g:0010000011:m:",
+ "g:00101110001:!:",
+ "g:00101110011:f:",
+ "g:001011100001:;:",
+ "g:001011100101:STOP:",
+ "g:0010111000000:k:",
+ "g:0010111001000:p:",
+ "g:00101110000010:):",
+ "g:00101110000011:\":",
+ "g:001011100100101:c:",
+ "g:001011100100111:/:",
+ "g:0010111001001000:ESCAPE:",
+ "g:0010111001001100:]:",
+ "g:0010111001001101:z:",
+ "g:00101110010010010:`:",
+ "g:001011100100100110:v:",
+ "g:001011100100100111:@:",
+ "h:0:e:",
+ "h:100:o:",
+ "h:101:i:",
+ "h:110: :",
+ "h:1111:a:",
+ "h:111001:r:",
+ "h:111011:t:",
+ "h:11100001:y:",
+ "h:11100011:l:",
+ "h:11101000:.:",
+ "h:11101001:n:",
+ "h:11101011:u:",
+ "h:111000000:d:",
+ "h:111000100:s:",
+ "h:111010100:,:",
+ "h:1110000011:w:",
+ "h:1110001010:':",
+ "h:1110001011:-:",
+ "h:11101010101:m:",
+ "h:11101010110:0x3a:",
+ "h:11101010111:b:",
+ "h:111000001001:c:",
+ "h:111000001011:?:",
+ "h:111010101000:!:",
+ "h:1110000010000:):",
+ "h:1110000010100:h:",
+ "h:1110000010101:k:",
+ "h:1110101010011:f:",
+ "h:11101010100101:g:",
+ "h:111000001000100:p:",
+ "h:111000001000101:;:",
+ "h:111000001000110:/:",
+ "h:111000001000111:STOP:",
+ "h:111010101001001:v:",
+ "h:1110101010010000:q:",
+ "h:11101010100100010:ESCAPE:",
+ "h:111010101001000110:\":",
+ "h:11101010100100011100:z:",
+ "h:11101010100100011101:j:",
+ "h:11101010100100011110:]:",
+ "h:11101010100100011111:*:",
+ "i:10:n:",
+ "i:000:t:",
+ "i:010:s:",
+ "i:0011:l:",
+ "i:1100:o:",
+ "i:1101:c:",
+ "i:1111:e:",
+ "i:00100:a:",
+ "i:01100:m:",
+ "i:01101:d:",
+ "i:01110:v:",
+ "i:11100:g:",
+ "i:11101:r:",
+ "i:001010:p:",
+ "i:011110:f:",
+ "i:0010110:z:",
+ "i:0111110: :",
+ "i:00101111:b:",
+ "i:01111110:k:",
+ "i:001011100:-:",
+ "i:001011101:x:",
+ "i:0111111100:u:",
+ "i:0111111110:q:",
+ "i:01111111010:.:",
+ "i:01111111110:,:",
+ "i:011111110111:w:",
+ "i:011111111111:':",
+ "i:0111111101101:i:",
+ "i:0111111111101:j:",
+ "i:01111111011001:0x3a:",
+ "i:01111111111000:h:",
+ "i:011111110110000:/:",
+ "i:011111111110011:y:",
+ "i:0111111101100011:?:",
+ "i:0111111111100100:P:",
+ "i:01111111011000101:R:",
+ "i:01111111111001011:!:",
+ "i:011111111110010100:):",
+ "i:011111111110010101:S:",
+ "i:0111111101100010000:STOP:",
+ "i:0111111101100010001:C:",
+ "i:0111111101100010010:ESCAPE:",
+ "i:01111111011000100110:D:",
+ "i:01111111011000100111:;:",
+ "j:0:o:",
+ "j:11:u:",
+ "j:101:a:",
+ "j:1001:e:",
+ "j:10000:i:",
+ "j:100011:y:",
+ "j:1000101: :",
+ "j:10001001:.:",
+ "j:100010000:':",
+ "j:1000100011:t:",
+ "j:10001000100:n:",
+ "j:100010001011:s:",
+ "j:1000100010100:ESCAPE:",
+ "j:1000100010101:h:",
+ "k:10: :",
+ "k:11:e:",
+ "k:000:s:",
+ "k:011:i:",
+ "k:0010:.:",
+ "k:01001:y:",
+ "k:001100:':",
+ "k:001101:a:",
+ "k:001110:p:",
+ "k:001111:,:",
+ "k:010100:l:",
+ "k:010101:f:",
+ "k:010110:n:",
+ "k:0100000:/:",
+ "k:0100010:-:",
+ "k:0100011:o:",
+ "k:01011101:0x3a:",
+ "k:010000111:b:",
+ "k:010111000:w:",
+ "k:010111001:m:",
+ "k:010111100:h:",
+ "k:010111110:u:",
+ "k:010111111:k:",
+ "k:0100001000:r:",
+ "k:0100001001:ESCAPE:",
+ "k:0100001010:?:",
+ "k:0100001100:t:",
+ "k:0100001101:g:",
+ "k:0101111011:d:",
+ "k:01000010110:j:",
+ "k:010000101110:):",
+ "k:010111101000:;:",
+ "k:010111101001:c:",
+ "k:010111101010:S:",
+ "k:0100001011110:v:",
+ "k:0100001011111:R:",
+ "k:0101111010110:!:",
+ "k:01011110101110:@:",
+ "k:010111101011110:\":",
+ "k:010111101011111:STOP:",
+ "l:010:a:",
+ "l:011:i:",
+ "l:100:l:",
+ "l:110:e:",
+ "l:111: :",
+ "l:0000:u:",
+ "l:0001:d:",
+ "l:0010:y:",
+ "l:1011:o:",
+ "l:10100:s:",
+ "l:001100:.:",
+ "l:001110:t:",
+ "l:0011010:v:",
+ "l:0011110:f:",
+ "l:1010100:m:",
+ "l:1010101:k:",
+ "l:1010110:p:",
+ "l:00110111:c:",
+ "l:00111110:-:",
+ "l:10101111:,:",
+ "l:001101101:0x3a:",
+ "l:001111111:b:",
+ "l:101011100:':",
+ "l:0011011000:r:",
+ "l:0011011001:h:",
+ "l:0011111100:n:",
+ "l:0011111101:g:",
+ "l:1010111011:w:",
+ "l:10101110100:?:",
+ "l:1010111010100:!:",
+ "l:1010111010110:z:",
+ "l:10101110101011:/:",
+ "l:101011101010100:;:",
+ "l:101011101011100:E:",
+ "l:101011101011101:*:",
+ "l:101011101011111:STOP:",
+ "l:1010111010101011:ESCAPE:",
+ "l:1010111010111100:):",
+ "l:10101110101010100:@:",
+ "l:10101110101010101:j:",
+ "l:10101110101111010:\":",
+ "l:101011101011110110:[:",
+ "l:101011101011110111:]:",
+ "m:00:a:",
+ "m:01:e:",
+ "m:111: :",
+ "m:1001:p:",
+ "m:1011:o:",
+ "m:1100:i:",
+ "m:10000:.:",
+ "m:10001:s:",
+ "m:11010:u:",
+ "m:11011:m:",
+ "m:101001:y:",
+ "m:101011:b:",
+ "m:1010000:,:",
+ "m:1010100:/:",
+ "m:10100010:]:",
+ "m:101000110:0x3a:",
+ "m:101010100:':",
+ "m:1010001111:r:",
+ "m:1010101011:f:",
+ "m:1010101100:l:",
+ "m:1010101110:n:",
+ "m:10100011100:?:",
+ "m:10100011101:!:",
+ "m:10101010100:STOP:",
+ "m:10101010101:w:",
+ "m:10101011011:h:",
+ "m:10101011110:-:",
+ "m:101010111110:4:",
+ "m:1010101101010:t:",
+ "m:1010101101011:@:",
+ "m:1010101111110:;:",
+ "m:1010101111111:c:",
+ "m:10101011010000:):",
+ "m:10101011010001:ESCAPE:",
+ "m:10101011010011:d:",
+ "m:101010110100101:g:",
+ "m:10101011010010000:[:",
+ "m:10101011010010001:v:",
+ "m:10101011010010010:k:",
+ "m:10101011010010011:z:",
+ "n:01: :",
+ "n:001:t:",
+ "n:100:g:",
+ "n:111:d:",
+ "n:0000:s:",
+ "n:1010:a:",
+ "n:1101:e:",
+ "n:10110:c:",
+ "n:11000:i:",
+ "n:000111:.:",
+ "n:101111:n:",
+ "n:110011:o:",
+ "n:0001001:u:",
+ "n:0001011:v:",
+ "n:0001100:f:",
+ "n:1011100:k:",
+ "n:1011101:':",
+ "n:1100100:y:",
+ "n:1100101:,:",
+ "n:00010000:m:",
+ "n:00010100:l:",
+ "n:00010101:-:",
+ "n:000100011:w:",
+ "n:000110101:0x3a:",
+ "n:0001000101:z:",
+ "n:0001101000:h:",
+ "n:0001101100:b:",
+ "n:0001101101:j:",
+ "n:0001101110:r:",
+ "n:00010001000:p:",
+ "n:00011010011:x:",
+ "n:00011011111:?:",
+ "n:000100010011:;:",
+ "n:000110100101:):",
+ "n:000110111100:!:",
+ "n:000110111101:q:",
+ "n:0001000100100:/:",
+ "n:0001000100101:STOP:",
+ "n:0001101001000:ESCAPE:",
+ "n:00011010010010:B:",
+ "n:0001101001001100:]:",
+ "n:0001101001001101:\":",
+ "n:0001101001001110:@:",
+ "n:0001101001001111:*:",
+ "o:001:u:",
+ "o:011: :",
+ "o:100:r:",
+ "o:111:n:",
+ "o:0000:l:",
+ "o:1100:m:",
+ "o:1101:f:",
+ "o:00010:v:",
+ "o:01000:s:",
+ "o:01001:p:",
+ "o:10100:t:",
+ "o:10101:o:",
+ "o:10111:w:",
+ "o:000110:k:",
+ "o:000111:i:",
+ "o:010100:g:",
+ "o:010111:c:",
+ "o:101101:d:",
+ "o:0101011:e:",
+ "o:0101100:y:",
+ "o:0101101:a:",
+ "o:1011001:b:",
+ "o:01010101:h:",
+ "o:10110000:.:",
+ "o:010101000:-:",
+ "o:010101001:,:",
+ "o:1011000101:':",
+ "o:1011000111:x:",
+ "o:10110001001:0x3a:",
+ "o:10110001101:z:",
+ "o:101100010001:?:",
+ "o:101100011001:j:",
+ "o:1011000100000:!:",
+ "o:1011000110001:q:",
+ "o:10110001000010:J:",
+ "o:10110001100000:/:",
+ "o:10110001100001:):",
+ "o:1011000100001101:;:",
+ "o:1011000100001110:G:",
+ "o:10110001000011000:\":",
+ "o:10110001000011110:ESCAPE:",
+ "o:101100010000110010:]:",
+ "o:101100010000110011:@:",
+ "o:1011000100001111100:4:",
+ "o:1011000100001111101:STOP:",
+ "o:1011000100001111110:B:",
+ "o:10110001000011111110:O:",
+ "o:10110001000011111111:C:",
+ "p:001:l:",
+ "p:010: :",
+ "p:011:o:",
+ "p:101:r:",
+ "p:111:e:",
+ "p:0000:p:",
+ "p:1100:a:",
+ "p:1101:i:",
+ "p:00011:t:",
+ "p:10000:u:",
+ "p:10001:h:",
+ "p:10010:s:",
+ "p:000101:m:",
+ "p:0001001:d:",
+ "p:1001101:y:",
+ "p:1001110:.:",
+ "p:1001111:,:",
+ "p:00010000:-:",
+ "p:000100011:?:",
+ "p:100110001:0x3a:",
+ "p:1001100100:':",
+ "p:1001100101:]:",
+ "p:1001100110:+:",
+ "p:1001100111:b:",
+ "p:00010001001:f:",
+ "p:00010001010:k:",
+ "p:00010001011:!:",
+ "p:10011000001:c:",
+ "p:10011000010:n:",
+ "p:10011000011:w:",
+ "p:000100010000:STOP:",
+ "p:000100010001:;:",
+ "p:100110000001:/:",
+ "p:1001100000001:g:",
+ "p:10011000000001:):",
+ "p:100110000000001:\":",
+ "p:1001100000000001:S:",
+ "p:10011000000000000:ESCAPE:",
+ "p:10011000000000001:B:",
+ "q:1:u:",
+ "q:000:,:",
+ "q:001:.:",
+ "q:011: :",
+ "q:01001:b:",
+ "q:01010:':",
+ "q:01011:i:",
+ "q:010001:a:",
+ "q:01000000:?:",
+ "q:01000001:0x3a:",
+ "q:01000011:):",
+ "q:010000100:ESCAPE:",
+ "q:010000101:w:",
+ "r:000:a:",
+ "r:001:o:",
+ "r:100:i:",
+ "r:110: :",
+ "r:111:e:",
+ "r:0100:s:",
+ "r:0101:t:",
+ "r:01110:d:",
+ "r:10100:n:",
+ "r:10101:y:",
+ "r:011010:u:",
+ "r:011011:m:",
+ "r:011111:k:",
+ "r:101101:l:",
+ "r:101110:.:",
+ "r:101111:r:",
+ "r:0110000:f:",
+ "r:0110010:,:",
+ "r:0110011:v:",
+ "r:1011000:c:",
+ "r:1011001:g:",
+ "r:01100011:':",
+ "r:01111000:-:",
+ "r:01111001:b:",
+ "r:01111011:p:",
+ "r:011000101:0x3a:",
+ "r:011110100:w:",
+ "r:0111101010:?:",
+ "r:0111101011:h:",
+ "r:01100010010:!:",
+ "r:011000100001:q:",
+ "r:011000100010:j:",
+ "r:011000100011:STOP:",
+ "r:011000100110:/:",
+ "r:0110001000001:;:",
+ "r:0110001001111:):",
+ "r:01100010011100:8:",
+ "r:01100010011101:z:",
+ "r:011000100000001:\":",
+ "r:011000100000011:]:",
+ "r:0110001000000000:T:",
+ "r:0110001000000100:x:",
+ "r:0110001000000101:ESCAPE:",
+ "r:01100010000000011:Z:",
+ "r:011000100000000100:*:",
+ "r:0110001000000001010:D:",
+ "r:0110001000000001011:B:",
+ "s:0: :",
+ "s:101:t:",
+ "s:1000:.:",
+ "s:1110:e:",
+ "s:10011:,:",
+ "s:11000:o:",
+ "s:11001:s:",
+ "s:11110:h:",
+ "s:11111:i:",
+ "s:100101:c:",
+ "s:110100:u:",
+ "s:110110:p:",
+ "s:1101111:a:",
+ "s:10010001:n:",
+ "s:10010011:m:",
+ "s:11010100:y:",
+ "s:11010110:0x3a:",
+ "s:11011100:l:",
+ "s:11011101:k:",
+ "s:100100001:b:",
+ "s:100100100:f:",
+ "s:110101010:w:",
+ "s:110101111:':",
+ "s:1001000000:!:",
+ "s:1001000001:g:",
+ "s:1001001010:r:",
+ "s:1101010110:?:",
+ "s:1101010111:-:",
+ "s:1101011101:q:",
+ "s:11010111001:d:",
+ "s:100100101100:/:",
+ "s:100100101101:):",
+ "s:100100101111:STOP:",
+ "s:110101110000:]:",
+ "s:110101110001:;:",
+ "s:1001001011101:v:",
+ "s:100100101110001:\":",
+ "s:100100101110011:z:",
+ "s:1001001011100000:j:",
+ "s:1001001011100001:ESCAPE:",
+ "s:1001001011100100:[:",
+ "s:10010010111001011:@:",
+ "s:100100101110010101:T:",
+ "s:1001001011100101000:x:",
+ "s:1001001011100101001:`:",
+ "t:10:h:",
+ "t:000:i:",
+ "t:010:o:",
+ "t:011:e:",
+ "t:111: :",
+ "t:0010:a:",
+ "t:00110:u:",
+ "t:11001:r:",
+ "t:11011:s:",
+ "t:001111:.:",
+ "t:110001:t:",
+ "t:110100:y:",
+ "t:0011101:c:",
+ "t:1100001:l:",
+ "t:00111001:-:",
+ "t:11000000:v:",
+ "t:11000001:m:",
+ "t:11010101:w:",
+ "t:11010110:,:",
+ "t:11010111:':",
+ "t:001110000:n:",
+ "t:0011100011:?:",
+ "t:1101010001:b:",
+ "t:1101010010:0x3a:",
+ "t:00111000100:!:",
+ "t:11010100000:z:",
+ "t:11010100110:d:",
+ "t:11010100111:f:",
+ "t:110101000010:x:",
+ "t:0011100010100:g:",
+ "t:0011100010101:;:",
+ "t:1101010000110:p:",
+ "t:00111000101100:P:",
+ "t:00111000101101:STOP:",
+ "t:00111000101111:):",
+ "t:11010100001110:/:",
+ "t:11010100001111:k:",
+ "t:0011100010111000:@:",
+ "t:0011100010111010:E:",
+ "t:00111000101110011:]:",
+ "t:00111000101110111:\":",
+ "t:001110001011100100:F:",
+ "t:001110001011101100:ESCAPE:",
+ "t:0011100010111001010:j:",
+ "t:0011100010111011010:1:",
+ "t:0011100010111011011:[:",
+ "t:00111000101110010110:\\:",
+ "t:001110001011100101110:K:",
+ "t:001110001011100101111:C:",
+ "u:011:t:",
+ "u:101:n:",
+ "u:110:s:",
+ "u:111:r:",
+ "u:0001:d:",
+ "u:0010:e:",
+ "u:0101:l:",
+ "u:1000:p:",
+ "u:00000:b:",
+ "u:00001: :",
+ "u:00110:i:",
+ "u:01000:a:",
+ "u:01001:g:",
+ "u:10010:c:",
+ "u:10011:m:",
+ "u:0011100:y:",
+ "u:00111010:z:",
+ "u:00111100:':",
+ "u:00111110:f:",
+ "u:00111111:k:",
+ "u:001111010:,:",
+ "u:0011101101:-:",
+ "u:0011101110:o:",
+ "u:0011110110:.:",
+ "u:0011110111:x:",
+ "u:00111011000:w:",
+ "u:00111011110:0x3a:",
+ "u:001110110010:q:",
+ "u:001110111110:h:",
+ "u:001110111111:v:",
+ "u:0011101100110:j:",
+ "u:001110110011100:u:",
+ "u:001110110011101:?:",
+ "u:0011101100111110:/:",
+ "u:0011101100111111:!:",
+ "u:00111011001111001:ESCAPE:",
+ "u:001110110011110000:\\:",
+ "u:001110110011110001:STOP:",
+ "u:001110110011110100:;:",
+ "u:001110110011110110:J:",
+ "u:001110110011110111:):",
+ "u:0011101100111101010:T:",
+ "u:0011101100111101011:]:",
+ "v:1:e:",
+ "v:01:i:",
+ "v:000:a:",
+ "v:0011:o:",
+ "v:00101:.:",
+ "v:001001: :",
+ "v:00100001:':",
+ "v:00100011:y:",
+ "v:001000000:u:",
+ "v:001000100:s:",
+ "v:0010001010:r:",
+ "v:00100000100:-:",
+ "v:00100000110:,:",
+ "v:00100010110:n:",
+ "v:001000001010:g:",
+ "v:001000001011:v:",
+ "v:001000001111:l:",
+ "v:001000101110:@:",
+ "v:001000101111:0x3a:",
+ "v:0010000011101:k:",
+ "v:00100000111000:b:",
+ "v:001000001110010:t:",
+ "v:0010000011100110:d:",
+ "v:00100000111001110:/:",
+ "v:001000001110011110:ESCAPE:",
+ "v:001000001110011111:1:",
+ "w:00:i:",
+ "w:011:e:",
+ "w:100: :",
+ "w:101:s:",
+ "w:110:h:",
+ "w:0101:a:",
+ "w:1111:o:",
+ "w:01000:.:",
+ "w:01001:w:",
+ "w:11100:n:",
+ "w:1110110:r:",
+ "w:11101010:,:",
+ "w:11101011:l:",
+ "w:11101111:y:",
+ "w:111010010:c:",
+ "w:111011101:b:",
+ "w:1110100010:0x3a:",
+ "w:1110100110:m:",
+ "w:1110100111:':",
+ "w:1110111000:d:",
+ "w:11101000000:f:",
+ "w:11101000001:]:",
+ "w:11101000010:!:",
+ "w:11101000111:k:",
+ "w:11101110010:-:",
+ "w:111010000111:g:",
+ "w:111010001100:?:",
+ "w:111010001101:t:",
+ "w:111011100111:p:",
+ "w:1110100001100:STOP:",
+ "w:1110100001101:u:",
+ "w:1110111001101:):",
+ "w:11101110011001:j:",
+ "w:111011100110001:q:",
+ "w:1110111001100000:/:",
+ "w:11101110011000010:;:",
+ "w:111011100110000111:[:",
+ "w:1110111001100001100:ESCAPE:",
+ "w:1110111001100001101:B:",
+ "x:01:p:",
+ "x:11:t:",
+ "x:101: :",
+ "x:0000:i:",
+ "x:0010:a:",
+ "x:1000:c:",
+ "x:00010:u:",
+ "x:00111:e:",
+ "x:10011:-:",
+ "x:000110:f:",
+ "x:001101:o:",
+ "x:100100:.:",
+ "x:0001110:,:",
+ "x:0001111:m:",
+ "x:0011001:y:",
+ "x:00110001:9:",
+ "x:10010101:':",
+ "x:10010110:q:",
+ "x:001100000:s:",
+ "x:100101000:0x3a:",
+ "x:100101110:h:",
+ "x:0011000011:?:",
+ "x:1001010010:l:",
+ "x:1001011110:w:",
+ "x:00110000100:A:",
+ "x:10010100110:x:",
+ "x:10010100111:b:",
+ "x:10010111111:):",
+ "x:001100001011:/:",
+ "x:0011000010100:4:",
+ "x:0011000010101:!:",
+ "x:1001011111000:g:",
+ "x:1001011111001:STOP:",
+ "x:1001011111011:;:",
+ "x:100101111101001:v:",
+ "x:100101111101010:F:",
+ "x:100101111101011:E:",
+ "x:1001011111010000:ESCAPE:",
+ "x:1001011111010001:C:",
+ "y:1: :",
+ "y:000:o:",
+ "y:0011:s:",
+ "y:0101:.:",
+ "y:01001:,:",
+ "y:01100:e:",
+ "y:01110:':",
+ "y:001001:a:",
+ "y:001010:i:",
+ "y:001011:d:",
+ "y:010001:n:",
+ "y:011011:0x3a:",
+ "y:011111:l:",
+ "y:0010000:w:",
+ "y:0110100:t:",
+ "y:0110101:m:",
+ "y:0111101:-:",
+ "y:00100011:b:",
+ "y:01000000:?:",
+ "y:01000001:r:",
+ "y:01000010:p:",
+ "y:01000011:f:",
+ "y:01111001:c:",
+ "y:0010001001:;:",
+ "y:0010001010:J:",
+ "y:0111100000:h:",
+ "y:0111100001:!:",
+ "y:0111100011:g:",
+ "y:00100010000:):",
+ "y:00100010111:/:",
+ "y:01111000101:]:",
+ "y:001000100011:k:",
+ "y:001000101100:ESCAPE:",
+ "y:001000101101:u:",
+ "y:011110001001:STOP:",
+ "y:0010001000100:z:",
+ "y:0111100010001:\":",
+ "y:00100010001011:j:",
+ "y:01111000100001:2:",
+ "y:001000100010100:y:",
+ "y:001000100010101:x:",
+ "y:0111100010000000:v:",
+ "y:0111100010000001:T:",
+ "y:0111100010000010:E:",
+ "y:0111100010000011:P:",
+ "z:10:e:",
+ "z:001:a:",
+ "z:011:z:",
+ "z:110: :",
+ "z:111:i:",
+ "z:0001:l:",
+ "z:0100:y:",
+ "z:01010:o:",
+ "z:000000:c:",
+ "z:000010:,:",
+ "z:000011:.:",
+ "z:010110:w:",
+ "z:0000010:':",
+ "z:00000110:0x3a:",
+ "z:00000111:t:",
+ "z:01011101:m:",
+ "z:010111000:k:",
+ "z:010111100:-:",
+ "z:010111101:u:",
+ "z:010111111:b:",
+ "z:01011100100:s:",
+ "z:01011100101:/:",
+ "z:01011100111:d:",
+ "z:01011111001:p:",
+ "z:01011111011:?:",
+ "z:010111001100:h:",
+ "z:010111110000:@:",
+ "z:010111110100:):",
+ "z:0101110011010:!:",
+ "z:0101111100011:v:",
+ "z:0101111101010:g:",
+ "z:01011100110110:f:",
+ "z:01011100110111:r:",
+ "z:01011111000100:q:",
+ "z:01011111000101:n:",
+ "z:01011111010110:ESCAPE:",
+ "z:01011111010111:]:",
+ "{:0:ESCAPE:",
+ "{:1:ESCAPE:",
+ "|:0:ESCAPE:",
+ "|:1:ESCAPE:",
+ "}:0:ESCAPE:",
+ "}:1:STOP:",
+ "~:0:ESCAPE:",
+ "~:1:ESCAPE:",
+ "0x7f:0:ESCAPE:",
+ "0x7f:1:ESCAPE:",
+ NULL,
+};
+
+// MediaHighWay Ver. 1
+
+typedef struct
+{
+ u_char Name [15];
+} sThemeMHW1;
+
+typedef struct
+{
+ u_char NetworkIdHigh :8;
+ u_char NetworkIdLow :8;
+ u_char TransportIdHigh :8;
+ u_char TransportIdLow :8;
+ u_char ServiceIdHigh :8;
+ u_char ServiceIdLow :8;
+ u_char Name [16];
+} sChannelMHW1;
+
+typedef struct
+{
+ u_char TableId :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char SectionSyntaxIndicator :1;
+ u_char :1;
+ u_char :2;
+ u_char SectionLengthHigh :4;
+#else
+ u_char SectionLengthHigh :4;
+ u_char :2;
+ u_char :1;
+ u_char SectionSyntaxIndicator :1;
+#endif
+ u_char SectionLengthLow :8;
+ u_char ChannelId :8;
+ u_char ThemeId :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char Day :3;
+ u_char Hours :5;
+#else
+ u_char Hours :5;
+ u_char Day :3;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char Minutes :6;
+ u_char :1;
+ u_char SummaryAvailable :1;
+#else
+ u_char SummaryAvailable :1;
+ u_char :1;
+ u_char Minutes :6;
+#endif
+ u_char :8;
+ u_char :8;
+ u_char DurationHigh :8;
+ u_char DurationLow :8;
+ u_char Title [23];
+ u_char PpvIdHigh :8;
+ u_char PpvIdMediumHigh :8;
+ u_char PpvIdMediumLow :8;
+ u_char PpvIdLow :8;
+ u_char ProgramIdHigh :8;
+ u_char ProgramIdMediumHigh :8;
+ u_char ProgramIdMediumLow :8;
+ u_char ProgramIdLow :8;
+ u_char :8;
+ u_char :8;
+ u_char :8;
+ u_char :8;
+} sTitleMHW1;
+
+typedef struct {
+ u_char TableId :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char SectionSyntaxIndicator :1;
+ u_char :1;
+ u_char :2;
+ u_char SectionLengthHigh :4;
+#else
+ u_char SectionLengthHigh :4;
+ u_char :2;
+ u_char :1;
+ u_char SectionSyntaxIndicator :1;
+#endif
+ u_char SectionLengthLow :8;
+ u_char ProgramIdHigh :8;
+ u_char ProgramIdMediumHigh :8;
+ u_char ProgramIdMediumLow :8;
+ u_char ProgramIdLow :8;
+ u_char Byte7 :8;
+ u_char Byte8 :8;
+ u_char Byte9 :8;
+ u_char NumReplays :8;
+} sSummaryMHW1;
+
+typedef struct {
+ u_char TableId :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char SectionSyntaxIndicator :1;
+ u_char :1;
+ u_char :2;
+ u_char SectionLengthHigh :4;
+#else
+ u_char SectionLengthHigh :4;
+ u_char :2;
+ u_char :1;
+ u_char SectionSyntaxIndicator :1;
+#endif
+ u_char SectionLengthLow :8;
+ u_char TableIdExtensionHigh :8;
+ u_char TableIdExtensionLow :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char Reserved :2;
+ u_char VersionNumber :5;
+ u_char CurrentNextIndicator :1;
+#else
+ u_char CurrentNextIndicator :1;
+ u_char VersionNumber :5;
+ u_char Reserved :2;
+#endif
+ u_char SectionNumber :8;
+ u_char LastSectionNumber :8;
+ u_char LanguageCodeHigh :8;
+ u_char LanguageCodeMedium :8;
+ u_char LanguageCodeLow :8;
+ u_char AlwaysZero0 :8;
+} sTitleBlockHeaderNagraGuide;
+
+typedef struct {
+ u_char ChannelIdHigh :8;
+ u_char ChannelIdLow :8;
+ u_char BlocklengthHigh :8;
+ u_char BlocklengthLow :8;
+ u_char NumberOfTitlesHigh :8;
+ u_char NumberOfTitlesMediumHigh :8;
+ u_char NumberOfTitlesMediumLow :8;
+ u_char NumberOfTitlesLow :8;
+} sTitleBlockNagraGuide; //all titles in one block are on the same channel
+
+typedef struct {
+ u_char EventIdHigh :8;
+ u_char EventIdMediumHigh :8;
+ u_char EventIdMediumLow :8;
+ u_char EventIdLow :8;
+ u_char StartTimeHigh :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char StartTimeLow :5;
+ u_char AlwaysZero16 :3;
+#else
+ u_char AlwaysZero16 :3;//can be 1,2,3 or 4 with night-programs etc.???
+ u_char StartTimeLow :5;
+#endif
+ u_char Duration :8;
+ u_char AlwaysZero1 :8;
+ u_char AlwaysZero2 :8;
+ u_char AlwaysZero3 :8;
+ u_char AlwaysZero4 :8;
+ u_char AlwaysZero5 :8;
+ u_char SumDataOffsetHigh :8;//address of relevant Summary Data Record
+ u_char SumDataOffsetMediumHigh :8;
+ u_char SumDataOffsetMediumLow :8;
+ u_char SumDataOffsetLow :8;
+ u_char AlwaysZero8 :8;
+ u_char AlwaysZero9 :8;
+ u_char AlwaysZero10 :8;
+ u_char AlwaysZero11 :8;
+ u_char OffsetToTextHigh :8;//offset from 2nd byte after languagecode gives length byte of title-text
+ u_char OffsetToTextMediumHigh :8;
+ u_char OffsetToTextMediumLow :8;
+ u_char OffsetToTextLow :8;
+ u_char OffsetToText2High :8;//offset from 2nd byte after languagecode gives length byte of title-text2
+ u_char OffsetToText2MediumHigh :8;
+ u_char OffsetToText2MediumLow :8;
+ u_char OffsetToText2Low :8;
+ u_char ThemeId :8;
+ u_char AlwaysZero17 :8;
+} sTitleNagraGuide;
+
+//first 4 bytes with zeroterminated language code
+typedef struct {
+ u_char AlwaysZero1 :8;
+ u_char AlwaysZero2 :8;
+ u_char AlwaysZero3 :8;
+ u_char AlwaysZero4 :8;
+ u_char Always1 :8;
+ u_char Always9 :8;
+ u_char Always7 :8;
+ u_char Always0 :8;
+ u_char AlwaysZero5 :8;
+ u_char AlwaysZero6 :8;
+ u_char AlwaysZero7 :8;
+ u_char AlwaysZero8 :8;
+ u_char AlwaysZero9 :8;
+ u_char Always0x01 :8;
+ u_char EventIdHigh :8;
+ u_char EventIdMediumHigh :8;
+ u_char EventIdMediumLow :8;
+ u_char EventIdLow :8;
+ u_char NumberOfBlocks :8;//every block > 2 adds 4 bytes, if block = 1 then no summtxtoffset so subtract 4 bytes!
+ u_char BlockIdHigh :8;
+ u_char BlockIdMediumHigh :8;
+ u_char BlockIdMediumLow :8;
+ u_char BlockIdLow :8;
+ u_char SummTxtOffsetHigh :8;//address from start of section + 4 points to relevant Always0x4e
+ u_char SummTxtOffsetMediumHigh :8;
+ u_char SummTxtOffsetMediumLow :8;
+ u_char SummTxtOffsetLow :8;
+ u_char Unknown1 :8;
+ u_char Unknown2 :8;
+} sSummaryDataNagraGuide;
+
+typedef struct {
+ u_char Always0x4e :8;//if 0x4e summarytext follows if 0x8c no summarytext GBR record follows
+ u_char Blocklength :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char TextNr :4;
+ u_char LastTextNr :4;
+#else
+ u_char LastTextNr :4;//last nr of block of text
+ u_char TextNr :4;//nr of a block of text, starts with 0!!!
+#endif
+ u_char LanguageCodeHigh :8;
+ u_char LanguageCodeMedium :8;
+ u_char LanguageCodeLow :8;
+ u_char AlwaysZero1 :8;
+ u_char Textlength :8;
+ u_char Text :8;
+} sSummaryTextNagraGuide;
+
+typedef struct {
+ u_char Always0x8c :8;
+ u_char Blocklength :8;
+ u_char AlwaysZero1 :8;
+ u_char AlwaysZero2 :8;
+ u_char Un1 :8;
+ u_char Un2 :8;
+ u_char Un3 :8;
+ u_char Un4 :8;
+ u_char AlwaysZero3 :8;
+ u_char Un5 :8;
+ u_char Un6 :8;
+ u_char Un7 :8;
+ u_char AlwaysZero4 :8;
+ u_char Un8 :8;
+ u_char Un9 :8;
+ u_char Nextlength :8;
+ u_char Always0x81 :8;
+ u_char EventIdHigh :8;
+ u_char EventIdMedium :8;
+ u_char EventIdLow :8;
+} sSummaryGBRNagraGuide;
+
+typedef struct {
+ u_char SatId :8;//is always 0x01
+ u_char NetworkIdHigh :8;
+ u_char NetworkIdLow :8;
+ u_char TransportIdHigh :8;
+ u_char TransportIdLow :8;
+ u_char ServiceIdHigh :8;
+ u_char ServiceIdLow :8;
+ u_char Nr8cBlocks :8;
+ u_char Always0x8c :8;//next three fields are 0x00 for FTA channels....
+ u_char Nr8cBytes :8;
+ u_char AlwaysZero1 :8;//from here on optional fields, not used for FTA channels like BVN, regional S23.5 broadcasts
+ u_char ProviderIdHigh :8;
+ u_char ProviderIdLow :8;
+ u_char Always0x08 :8;
+ u_char Always0x02 :8;
+ u_char Always0x01 :8;
+ u_char AlwaysZero2 :8;
+ u_char Always0x20 :8;
+ u_char Always0x0a :8;
+ u_char Un4 :8;
+ u_char Always0x81 :8;
+ u_char Un5 :8;
+ u_char Always0x44 :8;
+ u_char Un6 :8;
+ u_char Un7 :8;
+ u_char Un8 :8;
+ u_char Un9 :8;
+} sChannelsNagraGuide;
+
+typedef struct {
+ u_char TitleOffsetHigh :8;//address from start of section (in 0x02x0) + 4 points to eventid of title that has this theme
+ u_char TitleOffsetMediumHigh :8;
+ u_char TitleOffsetMediumLow :8;
+ u_char TitleOffsetLow :8;
+ u_char AlwaysZero1 :8;
+ u_char Un1 :8;
+ u_char AlwaysZero2 :8;
+ u_char Always1 :8;
+} sThemesTitlesNagraGuide;
+
+typedef struct { //first three bytes form unknown header, then X blocks, where X = number of distinct table_id_extensio
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char TableIdExtensionLow :6;//BIG_ENDIAN not tested!!
+ u_char TableIdExtensionHigh :2;
+ u_char TIE200 :1;
+ u_char Unknown1 :2;
+ u_char VersionNumber :5;//contains current version of table_id_extension
+#else
+ u_char TableIdExtensionHigh :2;
+ u_char TableIdExtensionLow :6;
+ u_char VersionNumber :5;//contains current version of table_id_extension
+ u_char Unknown1 :2;
+ u_char TIE200 :1;
+#endif
+ u_char Always0xd6 :8;
+ u_char DayCounter :8;//for most sections this increments each day
+} sSection0000BlockNagraGuide;
+
+#define HILO16( x ) ( ( ( x##High << 8 ) | x##Low ) & 0xffff )
+#define HILO32( x ) ( ( ( ( ( x##High << 24 ) | ( x##MediumHigh << 16 ) ) | ( x##MediumLow << 8 ) ) | x##Low ) & 0xffffffff )
+#define MjdToEpochTime(x) (((x##_hi << 8 | x##_lo)-40587)*86400)