diff options
Diffstat (limited to 'PLUGINS/epgdata')
-rw-r--r-- | PLUGINS/epgdata/Makefile | 52 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra | 176 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/epgd.conf | 10 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/epgdata-category.xml | 143 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/epgdata-genre.xml | 507 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl | 8 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/epgdata-utf-8.xsl | 8 | ||||
-rw-r--r-- | PLUGINS/epgdata/configs/epgdata.xsl | 208 | ||||
-rw-r--r-- | PLUGINS/epgdata/epgdata.c | 760 | ||||
-rw-r--r-- | PLUGINS/epgdata/epgdata.h | 52 | ||||
-rwxr-xr-x | PLUGINS/epgdata/scripts/getepgdataids | 37 | ||||
-rwxr-xr-x | PLUGINS/epgdata/scripts/getincludes | 6 |
12 files changed, 1967 insertions, 0 deletions
diff --git a/PLUGINS/epgdata/Makefile b/PLUGINS/epgdata/Makefile new file mode 100644 index 0000000..837c3c1 --- /dev/null +++ b/PLUGINS/epgdata/Makefile @@ -0,0 +1,52 @@ +# +# Makefile +# +# See the README file for copyright information and how to reach the author. +# +# + +EPGD_SRC ?= ../.. + +include $(EPGD_SRC)/Make.config + +PLUGIN = epgdata + +SOFILE = libepgd-epgdata.so +OBJS = epgdata.o + +CFLAGS += -I$(EPGD_SRC) + +all: $(SOFILE) + +$(SOFILE): $(OBJS) + $(CC) $(CFLAGS) -shared $(OBJS) $(LIBS) -o $@ + +install: $(SOFILE) install-config + install -D $(SOFILE) $(_PLGDEST)/ + +clean: + @-rm -f $(OBJS) core* *~ *.so + +install-config: + if ! test -d $(CONFDEST); then \ + mkdir -p $(CONFDEST); \ + chmod a+rx $(CONFDEST); \ + fi + if ! test -f $(CONFDEST)/channelmap.conf-epgdata-astra; then \ + install --mode=644 -D ./configs/channelmap.conf-epgdata-astra $(CONFDEST)/; \ + fi + for i in $(wildcard ./configs/epgdata*.xml) $(wildcard ./configs/*.xsl); do\ + if ! test -f "$(CONFDEST)/`basename $$i`"; then\ + install --mode=644 -D "$$i" $(CONFDEST)/; \ + fi;\ + done; + if ! grep -q "^epgdata" $(CONFDEST)/epgd.conf; then \ + cat ./configs/epgd.conf >> $(CONFDEST)/epgd.conf; \ + fi + + +#*************************************************************************** +# dependencies +#*************************************************************************** + +epgdata.o : epgdata.c epgdata.h diff --git a/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra b/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra new file mode 100644 index 0000000..7a3af70 --- /dev/null +++ b/PLUGINS/epgdata/configs/channelmap.conf-epgdata-astra @@ -0,0 +1,176 @@ +epgdata:71 = S19.2E-1-1019-10301 // Das Erste HD +epgdata:37 = S19.2E-1-1011-11110 // ZDF HD +epgdata:194 = S19.2E-1-1025-10331 // PHOENIX HD +epgdata:56 = S19.2E-1-1010-11150 // 3sat HD +epgdata:58 = S19.2E-1-1019-10302 // arte HD +epgdata:146 = S19.2E-1-1201-28396 // Einsfestival HD +epgdata:57 = S19.2E-1-1010-11160 // KiKA HD +epgdata:275 = S19.2E-1-1011-11140 // zdf.kultur HD +epgdata:276 = S19.2E-1-1010-11170 // ZDFinfo HD +epgdata:659 = S19.2E-1-1011-11130 // zdf_neo HD + +epgdata:71 = S19.2E-1-1101-28106 // Das Erste +epgdata:37 = S19.2E-1-1079-28006 // ZDF +epgdata:194 = S19.2E-1-1051-28725 // PHOENIX +epgdata:56 = S19.2E-1-1079-28007 // 3sat +epgdata:58 = S19.2E-1-1051-28724 // arte +epgdata:146 = S19.2E-1-1051-28722 // Einsfestival +epgdata:475 = S19.2E-1-1051-28723 // EinsPlus +epgdata:57 = S19.2E-1-1079-28008 // KiKA +epgdata:100 = S19.2E-1-1051-28721 // tagesschau24 +epgdata:275 = S19.2E-1-1079-28016 // zdf.kultur +epgdata:276 = S19.2E-1-1079-28011 // ZDFinfo +epgdata:659 = S19.2E-1-1079-28014 // zdf_neo + +epgdata:38 = S19.2E-1-1089-12003 // RTL Television +epgdata:41 = S19.2E-1-1089-12020 // RTL2 +epgdata:43 = S19.2E-1-1089-12040 // SUPER RTL +epgdata:763 = S19.2E-1-1089-12061 // RTLNITRO +epgdata:39 = S19.2E-1-1107-17500 // SAT.1 +epgdata:774 = S19.2E-1-1107-17504 // SAT.1 Gold +epgdata:40 = S19.2E-1-1107-17501 // ProSieben +epgdata:44 = S19.2E-1-1107-17502 // kabel eins +epgdata:507 = S19.2E-133-33-63 // DMAX +epgdata:694 = S19.2E-133-5-776 // SIXX +epgdata:42 = S19.2E-1-1089-12060 // VOX +epgdata:660 = S19.2E-1-1115-13110 // ServusTV Deutschland +epgdata:64 = S19.2E-133-33-9001 // SPORT1 +epgdata:65 = S19.2E-1-1091-31200 // Eurosport Deutschland +epgdata:66 = S19.2E-1-1089-12090 // n-tv +epgdata:175 = S19.2E-1-1107-17503 // N24 +epgdata:391 = S19.2E-1-1115-13102 // GoTV +// = S19.2E-133-7-65 // DELUXE MUSIC +// = S19.2E-1-1078-28676 // VIVA Germany +// = S19.2E-1-1021-4600 // a.tv + +epgdata:471 = S19.2E-133-1-42 // 13th Street +epgdata:123 = S19.2E-133-17-21 // Beate-Uhse.TV +epgdata:133 = S19.2E-133-17-24 // Classica +epgdata:138 = S19.2E-133-4-14 // Discovery Channel +epgdata:139 = S19.2E-133-17-34 // Disney Channel +epgdata:460 = S19.2E-133-17-26 // Disney Junior +epgdata:657 = S19.2E-133-17-28 // Disney XD +// = S19.2E-133-1-16 // Fox Serie +epgdata:152 = S19.2E-133-17-518 // Goldstar TV +epgdata:154 = S19.2E-133-17-22 // Heimatkanal +epgdata:160 = S19.2E-133-17-19 // Junior +epgdata:627 = S19.2E-133-1-168 // Motorvision TV +epgdata:626 = S19.2E-133-4-12 // NatGeo Wild +epgdata:453 = S19.2E-133-4-13 // National Geographic Channel +epgdata:527 = S19.2E-133-1-27 // RTL Crime +epgdata:529 = S19.2E-133-1-29 // RTL Passion +epgdata:701 = S19.2E-133-10-117 // Sky 3D +epgdata:615 = S19.2E-133-1-23 // Sky Krimi +epgdata:625 = S19.2E-133-4-52 // Spiegel Geschichte +epgdata:472 = S19.2E-133-17-36 // Syfy +epgdata:590 = S19.2E-133-1-50 // TNT Serie + +// = S19.2E-133-13-127 // 13th Street HD +// = S19.2E-133-10-125 // AXN HD +epgdata:490 = S19.2E-133-6-130 // Discovery HD +// = S19.2E-133-11-116 // Disney Channel HD +// = S19.2E-133-14-128 // E! Entertainm. HD +// = S19.2E-133-10-124 // Fox HD +epgdata:632 = S19.2E-133-11-113 // History HD +// = S19.2E-133-6-118 // Nat Geo Wild HD +// = S19.2E-133-13-112 // NatGeo HD +epgdata:762 = S19.2E-133-12-108 // Sky Sport News HD +// = S19.2E-133-12-126 // Syfy HD +// = S19.2E-133-11-123 // TNT Serie HD +// = S19.2E-133-14-101 // Universal HD +epgdata:10058 = S19.2E-133-10-106 // Sky Action HDD +epgdata:10059 = S19.2E-133-12-107 // Sky Hits HD + +epgdata:539 = S19.2E-1-1037-5253 // Animax +// = S19.2E-133-15-37 // AXN Action +epgdata:536 = S19.2E-133-15-57 // Biography Channel +epgdata:127 = S19.2E-133-15-56 // Bloomberg TV +epgdata:531 = S19.2E-133-15-39 // Cartoon Network (S) +// = S19.2E-1-1115-13105 // ESPN America (S) +epgdata:452 = S19.2E-133-15-58 // History +epgdata:492 = S19.2E-1-1107-17506 // kabel eins classics +epgdata:450 = S19.2E-133-15-33 // Kinowelt TV +// = S19.2E-133-15-38 // Romance TV +epgdata:528 = S19.2E-1-1089-12030 // RTL Living +epgdata:766 = S19.2E-1-1015-4701 // SAT.1 emotions +// = S19.2E-1-1107-17505 // ProSieben MAXX +epgdata:633 = S19.2E-133-15-35 // TNT Film (TCM) + +epgdata:631 = S19.2E-133-13-111 // Disney Cinemagic HD +// = S19.2E-133-12-115 // MGM HD +// = S19.2E-133-10-106 // Sky Action HD +epgdata:767 = S19.2E-133-13-110 // Sky Atlantic HD +epgdata:629 = S19.2E-133-6-131 // Sky Cinema HD +// = S19.2E-133-12-107 // Sky Hits HD + +epgdata:610 = S19.2E-133-2-10 // Sky Cinema +epgdata:611 = S19.2E-133-2-11 // Sky Cinema +1 +epgdata:612 = S19.2E-133-2-43 // Sky Cinema +24 +epgdata:630 = S19.2E-133-3-25 // Disney Cinemagic +epgdata:1196 = S19.2E-133-3-515 // MGM +epgdata:613 = S19.2E-133-2-9 // Sky Action +epgdata:617 = S19.2E-133-2-8 // Sky Comedy +epgdata:616 = S19.2E-133-2-20 // Sky Emotion +epgdata:618 = S19.2E-133-3-41 // Sky Hits +epgdata:614 = S19.2E-133-3-516 // Sky Nostalgie +// = S19.2E-133-3-17 // Sky Sport News + +epgdata:784 = S19.2E-133-14-119 // Sport1 US HD +epgdata:621 = S19.2E-133-6-129 // Sky Sport HD 1 +epgdata:697 = S19.2E-133-13-114 // Sky Sport HD 2 +// = S19.2E-133-6-268 // Sky Sport HD 3 +// = S19.2E-133-11-122 // Sport1+ HD +epgdata:619 = S19.2E-133-4-221 // Sky Sport 1 +epgdata:620 = S19.2E-133-4-222 // Sky Sport 2 +epgdata:564 = S19.2E-133-15-59 // sportdigital + +// = S19.2E-133-11-132 // Eurosport HD +// = S19.2E-133-14-109 // Eurosport 2 HD + +epgdata:54 = S19.2E-1-1117-13001 // ORF1 +epgdata:55 = S19.2E-1-1117-13002 // ORF2 +epgdata:757 = S19.2E-1-1115-13101 // ORF III +epgdata:759 = S19.2E-1-1003-13221 // ORF SPORT+ + +epgdata:115 = S19.2E-1-1117-13012 // ATV +epgdata:761 = S19.2E-1-1003-13223 // ATV2 +// = S19.2E-1-1082-20007 // PULS 4 Austria +epgdata:622 = S19.2E-133-1-30 // Sky Sport Austria +// = S19.2E-1-1115-13104 // LT1-OOE +// = S19.2E-1-1115-13111 // ServusTV Oesterreich + +// epgdata:10100 // Sat.1 Emotions HD +epgdata:104 = S19.2E-1-1093-28487 // BR alpha + +// epgdata:1183 = // Animal Planet +// epgdata:211 = // Rhein-Neckar-Fernsehen +// epgdata:266 = // VIVA +epgdata:277 = S19.2E-133-33-51 // Tele 5 +// epgdata:455 = // Fashion TV +// epgdata:465 = // MTV Dance +// epgdata:466 = // MTV Hits UK +// epgdata:468 = // AXN +// epgdata:469 = // Extreme Sports Channel +// epgdata:46 = // WDR +// epgdata:473 = // ESPN Classic +// epgdata:47 = // NDR +epgdata:486 = S19.2E-133-5-1793 // Das VIERTE +// epgdata:48 = // MDR +// epgdata:49 = // HR +// epgdata:504 = // Eurosport 2 +// epgdata:50 = // SWR +// epgdata:51 = // BR +// epgdata:52 = // RBB +// epgdata:537 = // Anixe HD +// epgdata:590 = // TNT Serie + +// epgdata:623 = // Sky Bundesliga +// epgdata:624 = // National Geographic Channel HD +// epgdata:628 = // Sky Select +// epgdata:698 = // SPORT1+ +// epgdata:743 = // Sky Sport HD Extra +// epgdata:756 = // Spiegel TV Wissen +// epgdata:758 = // E! Entertainment + + + diff --git a/PLUGINS/epgdata/configs/epgd.conf b/PLUGINS/epgdata/configs/epgd.conf new file mode 100644 index 0000000..e5c2073 --- /dev/null +++ b/PLUGINS/epgdata/configs/epgd.conf @@ -0,0 +1,10 @@ + +# --------------- +# epgdata plugin +# --------------- + +epgdata.url = http://www.epgdata.com +epgdata.pin = insert-your-pin-here + +# Download timeout in seconds (default 180) +#epgdata.timeout = 180 diff --git a/PLUGINS/epgdata/configs/epgdata-category.xml b/PLUGINS/epgdata/configs/epgdata-category.xml new file mode 100644 index 0000000..c047314 --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-category.xml @@ -0,0 +1,143 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!DOCTYPE category [ +<!ELEMENT category (data)+> +<!ELEMENT data (ca0,ca1,ca2)> +<!ENTITY nbsp " " > +<!ENTITY iexcl "¡" > +<!ENTITY cent "¢" > +<!ENTITY pound "£" > +<!ENTITY curren "¤" > +<!ENTITY yen "¥" > +<!ENTITY brvbar "¦" > +<!ENTITY sect "§" > +<!ENTITY uml "¨" > +<!ENTITY copy "©" > +<!ENTITY ordf "ª" > +<!ENTITY laquo "«" > +<!ENTITY not "¬" > +<!ENTITY shy "­" > +<!ENTITY reg "®" > +<!ENTITY macr "¯" > +<!ENTITY deg "°" > +<!ENTITY plusmn "±" > +<!ENTITY sup2 "²" > +<!ENTITY sup3 "³" > +<!ENTITY acute "´" > +<!ENTITY micro "µ" > +<!ENTITY para "¶" > +<!ENTITY middot "·" > +<!ENTITY cedil "¸" > +<!ENTITY sup1 "¹" > +<!ENTITY ordm "º" > +<!ENTITY raquo "»" > +<!ENTITY frac14 "¼" > +<!ENTITY frac12 "½" > +<!ENTITY frac34 "¾" > +<!ENTITY iquest "¿" > +<!ENTITY Agrave "À" > +<!ENTITY Aacute "Á" > +<!ENTITY Acirc "Â" > +<!ENTITY Atilde "Ã" > +<!ENTITY Auml "Ä" > +<!ENTITY Aring "Å" > +<!ENTITY AElig "Æ" > +<!ENTITY Ccedil "Ç" > +<!ENTITY Egrave "È" > +<!ENTITY Eacute "É" > +<!ENTITY Ecirc "Ê" > +<!ENTITY Euml "Ë" > +<!ENTITY Igrave "Ì" > +<!ENTITY Iacute "Í" > +<!ENTITY Icirc "Î" > +<!ENTITY Iuml "Ï" > +<!ENTITY ETH "Ð" > +<!ENTITY Ntilde "Ñ" > +<!ENTITY Ograve "Ò" > +<!ENTITY Oacute "Ó" > +<!ENTITY Ocirc "Ô" > +<!ENTITY Otilde "Õ" > +<!ENTITY Ouml "Ö" > +<!ENTITY times "×" > +<!ENTITY Oslash "Ø" > +<!ENTITY Ugrave "Ù" > +<!ENTITY Uacute "Ú" > +<!ENTITY Ucirc "Û" > +<!ENTITY Uuml "Ü" > +<!ENTITY Yacute "Ý" > +<!ENTITY THORN "Þ" > +<!ENTITY szlig "ß" > +<!ENTITY agrave "à" > +<!ENTITY aacute "á" > +<!ENTITY acirc "â" > +<!ENTITY atilde "ã" > +<!ENTITY auml "ä" > +<!ENTITY aring "å" > +<!ENTITY aelig "æ" > +<!ENTITY ccedil "ç" > +<!ENTITY egrave "è" > +<!ENTITY eacute "é" > +<!ENTITY ecirc "ê" > +<!ENTITY euml "ë" > +<!ENTITY igrave "ì" > +<!ENTITY iacute "í" > +<!ENTITY icirc "î" > +<!ENTITY iuml "ï" > +<!ENTITY eth "ð" > +<!ENTITY ntilde "ñ" > +<!ENTITY ograve "ò" > +<!ENTITY oacute "ó" > +<!ENTITY ocirc "ô" > +<!ENTITY otilde "õ" > +<!ENTITY ouml "ö" > +<!ENTITY divide "÷" > +<!ENTITY oslash "ø" > +<!ENTITY ugrave "ù" > +<!ENTITY uacute "ú" > +<!ENTITY ucirc "û" > +<!ENTITY uuml "ü" > +<!ENTITY yacute "ý" > +<!ENTITY thorn "þ" > +<!ENTITY yuml "ÿ" > +<!ENTITY quot """ > +<!ELEMENT ca0 (#PCDATA)> <!-- category_de --> +<!ELEMENT ca1 (#PCDATA)> <!-- category_long_de --> +<!ELEMENT ca2 (#PCDATA)> <!-- category_short_de --> +]> + +<category> + <data> + <ca0>100</ca0> + <ca1>Spielfilm</ca1> + <ca2>Spielfilm</ca2> + </data> + <data> + <ca0>200</ca0> + <ca1>Serie</ca1> + <ca2>Serie</ca2> + </data> + <data> + <ca0>300</ca0> + <ca1>Sport</ca1> + <ca2>Sport</ca2> + </data> + <data> + <ca0>400</ca0> + <ca1>Show</ca1> + <ca2>Show</ca2> + </data> + <data> + <ca0>500</ca0> + <ca1>Information</ca1> + <ca2>Information</ca2> + </data> + <data> + <ca0>600</ca0> + <ca1>Musik</ca1> + <ca2>Musik</ca2> + </data> + <data> + <ca0>700</ca0> + <ca1>Kinder</ca1> + <ca2>Kinder</ca2> + </data> +</category>
\ No newline at end of file diff --git a/PLUGINS/epgdata/configs/epgdata-genre.xml b/PLUGINS/epgdata/configs/epgdata-genre.xml new file mode 100644 index 0000000..ff63eaf --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-genre.xml @@ -0,0 +1,507 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!DOCTYPE genre [ +<!ELEMENT genre (data)+> +<!ELEMENT data (g0,g1)> +<!ENTITY nbsp " " > +<!ENTITY iexcl "¡" > +<!ENTITY cent "¢" > +<!ENTITY pound "£" > +<!ENTITY curren "¤" > +<!ENTITY yen "¥" > +<!ENTITY brvbar "¦" > +<!ENTITY sect "§" > +<!ENTITY uml "¨" > +<!ENTITY copy "©" > +<!ENTITY ordf "ª" > +<!ENTITY laquo "«" > +<!ENTITY not "¬" > +<!ENTITY shy "­" > +<!ENTITY reg "®" > +<!ENTITY macr "¯" > +<!ENTITY deg "°" > +<!ENTITY plusmn "±" > +<!ENTITY sup2 "²" > +<!ENTITY sup3 "³" > +<!ENTITY acute "´" > +<!ENTITY micro "µ" > +<!ENTITY para "¶" > +<!ENTITY middot "·" > +<!ENTITY cedil "¸" > +<!ENTITY sup1 "¹" > +<!ENTITY ordm "º" > +<!ENTITY raquo "»" > +<!ENTITY frac14 "¼" > +<!ENTITY frac12 "½" > +<!ENTITY frac34 "¾" > +<!ENTITY iquest "¿" > +<!ENTITY Agrave "À" > +<!ENTITY Aacute "Á" > +<!ENTITY Acirc "Â" > +<!ENTITY Atilde "Ã" > +<!ENTITY Auml "Ä" > +<!ENTITY Aring "Å" > +<!ENTITY AElig "Æ" > +<!ENTITY Ccedil "Ç" > +<!ENTITY Egrave "È" > +<!ENTITY Eacute "É" > +<!ENTITY Ecirc "Ê" > +<!ENTITY Euml "Ë" > +<!ENTITY Igrave "Ì" > +<!ENTITY Iacute "Í" > +<!ENTITY Icirc "Î" > +<!ENTITY Iuml "Ï" > +<!ENTITY ETH "Ð" > +<!ENTITY Ntilde "Ñ" > +<!ENTITY Ograve "Ò" > +<!ENTITY Oacute "Ó" > +<!ENTITY Ocirc "Ô" > +<!ENTITY Otilde "Õ" > +<!ENTITY Ouml "Ö" > +<!ENTITY times "×" > +<!ENTITY Oslash "Ø" > +<!ENTITY Ugrave "Ù" > +<!ENTITY Uacute "Ú" > +<!ENTITY Ucirc "Û" > +<!ENTITY Uuml "Ü" > +<!ENTITY Yacute "Ý" > +<!ENTITY THORN "Þ" > +<!ENTITY szlig "ß" > +<!ENTITY agrave "à" > +<!ENTITY aacute "á" > +<!ENTITY acirc "â" > +<!ENTITY atilde "ã" > +<!ENTITY auml "ä" > +<!ENTITY aring "å" > +<!ENTITY aelig "æ" > +<!ENTITY ccedil "ç" > +<!ENTITY egrave "è" > +<!ENTITY eacute "é" > +<!ENTITY ecirc "ê" > +<!ENTITY euml "ë" > +<!ENTITY igrave "ì" > +<!ENTITY iacute "í" > +<!ENTITY icirc "î" > +<!ENTITY iuml "ï" > +<!ENTITY eth "ð" > +<!ENTITY ntilde "ñ" > +<!ENTITY ograve "ò" > +<!ENTITY oacute "ó" > +<!ENTITY ocirc "ô" > +<!ENTITY otilde "õ" > +<!ENTITY ouml "ö" > +<!ENTITY divide "÷" > +<!ENTITY oslash "ø" > +<!ENTITY ugrave "ù" > +<!ENTITY uacute "ú" > +<!ENTITY ucirc "û" > +<!ENTITY uuml "ü" > +<!ENTITY yacute "ý" > +<!ENTITY thorn "þ" > +<!ENTITY yuml "ÿ" > +<!ENTITY quot """ > +<!ELEMENT g0 (#PCDATA)> <!-- genreid --> +<!ELEMENT g1 (#PCDATA)> <!-- genre --> +]> + +<genre> + <data> + <g0>101</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>102</g0> + <g1>Abenteuer</g1> + </data> + <data> + <g0>103</g0> + <g1>Action</g1> + </data> + <data> + <g0>104</g0> + <g1>Dokumentarfilm</g1> + </data> + <data> + <g0>105</g0> + <g1>Drama</g1> + </data> + <data> + <g0>106</g0> + <g1>Erotik</g1> + </data> + <data> + <g0>108</g0> + <g1>Fantasy</g1> + </data> + <data> + <g0>109</g0> + <g1>Heimat</g1> + </data> + <data> + <g0>110</g0> + <g1>Humor</g1> + </data> + <data> + <g0>112</g0> + <g1>Krimi</g1> + </data> + <data> + <g0>113</g0> + <g1>Kultur</g1> + </data> + <data> + <g0>114</g0> + <g1>Kurzfilm</g1> + </data> + <data> + <g0>115</g0> + <g1>Musik</g1> + </data> + <data> + <g0>116</g0> + <g1>Mystery + Horror</g1> + </data> + <data> + <g0>117</g0> + <g1>Romantik/Liebe</g1> + </data> + <data> + <g0>119</g0> + <g1>Science Fiction</g1> + </data> + <data> + <g0>121</g0> + <g1>Thriller</g1> + </data> + <data> + <g0>122</g0> + <g1>Western</g1> + </data> + <data> + <g0>123</g0> + <g1>Zeichentrick</g1> + </data> + <data> + <g0>201</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>202</g0> + <g1>Abenteuer</g1> + </data> + <data> + <g0>203</g0> + <g1>Action</g1> + </data> + <data> + <g0>205</g0> + <g1>Drama</g1> + </data> + <data> + <g0>206</g0> + <g1>Erotik</g1> + </data> + <data> + <g0>207</g0> + <g1>Familie</g1> + </data> + <data> + <g0>208</g0> + <g1>Fantasy</g1> + </data> + <data> + <g0>210</g0> + <g1>Humor</g1> + </data> + <data> + <g0>211</g0> + <g1>Krankenhaus</g1> + </data> + <data> + <g0>212</g0> + <g1>Krimi</g1> + </data> + <data> + <g0>214</g0> + <g1>Jugend</g1> + </data> + <data> + <g0>216</g0> + <g1>Mystery + Horror</g1> + </data> + <data> + <g0>218</g0> + <g1>Reality</g1> + </data> + <data> + <g0>219</g0> + <g1>Science Fiction</g1> + </data> + <data> + <g0>220</g0> + <g1>Soap</g1> + </data> + <data> + <g0>221</g0> + <g1>Thriller</g1> + </data> + <data> + <g0>222</g0> + <g1>Western</g1> + </data> + <data> + <g0>223</g0> + <g1>Zeichentrick</g1> + </data> + <data> + <g0>301</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>331</g0> + <g1>Boxen</g1> + </data> + <data> + <g0>332</g0> + <g1>Eishockey</g1> + </data> + <data> + <g0>334</g0> + <g1>Fußball</g1> + </data> + <data> + <g0>335</g0> + <g1>Olympia</g1> + </data> + <data> + <g0>336</g0> + <g1>Golf</g1> + </data> + <data> + <g0>337</g0> + <g1>Gymnastik</g1> + </data> + <data> + <g0>338</g0> + <g1>Handball</g1> + </data> + <data> + <g0>339</g0> + <g1>Motorsport</g1> + </data> + <data> + <g0>340</g0> + <g1>Radsport</g1> + </data> + <data> + <g0>341</g0> + <g1>Tennis</g1> + </data> + <data> + <g0>342</g0> + <g1>Wassersport</g1> + </data> + <data> + <g0>343</g0> + <g1>Wintersport</g1> + </data> + <data> + <g0>344</g0> + <g1>US-Sport</g1> + </data> + <data> + <g0>345</g0> + <g1>Leichtathletik</g1> + </data> + <data> + <g0>346</g0> + <g1>Volleyball</g1> + </data> + <data> + <g0>347</g0> + <g1>Extremsport</g1> + </data> + <data> + <g0>348</g0> + <g1>Reportagen</g1> + </data> + <data> + <g0>401</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>406</g0> + <g1>Erotik</g1> + </data> + <data> + <g0>418</g0> + <g1>Reality</g1> + </data> + <data> + <g0>450</g0> + <g1>Comedy</g1> + </data> + <data> + <g0>451</g0> + <g1>Familien-Show</g1> + </data> + <data> + <g0>452</g0> + <g1>Spielshows</g1> + </data> + <data> + <g0>453</g0> + <g1>Talkshows</g1> + </data> + <data> + <g0>454</g0> + <g1>Gerichtsshow</g1> + </data> + <data> + <g0>455</g0> + <g1>Homeshopping</g1> + </data> + <data> + <g0>456</g0> + <g1>Kochshow</g1> + </data> + <data> + <g0>457</g0> + <g1>Heimwerken</g1> + </data> + <data> + <g0>501</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>560</g0> + <g1>Geschichte</g1> + </data> + <data> + <g0>561</g0> + <g1>Magazin</g1> + </data> + <data> + <g0>564</g0> + <g1>Gesundheit</g1> + </data> + <data> + <g0>565</g0> + <g1>Motor + Verkehr</g1> + </data> + <data> + <g0>566</g0> + <g1>Nachrichten</g1> + </data> + <data> + <g0>567</g0> + <g1>Natur</g1> + </data> + <data> + <g0>568</g0> + <g1>Politik</g1> + </data> + <data> + <g0>569</g0> + <g1>Ratgeber</g1> + </data> + <data> + <g0>570</g0> + <g1>Reise</g1> + </data> + <data> + <g0>571</g0> + <g1>Wirtschaft</g1> + </data> + <data> + <g0>572</g0> + <g1>Wissen</g1> + </data> + <data> + <g0>573</g0> + <g1>Dokumentation</g1> + </data> + <data> + <g0>601</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>680</g0> + <g1>Jazz</g1> + </data> + <data> + <g0>681</g0> + <g1>Klassik</g1> + </data> + <data> + <g0>682</g0> + <g1>Musical</g1> + </data> + <data> + <g0>683</g0> + <g1>Rock</g1> + </data> + <data> + <g0>684</g0> + <g1>Volksmusik</g1> + </data> + <data> + <g0>685</g0> + <g1>Alternative</g1> + </data> + <data> + <g0>686</g0> + <g1>Pop</g1> + </data> + <data> + <g0>687</g0> + <g1>Clips</g1> + </data> + <data> + <g0>688</g0> + <g1>Show</g1> + </data> + <data> + <g0>689</g0> + <g1>Interview</g1> + </data> + <data> + <g0>690</g0> + <g1>Theater</g1> + </data> + <data> + <g0>691</g0> + <g1>Kino</g1> + </data> + <data> + <g0>692</g0> + <g1>Kultur</g1> + </data> + <data> + <g0>701</g0> + <g1>Verschiedenes</g1> + </data> + <data> + <g0>790</g0> + <g1>Filme</g1> + </data> + <data> + <g0>791</g0> + <g1>Nachrichten</g1> + </data> + <data> + <g0>792</g0> + <g1>Serien</g1> + </data> + <data> + <g0>793</g0> + <g1>Shows</g1> + </data> + <data> + <g0>795</g0> + <g1>Zeichentrick</g1> + </data> + <data> + <g0>796</g0> + <g1>Anime</g1> + </data> +</genre>
\ No newline at end of file diff --git a/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl b/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl new file mode 100644 index 0000000..24024ac --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-iso-8859-1.xsl @@ -0,0 +1,8 @@ +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/TR/xhtml1/strict"> +<xsl:output method="xml" omit-xml-declaration="no" encoding='iso-8859-15'/> + +<xsl:include href="epgdata.xsl" /> + +</xsl:stylesheet> diff --git a/PLUGINS/epgdata/configs/epgdata-utf-8.xsl b/PLUGINS/epgdata/configs/epgdata-utf-8.xsl new file mode 100644 index 0000000..96a7b92 --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata-utf-8.xsl @@ -0,0 +1,8 @@ +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/TR/xhtml1/strict"> +<xsl:output method="xml" omit-xml-declaration="no" encoding='utf-8'/> + +<xsl:include href="epgdata.xsl" /> + +</xsl:stylesheet> diff --git a/PLUGINS/epgdata/configs/epgdata.xsl b/PLUGINS/epgdata/configs/epgdata.xsl new file mode 100644 index 0000000..d5795ee --- /dev/null +++ b/PLUGINS/epgdata/configs/epgdata.xsl @@ -0,0 +1,208 @@ +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns="http://www.w3.org/TR/xhtml1/strict" + xmlns:exsl="http://exslt.org/common" + xmlns:date="http://exslt.org/dates-and-times" + xmlns:str="http://exslt.org/strings"> + + +<xsl:template match="/"> + + <events> + + <xsl:for-each select="//data"> + + <event> + <xsl:attribute name="id"><xsl:value-of select="d0"/></xsl:attribute> + <xsl:attribute name="provid"><xsl:value-of select="d2"/></xsl:attribute> + + <starttime> + <xsl:call-template name="date2UTC"> + <xsl:with-param name="date" select="str:replace(d4,' ','T')"/> + </xsl:call-template> + </starttime> + + <duration><xsl:value-of select="d7*60"/></duration> + + <xsl:if test="string-length(d8)"> + <vps> + <xsl:call-template name="date2UTC"> + <xsl:with-param name="date" select="concat(substring-before(d4,' '),'T',d8,':00')"/> + </xsl:call-template> + </vps> + </xsl:if> + + <title><xsl:value-of select="d19"/></title> + <xsl:if test="string-length(d20)"><shorttext><xsl:value-of select="d20"/></shorttext></xsl:if> + + <xsl:choose> + <xsl:when test="d19='Tatort'"> + <category><xsl:text>Serie</xsl:text></category> + </xsl:when> + <xsl:otherwise> + <xsl:if test="d10 > 0"><category><xsl:call-template name="getCATEGORY"><xsl:with-param name="categoryid" select="d10"/></xsl:call-template></category></xsl:if> + </xsl:otherwise> + </xsl:choose> + + <xsl:if test="string-length(d25)"><genre><xsl:call-template name="getGenre"><xsl:with-param name="genreid" select="d25"/></xsl:call-template></genre></xsl:if> + + <xsl:if test="string-length(d16)"><parentalrating><xsl:value-of select="d16"/></parentalrating></xsl:if> + + <xsl:if test="string-length(d21)"><longdescription><xsl:value-of select="d21"/></longdescription></xsl:if> + + <xsl:if test="string-length(d1)"><movieid><xsl:value-of select="d1"/></movieid></xsl:if> + + <xsl:variable name="TIPP"> + <xsl:if test="d18 = 1"><xsl:text>TagesTipp</xsl:text></xsl:if> + <xsl:if test="d18 = 2"><xsl:text>TopTipp</xsl:text></xsl:if> + </xsl:variable> + <xsl:if test="d18 > 0"><tipp><xsl:value-of select="$TIPP"/></tipp></xsl:if> + + <xsl:if test="string-length(d30) and d30 > 0"> + <xsl:choose> + <xsl:when test="d30 > 1"><numrating><xsl:value-of select="d30 -1"/></numrating></xsl:when> + <xsl:otherwise><numrating><xsl:value-of select="d30"/></numrating></xsl:otherwise> + </xsl:choose> + </xsl:if> + + <xsl:choose> + <xsl:when test="d30 = 5"> + <txtrating>Sehr empfehlenswert</txtrating> + </xsl:when> + <xsl:when test="d30 = 4"> + <txtrating>Empfehlenswert</txtrating> + </xsl:when> + <xsl:when test="d30 = 3"> + <txtrating>Eher durchschnittlich</txtrating> + </xsl:when> + <xsl:when test="d30 = 2 or d30 = 1"> + <txtrating>Eher uninteressant</txtrating> + </xsl:when> + </xsl:choose> + +<!-- + <xsl:if test="d30 > 0"><rating><xsl:call-template name="getRATING"><xsl:with-param name="ratingid" select="d30"/></xsl:call-template></rating></xsl:if> +--> + <xsl:if test="string-length(d32)"><country><xsl:value-of select="str:replace(d32,'|','/')"/></country></xsl:if> + <xsl:if test="string-length(d33)"><year><xsl:value-of select="d33"/></year></xsl:if> + <xsl:if test="string-length(d34)"><moderator><xsl:value-of select="str:replace(d34,'|',', ')"/></moderator></xsl:if> + <xsl:if test="string-length(d35)"><guest><xsl:value-of select="str:replace(d35,' -',',')"/></guest></xsl:if> + <xsl:if test="string-length(d36)"><director><xsl:value-of select="str:replace(d36,'|',', ')"/></director></xsl:if> + <xsl:if test="string-length(d37)"><actor><xsl:value-of select="str:replace(str:replace(d37,') -','), '),' ',' ')"/></actor></xsl:if> + + <xsl:variable name="AUDIO"> + <xsl:if test="d28=1"><xsl:text> DolbyDigital</xsl:text></xsl:if> + <xsl:if test="d27=1"><xsl:text> Stereo</xsl:text></xsl:if> + <xsl:if test="d12=1"><xsl:text> Zweikanal</xsl:text></xsl:if> + </xsl:variable> + + <xsl:if test="string-length($AUDIO)"> + <audio><xsl:value-of select="normalize-space($AUDIO)"/></audio> + </xsl:if> + + <xsl:variable name="FLAGS"> + <xsl:if test="d9=1"><xsl:text> [PrimeTime]</xsl:text></xsl:if> + <xsl:if test="d11=1"><xsl:text> [SchwarzWeiss]</xsl:text></xsl:if> + <xsl:if test="d13=1"><xsl:text> [Untertitel]</xsl:text></xsl:if> + <xsl:if test="d14=1"><xsl:text> [PayTV]</xsl:text></xsl:if> + <xsl:if test="d15=1"><xsl:text> [Hörfilm]</xsl:text></xsl:if> + <xsl:if test="d29=1"><xsl:text> [16:9]</xsl:text></xsl:if> + </xsl:variable> + + <xsl:if test="string-length($FLAGS)"> + <flags><xsl:value-of select="normalize-space($FLAGS)"/></flags> + </xsl:if> + + <xsl:if test="d26 > 0"><extepnum><xsl:value-of select="d26"/></extepnum></xsl:if> + + <xsl:if test="string-length(d40)"> + <images><xsl:value-of select="substring-before(d40,'.jpg')"/></images> + <imagetype><xsl:text>jpg</xsl:text></imagetype> + </xsl:if> + +<!-- +--> + + </event> + </xsl:for-each> + </events> +</xsl:template> + + + +<xsl:template name="getRATING"> + <xsl:param name="ratingid"/> + + <xsl:variable name="RATING"> + <xsl:choose> + <xsl:when test="$ratingid=1"><xsl:text> / Allgemein *</xsl:text></xsl:when> + <xsl:when test="$ratingid=2"><xsl:text> / Allgemein **</xsl:text></xsl:when> + <xsl:when test="$ratingid=3"><xsl:text> / Allgemein ***</xsl:text></xsl:when> + <xsl:when test="$ratingid=4"><xsl:text> / Allgemein ****</xsl:text></xsl:when> + <xsl:when test="$ratingid=5"><xsl:text> / Allgemein *****</xsl:text></xsl:when> + </xsl:choose> + </xsl:variable> + + <xsl:value-of select="$RATING"/> +</xsl:template> + + +<xsl:template name="getCATEGORY"> + <xsl:param name="categoryid"/> + + <xsl:variable name="CATEGORY"> + + <xsl:for-each select="document('epgdata-category.xml')//data"> + <xsl:choose> + <xsl:when test="$categoryid=ca0"><xsl:value-of select="ca1"/></xsl:when> + </xsl:choose> + </xsl:for-each> + </xsl:variable> + + <xsl:value-of disable-output-escaping="yes" select="$CATEGORY"/> +</xsl:template> + + +<xsl:template name="getGenre"> + <xsl:param name="genreid"/> + + <xsl:variable name="GENRE"> + + <xsl:for-each select="document('epgdata-genre.xml')//data"> + <xsl:choose> + <xsl:when test="$genreid=g0"><xsl:value-of select="g1"/></xsl:when> + </xsl:choose> + </xsl:for-each> + </xsl:variable> + + <xsl:value-of select="$GENRE"/> +</xsl:template> + + +<xsl:template name="date2UTC"> + <xsl:param name="date"/> + + <xsl:variable name="dststart"> + <xsl:value-of select="concat(date:year($date),'-03-',32-date:day-in-week(concat(date:year($date),'-03-31')),'T02:00:00')"/> + </xsl:variable> + + <xsl:variable name="dstend"> + <xsl:value-of select="concat(date:year($date),'-10-',32-date:day-in-week(concat(date:year($date),'-10-31')),'T03:00:00')"/> + </xsl:variable> + + <xsl:variable name="tz"> + <xsl:choose> + <xsl:when test="date:seconds(date:difference($dststart,$date)) >= 0"> + <xsl:choose> + <xsl:when test="date:seconds(date:difference($date,$dstend)) >= 0">+02:00</xsl:when> + <xsl:otherwise>+01:00</xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise>+01:00</xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:value-of select="date:seconds(concat($date,$tz))"/> +</xsl:template> + +</xsl:stylesheet> diff --git a/PLUGINS/epgdata/epgdata.c b/PLUGINS/epgdata/epgdata.c new file mode 100644 index 0000000..3cf31ef --- /dev/null +++ b/PLUGINS/epgdata/epgdata.c @@ -0,0 +1,760 @@ +/* + * epgdata.c + * + * See the README file for copyright information + * + */ + +#include <dirent.h> +#include <unistd.h> + +#include "epgdata.h" + +//*************************************************************************** +// Epgdata +//*************************************************************************** + +Epgdata::Epgdata() + : Plugin() +{ + pxsltStylesheet = 0; + stmtByFileRef = 0; + stmtCleanDouble = 0; + stmtMarkOldEvents = 0; + selectByDate = 0; + selectId = 0; + + pin = 0; + timeout = 3 * tmeSecondsPerMinute; + baseurl = strdup("http://www.epgdata.com"); +} + +Epgdata::~Epgdata() +{ + if (pxsltStylesheet) + xsltFreeStylesheet(pxsltStylesheet); + + delete stmtByFileRef; + delete selectByDate; + delete stmtCleanDouble; + delete stmtMarkOldEvents; + + free(baseurl); + free(pin); +} + +int Epgdata::init(cEpgd* aObject, int aUtf8) +{ + Plugin::init(aObject, aUtf8); + + pxsltStylesheet = loadXSLT(getSource(), confDir, utf8); + + return done; +} + +int Epgdata::initDb() +{ + int status = success; + + // -------- + // by fileref (for pictures) + // select name from fileref + // where source = ? and fileref = ? + + stmtByFileRef = new cDbStatement(obj->fileDb); + + stmtByFileRef->build("select "); + stmtByFileRef->bind("NAME", cDBS::bndOut); + stmtByFileRef->build(" from %s where ", obj->fileDb->TableName()); + stmtByFileRef->bind("SOURCE", cDBS::bndIn | cDBS::bndSet); + stmtByFileRef->bind("FILEREF", cDBS::bndIn | cDBS::bndSet, " and "); + + status += stmtByFileRef->prepare(); + + // --------------- + // (for cleanup double) + // select name from fileref + // where source = ? order by name desc + + stmtCleanDouble = new cDbStatement(obj->fileDb); + + stmtCleanDouble->build("select "); + stmtCleanDouble->bind("NAME", cDBS::bndOut); + stmtCleanDouble->build(" from %s where ", obj->fileDb->TableName()); + stmtCleanDouble->bind("SOURCE", cDBS::bndIn | cDBS::bndSet); + stmtCleanDouble->build(" order by name desc"); + + status += stmtCleanDouble->prepare(); + + // --------- + // select channelid, merge, mergesp from channelmap + // where source = ? and extid = ? + + selectId = new cDbStatement(obj->mapDb); + + selectId->build("select "); + selectId->bind("CHANNELID", cDBS::bndOut); + selectId->bind("MERGESP", cDBS::bndOut, ", "); + selectId->bind("MERGE", cDBS::bndOut, ", "); + selectId->build(" from %s where ", obj->mapDb->TableName()); + selectId->bind("SOURCE", cDBS::bndIn | cDBS::bndSet); + selectId->bind("EXTERNALID", cDBS::bndIn | cDBS::bndSet, " and "); + + status += selectId->prepare(); + + // --------- + // select name, tag from filerf + // where source = 'epgdata' + // and name like ? + + valueName.setField(obj->fileDb->getField("NAME")); + valueNameLike.setField(obj->fileDb->getField("NAME")); + + selectByDate = new cDbStatement(obj->fileDb); + + selectByDate->build("select "); + selectByDate->bind(&valueName, cDBS::bndOut); + selectByDate->bind("FILEREF", cDBS::bndOut, ", "); + selectByDate->build(" from %s where source = '%s' and ", + obj->fileDb->TableName(), getSource()); + selectByDate->bindCmp(0, &valueNameLike, "like"); + + status += selectByDate->prepare(); + +// // -------- +// // update events set delflg = ?, updflg = ?, fileref = ?, updsp = ? +// // where fileref = ? +// // and source = ?; +// // and updflg in (....) + +// valueFileRef.setField(obj->eventsDb->getField("FileRef")); +// stmtSetDelByFileref = new cDbStatement(obj->eventsDb); + +// stmtSetDelByFileref->build("update %s set ", obj->eventsDb->TableName()); +// stmtSetDelByFileref->bind("DelFlg", cDbService::bndIn |cDbService:: bndSet); +// stmtSetDelByFileref->bind("UpdFlg", cDbService::bndIn |cDbService:: bndSet, ", "); +// stmtSetDelByFileref->bind("FileRef", cDbService::bndIn | cDbService::bndSet, ", "); +// stmtSetDelByFileref->bind("UpdSp", cDbService::bndIn | cDbService::bndSet, ", "); +// stmtSetDelByFileref->build( " where "); +// stmtSetDelByFileref->bind(&valueFileRef, cDbService::bndIn |cDbService:: bndSet); +// stmtSetDelByFileref->bind("Source", cDbService::bndIn | cDbService::bndSet, " and "); +// stmtSetDelByFileref->build(" and updflg in (%s)", Us::getDeletable()); + +// status += stmtSetDelByFileref->prepare(); + + // ---------- + // update events + // set updflg = case when updflg in (...) then 'D' else updflg end, + // delflg = 'Y', + // updsp = unix_timestamp() + // where source = '...' + // and (source, fileref) not in (select source,fileref from fileref) + + stmtMarkOldEvents = new cDbStatement(obj->eventsDb); + + stmtMarkOldEvents->build("update %s set ", obj->eventsDb->TableName()); + stmtMarkOldEvents->build("updflg = case when updflg in (%s) then 'D' else updflg end, ", cEventState::getDeletable()); + stmtMarkOldEvents->build("delflg = 'Y', updsp = unix_timestamp()"); + stmtMarkOldEvents->build(" where source = '%s'", getSource()); + stmtMarkOldEvents->build(" and (source, fileref) not in (select source,fileref from fileref)"); + + status += stmtMarkOldEvents->prepare(); + + // ---------- + // if no epgdata entry in fileref read files from FS to table + + int count = 0; + obj->fileDb->countWhere("source = 'epgdata'", count); + + if (!count) + { + char* path = 0; + DIR* dir; + dirent* dp; + + asprintf(&path, "%s/%s", EpgdConfig.cachePath, getSource()); + chkDir(path); + + if (!(dir = opendir(path))) + { + tell(0, "Error: Opening cache path '%s' failed, %s", path, strerror(errno)); + free(path); + return fail; + } + + while ((dp = readdir(dir))) + { + char* fileRef = 0; + char* file = 0; + char* tag = 0; + struct stat sb; + + if (!strstr(dp->d_name, "_de_qy.zip")) + continue; + + asprintf(&file, "%s/%s", path, dp->d_name); + stat(file, &sb); + free(file); + + asprintf(&tag, "%ld", sb.st_size); + asprintf(&fileRef, "%s-%s", dp->d_name, tag); + + // store file and let tag NULL to indicate that processing is needed + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", dp->d_name); + obj->fileDb->setValue("SOURCE", getSource()); + obj->fileDb->setValue("EXTERNALID", "0"); + obj->fileDb->setValue("FILEREF", fileRef); + obj->fileDb->store(); + + tell(1, "Added '%s' to table fileref", dp->d_name); + free(fileRef); + free(tag); + } + + free(path); + closedir(dir); + } + + return success; +} + +int Epgdata::exitDb() +{ + delete stmtByFileRef; stmtByFileRef = 0; + delete stmtCleanDouble; stmtCleanDouble = 0; + delete selectByDate; selectByDate = 0; + delete selectId; selectId = 0; + delete stmtMarkOldEvents; stmtMarkOldEvents = 0; + + return success; +} + +//*************************************************************************** +// At Config Item +//*************************************************************************** + +int Epgdata::atConfigItem(const char* Name, const char* Value) +{ + if (!strcasecmp(Name, "Url")) { free(baseurl); baseurl = strdup(Value); } + else if (!strcasecmp(Name, "Pin")) { free(pin); pin = strdup(Value); } + else if (!strcasecmp(Name, "Timeout")) { timeout = atoi(Value); } + + else return fail; + + return success; +} + +//*************************************************************************** +// Ready +//*************************************************************************** + +int Epgdata::ready() +{ + static int count = na; + + if (isEmpty(pin)) + return no; + + if (count == na) + { + char* where; + + asprintf(&where, "source = '%s'", getSource()); + + if (obj->mapDb->countWhere(where, count) != success) + count = na; + + free(where); + } + + return count > 0; +} + +//*************************************************************************** +// Process Day +//*************************************************************************** + +int Epgdata::processDay(int day, int fullupdate, Statistic* statistic) +{ + char* directory = 0; + char* fspath = 0; + char* path = 0; // name of the zip file including the path + int haveOneForThisDay = no; + MemoryStruct data; + int fileSize = 0; + char* fileRef = 0; + char* url = 0; + char* logurl = 0; + int load = yes; + char* like = 0; + int bSize = 0; + char entryName[200+TB]; + MemoryStruct uzdata; + // char* oldFileRef = 0; + + int status; + + // path to zip files, url, .. + + asprintf(&directory, "%s/%s", EpgdConfig.cachePath, getSource()); + chkDir(directory); + asprintf(&url, "%s/index.php?action=sendPackage&iOEM=VDR&pin=%s&dayOffset=%d&dataType=xml", baseurl, pin, day); + asprintf(&logurl, "%s/index.php?action=sendPackage&iOEM=VDR&pin=%s&dayOffset=%d&dataType=xml", baseurl, "insert-your-pin-here", day); + + // first get the http header + + data.clear(); + data.headerOnly = yes; + + status = obj->downloadFile(url, fileSize, &data); + + if (status != success || isEmpty(data.name)) + { + tell(1, "Download header for day (%d) at '%s' failed, aborting, got name '%s', status was %d", + day, logurl, data.name ? data.name : "", status); + status = fail; + goto Exit; + } + + tell(2, "Got info for day (%d), file '%s' with tag '%s'", day, data.name, data.tag); + + asprintf(&fileRef, "%s-%s", data.name, data.tag); + asprintf(&path, "%s/%s", directory, data.name); + + // lookup file + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", data.name); + obj->fileDb->setValue("SOURCE", getSource()); + + // 1:1 match ? + + obj->fileDb->find(); + + asprintf(&like, "%.8s_%%", data.name); + valueNameLike.setValue(like); + free(like); + + // check for update + + if (selectByDate->find()) + { + haveOneForThisDay = yes; + // oldFileRef = strdup(obj->fileDb->getStrValue("FileRef")); + } + + if (haveOneForThisDay && day >= EpgdConfig.upddays) + { + // don't check for update of existing files more than 'upddays' in the future + + tell(2, "Skipping update check of file '%s' for day %d", data.name, day); + + statistic->nonUpdates++; + status = success; + load = no; + } + else if (haveOneForThisDay && obj->fileDb->hasValue("FileRef", fileRef)) + { + tell(2, "Skipping download of day (%d) due to non-update", day); + statistic->nonUpdates++; + status = success; + load = no; + } + + if (!load && !obj->fileDb->getRow()->getValue("Tag")->isNull()) + goto Exit; + + // not exist, update or not processed -> work + + // first check if we have it already on fs + + asprintf(&fspath, "%s/%s", directory, valueName.getStrValue()); + + if (!load && fileExists(fspath)) + { + tell(1, "File '%s' exist, loading from filesystem", fspath); + + obj->loadFromFs(&data, valueName.getStrValue(), getSource()); + + free(fileRef); + free(path); + path = strdup(fspath); + asprintf(&fileRef, "%s-%s", valueName.getStrValue(), data.tag); + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", valueName.getStrValue()); + obj->fileDb->setValue("SOURCE", getSource()); + } + + free(fspath); + + if (load) + { + tell(0, "Download file: '%s' to '%s", logurl, data.name); + + data.clear(); + + if (obj->downloadFile(url, fileSize, &data, timeout) != success) + { + tell(0, "Download of day (%d) from '%s' failed", day, logurl); + status = fail; + goto Exit; + } + + statistic->bytes += data.size; + statistic->files++; + + // store zip to FS + + obj->storeToFs(&data, data.name, getSource()); + } + + if (data.isEmpty()) + goto Exit; + + // unzip ... + + uzdata.clear(); + + if (unzip(path, /*filter*/ ".xml", uzdata.memory, bSize, entryName) == success) + { + tell(0, "Processing file '%s' for day %d (%d/%d)", + fileRef, day, haveOneForThisDay, load); + + uzdata.size = bSize; + + // store ? + + if (EpgdConfig.storeXmlToFs) + obj->storeToFs(&uzdata, entryName, getSource()); + + // process file .. + + obj->connection->startTransaction(); + + if ((status = processFile(uzdata.memory, uzdata.size, fileRef)) != success) + statistic->rejected++; + + if (!obj->dbConnected()) + { + status = fail; + goto Exit; + } + +// we can use this code instead of "stmtMarkOldEvents" !! +// but we have to complete it like tvm plugin! +// if (haveOneForThisDay && load && strcmp(oldFileRef, fileRef) != 0) +// { +// // mark 'old' entrys in events table as deleted +// // and 'fake' fileref to new to avoid deletion at cleanup + +// tell(0, "Removing events of fileref '%s' for day %d", oldFileRef, day); + +// obj->eventsDb->clear(); +// obj->eventsDb->setValue("DelFlg", "Y"); +// obj->eventsDb->setValue("UpdFlg", "D"); +// obj->eventsDb->setValue("FileRef", fileRef); // fake to new fileref +// obj->eventsDb->setValue("UpdSp", time(0)); +// obj->eventsDb->setValue("Source", getSource()); +// valueFileRef.setValue(oldFileRef); // old fileref +// stmtSetDelByFileref->execute(); +// } + + // Confirm processing of file + + obj->fileDb->setValue("EXTERNALID", "0"); + obj->fileDb->setValue("TAG", data.tag); + obj->fileDb->setValue("FILEREF", fileRef); + obj->fileDb->store(); + + obj->connection->commit(); + } + + Exit: + + // free(oldFileRef); + obj->fileDb->reset(); + selectByDate->freeResult(); + + uzdata.clear(); + free(url); + free(logurl); + free(fileRef); + free(directory); + free(path); + + return status; +} + +//*************************************************************************** +// Process File +//*************************************************************************** + +int Epgdata::processFile(const char* data, int size, const char* fileRef) +{ + xmlDocPtr transformedDoc; + xmlNodePtr xmlRoot; + int count = 0; + + if ((transformedDoc = obj->transformXml(data, size, pxsltStylesheet, fileRef)) == 0) + { + tell(0, "XSLT transformation for '%s' failed, ignoring", fileRef); + return fail; + } + + if (!(xmlRoot = xmlDocGetRootElement(transformedDoc))) + { + tell(0, "Invalid xml document returned from xslt for '%s', ignoring", fileRef); + return fail; + } + + // DEBUG: xmlSaveFile("/tmp/test.xml", transformedDoc); + + for (xmlNodePtr node = xmlRoot->xmlChildrenNode; node && obj->dbConnected(); node = node->next) + { + char* prop = 0; + tEventId eventid; + char* extid = 0; + + // skip all unexpected elements + + if (node->type != XML_ELEMENT_NODE || strcmp((char*)node->name, "event") != 0) + continue; + + // get/check eventid + + if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"id")) || !*prop || !(eventid = atoll(prop))) + { + xmlFree(prop); + tell(0, "Missing event id, ignoring!"); + continue; + } + + xmlFree(prop); + + // get/check provider id + + if (!(prop = (char*)xmlGetProp(node, (xmlChar*)"provid")) || !*prop || !atoi(prop)) + { + xmlFree(prop); + tell(0, "Missing provider id, ignoring!"); + continue; + } + + extid = strdup(prop); + xmlFree(prop); + + obj->mapDb->clear(); + obj->mapDb->setValue("EXTERNALID", extid); + obj->mapDb->setValue("SOURCE", getSource()); + free(extid); + + for (int f = selectId->find(); f; f = selectId->fetch()) + { + int insert; + const char* channelId = obj->mapDb->getStrValue("CHANNELID"); + + // create event .. + + obj->eventsDb->clear(); + obj->eventsDb->setBigintValue("EVENTID", eventid); + obj->eventsDb->setValue("CHANNELID", channelId); + + insert = !obj->eventsDb->find(); + + obj->eventsDb->setValue("SOURCE", getSource()); + obj->eventsDb->setValue("FILEREF", fileRef); + + // auto parse and set other fields + + obj->parseEvent(obj->eventsDb->getRow(), node); + + // ... + + time_t mergesp = obj->mapDb->getIntValue("MERGESP"); + long starttime = obj->eventsDb->getIntValue("STARTTIME"); + int merge = obj->mapDb->getIntValue("MERGE"); + + // store .. + + if (insert) + { + // handle insert + + obj->eventsDb->setValue("VERSION", 0xFF); + obj->eventsDb->setValue("TABLEID", 0L); + obj->eventsDb->setValue("USEID", 0L); + + if (starttime <= mergesp) + obj->eventsDb->setCharValue("UPDFLG", cEventState::usInactive); + else + obj->eventsDb->setCharValue("UPDFLG", merge > 1 ? cEventState::usMergeSpare : cEventState::usActive); + + obj->eventsDb->insert(); + } + else + { + if (obj->eventsDb->hasValue("DELFLG", "Y")) + obj->eventsDb->setValue("DELFLG", "N"); + + if (obj->eventsDb->hasValue("UPDFLG", "D")) + { + if (starttime <= mergesp) + obj->eventsDb->setCharValue("UPDFLG", cEventState::usInactive); + else + obj->eventsDb->setCharValue("UPDFLG", merge > 1 ? cEventState::usMergeSpare : cEventState::usActive); + } + + obj->eventsDb->update(); + } + + obj->eventsDb->reset(); + count++; + } + } + + selectId->freeResult(); + + xmlFreeDoc(transformedDoc); + + tell(2, "XML File '%s' processed, updated %d events", fileRef, count); + + return success; +} + +//*************************************************************************** +// Get Picture +//*************************************************************************** + +int Epgdata::getPicture(const char* imagename, const char* fileRef, MemoryStruct* data) +{ + int fileSize = 0; + char* path = 0; + char entryName[200+TB]; + + data->clear(); + + // lookup file information + + obj->fileDb->clear(); + obj->fileDb->setValue("FILEREF", fileRef); + obj->fileDb->setValue("SOURCE", getSource()); + + if (stmtByFileRef->find()) + asprintf(&path, "%s/epgdata/%s", EpgdConfig.cachePath, + obj->fileDb->getStrValue("Name")); + + stmtByFileRef->freeResult(); + + if (!path) + { + tell(0, "Error: No entry with fileref '%s' to lookup image '%s' found", + fileRef, imagename); + return 0; + } + + if (unzip(path, imagename, data->memory, fileSize, entryName) == success) + { + data->size = fileSize; + tell(2, "Unzip of image '%s' succeeded", imagename); + } + + free(path); + + return fileSize; +} + +int Epgdata::cleanupAfter() +{ + const char* ext = ".zip"; + struct dirent* dirent; + DIR* dir; + char* pdir; + int count = 0; + char* last = 0; + + // cleanup *.zip in FS cache ... + + // remove old versions for each day + + obj->fileDb->clear(); + obj->fileDb->setValue("SOURCE", getSource()); + + for (int f = stmtCleanDouble->find(); f; f = stmtCleanDouble->fetch()) + { + const char* name = obj->fileDb->getStrValue("NAME"); + + if (last && strncmp(name, last, 8) == 0) + { + char* where; + tell(1, "Remove old epgdata file '%s' from table", name); + asprintf(&where, "name = '%s'", name); + obj->fileDb->deleteWhere("%s", where); + free(where); + } + + free(last); + last = strdup(name); + } + + free(last); + stmtCleanDouble->freeResult(); + + // mark wasted events (delflg, ...) + + stmtMarkOldEvents->execute(); + + // cleanup filesystem, remove files which not referenced in table + + asprintf(&pdir, "%s/%s", EpgdConfig.cachePath, getSource()); + + if (!(dir = opendir(pdir))) + { + tell(1, "Can't open directory '%s', '%s'", pdir, strerror(errno)); + free(pdir); + + return done; + } + + tell(1, "Starting cleanup of epgdata zip's in '%s'", pdir); + + free(pdir); + + while ((dirent = readdir(dir))) + { + // check extension + + if (strncmp(dirent->d_name + strlen(dirent->d_name) - strlen(ext), ext, strlen(ext)) != 0) + continue; + + // lookup file + + obj->fileDb->clear(); + obj->fileDb->setValue("NAME", dirent->d_name); + obj->fileDb->setValue("SOURCE", getSource()); + + if (!obj->fileDb->find()) + { + asprintf(&pdir, "%s/%s/%s", EpgdConfig.cachePath, getSource(), dirent->d_name); + + if (!removeFile(pdir)) + count++; + + free(pdir); + } + + obj->fileDb->reset(); + } + + closedir(dir); + + tell(1, "Cleanup finished, removed (%d) epgdata files", count); + + return success; +} + +//*************************************************************************** + +extern "C" void* EPGPluginCreator() { return new Epgdata(); } diff --git a/PLUGINS/epgdata/epgdata.h b/PLUGINS/epgdata/epgdata.h new file mode 100644 index 0000000..0bb0d88 --- /dev/null +++ b/PLUGINS/epgdata/epgdata.h @@ -0,0 +1,52 @@ +/* + * epgdata.h + * + * See the README file for copyright information + * + */ + +#include "epgd.h" + +//*************************************************************************** +// Epgdata +//*************************************************************************** + +class Epgdata : public Plugin +{ + public: + + Epgdata(); + virtual ~Epgdata(); + + int init(cEpgd* aObject, int aUtf8); + int initDb(); + int exitDb(); + int atConfigItem(const char* Name, const char* Value); + + const char* getSource() { return "epgdata"; } + + int getPicture(const char* imagename, const char* fileRef, MemoryStruct* data); + int processDay(int day, int fullupdate, Statistic* statistic); + int cleanupAfter(); + int ready(); + + protected: + + int processFile(const char* data, int size, const char* fileRef); + + cDbValue valueNameLike; + cDbValue valueName; + cDbValue valueFileRef; + cDbStatement* stmtByFileRef; + cDbStatement* stmtCleanDouble; + cDbStatement* selectId; + cDbStatement* selectByDate; + cDbStatement* stmtMarkOldEvents; + xsltStylesheetPtr pxsltStylesheet; + + // config + + char* baseurl; + int timeout; + char* pin; +}; diff --git a/PLUGINS/epgdata/scripts/getepgdataids b/PLUGINS/epgdata/scripts/getepgdataids new file mode 100755 index 0000000..898a647 --- /dev/null +++ b/PLUGINS/epgdata/scripts/getepgdataids @@ -0,0 +1,37 @@ + +path="/tmp/epgdata/" +file=$path/"info.zip" + +mkdir -p $path + +cd $path +rm -f * + +wget "http://www.epgdata.com/index.php?action=sendInclude&iOEM=&pin=XYZ&dataType=xml" -q -O $file + +unzip $file > /dev/null 2>&1 +rm $file + +chanfile="channel_y.xml" + +cat $chanfile | while read line; do + + if [[ ${line} =~ "<ch0>" ]]; then + + chan=${line#*>} + chan=${chan%<*} + + else + + if [[ ${line} =~ "<ch4>" ]]; then + + id=${line#*>} + id=${id%<*} + + echo "epgdata:$id // $chan" + + fi + + fi + +done | sort diff --git a/PLUGINS/epgdata/scripts/getincludes b/PLUGINS/epgdata/scripts/getincludes new file mode 100755 index 0000000..120f1c1 --- /dev/null +++ b/PLUGINS/epgdata/scripts/getincludes @@ -0,0 +1,6 @@ + +rm -f include.zip +wget "http://www.epgdata.com/index.php?action=sendInclude&iOEM=&pin=&dataType=xml" -q -O include.zip +unzip include.zip +rm -f include.zip + |