diff options
| author | randomdan <randomdan@localhost> | 2011-03-17 10:44:20 +0000 | 
|---|---|---|
| committer | randomdan <randomdan@localhost> | 2011-03-17 10:44:20 +0000 | 
| commit | 51711b72590ebe30f7b4a6172b5c36ccff559d6c (patch) | |
| tree | baa460eba6e535e4ca4082ce3dd082a8d4ceb5f2 | |
| parent | Finally convert ytfs to use boost stuff (untested, but it does build) (diff) | |
| download | p2pvr-51711b72590ebe30f7b4a6172b5c36ccff559d6c.tar.bz2 p2pvr-51711b72590ebe30f7b4a6172b5c36ccff559d6c.tar.xz p2pvr-51711b72590ebe30f7b4a6172b5c36ccff559d6c.zip  | |
Work to date on p2pvr - basic EIT scanner
| -rw-r--r-- | p2pvr/Jamfile.jam | 0 | ||||
| -rw-r--r-- | p2pvr/cron/importSchedume.xml | 55 | ||||
| -rw-r--r-- | p2pvr/cron/sched.xml | 29 | ||||
| -rw-r--r-- | p2pvr/datasources/postgres.xml | 8 | ||||
| -rw-r--r-- | p2pvr/scanner/Jamfile.jam | 18 | ||||
| -rw-r--r-- | p2pvr/scanner/crc32.cpp | 61 | ||||
| -rw-r--r-- | p2pvr/scanner/dvb_info_tables.c | 312 | ||||
| -rw-r--r-- | p2pvr/scanner/ice_scan.cpp | 343 | ||||
| -rw-r--r-- | p2pvr/scanner/icescan.cpp | 0 | ||||
| -rw-r--r-- | p2pvr/scanner/langidents.c | 211 | ||||
| -rw-r--r-- | p2pvr/scanner/lookup.cpp | 52 | ||||
| -rw-r--r-- | p2pvr/scanner/p2scan.cpp | 761 | ||||
| -rw-r--r-- | p2pvr/scanner/scanner.ice | 7 | ||||
| -rw-r--r-- | p2pvr/scanner/si_tables.h | 1625 | ||||
| -rw-r--r-- | p2pvr/scanner/tv_grab_dvb.h | 32 | 
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 & 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 & 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  | 
