summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandomdan <randomdan@localhost>2011-03-17 10:44:20 +0000
committerrandomdan <randomdan@localhost>2011-03-17 10:44:20 +0000
commit51711b72590ebe30f7b4a6172b5c36ccff559d6c (patch)
treebaa460eba6e535e4ca4082ce3dd082a8d4ceb5f2
parentFinally convert ytfs to use boost stuff (untested, but it does build) (diff)
downloadp2pvr-51711b72590ebe30f7b4a6172b5c36ccff559d6c.tar.bz2
p2pvr-51711b72590ebe30f7b4a6172b5c36ccff559d6c.tar.xz
p2pvr-51711b72590ebe30f7b4a6172b5c36ccff559d6c.zip
Work to date on p2pvr - basic EIT scanner
-rw-r--r--p2pvr/Jamfile.jam0
-rw-r--r--p2pvr/cron/importSchedume.xml55
-rw-r--r--p2pvr/cron/sched.xml29
-rw-r--r--p2pvr/datasources/postgres.xml8
-rw-r--r--p2pvr/scanner/Jamfile.jam18
-rw-r--r--p2pvr/scanner/crc32.cpp61
-rw-r--r--p2pvr/scanner/dvb_info_tables.c312
-rw-r--r--p2pvr/scanner/ice_scan.cpp343
-rw-r--r--p2pvr/scanner/icescan.cpp0
-rw-r--r--p2pvr/scanner/langidents.c211
-rw-r--r--p2pvr/scanner/lookup.cpp52
-rw-r--r--p2pvr/scanner/p2scan.cpp761
-rw-r--r--p2pvr/scanner/scanner.ice7
-rw-r--r--p2pvr/scanner/si_tables.h1625
-rw-r--r--p2pvr/scanner/tv_grab_dvb.h32
15 files changed, 3514 insertions, 0 deletions
diff --git a/p2pvr/Jamfile.jam b/p2pvr/Jamfile.jam
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/p2pvr/Jamfile.jam
diff --git a/p2pvr/cron/importSchedume.xml b/p2pvr/cron/importSchedume.xml
new file mode 100644
index 0000000..928c2bd
--- /dev/null
+++ b/p2pvr/cron/importSchedume.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0"?>
+<block name="importSchedule" xmlns:p2="http://project2.randomdan.homeip.net">
+ <p2:library path="scanner/bin/gcc-4.5.2/debug/libp2pvr-scan-p2.so" />
+ <p2:eitrows name="schedule" demux="/dev/dvb/adapter0/demux0" />
+ <p2:sqlmerge name="mergeSchedule" datasource="postgres" targettable="programs">
+ <p2:iterate name="programs" source="schedule">
+ <p2:sqlmergeinsert name="insertProgram">
+ <parameters>
+ <param name="title"><value source="parent" attribute="title" depth="1" /></param>
+ <param name="titleLang"><value source="parent" attribute="titleLang" depth="1" /></param>
+ <param name="subtitle"><value source="parent" attribute="subtitle" depth="1" /></param>
+ <param name="subtitleLang"><value source="parent" attribute="subtitleLang" depth="1" /></param>
+ <param name="serviceID"><value source="parent" attribute="serviceID" depth="1" /></param>
+ <param name="descLang"><value source="parent" attribute="descLang" depth="1" /></param>
+ <param name="desc1"><value source="parent" attribute="desc1" depth="1" /></param>
+ <param name="desc2"><value source="parent" attribute="desc2" depth="1" /></param>
+ <param name="desc3"><value source="parent" attribute="desc3" depth="1" /></param>
+ <param name="videoAspect"><value source="parent" attribute="videoAspect" depth="1" /></param>
+ <param name="audioChannels"><value source="parent" attribute="audioChannels" depth="1" /></param>
+ <param name="language"><value source="parent" attribute="language" depth="1" /></param>
+ <param name="teletextSubtitleLang"><value source="parent" attribute="teletextSubtitleLang" depth="1" /></param>
+ <param name="category"><value source="parent" attribute="category" depth="1" /></param>
+ <param name="dvbRating"><value source="parent" attribute="dvbRating" depth="1" /></param>
+ <param name="contentIdentType"><value source="parent" attribute="contentIdentType" depth="1" /></param>
+ <param name="contentIdent"><value source="parent" attribute="contentIdent" depth="1" /></param>
+ <param name="startTime"><value source="parent" attribute="startTime" depth="1" /></param>
+ <param name="stopTime"><value source="parent" attribute="stopTime" depth="1" /></param>
+ <param name="eventID"><value source="parent" attribute="eventID" depth="1" /></param>
+ </parameters>
+ </p2:sqlmergeinsert>
+ </p2:iterate>
+ <columns>
+ <column>title</column>
+ <column>titleLang</column>
+ <column>subtitle</column>
+ <column>subtitleLang</column>
+ <column key="true">serviceID</column>
+ <column key="true">eventID</column>
+ <column>descLang</column>
+ <column>desc1</column>
+ <column>desc2</column>
+ <column>desc3</column>
+ <column>videoAspect</column>
+ <column>audioChannels</column>
+ <column>language</column>
+ <column>teletextSubtitleLang</column>
+ <column>category</column>
+ <column>dvbRating</column>
+ <column>contentIdentType</column>
+ <column>contentIdent</column>
+ <column>startTime</column>
+ <column>stopTime</column>
+ </columns>
+ </p2:sqlmerge>
+</block>
diff --git a/p2pvr/cron/sched.xml b/p2pvr/cron/sched.xml
new file mode 100644
index 0000000..db438d3
--- /dev/null
+++ b/p2pvr/cron/sched.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<block name="importSchedule" xmlns:p2="http://project2.randomdan.homeip.net">
+ <p2:library path="scanner/bin/gcc-4.5.2/debug/libp2pvr-scan-p2.so" />
+ <p2:eitrows name="schedule" demux="/dev/dvb/adapter0/demux0" />
+ <p2:view name="showSchedule" source="schedule" rootname="sched" recordname="show">
+ <columns>
+ <column name="title">title</column>
+ <column name="titleLang" source="attribute">titleLang</column>
+ <column name="subtitle" source="attribute">subtitle</column>
+ <column name="subtitleLang" source="attribute">subtitleLang</column>
+ <column name="serviceID" source="attribute">serviceID</column>
+ <column name="descLang" source="attribute">descLang</column>
+ <column name="desc1" source="attribute">desc1</column>
+ <column name="desc2" source="attribute">desc2</column>
+ <column name="desc3" source="attribute">desc3</column>
+ <column name="videoAspect" source="attribute">videoAspect</column>
+ <column name="audioChannels" source="attribute">audioChannels</column>
+ <column name="language" source="attribute">language</column>
+ <column name="teletextSubtitleLang" source="attribute">teletextSubtitleLang</column>
+ <column name="category" source="attribute">category</column>
+ <column name="dvbRating" source="attribute">dvbRating</column>
+ <column name="contentIdentType" source="attribute">contentIdentType</column>
+ <column name="contentIdent" source="attribute">contentIdent</column>
+ <column name="startTime" source="attribute">startTime</column>
+ <column name="stopTime" source="attribute">stopTime</column>
+ <column name="serviceID" source="attribute">serviceID</column>
+ </columns>
+ </p2:view>
+</block>
diff --git a/p2pvr/datasources/postgres.xml b/p2pvr/datasources/postgres.xml
new file mode 100644
index 0000000..df1ac0f
--- /dev/null
+++ b/p2pvr/datasources/postgres.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<project2:rdbmsdatasource xmlns:project2="http://project2.randomdan.homeip.net" name="postgres">
+ <readonly preferlocal="true">
+ <dsn host="defiant"><postgresql>host=defiant sslmode=disable user=p2tv dbname=gentoo options='-c search_path=p2tv,public'</postgresql></dsn>
+ <dsn host="firebrand"><postgresql>host=firebrand sslmode=disable user=p2tv dbname=gentoo options='-c search_path=p2tv,public'</postgresql></dsn>
+ </readonly>
+ <masterdsn><postgresql>host=defiant sslmode=disable user=p2tv dbname=gentoo options='-c search_path=p2tv,public'</postgresql></masterdsn>
+</project2:rdbmsdatasource>
diff --git a/p2pvr/scanner/Jamfile.jam b/p2pvr/scanner/Jamfile.jam
new file mode 100644
index 0000000..2117886
--- /dev/null
+++ b/p2pvr/scanner/Jamfile.jam
@@ -0,0 +1,18 @@
+project
+ : requirements
+ <variant>debug:<linkflags>-Wl,-z,defs <cflags>"-W -Wall -Werror -Wwrite-strings"
+ ;
+
+# Scanner base - the common part lifted from tv_grab_dvb
+lib p2pvr-scan-base : langidents.c crc32.cpp dvb_info_tables.c lookup.cpp ;
+
+# Scanner - the common part implementing the ICE interface
+lib p2pvr-scan-ice : icescan.cpp scanner.ice : <library>p2pvr-scan-base ;
+
+# Scanner - t
+lib p2pvr-scan-p2 : p2scan.cpp : <library>p2pvr-scan-base <library>../../project2//p2common ;
+
+# ScannerICE - the ICE test app
+#exe scanice : ice_scan.cpp : <library>p2pvr-scan ;
+
+explicit p2pvr-scan-ice ;
diff --git a/p2pvr/scanner/crc32.cpp b/p2pvr/scanner/crc32.cpp
new file mode 100644
index 0000000..3dec763
--- /dev/null
+++ b/p2pvr/scanner/crc32.cpp
@@ -0,0 +1,61 @@
+/* crc32.c: CRC32 routine
+ */
+#include <stdio.h>
+#include <stdint.h>
+
+static const uint32_t crc_table[256] = {
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
+ 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3,
+ 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef,
+ 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb,
+ 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4,
+ 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08,
+ 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc,
+ 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050,
+ 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1,
+ 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5,
+ 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9,
+ 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd,
+ 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2,
+ 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e,
+ 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a,
+ 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676,
+ 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+uint32_t _dvb_crc32(const uint8_t *data, size_t len)
+{
+ size_t i;
+ uint32_t crc = 0xffffffff;
+
+ for (i = 0; i < len; i++)
+ crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *data++) & 0xff];
+
+ return crc;
+}
diff --git a/p2pvr/scanner/dvb_info_tables.c b/p2pvr/scanner/dvb_info_tables.c
new file mode 100644
index 0000000..d8257be
--- /dev/null
+++ b/p2pvr/scanner/dvb_info_tables.c
@@ -0,0 +1,312 @@
+/*
+ * tv_grab_dvb - (c) Mark Bryars 2004
+ * God bless vim and macros, this would have taken forever to format otherwise.
+ */
+#include "tv_grab_dvb.h"
+
+const struct lookup_table description_table[] = {
+ { {0x00}, "\0UNDEFINED CONTENT"},
+ { {0x01}, "\0UNDEFINED CONTENT"},
+ { {0x02}, "\0UNDEFINED CONTENT"},
+ { {0x03}, "\0UNDEFINED CONTENT"},
+ { {0x04}, "\0UNDEFINED CONTENT"},
+ { {0x05}, "\0UNDEFINED CONTENT"},
+ { {0x06}, "\0UNDEFINED CONTENT"},
+ { {0x07}, "\0UNDEFINED CONTENT"},
+ { {0x08}, "\0UNDEFINED CONTENT"},
+ { {0x09}, "\0UNDEFINED CONTENT"},
+ { {0x0A}, "\0UNDEFINED CONTENT"},
+ { {0x0B}, "\0UNDEFINED CONTENT"},
+ { {0x0C}, "\0UNDEFINED CONTENT"},
+ { {0x0D}, "\0UNDEFINED CONTENT"},
+ { {0x0E}, "\0UNDEFINED CONTENT"},
+ { {0x0F}, "\0UNDEFINED CONTENT"},
+
+ { {0x10}, "Movie / Drama" },
+ { {0x11}, "Movie - detective/thriller" },
+ { {0x12}, "Movie - adventure/western/war" },
+ { {0x13}, "Movie - science fiction/fantasy/horror" },
+ { {0x14}, "Movie - comedy" },
+ { {0x15}, "Movie - soap/melodrama/folkloric" },
+ { {0x16}, "Movie - romance" },
+ { {0x17}, "Movie - serious/classical/religious/historical movie/drama" },
+ { {0x18}, "Movie - adult movie/drama" },
+ { {0x19}, "\0Movie - RESERVED" },
+ { {0x1A}, "\0Movie - RESERVED" },
+ { {0x1B}, "\0Movie - RESERVED" },
+ { {0x1C}, "\0Movie - RESERVED" },
+ { {0x1D}, "\0Movie - RESERVED" },
+ { {0x1E}, "\0Movie - RESERVED" },
+ { {0x1F}, NULL },
+
+ { {0x20}, "News / Current Affairs" },
+ { {0x21}, "New - news/weather report" },
+ { {0x22}, "New - news magazine" },
+ { {0x23}, "New - documentary" },
+ { {0x24}, "New - discussion/interview/debate" },
+ { {0x25}, "\0News - RESERVED" },
+ { {0x26}, "\0News - RESERVED" },
+ { {0x27}, "\0News - RESERVED" },
+ { {0x28}, "\0News - RESERVED" },
+ { {0x29}, "\0News - RESERVED" },
+ { {0x2A}, "\0News - RESERVED" },
+ { {0x2B}, "\0News - RESERVED" },
+ { {0x2C}, "\0News - RESERVED" },
+ { {0x2D}, "\0News - RESERVED" },
+ { {0x2E}, "\0News - RESERVED" },
+ { {0x2E}, NULL },
+
+ { {0x30}, "Show / Game Show" },
+ { {0x31}, "Show - game show/quiz/contest" },
+ { {0x32}, "Show - variety show" },
+ { {0x33}, "Show - talk show" },
+ { {0x34}, "\0Show - RESERVED" },
+ { {0x35}, "\0Show - RESERVED" },
+ { {0x36}, "\0Show - RESERVED" },
+ { {0x37}, "\0Show - RESERVED" },
+ { {0x38}, "\0Show - RESERVED" },
+ { {0x39}, "\0Show - RESERVED" },
+ { {0x3A}, "\0Show - RESERVED" },
+ { {0x3B}, "\0Show - RESERVED" },
+ { {0x3C}, "\0Show - RESERVED" },
+ { {0x3D}, "\0Show - RESERVED" },
+ { {0x3E}, "\0Show - RESERVED" },
+ { {0x3F}, NULL },
+
+ { {0x40}, "Sports" },
+ { {0x41}, "Sports - special events (Olympic Games, World Cup etc.)" },
+ { {0x42}, "Sports - sports magazines" },
+ { {0x43}, "Sports - football/soccer" },
+ { {0x44}, "Sports - tennis/squash" },
+ { {0x45}, "Sports - team sports (excluding football)" },
+ { {0x46}, "Sports - athletics" },
+ { {0x47}, "Sports - motor sport" },
+ { {0x48}, "Sports - water sport" },
+ { {0x49}, "Sports - winter sports" },
+ { {0x4A}, "Sports - equestrian" },
+ { {0x4B}, "Sports - martial sports" },
+ { {0x4C}, "\0Sports - RESERVED" },
+ { {0x4D}, "\0Sports - RESERVED" },
+ { {0x4E}, "\0Sports - RESERVED" },
+ { {0x4F}, NULL },
+
+ { {0x50}, "Childrens / Youth" },
+ { {0x51}, "Children - pre-school children's programmes" },
+ { {0x52}, "Children - entertainment programmes for 6 to 14" },
+ { {0x53}, "Children - entertainment programmes for 10 to 16" },
+ { {0x54}, "Children - informational/educational/school programmes" },
+ { {0x55}, "Children - cartoons/puppets" },
+ { {0x56}, "\0Children - RESERVED" },
+ { {0x57}, "\0Children - RESERVED" },
+ { {0x58}, "\0Children - RESERVED" },
+ { {0x59}, "\0Children - RESERVED" },
+ { {0x5A}, "\0Children - RESERVED" },
+ { {0x5B}, "\0Children - RESERVED" },
+ { {0x5C}, "\0Children - RESERVED" },
+ { {0x5D}, "\0Children - RESERVED" },
+ { {0x5E}, "\0Children - RESERVED" },
+ { {0x5F}, NULL },
+
+ { {0x60}, "Music / Ballet / Dance" },
+ { {0x61}, "Music - rock/pop" },
+ { {0x62}, "Music - serious music/classical music" },
+ { {0x63}, "Music - folk/traditional music" },
+ { {0x64}, "Music - jazz" },
+ { {0x65}, "Music - musical/opera" },
+ { {0x66}, "Music - ballet" },
+ { {0x67}, "\0Music - RESERVED" },
+ { {0x68}, "\0Music - RESERVED" },
+ { {0x69}, "\0Music - RESERVED" },
+ { {0x6A}, "\0Music - RESERVED" },
+ { {0x6B}, "\0Music - RESERVED" },
+ { {0x6C}, "\0Music - RESERVED" },
+ { {0x6D}, "\0Music - RESERVED" },
+ { {0x6E}, "\0Music - RESERVED" },
+ { {0x6F}, NULL },
+
+ { {0x70}, "Arts / Culture" },
+ { {0x71}, "Arts - performing arts" },
+ { {0x72}, "Arts - fine arts" },
+ { {0x73}, "Arts - religion" },
+ { {0x74}, "Arts - popular culture/traditional arts" },
+ { {0x75}, "Arts - literature" },
+ { {0x76}, "Arts - film/cinema" },
+ { {0x77}, "Arts - experimental film/video" },
+ { {0x78}, "Arts - broadcasting/press" },
+ { {0x79}, "Arts - new media" },
+ { {0x7A}, "Arts - arts/culture magazines" },
+ { {0x7B}, "Arts - fashion" },
+ { {0x7C}, "\0Arts - RESERVED" },
+ { {0x7D}, "\0Arts - RESERVED" },
+ { {0x7E}, "\0Arts - RESERVED" },
+ { {0x7F}, NULL },
+
+ { {0x80}, "Social / Policical / Economics" },
+ { {0x81}, "Social - magazines/reports/documentary" },
+ { {0x82}, "Social - economics/social advisory" },
+ { {0x83}, "Social - remarkable people" },
+ { {0x84}, "\0Social - RESERVED" },
+ { {0x85}, "\0Social - RESERVED" },
+ { {0x86}, "\0Social - RESERVED" },
+ { {0x87}, "\0Social - RESERVED" },
+ { {0x88}, "\0Social - RESERVED" },
+ { {0x89}, "\0Social - RESERVED" },
+ { {0x8A}, "\0Social - RESERVED" },
+ { {0x8b}, "\0Social - RESERVED" },
+ { {0x8C}, "\0Social - RESERVED" },
+ { {0x8D}, "\0Social - RESERVED" },
+ { {0x8E}, "\0Social - RESERVED" },
+ { {0x8F}, NULL },
+
+ { {0x90}, "Education / Science / Factual" },
+ { {0x91}, "Education - nature/animals/environment" },
+ { {0x92}, "Education - technology/natural sciences" },
+ { {0x93}, "Education - medicine/physiology/psychology" },
+ { {0x94}, "Education - foreign countries/expeditions" },
+ { {0x95}, "Education - social/spiritual sciences" },
+ { {0x96}, "Education - further education" },
+ { {0x97}, "Education - languages" },
+ { {0x98}, "\0Education - RESERVED" },
+ { {0x99}, "\0Education - RESERVED" },
+ { {0x9A}, "\0Education - RESERVED" },
+ { {0x9B}, "\0Education - RESERVED" },
+ { {0x9C}, "\0Education - RESERVED" },
+ { {0x9D}, "\0Education - RESERVED" },
+ { {0x9E}, "\0Education - RESERVED" },
+ { {0x9F}, NULL },
+
+ { {0xA0}, "Leisure / Hobbies" },
+ { {0xA1}, "Leisure - tourism/travel" },
+ { {0xA2}, "Leisure - handicraft" },
+ { {0xA3}, "Leisure - motoring" },
+ { {0xA4}, "Leisure - fitness &amp; health" },
+ { {0xA5}, "Leisure - cooking" },
+ { {0xA6}, "Leisure - advertizement/shopping" },
+ { {0xA7}, "Leisure - gardening" },
+ { {0xA8}, "\0Leisure - RESERVED" },
+ { {0xA9}, "\0Leisure - RESERVED" },
+ { {0xAA}, "\0Leisure - RESERVED" },
+ { {0xAB}, "\0Leisure - RESERVED" },
+ { {0xAC}, "\0Leisure - RESERVED" },
+ { {0xAD}, "\0Leisure - RESERVED" },
+ { {0xAE}, "\0Leisure - RESERVED" },
+ { {0xAF}, NULL },
+
+ // Special
+ { {0xB0}, "Original Language" },
+ { {0xB1}, "black &amp; white" },
+ { {0xB2}, "unpublished" },
+ { {0xB3}, "live broadcast" },
+ { {0xB4}, "\0Characteristics - RESERVED" },
+ { {0xB5}, "\0Characteristics - RESERVED" },
+ { {0xB6}, "\0Characteristics - RESERVED" },
+ { {0xB7}, "\0Characteristics - RESERVED" },
+ { {0xB8}, "\0Characteristics - RESERVED" },
+ { {0xB9}, "\0Characteristics - RESERVED" },
+ { {0xBA}, "\0Characteristics - RESERVED" },
+ { {0xBB}, "\0Characteristics - RESERVED" },
+ { {0xBC}, "\0Characteristics - RESERVED" },
+ { {0xBD}, "\0Characteristics - RESERVED" },
+ { {0xBE}, "\0Characteristics - RESERVED" },
+ { {0xBF}, NULL },
+
+ { {0xC0}, "\0RESERVED" },
+ { {0xC1}, "\0RESERVED" },
+ { {0xC2}, "\0RESERVED" },
+ { {0xC3}, "\0RESERVED" },
+ { {0xC4}, "\0RESERVED" },
+ { {0xC5}, "\0RESERVED" },
+ { {0xC6}, "\0RESERVED" },
+ { {0xC7}, "\0RESERVED" },
+ { {0xC8}, "\0RESERVED" },
+ { {0xC9}, "\0RESERVED" },
+ { {0xCA}, "\0RESERVED" },
+ { {0xCB}, "\0RESERVED" },
+ { {0xCC}, "\0RESERVED" },
+ { {0xCD}, "\0RESERVED" },
+ { {0xCE}, "\0RESERVED" },
+ { {0xCF}, "\0RESERVED" },
+
+ { {0xD0}, "\0RESERVED" },
+ { {0xD1}, "\0RESERVED" },
+ { {0xD2}, "\0RESERVED" },
+ { {0xD3}, "\0RESERVED" },
+ { {0xD4}, "\0RESERVED" },
+ { {0xD5}, "\0RESERVED" },
+ { {0xD6}, "\0RESERVED" },
+ { {0xD7}, "\0RESERVED" },
+ { {0xD8}, "\0RESERVED" },
+ { {0xD9}, "\0RESERVED" },
+ { {0xDA}, "\0RESERVED" },
+ { {0xDB}, "\0RESERVED" },
+ { {0xDC}, "\0RESERVED" },
+ { {0xDD}, "\0RESERVED" },
+ { {0xDE}, "\0RESERVED" },
+ { {0xDF}, "\0RESERVED" },
+
+ { {0xE0}, "\0RESERVED" },
+ { {0xE1}, "\0RESERVED" },
+ { {0xE2}, "\0RESERVED" },
+ { {0xE3}, "\0RESERVED" },
+ { {0xE4}, "\0RESERVED" },
+ { {0xE5}, "\0RESERVED" },
+ { {0xE6}, "\0RESERVED" },
+ { {0xE7}, "\0RESERVED" },
+ { {0xE8}, "\0RESERVED" },
+ { {0xE9}, "\0RESERVED" },
+ { {0xEA}, "\0RESERVED" },
+ { {0xEB}, "\0RESERVED" },
+ { {0xEC}, "\0RESERVED" },
+ { {0xED}, "\0RESERVED" },
+ { {0xEE}, "\0RESERVED" },
+ { {0xEF}, "\0RESERVED" },
+
+ // UK Freeview custom id
+ { {0xF0}, "Drama" },
+ { {0xF1}, NULL },
+ { {0xF2}, NULL },
+ { {0xF3}, NULL },
+ { {0xF4}, NULL },
+ { {0xF5}, NULL },
+ { {0xF6}, NULL },
+ { {0xF7}, NULL },
+ { {0xF8}, NULL },
+ { {0xF9}, NULL },
+ { {0xFA}, NULL },
+ { {0xFB}, NULL },
+ { {0xFC}, NULL },
+ { {0xFD}, NULL },
+ { {0xFE}, NULL },
+ { {0xFF}, NULL },
+
+ { {-1}, NULL }
+};
+
+const struct lookup_table aspect_table[] = {
+ { {0}, "4:3"}, // 4/3
+ { {1}, "16:9"}, // 16/9 WITH PAN VECTORS
+ { {2}, "16:9"}, // 16/9 WITHOUT
+ { {3}, "2.21:1"}, // >16/9 or 2.21/1 XMLTV no likey
+ {{-1}, NULL }
+};
+
+const struct lookup_table audio_table[] = {
+ {{0x01}, "mono" }, //single mono
+ {{0x02}, "mono" }, //dual mono - stereo??
+ {{0x03}, "stereo" },
+ {{0x05}, "surround" },
+ {{0x04}, "x-multilingual"}, // multilingual/channel
+ {{0x40}, "x-visuallyimpared"}, // visual impared sound
+ {{0x41}, "x-hardofhearing"}, // hard hearing sound
+ { {-1}, NULL }
+};
+
+const struct lookup_table crid_type_table[] = {
+ {{0x00}, "none" },
+ {{0x01}, "item" },
+ {{0x02}, "series" },
+ {{0x03}, "recommendation" },
+ {{0x31}, "item" }, // UK only? -- I can't find specs that use these
+ {{0x32}, "series" }, // UK only?
+ { {-1}, NULL }
+};
diff --git a/p2pvr/scanner/ice_scan.cpp b/p2pvr/scanner/ice_scan.cpp
new file mode 100644
index 0000000..24ea1bc
--- /dev/null
+++ b/p2pvr/scanner/ice_scan.cpp
@@ -0,0 +1,343 @@
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <assert.h>
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/version.h>
+
+#include "version.h"
+#include "scan.h"
+#include "dump-vdr.h"
+#include "dump-xine.h"
+#include "dump-dvbscan.h"
+#include "dump-kaffeine.h"
+#include "dump-mplayer.h"
+#include "dump-vlc-m3u.h"
+#include "dvbscan.h"
+#include "parse-dvbscan.h"
+#include "countries.h"
+#include "satellites.h"
+#include "atsc_psip_section.h"
+#include "descriptors.h"
+#include "lnb.h"
+#include "diseqc.h"
+
+#define MOD_USE_STANDARD 0x00
+#define MOD_OVERRIDE_MIN 0x01
+#define MOD_OVERRIDE_MAX 0x02
+
+static struct lnb_types_st this_lnb; // 20090320: DVB-S/S2, LNB type, initialized in main to 'UNIVERSAL'
+
+int main (int argc, char **argv)
+{
+ char frontend_devname [80];
+ int adapter = 999, frontend = 0, demux = 0;
+ int opt;
+ unsigned int i = 0, j;
+ int frontend_fd = -1;
+ int fe_open_mode;
+ uint16_t frontend_type = FE_OFDM;
+ int Radio_Services = 1;
+ int TV_Services = 1;
+ int Other_Services = 0; // 20080106: don't search other services by default.
+ int ext = 0;
+ int retVersion = 0;
+ int discover = 0;
+ int a=0,c=0,s=0,t=0;
+ int device_preferred = -1;
+ int valid_initial_data = 0;
+ int valid_rotor_data = 0;
+ int modulation_flags = MOD_USE_STANDARD;
+ char * country = NULL;
+ char * satellite = NULL;
+ char * initdata = NULL;
+ char * positionfile = NULL;
+ char sw_type = 0;
+
+ this_lnb = * lnb_enum(0);
+ this_lnb.low_val *= 1000;
+ this_lnb.high_val *= 1000;
+ this_lnb.switch_val *= 1000;
+
+ flags.version = version;
+ start_time = time(NULL);
+
+ while ((opt = getopt(argc, argv, "a:c:e:f:hi:kl:o:p:qr:s:t:vxA:D:E:FHI:LMO:PQ:R:S:T:VX")) != -1) {
+ switch (opt) {
+ case 'a': //adapter
+ adapter = strtoul(optarg, NULL, 0);
+ break;
+ case 'c': //country setting
+ country=strdup(optarg);
+ if (0 == strcasecmp(country, "?")) {
+ print_countries();
+ return(0);
+ }
+ break;
+ case 'e': //extended scan flags
+ ext = strtoul(optarg, NULL, 0);
+ if (ext & 0x01)
+ dvbc_symbolrate_max = 16;
+ if (ext & 0x02) {
+ modulation_max = 2;
+ modulation_flags |= MOD_OVERRIDE_MAX;
+ }
+ break;
+ case 'f': //frontend type
+ if (strcmp(optarg, "t") == 0) frontend_type = FE_OFDM;
+ if (strcmp(optarg, "c") == 0) frontend_type = FE_QAM;
+ if (strcmp(optarg, "a") == 0) frontend_type = FE_ATSC;
+ if (strcmp(optarg, "s") == 0) frontend_type = FE_QPSK;
+ if (strcmp(optarg, "?") == 0) discover++;
+ if (frontend_type == FE_ATSC)
+ this_channellist = ATSC_VSB;
+ break;
+ case 'h': //basic help
+ bad_usage("w_scan");
+ return 0;
+ break;
+ case 'i': //specify inversion
+ caps_inversion = strtoul(optarg, NULL, 0);
+ break;
+ case 'k': //kaffeine output
+ output_format = OUTPUT_KAFFEINE;
+ break;
+ case 'l': //satellite lnb type
+ if (strcmp(optarg, "?") == 0) {
+ struct lnb_types_st * p;
+ char ** cp;
+
+ while((p = lnb_enum(i++))) {
+ info("%s\n", p->name);
+ for (cp = p->desc; *cp;)
+ info("\t%s\n", *cp++);
+ }
+ return 0;
+ }
+ if (lnb_decode(optarg, &this_lnb) < 0)
+ fatal("LNB decoding failed. Use \"-l ?\" for list.\n");
+ /* MHz -> kHz */
+ this_lnb.low_val *= 1000;
+ this_lnb.high_val *= 1000;
+ this_lnb.switch_val *= 1000;
+ break;
+ case 'o': //vdr Version
+ flags.vdr_version = strtoul(optarg, NULL, 0);
+ if (flags.vdr_version > 2) flags.dump_provider = 1;
+ break;
+ case 'p': //satellite *p*osition file
+ positionfile=strdup(optarg);
+ break;
+ case 'q': //quite
+ if (--verbosity < 0)
+ verbosity = 0;
+ break;
+ case 'r': //satellite rotor position
+ flags.rotor_position = strtoul(optarg, NULL, 0);
+ break;
+ case 's': //satellite setting
+ satellite=strdup(optarg);
+ if (0 == strcasecmp(satellite, "?")) {
+ print_satellites();
+ return(0);
+ }
+ break;
+ case 't': //tuning speed
+ flags.tuning_timeout = strtoul(optarg, NULL, 0);
+ if ((flags.tuning_timeout < 1)) bad_usage(argv[0]);
+ if ((flags.tuning_timeout > 3)) bad_usage(argv[0]);
+ break;
+ case 'v': //verbose
+ verbosity++;
+ break;
+ case 'x': //dvbscan output
+ output_format = OUTPUT_DVBSCAN_TUNING_DATA;
+ break;
+ case 'A': //ATSC type
+ ATSC_type = strtoul(optarg,NULL,0);
+ switch (ATSC_type) {
+ case 1: ATSC_type = ATSC_VSB; break;
+ case 2: ATSC_type = ATSC_QAM; break;
+ case 3: ATSC_type = (ATSC_VSB + ATSC_QAM); break;
+ default:
+ bad_usage(argv[0]);
+ return -1;
+ }
+ /* if -A is specified, it implies -f a */
+ frontend_type = FE_ATSC;
+ break;
+ case 'D': //DiSEqC committed/uncommitted switch
+ sscanf(optarg,"%d%c", &i, &sw_type);
+ switch(sw_type) {
+ case 'u':
+ uncommitted_switch = i;
+ if (uncommitted_switch > 15)
+ fatal("uncommitted switch position needs to be < 16!\n");
+ flags.sw_pos = (flags.sw_pos & 0xF) | uncommitted_switch;
+ break;
+ case 'c':
+ committed_switch = i;
+ if (committed_switch > 3)
+ fatal("committed switch position needs to be < 4!\n");
+ flags.sw_pos = (flags.sw_pos & 0xF0) | committed_switch;
+ break;
+ default:
+ fatal("Could not parse Argument \"-D\"\n"
+ "Should be number followed \"u\" or \"c\"\n");
+ }
+ break;
+ case 'E': //include encrypted channels
+ flags.ca_select = strtoul(optarg, NULL, 0);
+ break;
+ case 'F': //filter timeout
+ flags.filter_timeout = 1;
+ break;
+ case 'H': //expert help
+ ext_help();
+ return 0;
+ break;
+ case 'I': //expert providing initial_tuning_data
+ initdata=strdup(optarg);
+ break;
+ case 'L': //vlc output
+ output_format = OUTPUT_VLC_M3U;
+ break;
+ case 'M': //mplayer output
+ output_format = OUTPUT_MPLAYER;
+ break;
+ case 'O': //other services
+ Other_Services = strtoul(optarg, NULL, 0);
+ if ((Other_Services < 0)) bad_usage(argv[0]);
+ if ((Other_Services > 1)) bad_usage(argv[0]);
+ break;
+ case 'P': //ATSC PSIP scan
+ no_ATSC_PSIP = 1;
+ break;
+ case 'Q': //specify DVB-C QAM
+ modulation_min=modulation_max=strtoul(optarg, NULL, 0);
+ modulation_flags |= MOD_OVERRIDE_MIN;
+ modulation_flags |= MOD_OVERRIDE_MAX;
+ break;
+ case 'R': //include Radio
+ Radio_Services = strtoul(optarg, NULL, 0);
+ if ((Radio_Services < 0)) bad_usage(argv[0]);
+ if ((Radio_Services > 1)) bad_usage(argv[0]);
+ break;
+ case 'S': //DVB-C symbolrate index
+ dvbc_symbolrate_min=dvbc_symbolrate_max=strtoul(optarg, NULL, 0);
+ break;
+ case 'T': //include TV
+ TV_Services = strtoul(optarg, NULL, 0);
+ if ((TV_Services < 0)) bad_usage(argv[0]);
+ if ((TV_Services > 1)) bad_usage(argv[0]);
+ break;
+ case 'V': //Version
+ retVersion++;
+ break;
+ case 'X': //xine output
+ output_format = OUTPUT_XINE;
+ break;
+ default: //undefined
+ bad_usage(argv[0]);
+ return -1;
+ }
+ }
+ info("w_scan version %d (compiled for DVB API %d.%d)\n", version, DVB_API_VERSION, DVB_API_VERSION_MINOR);
+ if ((flags.vdr_version < 7) && (frontend_type == FE_ATSC))
+ fatal("VDR up to version 1.7.13 doesn't support ATSC.\n"
+ "\tPlease add option '-o 7' enabling vdr-1.7 support or"
+ "\tchoose other output format, current: 'VDR channels.conf'.\n");
+ if (NULL == initdata) {
+ if ((NULL == country) && (frontend_type != FE_QPSK))
+ fatal("Missing argument \"-c\" (country setting)\n");
+ if ((NULL == satellite) && (frontend_type == FE_QPSK))
+ fatal("Missing argument \"-s\" (satellite setting)\n");
+ }
+ serv_select = 1 * TV_Services + 2 * Radio_Services + 4 * Other_Services;
+ if (caps_inversion > INVERSION_AUTO) {
+ info("Inversion out of range!\n");
+ bad_usage(argv[0]);
+ return -1;
+ }
+ if (((adapter > 7) && (adapter != 999)) || (adapter < 0)) {
+ info("Invalid adapter: out of range (0..7)\n");
+ bad_usage(argv[0]);
+ return -1;
+ }
+ switch(frontend_type) {
+ case FE_ATSC:
+ case FE_QAM:
+ case FE_OFDM:
+ if (country != NULL) {
+ int atsc = ATSC_type;
+ int dvb = frontend_type;
+ flags.atsc_type = ATSC_type;
+ choose_country(country, &atsc, &dvb, &frontend_type, &this_channellist);
+ //dvbc: setting qam loop
+ if ((modulation_flags & MOD_OVERRIDE_MAX) == MOD_USE_STANDARD)
+ modulation_max = dvbc_qam_max(2, this_channellist);
+ if ((modulation_flags & MOD_OVERRIDE_MIN) == MOD_USE_STANDARD)
+ modulation_min = dvbc_qam_min(2, this_channellist);
+ flags.list_id = txt_to_country(country);
+ free(country);
+ }
+ break;
+ case FE_QPSK:
+ if (satellite != NULL) {
+ choose_satellite(satellite, &this_channellist);
+ flags.list_id = txt_to_satellite(satellite);
+ free(satellite);
+ sat_list[this_channellist].rotor_position = flags.rotor_position;
+ }
+ else if (flags.rotor_position > -1)
+ fatal("Using rotor position needs option \"-s\"\n");
+ if (positionfile != NULL) {
+ valid_rotor_data = dvbscan_parse_rotor_positions(positionfile);
+ free(positionfile);
+ if (! valid_rotor_data)
+ fatal("could not parse rotor position file\n"
+ "CHECK IDENTIFIERS AND FILE FORMAT.\n");
+ }
+ break;
+ default:
+ fatal("Unknown frontend type %d\n", frontend_type);
+ }
+
+ if (initdata != NULL) {
+ valid_initial_data = dvbscan_parse_tuningdata(initdata, &flags);
+ free(initdata);
+ if (valid_initial_data == 0)
+ fatal("Could not read initial tuning data. EXITING.\n");
+ if (flags.fe_type != frontend_type) {
+ warning("\n"
+ "========================================================================\n"
+ "INITIAL TUNING DATA NEEDS FRONTEND TYPE %s, YOU SELECTED TYPE %s.\n"
+ "I WILL OVERRIDE YOUR DEFAULTS TO %s\n"
+ "========================================================================\n",
+ frontend_type_to_text(flags.fe_type),
+ frontend_type_to_text(frontend_type),
+ frontend_type_to_text(flags.fe_type));
+ frontend_type = flags.fe_type;
+ sleep(10); // enshure that user reads warning.
+ }
+ }
+ info("frontend_type %s, channellist %d\n", frontend_type_to_text(frontend_type), this_channellist);
+
+ for (i = 0; i < MAX_RUNNING; i++)
+ poll_fds[i].fd = -1;
+
+ fe_open_mode = O_RDWR;
+ if (adapter == 999)
+ fatal("***** NO USEABLE DVB CARD FOUND. *****\n"
+ "Please check wether dvb driver is loaded and\n"
+ "verify that no dvb application (i.e. vdr) is running.\n");
+
+
+ return 0;
+}
+
diff --git a/p2pvr/scanner/icescan.cpp b/p2pvr/scanner/icescan.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/p2pvr/scanner/icescan.cpp
diff --git a/p2pvr/scanner/langidents.c b/p2pvr/scanner/langidents.c
new file mode 100644
index 0000000..0165f67
--- /dev/null
+++ b/p2pvr/scanner/langidents.c
@@ -0,0 +1,211 @@
+#include "tv_grab_dvb.h"
+const struct lookup_table languageid_table[] = {
+ {{.c="aar"}, "aa"},
+ {{.c="abk"}, "ab"},
+ {{.c="afr"}, "af"},
+ {{.c="aka"}, "ak"},
+ {{.c="amh"}, "am"},
+ {{.c="ara"}, "ar"},
+ {{.c="arg"}, "an"},
+ {{.c="asm"}, "as"},
+ {{.c="ava"}, "av"},
+ {{.c="ave"}, "ae"},
+ {{.c="aym"}, "ay"},
+ {{.c="aze"}, "az"},
+ {{.c="bak"}, "ba"},
+ {{.c="bam"}, "bm"},
+ {{.c="bel"}, "be"},
+ {{.c="ben"}, "bn"},
+ {{.c="bih"}, "bh"},
+ {{.c="bis"}, "bi"},
+ {{.c="bod"}, "bo"},
+ {{.c="tib"}, "bo"},
+ {{.c="bos"}, "bs"},
+ {{.c="bre"}, "br"},
+ {{.c="bul"}, "bg"},
+ {{.c="cat"}, "ca"},
+ {{.c="ces"}, "cs"},
+ {{.c="cze"}, "cs"},
+ {{.c="cha"}, "ch"},
+ {{.c="che"}, "ce"},
+ {{.c="chu"}, "cu"},
+ {{.c="chv"}, "cv"},
+ {{.c="cor"}, "kw"},
+ {{.c="cos"}, "co"},
+ {{.c="cre"}, "cr"},
+ {{.c="cym"}, "cy"},
+ {{.c="wel"}, "cy"},
+ {{.c="dan"}, "da"},
+ {{.c="deu"}, "de"},
+ {{.c="ger"}, "de"},
+ {{.c="div"}, "dv"},
+ {{.c="dzo"}, "dz"},
+ {{.c="ell"}, "el"},
+ {{.c="gre"}, "el"},
+ {{.c="eng"}, "en"},
+ {{.c="epo"}, "eo"},
+ {{.c="est"}, "et"},
+ {{.c="eus"}, "eu"},
+ {{.c="baq"}, "eu"},
+ {{.c="ewe"}, "ee"},
+ {{.c="fao"}, "fo"},
+ {{.c="fas"}, "fa"},
+ {{.c="per"}, "fa"},
+ {{.c="fij"}, "fj"},
+ {{.c="fin"}, "fi"},
+ {{.c="fra"}, "fr"},
+ {{.c="fre"}, "fr"},
+ {{.c="fry"}, "fy"},
+ {{.c="ful"}, "ff"},
+ {{.c="gla"}, "gd"},
+ {{.c="gle"}, "ga"},
+ {{.c="glg"}, "gl"},
+ {{.c="glv"}, "gv"},
+ {{.c="grn"}, "gn"},
+ {{.c="guj"}, "gu"},
+ {{.c="hat"}, "ht"},
+ {{.c="hau"}, "ha"},
+ {{.c="heb"}, "he"},
+ {{.c="her"}, "hz"},
+ {{.c="hin"}, "hi"},
+ {{.c="hmo"}, "ho"},
+ {{.c="hrv"}, "hr"},
+ {{.c="scr"}, "hr"},
+ {{.c="hun"}, "hu"},
+ {{.c="hye"}, "hy"},
+ {{.c="arm"}, "hy"},
+ {{.c="ibo"}, "ig"},
+ {{.c="ido"}, "io"},
+ {{.c="iii"}, "ii"},
+ {{.c="iku"}, "iu"},
+ {{.c="ile"}, "ie"},
+ {{.c="ina"}, "ia"},
+ {{.c="ind"}, "id"},
+ {{.c="ipk"}, "ik"},
+ {{.c="isl"}, "is"},
+ {{.c="ice"}, "is"},
+ {{.c="ita"}, "it"},
+ {{.c="jav"}, "jv"},
+ {{.c="jpn"}, "ja"},
+ {{.c="kal"}, "kl"},
+ {{.c="kan"}, "kn"},
+ {{.c="kas"}, "ks"},
+ {{.c="kat"}, "ka"},
+ {{.c="geo"}, "ka"},
+ {{.c="kau"}, "kr"},
+ {{.c="kaz"}, "kk"},
+ {{.c="khm"}, "km"},
+ {{.c="kik"}, "ki"},
+ {{.c="kin"}, "rw"},
+ {{.c="kir"}, "ky"},
+ {{.c="kom"}, "kv"},
+ {{.c="kon"}, "kg"},
+ {{.c="kor"}, "ko"},
+ {{.c="kua"}, "kj"},
+ {{.c="kur"}, "ku"},
+ {{.c="lao"}, "lo"},
+ {{.c="lat"}, "la"},
+ {{.c="lav"}, "lv"},
+ {{.c="lim"}, "li"},
+ {{.c="lin"}, "ln"},
+ {{.c="lit"}, "lt"},
+ {{.c="ltz"}, "lb"},
+ {{.c="lub"}, "lu"},
+ {{.c="lug"}, "lg"},
+ {{.c="mah"}, "mh"},
+ {{.c="mal"}, "ml"},
+ {{.c="mar"}, "mr"},
+ {{.c="mkd"}, "mk"},
+ {{.c="mac"}, "mk"},
+ {{.c="mlg"}, "mg"},
+ {{.c="mlt"}, "mt"},
+ {{.c="mol"}, "mo"},
+ {{.c="mon"}, "mn"},
+ {{.c="mri"}, "mi"},
+ {{.c="mao"}, "mi"},
+ {{.c="msa"}, "ms"},
+ {{.c="may"}, "ms"},
+ {{.c="mya"}, "my"},
+ {{.c="bur"}, "my"},
+ {{.c="nau"}, "na"},
+ {{.c="nav"}, "nv"},
+ {{.c="nbl"}, "nr"},
+ {{.c="nde"}, "nd"},
+ {{.c="ndo"}, "ng"},
+ {{.c="nep"}, "ne"},
+ {{.c="nld"}, "nl"},
+ {{.c="dut"}, "nl"},
+ {{.c="nno"}, "nn"},
+ {{.c="nob"}, "nb"},
+ {{.c="nor"}, "no"},
+ {{.c="nya"}, "ny"},
+ {{.c="oci"}, "oc"},
+ {{.c="oji"}, "oj"},
+ {{.c="ori"}, "or"},
+ {{.c="orm"}, "om"},
+ {{.c="oss"}, "os"},
+ {{.c="pan"}, "pa"},
+ {{.c="pli"}, "pi"},
+ {{.c="pol"}, "pl"},
+ {{.c="por"}, "pt"},
+ {{.c="pus"}, "ps"},
+ {{.c="que"}, "qu"},
+ {{.c="roh"}, "rm"},
+ {{.c="ron"}, "ro"},
+ {{.c="rum"}, "ro"},
+ {{.c="run"}, "rn"},
+ {{.c="rus"}, "ru"},
+ {{.c="sag"}, "sg"},
+ {{.c="san"}, "sa"},
+ {{.c="sin"}, "si"},
+ {{.c="slk"}, "sk"},
+ {{.c="slo"}, "sk"},
+ {{.c="slv"}, "sl"},
+ {{.c="sme"}, "se"},
+ {{.c="smo"}, "sm"},
+ {{.c="sna"}, "sn"},
+ {{.c="snd"}, "sd"},
+ {{.c="som"}, "so"},
+ {{.c="sot"}, "st"},
+ {{.c="spa"}, "es"},
+ {{.c="sqi"}, "sq"},
+ {{.c="alb"}, "sq"},
+ {{.c="srd"}, "sc"},
+ {{.c="srp"}, "sr"},
+ {{.c="scc"}, "sr"},
+ {{.c="ssw"}, "ss"},
+ {{.c="sun"}, "su"},
+ {{.c="swa"}, "sw"},
+ {{.c="swe"}, "sv"},
+ {{.c="tah"}, "ty"},
+ {{.c="tam"}, "ta"},
+ {{.c="tat"}, "tt"},
+ {{.c="tel"}, "te"},
+ {{.c="tgk"}, "tg"},
+ {{.c="tgl"}, "tl"},
+ {{.c="tha"}, "th"},
+ {{.c="tir"}, "ti"},
+ {{.c="ton"}, "to"},
+ {{.c="tsn"}, "tn"},
+ {{.c="tso"}, "ts"},
+ {{.c="tuk"}, "tk"},
+ {{.c="tur"}, "tr"},
+ {{.c="twi"}, "tw"},
+ {{.c="uig"}, "ug"},
+ {{.c="ukr"}, "uk"},
+ {{.c="urd"}, "ur"},
+ {{.c="uzb"}, "uz"},
+ {{.c="ven"}, "ve"},
+ {{.c="vie"}, "vi"},
+ {{.c="vol"}, "vo"},
+ {{.c="wln"}, "wa"},
+ {{.c="wol"}, "wo"},
+ {{.c="xho"}, "xh"},
+ {{.c="yid"}, "yi"},
+ {{.c="yor"}, "yo"},
+ {{.c="zha"}, "za"},
+ {{.c="zho"}, "zh"},
+ {{.c="chi"}, "zh"},
+ {{.c="zul"}, "zu"},
+ {{-1}, NULL},
+};
diff --git a/p2pvr/scanner/lookup.cpp b/p2pvr/scanner/lookup.cpp
new file mode 100644
index 0000000..6d2a0b6
--- /dev/null
+++ b/p2pvr/scanner/lookup.cpp
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <string.h>
+
+#include "tv_grab_dvb.h"
+
+const char *lookup(const struct lookup_table *l, int id) {
+// printf("Looked up %x", id);
+ while ((l->u.i != id) && (l->u.i != -1))
+ l++;
+ return l->desc;
+}
+
+/* Read lookup_table from file into newly allocated table.
+ * The table is a single allocation consisting of two parts:
+ * first the array of structs, followed by a char-array of strings. */
+int load_lookup(struct lookup_table **l, const char *file) {
+ int name;
+ char value[256];
+ int n = 1, size = sizeof(struct lookup_table);
+
+ if (file == NULL)
+ return -1;
+
+ FILE *fd = fopen(file, "r");
+ if (!fd)
+ return -1;
+
+ // 1st: determine size needed
+ while (fscanf(fd, "%d %255s", &name, value) == 2) {
+ n++;
+ size += sizeof(struct lookup_table);
+ size += strlen(value) + 1;
+ }
+ struct lookup_table *p = *l = static_cast<struct lookup_table *>(malloc(size));
+ if (p == NULL)
+ return -1;
+
+ // 2nd: read data
+ rewind(fd);
+ char *c = (char *)(p + n);
+ while (fscanf(fd, "%d %255s", &p->u.i, c) == 2) {
+ p->desc = c;
+ c += strlen(c) + 1;
+ p++;
+ }
+ p->u.i = -1;
+ p->desc = NULL;
+
+ fclose(fd);
+ return 0;
+}
+
diff --git a/p2pvr/scanner/p2scan.cpp b/p2pvr/scanner/p2scan.cpp
new file mode 100644
index 0000000..cb3e0fc
--- /dev/null
+++ b/p2pvr/scanner/p2scan.cpp
@@ -0,0 +1,761 @@
+/*
+ * tv_grab_dvb - dump dvb epg info in xmltv
+ * Version 0.2 - 20/04/2004 - First Public Release
+ *
+ * Copyright (C) 2004 Mark Bryars <dvb at darkskiez d0t co d0t uk>
+ *
+ * DVB code Mercilessly ripped off from dvddate
+ * dvbdate Copyright (C) Laurence Culhane 2002 <dvbdate@holmes.demon.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+const char *id = "@(#) $Id: tv_grab_dvb.c 86 2010-10-29 20:27:31Z pmhahn $";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <signal.h>
+#include <time.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <glibmm.h>
+#include <boost/bind.hpp>
+
+#include <linux/dvb/dmx.h>
+#include "si_tables.h"
+#include "tv_grab_dvb.h"
+
+#include "variables.h"
+#include "rowProcessor.h"
+
+struct EitProgram {
+ VariableType serviceID;
+ VariableType eventID;
+ VariableType title;
+ VariableType titleLang;
+ VariableType subtitle;
+ VariableType subtitleLang;
+ VariableType descLang;
+ VariableType desc1;
+ VariableType desc2;
+ VariableType desc3;
+ VariableType videoAspect;
+ VariableType audioChannels;
+ VariableType language;
+ VariableType teletextSubtitleLang;
+ VariableType category;
+ VariableType dvbRating;
+ VariableType contentIdentType;
+ VariableType contentIdent;
+ VariableType startTime;
+ VariableType stopTime;
+};
+
+Glib::ustring title("title");
+#include "xmlObjectLoader.h"
+#include "rowSet.h"
+template <class C, class M>
+const M &
+getMember(M C::*t, C * p) {
+ return p->*t;
+}
+SimpleMessageException(NoSuchAttribute);
+class EitRows : public RowSet {
+ public:
+ EitRows(const xmlpp::Element * p);
+ ~EitRows();
+ void execute(const RowProcessor *) const;
+ void loadComplete(const CommonObjects *) {
+ }
+ void setFilter(const Glib::ustring &) {
+ }
+ unsigned int columnCount() const {
+ return 1;
+ }
+ const Glib::ustring & getColumnName(unsigned int) const {
+ return title;
+ }
+ VariableType getCurrentValue(const Glib::ustring &) const {
+ return current->title;
+ }
+ VariableType getCurrentValue(unsigned int) const {
+ return current->title;
+ }
+ bool isNull(unsigned int ) const {
+ return false;
+ }
+ bool isNull(const Glib::ustring & ) const {
+ return false;
+ }
+#define returnAttr(name) if (attrName == #name) return boost::bind(getMember<EitProgram, VariableType>, &EitProgram::name, boost::ref(current))
+ RowAttribute resolveAttr(const Glib::ustring & attrName) const {
+ returnAttr(serviceID);
+ returnAttr(eventID);
+ returnAttr(title);
+ returnAttr(titleLang);
+ returnAttr(subtitle);
+ returnAttr(subtitleLang);
+ returnAttr(descLang);
+ returnAttr(desc1);
+ returnAttr(desc2);
+ returnAttr(desc3);
+ returnAttr(videoAspect);
+ returnAttr(audioChannels);
+ returnAttr(language);
+ returnAttr(teletextSubtitleLang);
+ returnAttr(category);
+ returnAttr(dvbRating);
+ returnAttr(contentIdentType);
+ returnAttr(contentIdent);
+ returnAttr(startTime);
+ returnAttr(stopTime);
+ throw NoSuchAttribute(attrName);
+ }
+ private:
+ enum ER { TITLE, SUB_TITLE };
+ enum CR { LANGUAGE, VIDEO, AUDIO, SUBTITLES };
+ Variable demux;
+ Variable timeout;
+ void openInput() const;
+ void readEventTables(const RowProcessor *) const;
+ bool parseEIT(const u_char *data, size_t len, const RowProcessor *) const;
+ void parseEventDescription(const u_char *data, enum ER round) const;
+ void parseLongEventDescription(const u_char *data) const;
+ void parseComponentDescription(const u_char *data, enum CR round, int *seen) const;
+ void parseContentDescription(const u_char *data) const;
+ void parseRatingDescription(const u_char *data) const;
+ void parseContentIdentifierDescription(const u_char *data) const;
+ void parseDescription(const u_char * data, size_t len) const;
+
+ Glib::ustring convert(const char * txt) const;
+
+ mutable int fd_epg;
+ mutable EitProgram * current;
+
+ static const std::string EitEncoding;
+ static const std::string UTF8;
+};
+
+DECLARE_LOADER("eitrows", EitRows);
+
+const std::string EitRows::EitEncoding("ISO6937");
+const std::string EitRows::UTF8("UTF8");
+
+EitRows::EitRows(const xmlpp::Element * p) :
+ RowSet(p),
+ demux(p, "demux", false, "/dev/dvb/adapter0/demux0"),
+ timeout(p, "timeout", false, 10000),
+ fd_epg(0),
+ current(NULL)
+{
+}
+
+EitRows::~EitRows()
+{
+ if (fd_epg) {
+ close(fd_epg);
+ }
+}
+
+static int time_offset = 0;
+static int chan_filter = 0;
+static int chan_filter_mask = 0;
+static bool ignore_bad_dates = true;
+static bool ignore_updates = true;
+static bool silent = false;
+
+typedef struct chninfo {
+ struct chninfo *next;
+ int sid;
+ int eid;
+ int ver;
+} chninfo_t;
+
+static struct chninfo *channels;
+
+/* Parse command line arguments. {{{ */
+int do_options(int arg_count, char **arg_strings) {
+ static const struct option Long_Options[] = {
+ {"help", 0, 0, 'h'},
+ {"chanidents", 1, 0, 'c'},
+ {0, 0, 0, 0}
+ };
+ int Option_Index = 0;
+
+ while (1) {
+ int c = getopt_long(arg_count, arg_strings, "udscmpnht:o:f:i:e:", Long_Options, &Option_Index);
+ if (c == EOF)
+ break;
+ switch (c) {
+ case 'u':
+ ignore_updates = false;
+ break;
+ case 'd':
+ ignore_bad_dates = false;
+ break;
+ case 'n':
+ chan_filter = 0x4e;
+ chan_filter_mask = 0xfe;
+ break;
+ case 'm':
+ chan_filter = 0x4e;
+ chan_filter_mask = 0xff;
+ break;
+ case 'p':
+ chan_filter = 0x4f;
+ chan_filter_mask = 0xff;
+ break;
+ case 's':
+ silent = true;
+ break;
+ case 'h':
+ case '?':
+ break;
+ case 0:
+ default:
+ _exit(1);
+ }
+ }
+ return 0;
+} /*}}}*/
+
+
+/* Parse language-id translation file. {{{ */
+static const char *xmllang(const u_char *l) {
+ static union lookup_key lang;
+ lang.c[0] = (char)l[0];
+ lang.c[1] = (char)l[1];
+ lang.c[2] = (char)l[2];
+ lang.c[3] = '\0';
+
+ const char *c = lookup(languageid_table, lang.i);
+ return c ? c : lang.c;
+} /*}}}*/
+
+Glib::ustring
+EitRows::convert(const char * txt) const
+{
+ char enc[20];
+ switch ((unsigned char)*txt) {
+ case 0x20 ... 0xFF:
+ return Glib::convert(txt, UTF8, EitEncoding);
+ case 0x01 ... 0x05:
+ snprintf(enc, sizeof(enc), "ISO-8859-%d\n", txt[0] + 4);
+ return Glib::convert(txt + 1, UTF8, "ISO-8859-5");
+ case 0x10:
+ snprintf(enc, sizeof(enc), "ISO-8859-%02x%02x\n", txt[1], txt[2]);
+ return Glib::convert(txt + 3, UTF8, enc);
+ case 0x11:
+ return Glib::convert(txt, UTF8, "ISO-10646");
+ case 0x06 ... 0x0F:
+ case 0x12 ... 0x1F:
+ // Values for the first byte of "0x00", "0x06" to "0x0F", and "0x12" to "0x1F" are reserved for future use.
+ //fprintf(stderr, "Reserved encoding: %02x\n", txt[0]);
+ //fprintf(stderr, "%s\n", txt);
+ case 0x00: // empty string
+ return "";
+ }
+}
+
+/* Parse 0x4D Short Event Descriptor. {{{ */
+void
+EitRows::parseEventDescription(const u_char *data, enum ER round) const {
+ assert(GetDescriptorTag(data) == 0x4D);
+ const struct descr_short_event *evtdesc = reinterpret_cast<const struct descr_short_event *>(data);
+ char evt[256];
+ char dsc[256];
+
+ size_t evtlen = evtdesc->event_name_length;
+ if (round == TITLE) {
+ if (!evtlen)
+ return;
+ assert(evtlen < sizeof(evt));
+ memcpy(evt, &evtdesc->data, evtlen);
+ evt[evtlen] = '\0';
+ current->titleLang = xmllang(&evtdesc->lang_code1);
+ current->title = convert(evt);
+ return;
+ }
+
+ if (round == SUB_TITLE) {
+ size_t dsclen = evtdesc->data[evtlen];
+ assert(dsclen < sizeof(dsc));
+ memcpy(dsc, &evtdesc->data[evtlen+1], dsclen);
+ dsc[dsclen] = '\0';
+
+ if (*dsc) {
+ current->subtitleLang = xmllang(&evtdesc->lang_code1);
+ current->subtitle = convert(dsc);
+ }
+ }
+} /*}}}*/
+
+/* Parse 0x4E Extended Event Descriptor. {{{ */
+void
+EitRows::parseLongEventDescription(const u_char *data) const {
+ assert(GetDescriptorTag(data) == 0x4E);
+ const struct descr_extended_event *levt = reinterpret_cast<const struct descr_extended_event *>(data);
+ char dsc[256];
+ bool non_empty = (levt->descriptor_number || levt->last_descriptor_number || levt->length_of_items || levt->data[0]);
+
+ if (non_empty && levt->descriptor_number == 0) {
+ current->descLang = levt->lang_code1;
+
+ const u_char *p = reinterpret_cast<const u_char *>(&levt->data);
+ const void *data_end = data + DESCR_GEN_LEN + GetDescriptorLength(data);
+ while (p < levt->data + levt->length_of_items) {
+ const struct item_extended_event *name = reinterpret_cast<const struct item_extended_event *>(p);
+ size_t name_len = name->item_description_length;
+ assert(p + ITEM_EXTENDED_EVENT_LEN + name_len < data_end);
+ assert(name_len < sizeof(dsc));
+ memcpy(dsc, &name->data, name_len);
+ dsc[name_len] = '\0';
+ current->desc1 = convert(dsc);
+
+ p += ITEM_EXTENDED_EVENT_LEN + name_len;
+
+ const struct item_extended_event *value = reinterpret_cast<const struct item_extended_event *>(p);
+ size_t value_len = value->item_description_length;
+ assert(p + ITEM_EXTENDED_EVENT_LEN + value_len < data_end);
+ assert(value_len < sizeof(dsc));
+ memcpy(dsc, &value->data, value_len);
+ dsc[value_len] = '\0';
+ current->desc2 = convert(dsc);
+
+ p += ITEM_EXTENDED_EVENT_LEN + value_len;
+ }
+ const struct item_extended_event *text = reinterpret_cast<const struct item_extended_event *>(p);
+ size_t len = text->item_description_length;
+ if (non_empty && len) {
+ assert(len < sizeof(dsc));
+ memcpy(dsc, &text->data, len);
+ dsc[len] = '\0';
+ current->desc3 = convert(dsc);
+ }
+
+ }
+} /*}}}*/
+
+/* Parse 0x50 Component Descriptor. {{{
+ video is a flag, 1=> output the video information, 0=> output the
+ audio information. seen is a pointer to a counter to ensure we
+ only output the first one of each (XMLTV can't cope with more than
+ one) */
+void
+EitRows::parseComponentDescription(const u_char *data, enum CR round, int *seen) const {
+ assert(GetDescriptorTag(data) == 0x50);
+ const struct descr_component *dc = reinterpret_cast<const struct descr_component *>(data);
+ char buf[256];
+
+ size_t len = dc->descriptor_length;
+ assert(len < sizeof(buf));
+ memcpy(buf, &dc->data, len);
+ buf[len] = '\0';
+
+ switch (dc->stream_content) {
+ case 0x01: // Video Info
+ if (round == VIDEO && !*seen) {
+ //if ((dc->component_type-1)&0x08) //HD TV
+ //if ((dc->component_type-1)&0x04) //30Hz else 25
+ current->videoAspect = lookup(aspect_table, (dc->component_type-1) & 0x03);
+ (*seen)++;
+ }
+ break;
+ case 0x02: // Audio Info
+ if (round == AUDIO && !*seen) {
+ current->audioChannels = lookup(audio_table, (dc->component_type));
+ (*seen)++;
+ }
+ if (round == LANGUAGE) {
+ if (!*seen)
+ current->language = xmllang(&dc->lang_code1);
+ (*seen)++;
+ }
+ break;
+ case 0x03: // Teletext Info
+ if (round == SUBTITLES) {
+ // FIXME: is there a suitable XMLTV output for this?
+ // if ((dc->component_type)&0x10) //subtitles
+ // if ((dc->component_type)&0x20) //subtitles for hard of hearing
+ current->teletextSubtitleLang = xmllang(&dc->lang_code1);
+ }
+ break;
+ // case 0x04: // AC3 info
+ }
+} /*}}}*/
+
+static inline void set_bit(int *bf, int b) {
+ int i = b / 8 / sizeof(int);
+ int s = b % (8 * sizeof(int));
+ bf[i] |= (1 << s);
+}
+
+static inline bool get_bit(int *bf, int b) {
+ int i = b / 8 / sizeof(int);
+ int s = b % (8 * sizeof(int));
+ return bf[i] & (1 << s);
+}
+
+/* Parse 0x54 Content Descriptor. {{{ */
+void
+EitRows::parseContentDescription(const u_char *data) const {
+ assert(GetDescriptorTag(data) == 0x54);
+ const struct descr_content *dc = reinterpret_cast<const struct descr_content *>(data);
+ int once[256/8/sizeof(int)] = {0,};
+ for (const u_char * p = reinterpret_cast<const u_char*>(&dc->data); p < data + dc->descriptor_length; p += NIBBLE_CONTENT_LEN) {
+ const struct nibble_content *nc = reinterpret_cast<const nibble_content *>(p);
+ int c1 = (nc->content_nibble_level_1 << 4) + nc->content_nibble_level_2;
+ if (c1 > 0 && !get_bit(once, c1)) {
+ set_bit(once, c1);
+ const char *c = lookup(description_table, c1);
+ if (c)
+ if (c[0])
+ current->category = c;
+ }
+ // This is weird in the uk, they use user but not content, and almost the same values
+ }
+} /*}}}*/
+
+/* Parse 0x55 Rating Descriptor. {{{ */
+void
+EitRows::parseRatingDescription(const u_char *data) const {
+ assert(GetDescriptorTag(data) == 0x55);
+ const struct descr_parental_rating *pr = reinterpret_cast<const struct descr_parental_rating *>(data);
+ for (const u_char * p = reinterpret_cast<const u_char *>(&pr->data); p < data + pr->descriptor_length; p += PARENTAL_RATING_ITEM_LEN) {
+ const struct parental_rating_item *pr = reinterpret_cast<const struct parental_rating_item *>(p);
+ switch (pr->rating) {
+ case 0x00: /*undefined*/
+ break;
+ case 0x01 ... 0x0F:
+ current->dvbRating = pr->rating + 3;
+ break;
+ case 0x10 ... 0xFF: /*broadcaster defined*/
+ break;
+ }
+ }
+} /*}}}*/
+
+/* Parse 0x5F Private Data Specifier. {{{ */
+int parsePrivateDataSpecifier(const u_char *data) {
+ assert(GetDescriptorTag(data) == 0x5F);
+ return GetPrivateDataSpecifier(data);
+} /*}}}*/
+
+/* Parse 0x76 Content Identifier Descriptor. {{{ */
+/* See ETSI TS 102 323, section 12 */
+void
+EitRows::parseContentIdentifierDescription(const u_char *data) const {
+ assert(GetDescriptorTag(data) == 0x76);
+ const struct descr_content_identifier *ci = reinterpret_cast<const struct descr_content_identifier *>(data);
+ for (const u_char * p = reinterpret_cast<const u_char *>(&ci->data); p < data + ci->descriptor_length; /* at end */) {
+ const struct descr_content_identifier_crid *crid = reinterpret_cast<const struct descr_content_identifier_crid *>(p);
+ struct descr_content_identifier_crid_local *crid_data;
+
+ int crid_length = 3;
+
+ char type_buf[32];
+ const char *type;
+ char buf[256];
+
+ type = lookup(crid_type_table, crid->crid_type);
+ if (type == NULL)
+ {
+ type = type_buf;
+ sprintf(type_buf, "0x%2x", crid->crid_type);
+ }
+
+ switch (crid->crid_location)
+ {
+ case 0x01: /* Carried in Content Identifier Table (CIT) */
+ break;
+ default:
+ break;
+ case 0x00: /* Carried explicitly within descriptor */
+ crid_data = (descr_content_identifier_crid_local_t *)&crid->crid_ref_data;
+ size_t cridlen = crid_data->crid_length;
+ assert(cridlen < sizeof(buf));
+ memcpy(buf, &crid_data->crid_byte, cridlen);
+ buf[cridlen] = '\0';
+
+ current->contentIdentType = type;
+ current->contentIdent = buf;
+ crid_length = 2 + crid_data->crid_length;
+ break;
+ }
+
+ p += crid_length;
+ }
+} /*}}}*/
+
+/* Parse Descriptor. {{{
+ * Tags should be output in this order:
+
+'title', 'sub-title', 'desc', 'credits', 'date', 'category', 'language',
+'orig-language', 'length', 'icon', 'url', 'country', 'episode-num',
+'video', 'audio', 'previously-shown', 'premiere', 'last-chance',
+'new', 'subtitles', 'rating', 'star-rating'
+*/
+void
+EitRows::parseDescription(const u_char * data, size_t len) const {
+ int round, pds = 0;
+
+ for (round = 0; round < 8; round++) {
+ int seen = 0; // no title/language/video/audio/subtitles seen in this round
+ for (const u_char * p = data; p < data + len; p += DESCR_GEN_LEN + GetDescriptorLength(p)) {
+ const struct descr_gen *desc = reinterpret_cast<const struct descr_gen *>(p);
+ switch (GetDescriptorTag(desc)) {
+ case 0:
+ break;
+ case 0x4D: //short evt desc, [title] [sub-title]
+ // there can be multiple language versions of these
+ if (round == 0) {
+ parseEventDescription(p, TITLE);
+ }
+ else if (round == 1)
+ parseEventDescription(p, SUB_TITLE);
+ break;
+ case 0x4E: //long evt descriptor [desc]
+ if (round == 2)
+ parseLongEventDescription(p);
+ break;
+ case 0x50: //component desc [language] [video] [audio] [subtitles]
+ if (round == 4)
+ parseComponentDescription(p, LANGUAGE, &seen);
+ else if (round == 5)
+ parseComponentDescription(p, VIDEO, &seen);
+ else if (round == 6)
+ parseComponentDescription(p, AUDIO, &seen);
+ else if (round == 7)
+ parseComponentDescription(p, SUBTITLES, &seen);
+ break;
+ case 0x53: // CA Identifier Descriptor
+ break;
+ case 0x54: // content desc [category]
+ if (round == 3)
+ parseContentDescription(p);
+ break;
+ case 0x55: // Parental Rating Descriptor [rating]
+ if (round == 7)
+ parseRatingDescription(p);
+ break;
+ case 0x5f: // Private Data Specifier
+ pds = parsePrivateDataSpecifier(p);
+ break;
+ case 0x64: // Data broadcast desc - Text Desc for Data components
+ break;
+ case 0x69: // Programm Identification Label
+ break;
+ case 0x81: // TODO ???
+ if (pds == 5) // ARD_ZDF_ORF
+ break;
+ case 0x82: // VPS (ARD, ZDF, ORF)
+ if (pds == 5) // ARD_ZDF_ORF
+ // TODO: <programme @vps-start="???">
+ break;
+ case 0x4F: // Time Shifted Event
+ case 0x52: // Stream Identifier Descriptor
+ case 0x5E: // Multi Lingual Component Descriptor
+ case 0x83: // Logical Channel Descriptor (some kind of news-ticker on ARD-MHP-Data?)
+ case 0x84: // Preferred Name List Descriptor
+ case 0x85: // Preferred Name Identifier Descriptor
+ case 0x86: // Eacem Stream Identifier Descriptor
+ break;
+ case 0x76: // Content identifier descriptor
+ if (round == 5)
+ parseContentIdentifierDescription(p);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+} /*}}}*/
+
+/* Check that program has at least a title as is required by xmltv.dtd. {{{ */
+static bool validateDescription(const u_char *data, size_t len) {
+ for (const u_char * p = data; p < data + len; p += DESCR_GEN_LEN + GetDescriptorLength(p)) {
+ const struct descr_gen *desc = reinterpret_cast<const struct descr_gen *>(p);
+ if (GetDescriptorTag(desc) == 0x4D) {
+ const struct descr_short_event *evtdesc = reinterpret_cast<const struct descr_short_event *>(p);
+ // make sure that title isn't empty
+ if (evtdesc->event_name_length) return true;
+ }
+ }
+ return false;
+} /*}}}*/
+
+/* Use the routine specified in ETSI EN 300 468 V1.4.1, {{{
+ * "Specification for Service Information in Digital Video Broadcasting"
+ * to convert from Modified Julian Date to Year, Month, Day. */
+static boost::posix_time::ptime parseMJD(long int mjd) {
+ int year = (int) ((mjd - 15078.2) / 365.25);
+ int month = (int) ((mjd - 14956.1 - (int) (year * 365.25)) / 30.6001);
+ int day = mjd - 14956 - (int) (year * 365.25) - (int) (month * 30.6001);
+ int i = (month == 14 || month == 15) ? 1 : 0;
+ year += i ;
+ month = month - 1 - i * 12;
+
+ return boost::posix_time::ptime(boost::gregorian::date(1900 + year, month, day));
+} /*}}}*/
+
+bool
+EitRows::parseEIT(const u_char *data, size_t len, const RowProcessor * rp) const {
+ const struct eit *e = reinterpret_cast<const struct eit *>(data);
+
+ len -= 4; //remove CRC
+
+ // For each event listing
+ bool found = false;
+ for (const u_char *p = reinterpret_cast<const u_char *>(&e->data); p < data + len; p += EIT_EVENT_LEN + GetEITDescriptorsLoopLength(p)) {
+ const struct eit_event *evt = reinterpret_cast<const struct eit_event *>(p);
+ struct chninfo *c;
+ // find existing information?
+ for (c = channels; c != NULL; c = c->next) {
+ // found it
+ if (c->sid == HILO(e->service_id) && (c->eid == HILO(evt->event_id))) {
+ if (c->ver <= e->version_number) // seen it before or its older FIXME: wrap-around to 0
+ return false;
+ else {
+ c->ver = e->version_number; // update outputted version
+ if (ignore_updates) {
+ return false;
+ }
+ break;
+ }
+ }
+ }
+
+ // its a new program
+ if (c == NULL) {
+ chninfo_t *nc = static_cast<struct chninfo *>(malloc(sizeof(struct chninfo)));
+ nc->sid = HILO(e->service_id);
+ nc->eid = HILO(evt->event_id);
+ nc->ver = e->version_number;
+ nc->next = channels;
+ channels = nc;
+ }
+
+ // No program info at end! Just skip it
+ if (GetEITDescriptorsLoopLength(evt) == 0)
+ return false;
+
+ boost::posix_time::ptime startTime = parseMJD(HILO(evt->mjd)) + boost::posix_time::time_duration(
+ BcdCharToInt(evt->start_time_h) + time_offset,
+ BcdCharToInt(evt->start_time_m),
+ BcdCharToInt(evt->start_time_s));
+ EitProgram results;
+ current = &results;
+ results.startTime = startTime;
+ results.stopTime = startTime + boost::posix_time::time_duration(
+ BcdCharToInt(evt->duration_h),
+ BcdCharToInt(evt->duration_m),
+ BcdCharToInt(evt->duration_s));
+
+ // a program must have a title that isn't empty
+ if (!validateDescription(reinterpret_cast<const u_char *>(&evt->data), GetEITDescriptorsLoopLength(evt))) {
+ return false;
+ }
+
+
+ results.serviceID = HILO(e->service_id);
+ results.eventID = HILO(evt->event_id);
+
+ //1 Airing, 2 Starts in a few seconds, 3 Pausing, 4 About to air
+
+ parseDescription(reinterpret_cast<const u_char *>(&evt->data), GetEITDescriptorsLoopLength(evt));
+ rowNum += 1;
+ rp->rowReady();
+ found = true;
+ }
+ return found;
+}
+
+SimpleMessageException(ErrorReadingData);
+void
+EitRows::readEventTables(const RowProcessor * rp) const
+{
+ u_char buf[1<<12];
+ struct pollfd ufd;
+ memset(&ufd, 0, sizeof(pollfd));
+ ufd.fd = fd_epg;
+ ufd.events = POLLIN;
+ size_t n;
+ time_t lastuseful = 0;
+ while ((poll(&ufd, 1, (int64_t)timeout()) == 1) && (n = read(fd_epg, buf, sizeof(buf)))) {
+ if (n < sizeof(struct si_tab))
+ throw ErrorReadingData("Smaller that si_tab");
+ struct si_tab *tab = (struct si_tab *)buf;
+ size_t l = sizeof(struct si_tab) + GetSectionLength(tab);
+ if (n < l)
+ throw ErrorReadingData("Smaller that section length");
+ if (_dvb_crc32(buf, l) == 0) {
+ if (parseEIT(buf, l, rp)) {
+ time(&lastuseful);
+ }
+ else {
+ if (lastuseful < time(NULL) - 5) {
+ break;
+ }
+ }
+ }
+ }
+}
+
+SimpleMessageException(DemuxOpenFailure);
+SimpleMessageException(DemuxSetFilterFailure);
+
+void
+EitRows::openInput() const
+{
+ if ((fd_epg = open(demux(), O_RDWR)) < 0) {
+ throw DemuxOpenFailure(strerror(errno));
+ }
+
+ struct dmx_sct_filter_params sctFilterParams;
+ memset(&sctFilterParams, 0, sizeof(dmx_sct_filter_params));
+ sctFilterParams.pid = 18; // EIT data
+ sctFilterParams.timeout = 0;
+ sctFilterParams.flags = DMX_IMMEDIATE_START;
+ sctFilterParams.filter.filter[0] = chan_filter; // 4e is now/next this multiplex, 4f others
+ sctFilterParams.filter.mask[0] = chan_filter_mask;
+
+ if (ioctl(fd_epg, DMX_SET_FILTER, &sctFilterParams) < 0) {
+ throw DemuxSetFilterFailure(strerror(errno));
+ }
+}
+
+void
+EitRows::execute(const RowProcessor * rp) const
+{
+ openInput();
+ readEventTables(rp);
+ if (rowNum < 10) {
+ }
+ close(fd_epg);
+ fd_epg = 0;
+}
+
diff --git a/p2pvr/scanner/scanner.ice b/p2pvr/scanner/scanner.ice
new file mode 100644
index 0000000..7730a1c
--- /dev/null
+++ b/p2pvr/scanner/scanner.ice
@@ -0,0 +1,7 @@
+module P2TV {
+ interface Scanner {
+ void updatePrograms(bool zap, int adapter, int frontend);
+ void updateNowAndNext(bool zap, int adapter, int frontend);
+ };
+};
+
diff --git a/p2pvr/scanner/si_tables.h b/p2pvr/scanner/si_tables.h
new file mode 100644
index 0000000..ce3b972
--- /dev/null
+++ b/p2pvr/scanner/si_tables.h
@@ -0,0 +1,1625 @@
+//////////////////////////////////////////////////////////////
+/// ///
+/// si_tables.h: definitions for data structures of the ///
+/// incoming SI data stream ///
+/// ///
+//////////////////////////////////////////////////////////////
+
+// $Revision: 84 $
+// $Date: 2010-03-05 17:46:16 +0000 (Fri, 05 Mar 2010) $
+// $Author: cpaton $
+//
+// (C) 2001-03 Rolf Hakenes <hakenes@hippomi.de>, under the
+// GNU GPL with contribution of Oleg Assovski,
+// www.satmania.com
+//
+// libsi is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2, or (at your option)
+// any later version.
+//
+// libsi is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You may have received a copy of the GNU General Public License
+// along with libsi; see the file COPYING. If not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#define HILO(x) (x##_hi << 8 | x##_lo)
+#define HILO2(x) (x##1 << 8 | x##2)
+#define HILO3(x) (x##1 << 16 | x##2 << 8 | x##3)
+#define HILO4(x) (x##4 << 24 | x##2 << 16 | x##3 << 8 | x##4)
+
+#define MjdToEpochTime(x) ((HILO(x)-40587)*86400)
+#define BcdTimeToSeconds(x) ((3600 * ((10*((x##_h & 0xF0)>>4)) + (x##_h & 0xF))) + \
+ (60 * ((10*((x##_m & 0xF0)>>4)) + (x##_m & 0xF))) + \
+ ((10*((x##_s & 0xF0)>>4)) + (x##_s & 0xF)))
+#define BcdTimeToMinutes(x) ((60 * ((10*((x##_h & 0xF0)>>4)) + (x##_h & 0xF))) + \
+ (((10*((x##_m & 0xF0)>>4)) + (x##_m & 0xF))))
+#define BcdCharToInt(x) (10*((x & 0xF0)>>4) + (x & 0xF))
+#define CheckBcdChar(x) ((((x & 0xF0)>>4) <= 9) && \
+ ((x & 0x0F) <= 9))
+#define CheckBcdSignedChar(x) ((((x & 0xF0)>>4) >= 0) && (((x & 0xF0)>>4) <= 9) && \
+ ((x & 0x0F) >= 0) && ((x & 0x0F) <= 9))
+
+#define GetTableId(x) (((si_tab_t *)(x))->table_id)
+#define GetSectionLength(x) HILO(((si_tab_t *)(x))->section_length)
+typedef struct si_tab {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+} si_tab_t;
+
+/*
+ *
+ * ETSI ISO/IEC 13818-1 specifies SI which is referred to as PSI. The PSI
+ * data provides information to enable automatic configuration of the
+ * receiver to demultiplex and decode the various streams of programs
+ * within the multiplex. The PSI data is structured as four types of table.
+ * The tables are transmitted in sections.
+ *
+ * 1) Program Association Table (PAT):
+ *
+ * - for each service in the multiplex, the PAT indicates the location
+ * (the Packet Identifier (PID) values of the Transport Stream (TS)
+ * packets) of the corresponding Program Map Table (PMT).
+ * It also gives the location of the Network Information Table (NIT).
+ *
+ */
+#define TableHasMoreSections(x) (((pat_t *)(x))->last_section_number > ((pat_t *)(x))->section_number)
+#define GetSectionNumber(x) ((pat_t *)(x))->section_number
+#define GetLastSectionNumber(x) ((pat_t *)(x))->last_section_number
+#define GetServiceId(x) HILO(((eit_t *)(x))->service_id)
+#define GetLastTableId(x) ((eit_t *)(x))->segment_last_table_id
+#define GetSegmentLastSectionNumber(x) ((eit_t *)(x))->segment_last_section_number
+typedef struct pat {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number /*:8*/;
+ u_char last_section_number /*:8*/;
+} pat_t;
+#define PAT_LEN sizeof (pat_t)
+
+typedef struct pat_prog {
+ u_char program_number_hi /*:8*/;
+ u_char program_number_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char network_pid_hi :5;
+#else
+ u_char network_pid_hi :5;
+ u_char :3;
+#endif
+ u_char network_pid_lo /*:8*/;
+ /* or program_map_pid (if prog_num=0)*/
+} pat_prog_t;
+#define PAT_PROG_LEN sizeof (pat_prog_t)
+
+/*
+ *
+ * 2) Conditional Access Table (CAT):
+ *
+ * - the CAT provides information on the CA systems used in the
+ * multiplex; the information is private and dependent on the CA
+ * system, but includes the location of the EMM stream, when
+ * applicable.
+ *
+ */
+typedef struct cat {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char :8;
+ u_char :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number /*:8*/;
+ u_char last_section_number /*:8*/;
+} cat_t;
+#define CAT_LEN sizeof (cat_t)
+
+/*
+ *
+ * 3) Program Map Table (PMT):
+ *
+ * - the PMT identifies and indicates the locations of the streams that
+ * make up each service, and the location of the Program Clock
+ * Reference fields for a service.
+ *
+ */
+typedef struct pmt {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char dummy :1; // has to be 0
+ u_char :2;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :2;
+ u_char dummy :1; // has to be 0
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char program_number_hi /*:8*/;
+ u_char program_number_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number /*:8*/;
+ u_char last_section_number /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char PCR_PID_hi :5;
+#else
+ u_char PCR_PID_hi :5;
+ u_char :3;
+#endif
+ u_char PCR_PID_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char program_info_length_hi :4;
+#else
+ u_char program_info_length_hi :4;
+ u_char :4;
+#endif
+ u_char program_info_length_lo /*:8*/;
+ //descriptors
+} pmt_t;
+#define PMT_LEN sizeof (pmt_t)
+
+typedef struct pmt_info {
+ u_char stream_type /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char elementary_PID_hi :5;
+#else
+ u_char elementary_PID_hi :5;
+ u_char :3;
+#endif
+ u_char elementary_PID_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char ES_info_length_hi :4;
+#else
+ u_char ES_info_length_hi :4;
+ u_char :4;
+#endif
+ u_char ES_info_length_lo /*:8*/;
+ // descriptors
+} pmt_info_t;
+#define PMT_INFO_LEN sizeof (pmt_info_t)
+
+/*
+ *
+ * 4) Network Information Table (NIT):
+ *
+ * - the NIT is intended to provide information about the physical
+ * network. The syntax and semantics of the NIT are defined in
+ * ETSI EN 300 468.
+ *
+ */
+typedef struct nit {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char network_id_hi /*:8*/;
+ u_char network_id_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number /*:8*/;
+ u_char last_section_number /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char network_descriptor_length_hi :4;
+#else
+ u_char network_descriptor_length_hi :4;
+ u_char :4;
+#endif
+ u_char network_descriptor_length_lo /*:8*/;
+ /* descriptors */
+} nit_t;
+#define NIT_LEN sizeof (nit_t)
+
+typedef struct nit_mid { // after descriptors
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char transport_stream_loop_length_hi :4;
+#else
+ u_char transport_stream_loop_length_hi :4;
+ u_char :4;
+#endif
+ u_char transport_stream_loop_length_lo /*:8*/;
+} nit_mid_t;
+#define SIZE_NIT_MID sizeof (nit_mid_t)
+
+typedef struct nit_end {
+ long CRC;
+} nit_end_t;
+#define SIZE_NIT_END sizeof (nit_end_t)
+
+typedef struct nit_ts {
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char transport_descriptors_length_hi :4;
+#else
+ u_char transport_descriptors_length_hi :4;
+ u_char :4;
+#endif
+ u_char transport_descriptors_length_lo /*:8*/;
+ /* descriptors */
+} nit_ts_t;
+#define NIT_TS_LEN sizeof (nit_ts_t)
+
+/*
+ *
+ * In addition to the PSI, data is needed to provide identification of
+ * services and events for the user. In contrast with the PAT, CAT, and
+ * PMT of the PSI, which give information only for the multiplex in which
+ * they are contained (the actual multiplex), the additional information
+ * defined within the present document can also provide information on
+ * services and events carried by different multiplexes, and even on other
+ * networks. This data is structured as nine tables:
+ *
+ * 1) Bouquet Association Table (BAT):
+ *
+ * - the BAT provides information regarding bouquets. As well as giving
+ * the name of the bouquet, it provides a list of services for each
+ * bouquet.
+ *
+ */
+/* SEE NIT (It has the same structure but has different allowed descriptors) */
+/*
+ *
+ * 2) Service Description Table (SDT):
+ *
+ * - the SDT contains data describing the services in the system e.g.
+ * names of services, the service provider, etc.
+ *
+ */
+typedef struct sdt {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number /*:8*/;
+ u_char last_section_number /*:8*/;
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char :8;
+} sdt_t;
+#define SDT_LEN sizeof (sdt_t)
+#define GetSDTTransportStreamId(x) HILO(((sdt_t *)x)->transport_stream_id)
+#define GetSDTOriginalNetworkId(x) HILO(((sdt_t *)x)->original_network_id)
+
+typedef struct sdt_descr {
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :6;
+ u_char eit_schedule_flag :1;
+ u_char eit_present_following_flag :1;
+ u_char running_status :3;
+ u_char free_ca_mode :1;
+ u_char descriptors_loop_length_hi :4;
+#else
+ u_char eit_present_following_flag :1;
+ u_char eit_schedule_flag :1;
+ u_char :6;
+ u_char descriptors_loop_length_hi :4;
+ u_char free_ca_mode :1;
+ u_char running_status :3;
+#endif
+ u_char descriptors_loop_length_lo /*:8*/;
+ u_char data[];
+} sdt_descr_t;
+#define SDT_DESCR_LEN sizeof (sdt_descr_t)
+#define GetSDTDescriptorsLoopLength(x) HILO(((sdt_descr_t *)x)->descriptors_loop_length)
+
+/*
+ *
+ * 3) Event Information Table (EIT):
+ *
+ * - the EIT contains data concerning events or programmes such as event
+ * name, start time, duration, etc.; - the use of different descriptors
+ * allows the transmission of different kinds of event information e.g.
+ * for different service types.
+ *
+ */
+typedef struct eit {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char version_number :5;
+ u_char current_next_indicator :1;
+#else
+ u_char current_next_indicator :1;
+ u_char version_number :5;
+ u_char :2;
+#endif
+ u_char section_number /*:8*/;
+ u_char last_section_number /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char segment_last_section_number /*:8*/;
+ u_char segment_last_table_id /*:8*/;
+ u_char data[]; /* struct eit_event */
+} eit_t;
+#define EIT_LEN sizeof (eit_t)
+
+typedef struct eit_event {
+ u_char event_id_hi /*:8*/;
+ u_char event_id_lo /*:8*/;
+ u_char mjd_hi /*:8*/;
+ u_char mjd_lo /*:8*/;
+ u_char start_time_h /*:8*/;
+ u_char start_time_m /*:8*/;
+ u_char start_time_s /*:8*/;
+ u_char duration_h /*:8*/;
+ u_char duration_m /*:8*/;
+ u_char duration_s /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char running_status :3;
+ u_char free_ca_mode :1;
+ u_char descriptors_loop_length_hi :4;
+#else
+ u_char descriptors_loop_length_hi :4;
+ u_char free_ca_mode :1;
+ u_char running_status :3;
+#endif
+ u_char descriptors_loop_length_lo /*:8*/;
+ u_char data[]; /* struct descr_gen */
+} eit_event_t;
+#define EIT_EVENT_LEN sizeof (eit_event_t)
+#define GetEITDescriptorsLoopLength(x) HILO(((eit_event_t *)x)->descriptors_loop_length)
+
+/*
+ *
+ * 4) Running Status Table (RST):
+ *
+ * - the RST gives the status of an event (running/not running). The RST
+ * updates this information and allows timely automatic switching to
+ * events.
+ *
+ */
+ /* TO BE DONE */
+/*
+ *
+ * 5) Time and Date Table (TDT):
+ *
+ * - the TDT gives information relating to the present time and date.
+ * This information is given in a separate table due to the frequent
+ * updating of this information.
+ *
+ */
+
+typedef struct tdt {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char utc_mjd_hi /*:8*/;
+ u_char utc_mjd_lo /*:8*/;
+ u_char utc_time_h /*:8*/;
+ u_char utc_time_m /*:8*/;
+ u_char utc_time_s /*:8*/;
+} tdt_t;
+#define TDT_LEN sizeof (tdt_t)
+
+/*
+ *
+ * 6) Time Offset Table (TOT):
+ *
+ * - the TOT gives information relating to the present time and date and
+ * local time offset. This information is given in a separate table due
+ * to the frequent updating of the time information.
+ *
+ */
+typedef struct tot {
+ u_char table_id /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char section_syntax_indicator :1;
+ u_char :3;
+ u_char section_length_hi :4;
+#else
+ u_char section_length_hi :4;
+ u_char :3;
+ u_char section_syntax_indicator :1;
+#endif
+ u_char section_length_lo /*:8*/;
+ u_char utc_mjd_hi /*:8*/;
+ u_char utc_mjd_lo /*:8*/;
+ u_char utc_time_h /*:8*/;
+ u_char utc_time_m /*:8*/;
+ u_char utc_time_s /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char descriptors_loop_length_hi :4;
+#else
+ u_char descriptors_loop_length_hi :4;
+ u_char :4;
+#endif
+ u_char descriptors_loop_length_lo /*:8*/;
+} tot_t;
+#define TOT_LEN sizeof (tot_t)
+
+/*
+ *
+ * 7) Stuffing Table (ST):
+ *
+ * - the ST is used to invalidate existing sections, for example at
+ * delivery system boundaries.
+ *
+ */
+ /* TO BE DONE */
+/*
+ *
+ * 8) Selection Information Table (SIT):
+ *
+ * - the SIT is used only in "partial" (i.e. recorded) bitstreams. It
+ * carries a summary of the SI information required to describe the
+ * streams in the partial bitstream.
+ *
+ */
+ /* TO BE DONE */
+/*
+ *
+ * 9) Discontinuity Information Table (DIT):
+ *
+ * - the DIT is used only in "partial" (i.e. recorded) bitstreams.
+ * It is inserted where the SI information in the partial bitstream may
+ * be discontinuous. Where applicable the use of descriptors allows a
+ * flexible approach to the organization of the tables and allows for
+ * future compatible extensions.
+ *
+ */
+ /* TO BE DONE */
+/*
+ *
+ * The following describes the different descriptors that can be used within
+ * the SI.
+ *
+ * The following semantics apply to all the descriptors defined in this
+ * subclause:
+ *
+ * descriptor_tag: The descriptor tag is an 8-bit field which identifies
+ * each descriptor. Those values with MPEG-2 normative
+ * meaning are described in ISO/IEC 13818-1. The values of
+ * descriptor_tag are defined in 'libsi.h'
+ * descriptor_length: The descriptor length is an 8-bit field specifying the
+ * total number of bytes of the data portion of the
+ * descriptor following the byte defining the value of
+ * this field.
+ *
+ */
+
+typedef struct descr_gen {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+} descr_gen_t;
+#define DESCR_GEN_LEN sizeof (descr_gen_t)
+#define CastGenericDescriptor(x) ((descr_gen_t *)(x))
+
+#define GetDescriptorTag(x) (((descr_gen_t *)x)->descriptor_tag)
+#define GetDescriptorLength(x) (((descr_gen_t *)x)->descriptor_length)
+
+/* 0x09 ca_descriptor */
+typedef struct descr_ca {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char CA_type_hi /*:8*/;
+ u_char CA_type_lo /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :3;
+ u_char CA_PID_hi :5;
+#else
+ u_char CA_PID_hi :5;
+ u_char :3;
+#endif
+ u_char CA_PID_lo /*:8*/;
+} descr_ca_t;
+#define DESCR_CA_LEN sizeof (descr_ca_t)
+#define CastCaDescriptor(x) ((descr_ca_t *)(x))
+
+/* 0x0A iso_639_language_descriptor */
+typedef struct descr_iso_639_language {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+} descr_iso_639_language_t;
+#define DESCR_ISO_639_LANGUAGE_LEN sizeof (descr_iso_639_language_t)
+#define CastIso639LanguageDescriptor(x) ((descr_iso_639_language_t *)(x))
+
+/* 0x40 network_name_descriptor */
+typedef struct descr_network_name {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+} descr_network_name_t;
+#define DESCR_NETWORK_NAME_LEN sizeof (descr_network_name_t)
+#define CastNetworkNameDescriptor(x) ((descr_network_name_t *)(x))
+
+/* 0x41 service_list_descriptor */
+typedef struct descr_service_list {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+} descr_service_list_t;
+#define DESCR_SERVICE_LIST_LEN sizeof (descr_service_list_t)
+#define CastServiceListDescriptor(x) ((descr_service_list_t *)(x))
+
+typedef struct descr_service_list_loop {
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+ u_char service_type /*:8*/;
+} descr_service_list_loop_t;
+#define DESCR_SERVICE_LIST_LOOP_LEN sizeof (descr_service_list_loop_t)
+#define CastServiceListDescriptorLoop(x) ((descr_service_list_loop_t *)(x))
+
+/* 0x42 stuffing_descriptor */
+typedef struct descr_stuffing {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[];
+} descr_stuffing_t;
+#define DESCR_STUFFING_LEN sizeof (descr_stuffing_t)
+#define CastStuffingDescriptor(x) ((descr_stuffing_t *)(x))
+
+/* 0x43 satellite_delivery_system_descriptor */
+typedef struct descr_satellite_delivery_system {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char frequency1 /*:8*/;
+ u_char frequency2 /*:8*/;
+ u_char frequency3 /*:8*/;
+ u_char frequency4 /*:8*/;
+ u_char orbital_position1 /*:8*/;
+ u_char orbital_position2 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char west_east_flag :1;
+ u_char polarization :2;
+ u_char modulation :5;
+#else
+ u_char modulation :5;
+ u_char polarization :2;
+ u_char west_east_flag :1;
+#endif
+ u_char symbol_rate1 /*:8*/;
+ u_char symbol_rate2 /*:8*/;
+ u_char symbol_rate3 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char symbol_rate4 :4;
+ u_char fec_inner :4;
+#else
+ u_char fec_inner :4;
+ u_char symbol_rate4 :4;
+#endif
+} descr_satellite_delivery_system_t;
+#define DESCR_SATELLITE_DELIVERY_SYSTEM_LEN sizeof (descr_satellite_delivery_system_t)
+#define CastSatelliteDeliverySystemDescriptor(x) ((descr_satellite_delivery_system_t *)(x))
+#define GetSatelliteDeliverySystemFrequency(x) HILO4(((descr_satellite_delivert_system_t *)x)->frequency)
+#define GetSatelliteDeliverySystemSymbolRate(x) HILO4(((descr_satellite_delivert_system_t *)x)->symbol_rate)
+
+
+/* 0x44 cable_delivery_system_descriptor */
+typedef struct descr_cable_delivery_system {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char frequency1 /*:8*/;
+ u_char frequency2 /*:8*/;
+ u_char frequency3 /*:8*/;
+ u_char frequency4 /*:8*/;
+ u_char :8;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char fec_outer :4;
+#else
+ u_char fec_outer :4;
+ u_char :4;
+#endif
+ u_char modulation /*:8*/;
+ u_char symbol_rate1 /*:8*/;
+ u_char symbol_rate2 /*:8*/;
+ u_char symbol_rate3 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char symbol_rate4 :4;
+ u_char fec_inner :4;
+#else
+ u_char fec_inner :4;
+ u_char symbol_rate4 :4;
+#endif
+} descr_cable_delivery_system_t;
+#define DESCR_CABLE_DELIVERY_SYSTEM_LEN sizeof (descr_cable_delivery_system_t)
+#define CastCableDeliverySystemDescriptor(x) ((descr_cable_delivery_system_t *)(x))
+#define GetCableDeliverySystemFrequency(x) HILO4(((descr_cable_delivert_system_t *)x)->frequency)
+#define GetCableDeliverySystemSymbolRate(x) HILO4(((descr_cable_delivert_system_t *)x)->symbol_rate)
+
+/* 0x45 vbi_data_descriptor */
+typedef struct descr_vbi_data {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_vbi_data_t;
+#define DESCR_VBI_DATA_LEN sizeof (descr_vbi_data_t)
+#define CastVbiDataDescriptor(x) ((descr_vbi_data_t *)(x))
+
+/* 0x46 vbi_teletext_descriptor */
+typedef struct descr_vbi_teletext {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_vbi_teletext_t;
+#define DESCR_VBI_TELETEXT_LEN sizeof (descr_vbi_teletext_t)
+#define CastVbiDescriptor(x) ((descr_vbi_teletext_t *)(x))
+
+/* 0x47 bouquet_name_descriptor */
+typedef struct descr_bouquet_name {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+} descr_bouquet_name_t;
+#define DESCR_BOUQUET_NAME_LEN sizeof (descr_bouquet_name_t)
+
+#define CastBouquetNameDescriptor(x) ((descr_bouquet_name_t *)(x))
+
+/* 0x48 service_descriptor */
+typedef struct descr_service {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char service_type /*:8*/;
+ u_char provider_name_length /*:8*/;
+} descr_service_t;
+#define DESCR_SERVICE_LEN sizeof (descr_service_t)
+#define CastServiceDescriptor(x) ((descr_service_t *)(x))
+
+/* 0x49 country_availability_descriptor */
+typedef struct descr_country_availability {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char country_availability_flag :1;
+ u_char :7;
+#else
+ u_char :7;
+ u_char country_availability_flag :1;
+#endif
+} descr_country_availability_t;
+#define DESCR_COUNTRY_AVAILABILITY_LEN sizeof (descr_country_availability_t)
+#define CastCountryAvailabilityDescriptor(x) ((descr_country_availability_t *)(x))
+
+/* 0x4A linkage_descriptor */
+typedef struct descr_linkage {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+ u_char linkage_type /*:8*/;
+} descr_linkage_t;
+#define DESCR_LINKAGE_LEN sizeof (descr_linkage_t)
+#define CastLinkageDescriptor(x) ((descr_linkage_t *)(x))
+
+/* 0x4B nvod_reference_descriptor */
+typedef struct descr_nvod_reference {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct item_nvod_reference */
+} descr_nvod_reference_t;
+#define DESCR_NVOD_REFERENCE_LEN sizeof (descr_nvod_reference_t)
+#define CastNvodReferenceDescriptor(x) ((descr_nvod_reference_t *)(x))
+
+typedef struct item_nvod_reference {
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+} item_nvod_reference_t;
+#define ITEM_NVOD_REFERENCE_LEN sizeof (item_nvod_reference_t)
+#define CastNvodReferenceItem(x) ((item_nvod_reference_t *)(x))
+
+/* 0x4C time_shifted_service_descriptor */
+typedef struct descr_time_shifted_service {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char reference_service_id_hi /*:8*/;
+ u_char reference_service_id_lo /*:8*/;
+} descr_time_shifted_service_t;
+#define DESCR_TIME_SHIFTED_SERVICE_LEN sizeof (descr_time_shifted_service_t)
+#define CastTimeShiftedServiceDescriptor(x) ((descr_time_shifted_service_t *)(x))
+
+/* 0x4D short_event_descriptor */
+typedef struct descr_short_event {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char event_name_length /*:8*/;
+ u_char data[];
+} descr_short_event_t;
+#define DESCR_SHORT_EVENT_LEN sizeof (descr_short_event_t)
+#define CastShortEventDescriptor(x) ((descr_short_event_t *)(x))
+
+/* 0x4E extended_event_descriptor */
+typedef struct descr_extended_event {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char descriptor_number :4;
+ u_char last_descriptor_number :4;
+#else
+ u_char last_descriptor_number :4;
+ u_char descriptor_number :4;
+#endif
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char length_of_items /*:8*/;
+ u_char data[]; /* struct item_extended_event */
+} descr_extended_event_t;
+#define DESCR_EXTENDED_EVENT_LEN sizeof (descr_extended_event_t)
+#define CastExtendedEventDescriptor(x) ((descr_extended_event_t *)(x))
+
+typedef struct item_extended_event {
+ u_char item_description_length /*:8*/;
+ u_char data[];
+} item_extended_event_t;
+#define ITEM_EXTENDED_EVENT_LEN sizeof (item_extended_event_t)
+#define CastExtendedEventItem(x) ((item_extended_event_t *)(x))
+
+/* 0x4F time_shifted_event_descriptor */
+typedef struct descr_time_shifted_event {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char reference_service_id_hi /*:8*/;
+ u_char reference_service_id_lo /*:8*/;
+ u_char reference_event_id_hi /*:8*/;
+ u_char reference_event_id_lo /*:8*/;
+} descr_time_shifted_event_t;
+#define DESCR_TIME_SHIFTED_EVENT_LEN sizeof (descr_time_shifted_event_t)
+#define CastTimeShiftedEventDescriptor(x) ((descr_time_shifted_event_t *)(x))
+
+/* 0x50 component_descriptor */
+typedef struct descr_component {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char stream_content :4;
+#else
+ u_char stream_content :4;
+ u_char :4;
+#endif
+ u_char component_type /*:8*/;
+ u_char component_tag /*:8*/;
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char data[];
+} descr_component_t;
+#define DESCR_COMPONENT_LEN sizeof (descr_component_t)
+#define CastComponentDescriptor(x) ((descr_component_t *)(x))
+
+/* 0x51 mosaic_descriptor */
+typedef struct descr_mosaic {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char mosaic_entry_point :1;
+ u_char number_of_horizontal_elementary_cells :3;
+ u_char :1;
+ u_char number_of_vertical_elementary_cells :3;
+#else
+ u_char number_of_vertical_elementary_cells :3;
+ u_char :1;
+ u_char number_of_horizontal_elementary_cells :3;
+ u_char mosaic_entry_point :1;
+#endif
+ u_char data[]; /* struct item_mosaic */
+} descr_mosaic_t;
+#define DESCR_MOSAIC_LEN sizeof (descr_mosaic_t)
+#define CastMosaicDescriptor(x) ((descr_mosaic_t *)(x))
+
+typedef struct item_mosaic {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char logical_cell_id :6;
+ u_char :7;
+ u_char logical_cell_presentation_info :3;
+#else
+ u_char :2;
+ u_char logical_cell_id :6;
+ u_char logical_cell_presentation_info :3; /*0=undefined, 1=video, 2=still picture, 3=graphical text, 4--7=reserved*/
+ u_char :5;
+#endif
+ u_char elementary_cell_field_length /*:8*/;
+ u_char data[]; /* struct item_mosaic_cell; struct item_mosaic_end */
+} item_mosaic_t;
+typedef struct item_mosaic_end {
+ u_char cell_linkage_info /*:8*/; /*0=undefined, 1=bouquet, 2=service, 3=other mosaic, 4=event, 5--255=reserved*/
+ u_char data[]; /* union item_cell_linkage */
+} item_mosaic_end_t;
+
+typedef struct item_mosaic_cell {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char elementary_cell_id :6;
+#else
+ u_char elementary_cell_id :6;
+ u_char :2;
+#endif
+} item_mosaic_cell_t;
+typedef union item_mosaic_cell_linkage {
+ struct item_mosaic_cell_bouquet {
+ u_char bouquet_id_hi /*:8*/;
+ u_char bouquet_id_lo /*:8*/;
+ } bouquet;
+ struct item_mosaic_cell_service {
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+ } service;
+ struct item_mosaic_cell_other {
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+ } other;
+ struct item_mosaic_cell_event {
+ u_char original_network_id_hi /*:8*/;
+ u_char original_network_id_lo /*:8*/;
+ u_char transport_stream_id_hi /*:8*/;
+ u_char transport_stream_id_lo /*:8*/;
+ u_char service_id_hi /*:8*/;
+ u_char service_id_lo /*:8*/;
+ u_char event_id_hi /*:8*/;
+ u_char event_id_lo /*:8*/;
+ } event;
+} item_mosaic_cell_linkage_t;
+
+/* 0x52 stream_identifier_descriptor */
+typedef struct descr_stream_identifier {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char component_tag /*:8*/;
+} descr_stream_identifier_t;
+#define DESCR_STREAM_IDENTIFIER_LEN sizeof (descr_stream_identifier_t)
+#define CastStreamIdentifierDescriptor(x) ((descr_stream_identifier_t *)(x))
+
+/* 0x53 ca_identifier_descriptor */
+typedef struct descr_ca_identifier {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+} descr_ca_identifier_t;
+#define DESCR_CA_IDENTIFIER_LEN sizeof (descr_ca_identifier_t)
+#define CastCaIdentifierDescriptor(x) ((descr_ca_identifier_t *)(x))
+
+/* 0x54 content_descriptor */
+typedef struct descr_content {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct nibble_content */
+} descr_content_t;
+#define DESCR_CONTENT_LEN sizeof (descr_content_t)
+#define CastContentDescriptor(x) ((descr_content_t *)(x))
+
+typedef struct nibble_content {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char content_nibble_level_1 :4;
+ u_char content_nibble_level_2 :4;
+ u_char user_nibble_1 :4;
+ u_char user_nibble_2 :4;
+#else
+ u_char user_nibble_2 :4;
+ u_char user_nibble_1 :4;
+ u_char content_nibble_level_2 :4;
+ u_char content_nibble_level_1 :4;
+#endif
+} nibble_content_t;
+#define NIBBLE_CONTENT_LEN sizeof (nibble_content_t)
+#define CastContentNibble(x) ((nibble_content_t *)(x))
+
+/* 0x55 parental_rating_descriptor */
+typedef struct descr_parental_rating {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct parental_rating_item */
+} descr_parental_rating_t;
+#define DESCR_PARENTAL_RATING_LEN sizeof (descr_parental_rating_t)
+#define CastParentalRatingDescriptor(x) ((descr_parental_rating_t *)(x))
+
+typedef struct parental_rating_item {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char rating /*:8*/;
+} parental_rating_item_t;
+#define PARENTAL_RATING_ITEM_LEN sizeof (parental_rating_item_t)
+#define CastParentalRatingItem(x) ((parental_rating_item_t *)(x))
+
+/* 0x56 teletext_descriptor */
+typedef struct descr_teletext {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct item_teletext */
+} descr_teletext_t;
+#define DESCR_TELETEXT_LEN sizeof (descr_teletext_t)
+#define CastTeletextDescriptor(x) ((descr_teletext_t *)(x))
+
+typedef struct item_teletext {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char type :5;
+ u_char magazine_number :3;
+#else
+ u_char magazine_number :3;
+ u_char type :5;
+#endif
+ u_char page_number /*:8*/;
+} item_teletext_t;
+#define ITEM_TELETEXT_LEN sizeof (item_teletext_t)
+#define CastTeletextItem(x) ((item_teletext_t *)(x))
+
+/* 0x57 telephone_descriptor */
+typedef struct descr_telephone {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char foreign_availability :1;
+ u_char connection_type :5;
+#else
+ u_char connection_type :5;
+ u_char foreign_availability :1;
+ u_char :2;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :1;
+ u_char country_prefix_length :2;
+ u_char international_area_code_length :3;
+ u_char operator_code_length :2;
+#else
+ u_char operator_code_length :2;
+ u_char international_area_code_length :3;
+ u_char country_prefix_length :2;
+ u_char :1;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :1;
+ u_char national_area_code_length :3;
+ u_char core_number_length :4;
+#else
+ u_char core_number_length :4;
+ u_char national_area_code_length :3;
+ u_char :1;
+#endif
+ u_char data[]; /* coutry area operator national core */
+} descr_telephone_t;
+#define DESCR_TELEPHONE_LEN sizeof (descr_telephone_t)
+#define CastTelephoneDescriptor(x) ((descr_telephone_t *)(x))
+
+/* 0x58 local_time_offset_descriptor */
+typedef struct descr_local_time_offset {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+} descr_local_time_offset_t;
+#define DESCR_LOCAL_TIME_OFFSET_LEN sizeof (descr_local_time_offset_t)
+#define CastLocalTimeOffsetDescriptor(x) ((descr_local_time_offset_t *)(x))
+
+typedef struct local_time_offset_entry {
+ u_char country_code1 /*:8*/;
+ u_char country_code2 /*:8*/;
+ u_char country_code3 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char country_region_id :6;
+ u_char :1;
+ u_char local_time_offset_polarity :1;
+#else
+ u_char local_time_offset_polarity :1;
+ u_char :1;
+ u_char country_region_id :6;
+#endif
+ u_char local_time_offset_h /*:8*/;
+ u_char local_time_offset_m /*:8*/;
+ u_char time_of_change_mjd_hi /*:8*/;
+ u_char time_of_change_mjd_lo /*:8*/;
+ u_char time_of_change_time_h /*:8*/;
+ u_char time_of_change_time_m /*:8*/;
+ u_char time_of_change_time_s /*:8*/;
+ u_char next_time_offset_h /*:8*/;
+ u_char next_time_offset_m /*:8*/;
+} local_time_offset_entry_t ;
+#define LOCAL_TIME_OFFSET_ENTRY_LEN sizeof (local_time_offset_entry_t)
+#define CastLocalTimeOffsetEntry(x) ((local_time_offset_entry_t *)(x))
+
+/* 0x59 subtitling_descriptor */
+typedef struct descr_subtitling {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* item_subtitling */
+} descr_subtitling_t;
+#define DESCR_SUBTITLING_LEN sizeof (descr_subtitling_t)
+#define CastSubtitlingDescriptor(x) ((descr_subtitling_t *)(x))
+
+typedef struct item_subtitling {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char subtitling_type /*:8*/;
+ u_char composition_page_id_hi /*:8*/;
+ u_char composition_page_id_lo /*:8*/;
+ u_char ancillary_page_id_hi /*:8*/;
+ u_char ancillary_page_id_lo /*:8*/;
+} item_subtitling_t;
+#define ITEM_SUBTITLING_LEN sizeof (item_subtitling_t)
+#define CastSubtitlingItem(x) ((item_subtitling_t *)(x))
+
+/* 0x5A terrestrial_delivery_system_descriptor */
+typedef struct descr_terrestrial_delivery {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char frequency1 /*:8*/;
+ u_char frequency2 /*:8*/;
+ u_char frequency3 /*:8*/;
+ u_char frequency4 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char bandwidth :3;
+ u_char :5;
+#else
+ u_char :5;
+ u_char bandwidth :3;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char constellation :2;
+ u_char hierarchy :3;
+ u_char code_rate_HP :3;
+#else
+ u_char code_rate_HP :3;
+ u_char hierarchy :3;
+ u_char constellation :2;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char code_rate_LP :3;
+ u_char guard_interval :2;
+ u_char transmission_mode :2;
+ u_char other_frequency_flag :1;
+#else
+ u_char other_frequency_flag :1;
+ u_char transmission_mode :2;
+ u_char guard_interval :2;
+ u_char code_rate_LP :3;
+#endif
+ u_char reserver2 /*:8*/;
+ u_char reserver3 /*:8*/;
+ u_char reserver4 /*:8*/;
+ u_char reserver5 /*:8*/;
+} descr_terrestrial_delivery_system_t;
+#define DESCR_TERRESTRIAL_DELIVERY_SYSTEM_LEN sizeof (descr_terrestrial_delivery_system_t)
+#define CastTerrestrialDeliverySystemDescriptor(x) ((descr_terrestrial_delivery_system_t *)(x))
+#define GetTerrestrialDeliverySystemFrequency(x) HILO4(((descr_terrestrial_delivert_system_t *)x)->frequency)
+
+/* 0x5B multilingual_network_name_descriptor */
+typedef struct descr_multilingual_network_name {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct item_multilingual_network_name */
+} descr_multilingual_network_name_t;
+#define DESCR_MULTILINGUAL_NETWORK_NAME_LEN sizeof (descr_multilingual_network_name_t)
+#define CastMultilingualNetworkNameDescriptor(x) ((descr_multilingual_network_name_t *)(x))
+
+typedef struct item_multilingual_network_name {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char network_name_length /*:8*/;
+ u_char network_name[];
+} item_multilingual_network_name_t;
+
+/* 0x5C multilingual_bouquet_name_descriptor */
+typedef struct descr_multilingual_bouquet_name {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char names[]; /* struct item_multilingual_bouquet_name */
+} descr_multilingual_bouquet_name_t;
+#define DESCR_MULTILINGUAL_BOUQUET_NAME_LEN sizeof (descr_multilingual_bouquet_name_t)
+#define CastMultilingualBouquetNameDescriptor(x) ((descr_multilingual_bouquet_name_t *)(x))
+
+typedef struct item_multilingual_bouquet_name {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char bouquet_name_length /*:8*/;
+ u_char bouquet_name[];
+} item_multilingual_bouquet_name_t;
+
+/* 0x5D multilingual_service_name_descriptor */
+typedef struct descr_multilingual_service_name {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct multilingual_service_name_item */
+} descr_multilingual_service_name_t;
+#define DESCR_MULTILINGUAL_SERVICE_NAME_LEN sizeof (descr_multilingual_service_name_t)
+#define CastMultilingualServiceNameDescriptor(x) ((descr_multilingual_service_name_t *)(x))
+
+typedef struct multilingual_service_name_item {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char data[]; /* struct multilingual_service_name_item_(mid|end) */
+} multilingual_service_name_item_t;
+typedef struct multilingual_service_name_item_mid {
+ u_char service_provider_name_length /*:8*/;
+ u_char service_provider_name[];
+} multilingual_service_name_item_mid_t;
+typedef struct multilingual_service_name_item_end {
+ u_char service_name_length /*:8*/;
+ u_char service_name[];
+} multilingual_service_name_item_end_t;
+
+/* 0x5E multilingual_component_descriptor */
+typedef struct descr_multilingual_component {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char component_tag /*:8*/;
+ u_char data[]; /* struct multilingual_component_item */
+} descr_multilingual_component_t;
+#define DESCR_MULTILINGUAL_COMPONENT_LEN sizeof (descr_multilingual_component_t)
+#define CastMultilingualComponentDescriptor(x) ((descr_multilingual_component_t *)(x))
+
+typedef struct item_multilingual_component {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char text_description_length /*:8*/;
+ u_char text_description[];
+} item_multilingual_component_t;
+
+/* 0x5F private_data_specifier_descriptor */
+typedef struct descr_private_data_specifier {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char private_data_specifier1 /*:8*/;
+ u_char private_data_specifier2 /*:8*/;
+ u_char private_data_specifier3 /*:8*/;
+ u_char private_data_specifier4 /*:8*/;
+} descr_private_data_specifier_t;
+#define DESCR_PRIVATE_DATA_SPECIFIER_LEN sizeof (descr_private_data_specifier_t)
+#define CastPrivateDataSpecifierDescriptor(x) ((descr_private_data_specifier_t *)(x))
+#define GetPrivateDataSpecifier(x) HILO4(((descr_private_data_specifier_t *)x)->private_data_specifier)
+
+/* 0x60 service_move_descriptor */
+typedef struct descr_service_move {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char new_original_network_id_hi /*:8*/;
+ u_char new_original_network_id_lo /*:8*/;
+ u_char new_transport_stream_id_hi /*:8*/;
+ u_char new_transport_stream_id_lo /*:8*/;
+ u_char new_service_id_hi /*:8*/;
+ u_char new_service_id_lo /*:8*/;
+} descr_service_move_t;
+#define DESCR_SERVICE_MOVE_LEN sizeof (descr_service_move_t)
+#define CastServiceMoveDescriptor(x) ((descr_service_move_t *)(x))
+
+/* 0x61 short_smoothing_buffer_descriptor */
+typedef struct descr_short_smoothing_buffer {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char sb_size :2;
+ u_char sb_leak_rate :6;
+#else
+ u_char sb_leak_rate :6;
+ u_char sb_size :2;
+#endif
+ u_char data[];
+} descr_short_smoothing_buffer_t;
+#define DESCR_SHORT_SMOOTHING_BUFFER_LEN sizeof (descr_short_smoothing_buffer_t)
+#define CastShortSmoothingBufferDescriptor(x) ((descr_short_smoothing_buffer_t *)(x))
+
+/* 0x62 frequency_list_descriptor */
+typedef struct descr_frequency_list {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :6;
+ u_char coding_type :2; /* 00=not def 01=satelite 10=cable 11=terrestrial */
+#else
+ u_char coding_type :2; /* 00=not def 01=satelite 10=cable 11=terrestrial */
+ u_char :6;
+#endif
+ u_char centre_frequency1 /*:8*/;
+ u_char centre_frequency2 /*:8*/;
+ u_char centre_frequency3 /*:8*/;
+ u_char centre_frequency4 /*:8*/;
+} descr_frequency_list_t;
+#define DESCR_FREQUENCY_LIST_LEN sizeof (descr_frequency_list_t)
+#define CastFrequencyListDescriptor(x) ((descr_frequency_list_t *)(x))
+
+/* 0x63 partial_transport_stream_descriptor */
+typedef struct descr_partial_transport_stream {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char peak_rate1 :6;
+#else
+ u_char peak_rate1 :6;
+ u_char :2;
+#endif
+ u_char peak_rate2 /*:8*/;
+ u_char peak_rate3 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char minimum_overall_smoothing_rate1 :6;
+#else
+ u_char minimum_overall_smoothing_rate1 :6;
+ u_char :2;
+#endif
+ u_char minimum_overall_smoothing_rate2 /*:8*/;
+ u_char minimum_overall_smoothing_rate3 /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :2;
+ u_char maximum_overall_smoothing_rate1 :6;
+#else
+ u_char maximum_overall_smoothing_rate1 :6;
+ u_char :2;
+#endif
+ u_char maximum_overall_smoothing_rate2 /*:8*/;
+} descr_partial_transport_stream_t;
+#define DESCR_PARTIAL_TRANSPORT_STREAM_LEN sizeof (descr_partial_transport_stream_t)
+#define CastPartialDescriptor(x) ((descr_partial_transport_stream_t *)(x))
+#define GetPartialTransportStreamCentreFrequency(x) HILO4(((descr_partial_transport_stream_t *)x)->centre_frequency)
+#define GetPTSPeakRate(x) HILO2(((descr_partial_transport_stream *)x)->peak_rate)
+#define GetPTSMinOSRate(x) HILO3(((descr_partial_transport_stream *)x)->minimum_overall_smoothing_rate)
+#define GetPTSMaxOSRate(x) HILO2(((descr_partial_transport_stream *)x)->minimum_overall_smoothing_rate)
+
+/* 0x64 data_broadcast_descriptor */
+typedef struct descr_data_broadcast {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data_broadcast_id_hi /*:8*/;
+ u_char data_broadcast_id_lo /*:8*/;
+ u_char component_tag /*:8*/;
+ u_char selector_length /*:8*/;
+ u_char data[]; /* char[]; struct descr_data_broadcast_end */
+} descr_data_broadcast_t;
+typedef struct descr_data_broadcast_end {
+ u_char lang_code1 /*:8*/;
+ u_char lang_code2 /*:8*/;
+ u_char lang_code3 /*:8*/;
+ u_char text_length /*:8*/;
+ u_char text[];
+} descr_data_broadcast_end_t;
+
+/* 0x65 ca_system_descriptor */
+typedef struct descr_ca_system {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[]; /* struct item_ca_system */
+} descr_ca_system_t;
+#define DESCR_CA_SYSTEM_LEN sizeof (descr_ca_system_t)
+#define CastCaSystemDescriptor(x) ((descr_ca_system_t *)(x))
+
+typedef struct item_ca_system {
+ u_char CA_system_id_hi /*:8*/;
+ u_char CA_system_id_lo /*:8*/;
+} item_ca_system_t;
+
+/* 0x66 data_broadcast_id_descriptor */
+typedef struct descr_data_broadcast_id {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data_broadcast_id_hi /*:8*/;
+ u_char data_broadcast_id_lo /*:8*/;
+} descr_data_broadcast_id_t;
+#define DESCR_DATA_BROADCAST_ID_LEN sizeof (descr_data_broadcast_id_t)
+#define CastDataBroadcastIdDescriptor(x) ((descr_data_broadcast_id_t *)(x))
+
+/* 0x67 transport_stream_descriptor */
+typedef struct descr_transport_stream {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_transport_stream_t;
+#define DESCR_TRANSPORT_STREAM_LEN sizeof (descr_transport_stream_t)
+#define CastTransportStreamDescriptor(x) ((descr_transport_stream_t *)(x))
+
+/* 0x68 dsng_descriptor */
+typedef struct descr_dsng {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_dsng_t;
+#define DESCR_DSNG_LEN sizeof (descr_dsng_t)
+#define CastDsngDescriptor(x) ((descr_dsng_t *)(x))
+
+/* 0x69 programme_identificaion_label_descriptor */
+typedef struct descr_pdc {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char :4;
+ u_char day :5;
+ u_char month :4;
+ u_char hour :5;
+ u_char minute :6;
+#else
+ u_char minute :6;
+ u_char hour :5;
+ u_char month :4;
+ u_char day :5;
+ u_char :4;
+#endif
+} descr_pdc_t;
+#define DESCR_PDC_LEN sizeof (descr_pdc_t)
+#define CastPdcDescriptor(x) ((descr_pdc_t *)(x))
+
+/* 0x6A ac3_descriptor */
+typedef struct descr_ac3 {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char ac3_type_flag :1;
+ u_char bsid_flag :1;
+ u_char mainid_flag :1;
+ u_char asvc_flag :1;
+ u_char :4;
+#else
+ u_char :4;
+ u_char asvc_flag :1;
+ u_char mainid_flag :1;
+ u_char bsid_flag :1;
+ u_char ac3_type_flag :1;
+#endif
+ u_char ac3_type /*:8*/;
+ u_char bsid /*:8*/;
+ u_char mainid /*:8*/;
+ u_char asvc /*:8*/;
+} descr_ac3_t;
+#define DESCR_AC3_LEN sizeof (descr_ac3_t)
+#define CastAc3Descriptor(x) ((descr_ac3_t *)(x))
+
+/* 0x6B ancillary_data_descriptor */
+typedef struct descr_ancillary_data {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char ancillary_data_identifier /*:8*/;
+} descr_ancillary_data_t;
+#define DESCR_ANCILLARY_DATA_LEN sizeof (descr_ancillary_data_t)
+#define CastAncillaryDataDescriptor(x) ((descr_ancillary_data_t *)(x))
+
+/* 0x6C cell_list_descriptor */
+typedef struct descr_cell_list {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_cell_list_t;
+#define DESCR_CELL_LIST_LEN sizeof (descr_cell_list_t)
+#define CastCellListDescriptor(x) ((descr_cell_list_t *)(x))
+
+/* 0x6D cell_frequency_link_descriptor */
+typedef struct descr_cell_frequency_link {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_cell_frequency_link_t;
+#define DESCR_CELL_FREQUENCY_LINK_LEN sizeof (descr_cell_frequency_link_t)
+#define CastCellFrequencyLinkDescriptor(x) ((descr_cell_frequency_link_t *)(x))
+
+/* 0x6E announcement_support_descriptor */
+typedef struct descr_announcement_support {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ /* TBD */
+} descr_announcement_support_t;
+#define DESCR_ANNOUNCEMENT_SUPPORT_LEN sizeof (descr_announcement_support_t)
+#define CastAnnouncementSupportDescriptor(x) ((descr_announcement_support_t *)(x))
+
+/* 0x76 content_identifier_descriptor */
+typedef struct descr_content_identifier {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char data[];
+} descr_content_identifier_t;
+
+typedef struct descr_content_identifier_crid {
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char crid_type :6;
+ u_char crid_location :2;
+#else
+ u_char crid_location :2;
+ u_char crid_type :6;
+#endif
+ u_char crid_ref_data[];
+} descr_content_identifier_crid_t;
+
+typedef struct descr_content_identifier_crid_local {
+ u_char crid_length /*:8*/;
+ u_char crid_byte[];
+} descr_content_identifier_crid_local_t;
+
+
+/* 0x80 custom_category_descriptor TODO */
+typedef struct descr_custom_category {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char dummy /*:8*/; // 7F
+ u_char data_length /*:8*/;
+ u_char data[]; /* struct custom_category_item(1|2) */
+} descr_custom_category_t;
+struct custom_category_item1 {
+ u_char dummy /*:8*/; // 10 40
+};
+struct custom_category_item2 {
+ u_char length /*:8*/;
+ u_char data[]; /* struct custom_category_item3 */
+};
+struct custom_category_item3 {
+ u_char dummy0 /*:8*/; // FF
+#if BYTE_ORDER == BIG_ENDIAN
+ u_char content_nibble_level_1 :4;
+ u_char content_nibble_level_2 :4;
+ u_char user_nibble_1 :4;
+ u_char user_nibble_2 :4;
+#else
+ u_char user_nibble_2 :4;
+ u_char user_nibble_1 :4;
+ u_char content_nibble_level_2 :4;
+ u_char content_nibble_level_1 :4;
+#endif
+ u_char dummy1[2] /*:8*/; // CF E2 | D4 48
+ u_char text_length /*:8*/;
+ u_char text[];
+};
+
+/* 0x81 xxx_descriptor TODO */
+typedef struct descr_xxx {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char dummy /*:8 FF*/;
+} descr_xxx_t;
+#define DESCR_XXX_LEN sizeof (descr_xxx_t)
+#define CastXxxDescriptor(x) ((descr_xxx_t *)(x))
+
+/* 0x82 vps_descriptor TODO */
+typedef struct descr_vps {
+ u_char descriptor_tag /*:8*/;
+ u_char descriptor_length /*:8*/;
+ u_char hour[2] /*:8*/;
+ u_char delimiter_time /*:8 ':'*/;
+ u_char minute[2] /*:8*/;
+ u_char day[2] /*:8*/;
+ u_char delimiter_date /*:8 '.'*/;
+ u_char month[2] /*:8*/;
+ u_char delimiter /*:8 '#'*/;
+ u_char number[2] /*:8*/;
+} descr_vps_t;
+#define DESCR_VPS_LEN sizeof (descr_vps_t)
+#define CastVpsDescriptor(x) ((descr_vps_t *)(x))
diff --git a/p2pvr/scanner/tv_grab_dvb.h b/p2pvr/scanner/tv_grab_dvb.h
new file mode 100644
index 0000000..460b7f6
--- /dev/null
+++ b/p2pvr/scanner/tv_grab_dvb.h
@@ -0,0 +1,32 @@
+#ifndef __tv_grab_dvd
+#define __tv_grab_dvd
+
+#include <stdint.h>
+#include <stdlib.h>
+
+/* lookup.c */
+union lookup_key {
+ int i;
+ char c[4];
+};
+struct lookup_table {
+ union lookup_key u;
+ const char *desc;
+};
+
+extern const char *lookup(const struct lookup_table *l, int id);
+extern int load_lookup(struct lookup_table **l, const char *file);
+
+/* dvb_info_tables.c */
+extern const struct lookup_table description_table[];
+extern const struct lookup_table aspect_table[];
+extern const struct lookup_table audio_table[];
+extern const struct lookup_table crid_type_table[];
+
+/* langidents.c */
+extern const struct lookup_table languageid_table[];
+
+/* crc32.c */
+extern uint32_t _dvb_crc32(const uint8_t *data, size_t len);
+
+#endif