By Anders Holst:
[enigma2.git] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
20
21                 /* for subtitles */
22 #include <lib/gui/esubtitle.h>
23
24 #include <sys/vfs.h>
25 #include <sys/stat.h>
26
27 #include <byteswap.h>
28 #include <netinet/in.h>
29
30 #ifndef BYTE_ORDER
31 #error no byte order defined!
32 #endif
33
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
35 {
36         DECLARE_REF(eStaticServiceDVBInformation);
37 public:
38         RESULT getName(const eServiceReference &ref, std::string &name);
39         int getLength(const eServiceReference &ref);
40         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41         PyObject *getInfoObject(const eServiceReference &ref, int);
42 };
43
44 DEFINE_REF(eStaticServiceDVBInformation);
45
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
47 {
48         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49         if ( !ref.name.empty() )
50         {
51                 if (service.getParentTransportStreamID().get()) // linkage subservice
52                 {
53                         ePtr<iServiceHandler> service_center;
54                         if (!eServiceCenter::getInstance(service_center))
55                         {
56                                 eServiceReferenceDVB parent = service;
57                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
58                                 parent.setServiceID( service.getParentServiceID() );
59                                 parent.setParentTransportStreamID(eTransportStreamID(0));
60                                 parent.setParentServiceID(eServiceID(0));
61                                 parent.name="";
62                                 ePtr<iStaticServiceInformation> service_info;
63                                 if (!service_center->info(parent, service_info))
64                                 {
65                                         if (!service_info->getName(parent, name))
66                                                 name=buildShortName(name) + " - ";
67                                 }
68                         }
69                 }
70                 else
71                         name="";
72                 name += ref.name;
73                 return 0;
74         }
75         else
76                 return -1;
77 }
78
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
80 {
81         return -1;
82 }
83
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
85 {
86         ePtr<eDVBResourceManager> res_mgr;
87         if ( eDVBResourceManager::getInstance( res_mgr ) )
88                 eDebug("isPlayable... no res manager!!");
89         else
90         {
91                 eDVBChannelID chid, chid_ignore;
92                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94                 return res_mgr->canAllocateChannel(chid, chid_ignore);
95         }
96         return false;
97 }
98
99 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
103
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
105 {
106         if (r.type == eServiceReference::idDVB)
107         {
108                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
109                 switch(what)
110                 {
111                         case iServiceInformation::sTransponderData:
112                         {
113                                 ePtr<eDVBResourceManager> res;
114                                 if (!eDVBResourceManager::getInstance(res))
115                                 {
116                                         ePtr<iDVBChannelList> db;
117                                         if (!res->getChannelList(db))
118                                         {
119                                                 eDVBChannelID chid;
120                                                 ref.getChannelID(chid);
121                                                 ePtr<iDVBFrontendParameters> feparm;
122                                                 if (!db->getChannelFrontendData(chid, feparm))
123                                                 {
124                                                         int system;
125                                                         if (!feparm->getSystem(system))
126                                                         {
127                                                                 ePyObject dict = PyDict_New();
128                                                                 switch(system)
129                                                                 {
130                                                                         case iDVBFrontend::feSatellite:
131                                                                         {
132                                                                                 eDVBFrontendParametersSatellite s;
133                                                                                 feparm->getDVBS(s);
134                                                                                 PutSatelliteDataToDict(dict, s);
135                                                                                 break;
136                                                                         }
137                                                                         case iDVBFrontend::feTerrestrial:
138                                                                         {
139                                                                                 eDVBFrontendParametersTerrestrial t;
140                                                                                 feparm->getDVBT(t);
141                                                                                 PutTerrestrialDataToDict(dict, t);
142                                                                                 break;
143                                                                         }
144                                                                         case iDVBFrontend::feCable:
145                                                                         {
146                                                                                 eDVBFrontendParametersCable c;
147                                                                                 feparm->getDVBC(c);
148                                                                                 PutCableDataToDict(dict, c);
149                                                                                 break;
150                                                                         }
151                                                                         default:
152                                                                                 eDebug("unknown frontend type %d", system);
153                                                                                 Py_DECREF(dict);
154                                                                                 break;
155                                                                 }
156                                                                 return dict;
157                                                         }
158                                                 }
159                                         }
160                                 }
161                         }
162                 }
163         }
164         Py_RETURN_NONE;
165 }
166
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
168
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
170 {
171         ePtr<iDVBChannelList> db;
172         ePtr<eDVBResourceManager> res;
173
174         int err;
175         if ((err = eDVBResourceManager::getInstance(res)) != 0)
176         {
177                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
178                 return err;
179         }
180         if ((err = res->getChannelList(db)) != 0)
181         {
182                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
183                 return err;
184         }
185
186         eBouquet *bouquet=0;
187         if ((err = db->getBouquet(ref, bouquet)) != 0)
188         {
189                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
190                 return -1;
191         }
192
193         if ( bouquet && bouquet->m_bouquet_name.length() )
194         {
195                 name = bouquet->m_bouquet_name;
196                 return 0;
197         }
198         else
199                 return -1;
200 }
201
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
203 {
204         if (ref.flags & eServiceReference::isGroup)
205         {
206                 ePtr<iDVBChannelList> db;
207                 ePtr<eDVBResourceManager> res;
208
209                 if (eDVBResourceManager::getInstance(res))
210                 {
211                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
212                         return 0;
213                 }
214
215                 if (res->getChannelList(db))
216                 {
217                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
218                         return 0;
219                 }
220
221                 eBouquet *bouquet=0;
222                 if (db->getBouquet(ref, bouquet))
223                 {
224                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
225                         return 0;
226                 }
227
228                 int prio_order = eDVBFrontend::getTypePriorityOrder();
229                 int cur=0;
230                 eDVBChannelID chid, chid_ignore;
231                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
233                 {
234                         static unsigned char prio_map[6][3] = {
235                                 { 3, 2, 1 }, // -S -C -T
236                                 { 3, 1, 2 }, // -S -T -C
237                                 { 2, 3, 1 }, // -C -S -T
238                                 { 1, 3, 2 }, // -C -T -S
239                                 { 1, 2, 3 }, // -T -C -S
240                                 { 2, 1, 3 }  // -T -S -C
241                         };
242                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243                         int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
244                         switch(tmp)
245                         {
246                                 case 0:
247                                         break;
248                                 case 30000: // cached DVB-T channel
249                                 case 1: // DVB-T frontend
250                                         tmp = prio_map[prio_order][2];
251                                         break;
252                                 case 40000: // cached DVB-C channel
253                                 case 2:
254                                         tmp = prio_map[prio_order][1];
255                                         break;
256                                 default: // DVB-S
257                                         tmp = prio_map[prio_order][0];
258                                         break;
259                         }
260                         if (tmp > cur)
261                         {
262                                 m_playable_service = *it;
263                                 cur = tmp;
264                         }
265                 }
266                 if (cur)
267                         return cur;
268         }
269         m_playable_service = eServiceReference();
270         return 0;
271 }
272
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
274 {
275         return -1;
276 }
277
278 #include <lib/dvb/epgcache.h>
279
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
281 {
282         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
283 }
284
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
286 {
287         DECLARE_REF(eStaticServiceDVBPVRInformation);
288         eServiceReference m_ref;
289         eDVBMetaParser m_parser;
290 public:
291         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292         RESULT getName(const eServiceReference &ref, std::string &name);
293         int getLength(const eServiceReference &ref);
294         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296         int getInfo(const eServiceReference &ref, int w);
297         std::string getInfoString(const eServiceReference &ref,int w);
298         PyObject *getInfoObject(const eServiceReference &r, int what);
299 };
300
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
302
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
304 {
305         m_ref = ref;
306         m_parser.parseFile(ref.path);
307 }
308
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
310 {
311         ASSERT(ref == m_ref);
312         if (m_parser.m_name.size())
313                 name = m_parser.m_name;
314         else
315         {
316                 name = ref.path;
317                 size_t n = name.rfind('/');
318                 if (n != std::string::npos)
319                         name = name.substr(n + 1);
320         }
321         return 0;
322 }
323
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
325 {
326         ASSERT(ref == m_ref);
327         
328         eDVBTSTools tstools;
329         
330         struct stat s;
331         stat(ref.path.c_str(), &s);
332
333         if (tstools.openFile(ref.path.c_str(), 1))
334                 return 0;
335
336                         /* check if cached data is still valid */
337         if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338                 return m_parser.m_length / 90000;
339
340                         /* open again, this time with stream info */
341         if (tstools.openFile(ref.path.c_str()))
342                 return 0;
343
344                         /* otherwise, re-calc length and update meta file */
345         pts_t len;
346         if (tstools.calcLen(len))
347                 return 0;
348
349         m_parser.m_length = len;
350         m_parser.m_filesize = s.st_size;
351         m_parser.updateMeta(ref.path);
352         return m_parser.m_length / 90000;
353 }
354
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
356 {
357         switch (w)
358         {
359         case iServiceInformation::sDescription:
360                 return iServiceInformation::resIsString;
361         case iServiceInformation::sServiceref:
362                 return iServiceInformation::resIsString;
363         case iServiceInformation::sFileSize:
364                 return m_parser.m_filesize;
365         case iServiceInformation::sTimeCreate:
366                 if (m_parser.m_time_create)
367                         return m_parser.m_time_create;
368                 else
369                         return iServiceInformation::resNA;
370         default:
371                 return iServiceInformation::resNA;
372         }
373 }
374
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
376 {
377         switch (w)
378         {
379         case iServiceInformation::sDescription:
380                 return m_parser.m_description;
381         case iServiceInformation::sServiceref:
382                 return m_parser.m_ref.toString();
383         case iServiceInformation::sTags:
384                 return m_parser.m_tags;
385         default:
386                 return "";
387         }
388 }
389
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
391 {
392         switch (what)
393         {
394         case iServiceInformation::sFileSize:
395                 return PyLong_FromLongLong(m_parser.m_filesize);
396         default:
397                 Py_RETURN_NONE;
398         }
399 }
400
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
402 {
403         if (!ref.path.empty())
404         {
405                 ePtr<eServiceEvent> event = new eServiceEvent;
406                 std::string filename = ref.path;
407                 filename.erase(filename.length()-2, 2);
408                 filename+="eit";
409                 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
410                 {
411                         evt = event;
412                         return 0;
413                 }
414         }
415         evt = 0;
416         return -1;
417 }
418
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
420 {
421         DECLARE_REF(eDVBPVRServiceOfflineOperations);
422         eServiceReferenceDVB m_ref;
423 public:
424         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
425         
426         RESULT deleteFromDisk(int simulate);
427         RESULT getListOfFilenames(std::list<std::string> &);
428         RESULT reindex();
429 };
430
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
432
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
434 {
435 }
436
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
438 {
439         if (simulate)
440                 return 0;
441         else
442         {
443                 std::list<std::string> res;
444                 if (getListOfFilenames(res))
445                         return -1;
446                 
447                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
448                 if (!eraser)
449                         eDebug("FATAL !! can't get background file eraser");
450                 
451                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
452                 {
453                         eDebug("Removing %s...", i->c_str());
454                         if (eraser)
455                                 eraser->erase(i->c_str());
456                         else
457                                 ::unlink(i->c_str());
458                 }
459                 
460                 return 0;
461         }
462 }
463
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
465 {
466         res.clear();
467         res.push_back(m_ref.path);
468
469 // handling for old splitted recordings (enigma 1)
470         char buf[255];
471         int slice=1;
472         while(true)
473         {
474                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
475                 struct stat s;
476                 if (stat(buf, &s) < 0)
477                         break;
478                 res.push_back(buf);
479         }       
480
481         res.push_back(m_ref.path + ".meta");
482         res.push_back(m_ref.path + ".ap");
483         res.push_back(m_ref.path + ".sc");
484         res.push_back(m_ref.path + ".cuts");
485         std::string tmp = m_ref.path;
486         tmp.erase(m_ref.path.length()-3);
487         res.push_back(tmp + ".eit");
488         return 0;
489 }
490
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
492 {
493         const char *filename = m_ref.path.c_str();
494         eDebug("reindexing %s...", filename);
495
496         eMPEGStreamInformation info;
497         eMPEGStreamParserTS parser(info);
498         
499         info.startSave(filename);
500         
501         eRawFile f;
502         
503         int err = f.open(m_ref.path.c_str(), 0);
504         if (err < 0)
505                 return -1;
506         
507         off_t length = f.length();
508         unsigned char buffer[188*256*4];
509         while (1)
510         {
511                 off_t offset = f.lseek(0, SEEK_CUR);
512                 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513                 int r = f.read(buffer, sizeof(buffer));
514                 if (!r)
515                         break;
516                 if (r < 0)
517                         return r;
518                 parser.parseData(offset, buffer, r);
519         }
520         
521         info.stopSave();
522         f.close();
523         
524         return 0;
525 }
526
527 DEFINE_REF(eServiceFactoryDVB)
528
529 eServiceFactoryDVB::eServiceFactoryDVB()
530 {
531         ePtr<eServiceCenter> sc;
532         
533         eServiceCenter::getPrivInstance(sc);
534         if (sc)
535         {
536                 std::list<std::string> extensions;
537                 extensions.push_back("ts");
538                 extensions.push_back("trp");
539                 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
540         }
541
542         m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
543         m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
544 }
545
546 eServiceFactoryDVB::~eServiceFactoryDVB()
547 {
548         ePtr<eServiceCenter> sc;
549         
550         eServiceCenter::getPrivInstance(sc);
551         if (sc)
552                 sc->removeServiceFactory(eServiceFactoryDVB::id);
553 }
554
555 DEFINE_REF(eDVBServiceList);
556
557 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
558 {
559 }
560
561 eDVBServiceList::~eDVBServiceList()
562 {
563 }
564
565 RESULT eDVBServiceList::startQuery()
566 {
567         ePtr<iDVBChannelList> db;
568         ePtr<eDVBResourceManager> res;
569         
570         int err;
571         if ((err = eDVBResourceManager::getInstance(res)) != 0)
572         {
573                 eDebug("no resource manager");
574                 return err;
575         }
576         if ((err = res->getChannelList(db)) != 0)
577         {
578                 eDebug("no channel list");
579                 return err;
580         }
581         
582         ePtr<eDVBChannelQuery> q;
583         
584         if (!m_parent.path.empty())
585         {
586                 eDVBChannelQuery::compile(q, m_parent.path);
587                 if (!q)
588                 {
589                         eDebug("compile query failed");
590                         return err;
591                 }
592         }
593         
594         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
595         {
596                 eDebug("startQuery failed");
597                 return err;
598         }
599
600         return 0;
601 }
602
603 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
604 {
605         eServiceReferenceDVB ref;
606         
607         if (!m_query)
608                 return -1;
609
610         while (!m_query->getNextResult(ref))
611                 list.push_back(ref);
612
613         if (sorted)
614                 list.sort(iListableServiceCompare(this));
615
616         return 0;
617 }
618
619 //   The first argument of this function is a format string to specify the order and
620 //   the content of the returned list
621 //   useable format options are
622 //   R = Service Reference (as swig object .. this is very slow)
623 //   S = Service Reference (as python string object .. same as ref.toString())
624 //   C = Service Reference (as python string object .. same as ref.toCompareString())
625 //   N = Service Name (as python string object)
626 //   n = Short Service Name (short name brakets used) (as python string object)
627 //   when exactly one return value per service is selected in the format string,
628 //   then each value is directly a list entry
629 //   when more than one value is returned per service, then the list is a list of
630 //   python tuples
631 //   unknown format string chars are returned as python None values !
632 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
633 {
634         ePyObject ret;
635         std::list<eServiceReference> tmplist;
636         int retcount=1;
637
638         if (!format || !(retcount=strlen(format)))
639                 format = "R"; // just return service reference swig object ...
640
641         if (!getContent(tmplist, sorted))
642         {
643                 int services=tmplist.size();
644                 ePtr<iStaticServiceInformation> sptr;
645                 eServiceCenterPtr service_center;
646
647                 if (strchr(format, 'N') || strchr(format, 'n'))
648                         eServiceCenter::getPrivInstance(service_center);
649
650                 ret = PyList_New(services);
651                 std::list<eServiceReference>::iterator it(tmplist.begin());
652
653                 for (int cnt=0; cnt < services; ++cnt)
654                 {
655                         eServiceReference &ref=*it++;
656                         ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
657                         for (int i=0; i < retcount; ++i)
658                         {
659                                 ePyObject tmp;
660                                 switch(format[i])
661                                 {
662                                 case 'R':  // service reference (swig)object
663                                         tmp = NEW_eServiceReference(ref);
664                                         break;
665                                 case 'C':  // service reference compare string
666                                         tmp = PyString_FromString(ref.toCompareString().c_str());
667                                         break;
668                                 case 'S':  // service reference string
669                                         tmp = PyString_FromString(ref.toString().c_str());
670                                         break;
671                                 case 'N':  // service name
672                                         if (service_center)
673                                         {
674                                                 service_center->info(ref, sptr);
675                                                 if (sptr)
676                                                 {
677                                                         std::string name;
678                                                         sptr->getName(ref, name);
679
680                                                         // filter short name brakets
681                                                         size_t pos;
682                                                         while((pos = name.find("\xc2\x86")) != std::string::npos)
683                                                                 name.erase(pos,2);
684                                                         while((pos = name.find("\xc2\x87")) != std::string::npos)
685                                                                 name.erase(pos,2);
686
687                                                         if (name.length())
688                                                                 tmp = PyString_FromString(name.c_str());
689                                                 }
690                                         }
691                                         if (!tmp)
692                                                 tmp = PyString_FromString("<n/a>");
693                                         break;
694                                 case 'n':  // short service name
695                                         if (service_center)
696                                         {
697                                                 service_center->info(ref, sptr);
698                                                 if (sptr)
699                                                 {
700                                                         std::string name;
701                                                         sptr->getName(ref, name);
702                                                         name = buildShortName(name);
703                                                         if (name.length())
704                                                                 tmp = PyString_FromString(name.c_str());
705                                                 }
706                                         }
707                                         if (!tmp)
708                                                 tmp = PyString_FromString("<n/a>");
709                                         break;
710                                 default:
711                                         if (tuple)
712                                         {
713                                                 tmp = Py_None;
714                                                 Py_INCREF(Py_None);
715                                         }
716                                         break;
717                                 }
718                                 if (tmp)
719                                 {
720                                         if (tuple)
721                                                 PyTuple_SET_ITEM(tuple, i, tmp);
722                                         else
723                                                 PyList_SET_ITEM(ret, cnt, tmp);
724                                 }
725                         }
726                         if (tuple)
727                                 PyList_SET_ITEM(ret, cnt, tuple);
728                 }
729         }
730         return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
731 }
732
733 RESULT eDVBServiceList::getNext(eServiceReference &ref)
734 {
735         if (!m_query)
736                 return -1;
737         
738         return m_query->getNextResult((eServiceReferenceDVB&)ref);
739 }
740
741 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
742 {
743         if (m_parent.flags & eServiceReference::canDescent) // bouquet
744         {
745                 ePtr<iDVBChannelList> db;
746                 ePtr<eDVBResourceManager> resm;
747
748                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
749                         return -1;
750
751                 if (db->getBouquet(m_parent, m_bouquet) != 0)
752                         return -1;
753
754                 res = this;
755                 
756                 return 0;
757         }
758         res = 0;
759         return -1;
760 }
761
762 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
763 {
764         if (!m_bouquet)
765                 return -1;
766         return m_bouquet->addService(ref, before);
767 }
768
769 RESULT eDVBServiceList::removeService(eServiceReference &ref)
770 {
771         if (!m_bouquet)
772                 return -1;
773         return m_bouquet->removeService(ref);
774 }
775
776 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
777 {
778         if (!m_bouquet)
779                 return -1;
780         return m_bouquet->moveService(ref, pos);
781 }
782
783 RESULT eDVBServiceList::flushChanges()
784 {
785         if (!m_bouquet)
786                 return -1;
787         return m_bouquet->flushChanges();
788 }
789
790 RESULT eDVBServiceList::setListName(const std::string &name)
791 {
792         if (!m_bouquet)
793                 return -1;
794         return m_bouquet->setListName(name);
795 }
796
797 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
798 {
799         ePtr<eDVBService> service;
800         int r = lookupService(service, ref);
801         if (r)
802                 service = 0;
803                 // check resources...
804         ptr = new eDVBServicePlay(ref, service);
805         return 0;
806 }
807
808 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
809 {
810         if (ref.path.empty())
811         {
812                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
813                 return 0;
814         } else
815         {
816                 ptr = 0;
817                 return -1;
818         }
819 }
820
821 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
822 {
823         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
824         if (list->startQuery())
825         {
826                 ptr = 0;
827                 return -1;
828         }
829         
830         ptr = list;
831         return 0;
832 }
833
834 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
835 {
836         /* is a listable service? */
837         if (ref.flags & eServiceReference::canDescent) // bouquet
838         {
839                 if ( !ref.name.empty() )  // satellites or providers list
840                         ptr = m_StaticServiceDVBInfo;
841                 else // a dvb bouquet
842                         ptr = m_StaticServiceDVBBouquetInfo;
843         }
844         else if (!ref.path.empty()) /* do we have a PVR service? */
845                 ptr = new eStaticServiceDVBPVRInformation(ref);
846         else // normal dvb service
847         {
848                 ePtr<eDVBService> service;
849                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
850                         ptr = m_StaticServiceDVBInfo;
851                 else
852                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
853                         ptr = service;
854         }
855         return 0;
856 }
857
858 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
859 {
860         if (ref.path.empty())
861         {
862                 ptr = 0;
863                 return -1;
864         } else
865         {
866                 ptr = new eDVBPVRServiceOfflineOperations(ref);
867                 return 0;
868         }
869 }
870
871 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
872 {
873         if (!ref.path.empty()) // playback
874         {
875                 eDVBMetaParser parser;
876                 int ret=parser.parseFile(ref.path);
877                 service = new eDVBService;
878                 if (!ret)
879                         eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
880         }
881         else
882         {
883                         // TODO: handle the listing itself
884                 // if (ref.... == -1) .. return "... bouquets ...";
885                 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
886                         // TODO: cache
887                 ePtr<iDVBChannelList> db;
888                 ePtr<eDVBResourceManager> res;
889         
890                 int err;
891                 if ((err = eDVBResourceManager::getInstance(res)) != 0)
892                 {
893                         eDebug("no resource manager");
894                         return err;
895                 }
896                 if ((err = res->getChannelList(db)) != 0)
897                 {
898                         eDebug("no channel list");
899                         return err;
900                 }
901         
902                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
903                 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
904                 {
905                         eDebug("getService failed!");
906                         return err;
907                 }
908         }
909
910         return 0;
911 }
912
913 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
914         m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
915 {
916         m_is_primary = 1;
917         m_is_pvr = !m_reference.path.empty();
918         
919         m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
920         m_skipmode = 0;
921         
922         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
923         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
924         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
925
926         m_cuesheet_changed = 0;
927         m_cutlist_enabled = 1;
928         
929         m_subtitle_widget = 0;
930         
931         m_tune_state = -1;
932
933         m_subtitle_sync_timer = eTimer::create(eApp);
934
935         CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
936 }
937
938 eDVBServicePlay::~eDVBServicePlay()
939 {
940         if (m_is_pvr)
941         {
942                 eDVBMetaParser meta;
943                 int ret=meta.parseFile(m_reference.path);
944                 if (!ret)
945                 {
946                         char tmp[255];
947                         meta.m_service_data="";
948                         sprintf(tmp, "f:%x", m_dvb_service->m_flags);
949                         meta.m_service_data += tmp;
950                         // cached pids
951                         for (int x=0; x < eDVBService::cacheMax; ++x)
952                         {
953                                 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
954                                 if (entry != -1)
955                                 {
956                                         sprintf(tmp, ",c:%02d%04x", x, entry);
957                                         meta.m_service_data += tmp;
958                                 }
959                         }
960                         meta.updateMeta(m_reference.path);
961                 }
962         }
963         delete m_subtitle_widget;
964 }
965
966 void eDVBServicePlay::gotNewEvent()
967 {
968 #if 0
969                 // debug only
970         ePtr<eServiceEvent> m_event_now, m_event_next;
971         getEvent(m_event_now, 0);
972         getEvent(m_event_next, 1);
973
974         if (m_event_now)
975                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
976         if (m_event_next)
977                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
978 #endif
979         m_event((iPlayableService*)this, evUpdatedEventInfo);
980 }
981
982 void eDVBServicePlay::serviceEvent(int event)
983 {
984         m_tune_state = event;
985
986         switch (event)
987         {
988         case eDVBServicePMTHandler::eventTuned:
989         {
990                 ePtr<iDVBDemux> m_demux;
991                 if (!m_service_handler.getDataDemux(m_demux))
992                 {
993                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
994                         int sid = ref.getParentServiceID().get();
995                         if (!sid)
996                                 sid = ref.getServiceID().get();
997                         if ( ref.getParentTransportStreamID().get() &&
998                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
999                                 m_event_handler.startOther(m_demux, sid);
1000                         else
1001                                 m_event_handler.start(m_demux, sid);
1002                 }
1003                 m_event((iPlayableService*)this, evTunedIn);
1004                 break;
1005         }
1006         case eDVBServicePMTHandler::eventNoResources:
1007         case eDVBServicePMTHandler::eventNoPAT:
1008         case eDVBServicePMTHandler::eventNoPATEntry:
1009         case eDVBServicePMTHandler::eventNoPMT:
1010         case eDVBServicePMTHandler::eventTuneFailed:
1011         case eDVBServicePMTHandler::eventMisconfiguration:
1012         {
1013                 eDebug("DVB service failed to tune - error %d", event);
1014                 m_event((iPlayableService*)this, evTuneFailed);
1015                 break;
1016         }
1017         case eDVBServicePMTHandler::eventNewProgramInfo:
1018         {
1019                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1020                 if (m_timeshift_enabled)
1021                         updateTimeshiftPids();
1022                 if (!m_timeshift_active)
1023                         updateDecoder();
1024                 if (m_first_program_info && m_is_pvr)
1025                 {
1026                         m_first_program_info = 0;
1027                         seekTo(0);
1028                 }
1029                 m_event((iPlayableService*)this, evUpdatedInfo);
1030                 break;
1031         }
1032         case eDVBServicePMTHandler::eventEOF:
1033                 m_event((iPlayableService*)this, evEOF);
1034                 break;
1035         case eDVBServicePMTHandler::eventSOF:
1036                 m_event((iPlayableService*)this, evSOF);
1037                 break;
1038         }
1039 }
1040
1041 void eDVBServicePlay::serviceEventTimeshift(int event)
1042 {
1043         switch (event)
1044         {
1045         case eDVBServicePMTHandler::eventNewProgramInfo:
1046                 if (m_timeshift_active)
1047                         updateDecoder();
1048                 break;
1049         case eDVBServicePMTHandler::eventSOF:
1050                 m_event((iPlayableService*)this, evSOF);
1051                 break;
1052         case eDVBServicePMTHandler::eventEOF:
1053                 if ((!m_is_paused) && (m_skipmode >= 0))
1054                 {
1055                         eDebug("timeshift EOF, so let's go live");
1056                         switchToLive();
1057                 }
1058                 break;
1059         }
1060 }
1061
1062 RESULT eDVBServicePlay::start()
1063 {
1064         eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1065
1066                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
1067                    two (one for decoding, one for data source), as we must be prepared
1068                    to start recording from the data demux. */
1069         if (m_is_pvr)
1070         {
1071                 eDVBMetaParser meta;
1072                 if (!meta.parseFile(m_reference.path))
1073                 {
1074                         service = meta.m_ref;
1075                         service.path = m_reference.path;
1076                 }
1077                 m_cue = new eCueSheet();
1078         }
1079         else
1080                 m_event(this, evStart);
1081
1082         m_first_program_info = 1;
1083         m_service_handler.tune(service, m_is_pvr, m_cue, false, m_dvb_service);
1084
1085         if (m_is_pvr)
1086         {
1087                 /* inject EIT if there is a stored one */
1088                 std::string filename = service.path;
1089                 filename.erase(filename.length()-2, 2);
1090                 filename+="eit";
1091                 ePtr<eServiceEvent> event = new eServiceEvent;
1092                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1093                 {
1094                         ePtr<eServiceEvent> empty;
1095                         m_event_handler.inject(event, 0);
1096                         m_event_handler.inject(empty, 1);
1097                 }
1098                 loadCuesheet();
1099                 m_event(this, evStart);
1100         }
1101         return 0;
1102 }
1103
1104 RESULT eDVBServicePlay::stop()
1105 {
1106                 /* add bookmark for last play position */
1107         if (m_is_pvr)
1108         {
1109                 pts_t play_position, length;
1110                 if (!getPlayPosition(play_position))
1111                 {
1112                                 /* remove last position */
1113                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1114                         {
1115                                 if (i->what == 3) /* current play position */
1116                                 {
1117                                         m_cue_entries.erase(i);
1118                                         i = m_cue_entries.begin();
1119                                         continue;
1120                                 } else
1121                                         ++i;
1122                         }
1123                         
1124                         if (getLength(length))
1125                                 length = 0;
1126                         
1127                         if (length)
1128                         {
1129                                 int perc = play_position * 100LL / length;
1130                         
1131                                         /* only store last play position when between 1% and 99% */
1132                                 if ((1 < perc) && (perc < 99))
1133                                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1134                         }
1135                         m_cuesheet_changed = 1;
1136                 }
1137         }
1138
1139         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1140
1141         m_service_handler_timeshift.free();
1142         m_service_handler.free();
1143         
1144         if (m_is_pvr && m_cuesheet_changed)
1145         {
1146                 struct stat s;
1147                                 /* save cuesheet only when main file is accessible. */
1148                 if (!::stat(m_reference.path.c_str(), &s))
1149                         saveCuesheet();
1150         }
1151         m_event((iPlayableService*)this, evStopped);
1152         return 0;
1153 }
1154
1155 RESULT eDVBServicePlay::setTarget(int target)
1156 {
1157         m_is_primary = !target;
1158         return 0;
1159 }
1160
1161 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1162 {
1163         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1164         return 0;
1165 }
1166
1167 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1168 {
1169                 /* note: we check for timeshift to be enabled,
1170                    not neccessary active. if you pause when timeshift
1171                    is not active, you should activate it when unpausing */
1172         if ((!m_is_pvr) && (!m_timeshift_enabled))
1173         {
1174                 ptr = 0;
1175                 return -1;
1176         }
1177
1178         ptr = this;
1179         return 0;
1180 }
1181
1182 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1183 {
1184         ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1185         eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1186         setFastForward_internal(0);
1187         if (m_decoder)
1188                 return m_decoder->setSlowMotion(ratio);
1189         else
1190                 return -1;
1191 }
1192
1193 RESULT eDVBServicePlay::setFastForward(int ratio)
1194 {
1195         eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1196         ASSERT(ratio);
1197         return setFastForward_internal(ratio);
1198 }
1199
1200 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1201 {
1202         int skipmode, ffratio;
1203         
1204         if (ratio > 8)
1205         {
1206                 skipmode = ratio;
1207                 ffratio = 1;
1208         } else if (ratio > 0)
1209         {
1210                 skipmode = 0;
1211                 ffratio = ratio;
1212         } else if (!ratio)
1213         {
1214                 skipmode = 0;
1215                 ffratio = 0;
1216         } else // if (ratio < 0)
1217         {
1218                 skipmode = ratio;
1219                 ffratio = 1;
1220         }
1221
1222         if (m_skipmode != skipmode)
1223         {
1224                 eDebug("setting cue skipmode to %d", skipmode);
1225                 if (m_cue)
1226                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1227         }
1228         
1229         m_skipmode = skipmode;
1230         
1231         if (!m_decoder)
1232                 return -1;
1233                 
1234         if (ffratio == 0)
1235                 ; /* return m_decoder->play(); is done in caller*/
1236         else if (ffratio != 1)
1237                 return m_decoder->setFastForward(ffratio);
1238         else
1239                 return m_decoder->setTrickmode();
1240         return 0;
1241 }
1242
1243 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1244 {
1245         if (m_is_pvr || m_timeshift_enabled)
1246         {
1247                 ptr = this;
1248                 return 0;
1249         }
1250         
1251         ptr = 0;
1252         return -1;
1253 }
1254
1255         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1256 RESULT eDVBServicePlay::getLength(pts_t &len)
1257 {
1258         ePtr<iDVBPVRChannel> pvr_channel;
1259         
1260         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1261                 return -1;
1262         
1263         return pvr_channel->getLength(len);
1264 }
1265
1266 RESULT eDVBServicePlay::pause()
1267 {
1268         eDebug("eDVBServicePlay::pause");
1269         setFastForward_internal(0);
1270         if (m_decoder)
1271         {
1272                 m_is_paused = 1;
1273                 return m_decoder->pause();
1274         } else
1275                 return -1;
1276 }
1277
1278 RESULT eDVBServicePlay::unpause()
1279 {
1280         eDebug("eDVBServicePlay::unpause");
1281         setFastForward_internal(0);
1282         if (m_decoder)
1283         {
1284                 m_is_paused = 0;
1285                 return m_decoder->play();
1286         } else
1287                 return -1;
1288 }
1289
1290 RESULT eDVBServicePlay::seekTo(pts_t to)
1291 {
1292         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1293         
1294         if (!m_decode_demux)
1295                 return -1;
1296
1297         ePtr<iDVBPVRChannel> pvr_channel;
1298         
1299         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1300                 return -1;
1301         
1302         if (!m_cue)
1303                 return -1;
1304         
1305         m_cue->seekTo(0, to);
1306         m_dvb_subtitle_pages.clear();
1307         m_subtitle_pages.clear();
1308
1309         return 0;
1310 }
1311
1312 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1313 {
1314         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1315         
1316         if (!m_decode_demux)
1317                 return -1;
1318
1319         ePtr<iDVBPVRChannel> pvr_channel;
1320         
1321         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1322                 return -1;
1323         
1324         int mode = 1;
1325         
1326                         /* HACK until we have skip-AP api */
1327         if ((to > 0) && (to < 100))
1328                 mode = 2;
1329         
1330         to *= direction;
1331         
1332         if (!m_cue)
1333                 return 0;
1334         
1335         m_cue->seekTo(mode, to);
1336         m_dvb_subtitle_pages.clear();
1337         m_subtitle_pages.clear();
1338         return 0;
1339 }
1340
1341 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1342 {
1343         ePtr<iDVBPVRChannel> pvr_channel;
1344         
1345         if (!m_decode_demux)
1346                 return -1;
1347         
1348         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1349                 return -1;
1350         
1351         int r = 0;
1352
1353                 /* if there is a decoder, use audio or video PTS */
1354         if (m_decoder)
1355         {
1356                 r = m_decoder->getPTS(0, pos);
1357                 if (r)
1358                         return r;
1359         }
1360         
1361                 /* fixup */
1362         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1363 }
1364
1365 RESULT eDVBServicePlay::setTrickmode(int trick)
1366 {
1367                 /* currently unimplemented */
1368         return -1;
1369 }
1370
1371 RESULT eDVBServicePlay::isCurrentlySeekable()
1372 {
1373         return m_is_pvr || m_timeshift_active;
1374 }
1375
1376 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1377 {
1378         ptr = this;
1379         return 0;
1380 }
1381
1382 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1383 {
1384         ptr = this;
1385         return 0;
1386 }
1387
1388 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1389 {
1390         ptr = this;
1391         return 0;
1392 }
1393
1394 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1395 {
1396         ptr = this;
1397         return 0;
1398 }
1399
1400 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1401 {
1402         ptr = this;
1403         return 0;
1404 }
1405
1406 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1407 {
1408         ptr = 0;
1409         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1410                 (m_timeshift_enabled || !m_is_pvr))
1411         {
1412                 if (!m_timeshift_enabled)
1413                 {
1414                         /* query config path */
1415                         std::string tspath;
1416                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1417                                 eDebug("could not query ts path from config");
1418                                 return -4;
1419                         }
1420                         tspath.append("/");
1421                         /* we need enough diskspace */
1422                         struct statfs fs;
1423                         if (statfs(tspath.c_str(), &fs) < 0)
1424                         {
1425                                 eDebug("statfs failed!");
1426                                 return -2;
1427                         }
1428                 
1429                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1430                         {
1431                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1432                                 return -3;
1433                         }
1434                 }
1435                 ptr = this;
1436                 return 0;
1437         }
1438         return -1;
1439 }
1440
1441 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1442 {
1443         if (m_is_pvr)
1444         {
1445                 ptr = this;
1446                 return 0;
1447         }
1448         ptr = 0;
1449         return -1;
1450 }
1451
1452 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1453 {
1454         ptr = this;
1455         return 0;
1456 }
1457
1458 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1459 {
1460         ptr = this;
1461         return 0;
1462 }
1463
1464 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1465 {
1466         ptr = this;
1467         return 0;
1468 }
1469
1470 RESULT eDVBServicePlay::getName(std::string &name)
1471 {
1472         if (m_is_pvr)
1473         {
1474                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1475                 return i->getName(m_reference, name);
1476         }
1477         else if (m_dvb_service)
1478         {
1479                 m_dvb_service->getName(m_reference, name);
1480                 if (name.empty())
1481                         name = "(...)";
1482         }
1483         else if (!m_reference.name.empty())
1484                 eStaticServiceDVBInformation().getName(m_reference, name);
1485         else
1486                 name = "DVB service";
1487         return 0;
1488 }
1489
1490 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1491 {
1492         return m_event_handler.getEvent(evt, nownext);
1493 }
1494
1495 int eDVBServicePlay::getInfo(int w)
1496 {
1497         eDVBServicePMTHandler::program program;
1498
1499         if (w == sCAIDs)
1500                 return resIsPyObject;
1501
1502         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1503
1504         int no_program_info = 0;
1505
1506         if (h.getProgramInfo(program))
1507                 no_program_info = 1;
1508
1509         switch (w)
1510         {
1511         case sVideoHeight:
1512                 if (m_decoder)
1513                         return m_decoder->getVideoHeight();
1514                 break;
1515         case sVideoWidth:
1516                 if (m_decoder)
1517                         return m_decoder->getVideoWidth();
1518                 break;
1519         case sFrameRate:
1520                 if (m_decoder)
1521                         return m_decoder->getVideoFrameRate();
1522                 break;
1523         case sProgressive:
1524                 if (m_decoder)
1525                         return m_decoder->getVideoProgressive();
1526                 break;
1527         case sAspect:
1528         {
1529                 int aspect = -1;
1530                 if (m_decoder)
1531                         aspect = m_decoder->getVideoAspect();
1532                 if (aspect == -1 && no_program_info)
1533                         break;
1534                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1535                 {
1536                         ePtr<eServiceEvent> evt;
1537                         if (!m_event_handler.getEvent(evt, 0))
1538                         {
1539                                 ePtr<eComponentData> data;
1540                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1541                                 {
1542                                         if ( data->getStreamContent() == 1 )
1543                                         {
1544                                                 switch(data->getComponentType())
1545                                                 {
1546                                                         // SD
1547                                                         case 1: // 4:3 SD PAL
1548                                                         case 2:
1549                                                         case 3: // 16:9 SD PAL
1550                                                         case 4: // > 16:9 PAL
1551                                                         case 5: // 4:3 SD NTSC
1552                                                         case 6: 
1553                                                         case 7: // 16:9 SD NTSC
1554                                                         case 8: // > 16:9 NTSC
1555
1556                                                         // HD
1557                                                         case 9: // 4:3 HD PAL
1558                                                         case 0xA:
1559                                                         case 0xB: // 16:9 HD PAL
1560                                                         case 0xC: // > 16:9 HD PAL
1561                                                         case 0xD: // 4:3 HD NTSC
1562                                                         case 0xE:
1563                                                         case 0xF: // 16:9 HD NTSC
1564                                                         case 0x10: // > 16:9 HD PAL
1565                                                                 return data->getComponentType();
1566                                                 }
1567                                         }
1568                                 }
1569                         }
1570                 }
1571                 else
1572                         return aspect;
1573                 break;
1574         }
1575         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1576         case sVideoPID:
1577                 if (m_dvb_service)
1578                 {
1579                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1580                         if (vpid != -1)
1581                                 return vpid;
1582                 }
1583                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1584         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1585         case sAudioPID:
1586                 if (m_dvb_service)
1587                 {
1588                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1589                         if (apid != -1)
1590                                 return apid;
1591                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1592                         if (apid != -1)
1593                                 return apid;
1594                 }
1595                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1596         case sPCRPID:
1597                 if (m_dvb_service)
1598                 {
1599                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1600                         if (pcrpid != -1)
1601                                 return pcrpid;
1602                 }
1603                 if (no_program_info) return -1; return program.pcrPid;
1604         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1605         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1606         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1607         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1608         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1609         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1610         case sProvider: if (!m_dvb_service) return -1; return -2;
1611         case sServiceref: return resIsString;
1612         case sDVBState: return m_tune_state;
1613         default:
1614                 break;
1615         }
1616         return -1;
1617 }
1618
1619 std::string eDVBServicePlay::getInfoString(int w)
1620 {
1621         switch (w)
1622         {
1623         case sProvider:
1624                 if (!m_dvb_service) return "";
1625                 return m_dvb_service->m_provider_name;
1626         case sServiceref:
1627                 return m_reference.toString();
1628         default:
1629                 break;
1630         }
1631         return iServiceInformation::getInfoString(w);
1632 }
1633
1634 PyObject *eDVBServicePlay::getInfoObject(int w)
1635 {
1636         switch (w)
1637         {
1638         case sCAIDs:
1639                 return m_service_handler.getCaIds();
1640         case sTransponderData:
1641                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1642         default:
1643                 break;
1644         }
1645         return iServiceInformation::getInfoObject(w);
1646 }
1647
1648 int eDVBServicePlay::getNumberOfTracks()
1649 {
1650         eDVBServicePMTHandler::program program;
1651         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1652         if (h.getProgramInfo(program))
1653                 return 0;
1654         return program.audioStreams.size();
1655 }
1656
1657 int eDVBServicePlay::getCurrentTrack()
1658 {
1659         eDVBServicePMTHandler::program program;
1660         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1661         if (h.getProgramInfo(program))
1662                 return 0;
1663
1664         int max = program.audioStreams.size();
1665         int i;
1666
1667         for (i = 0; i < max; ++i)
1668                 if (program.audioStreams[i].pid == m_current_audio_pid)
1669                         return i;
1670
1671         return 0;
1672 }
1673
1674 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1675 {
1676         int ret = selectAudioStream(i);
1677
1678         if (m_decoder->set())
1679                 return -5;
1680
1681         return ret;
1682 }
1683
1684 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1685 {
1686         eDVBServicePMTHandler::program program;
1687         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1688
1689         if (h.getProgramInfo(program))
1690                 return -1;
1691         
1692         if (i >= program.audioStreams.size())
1693                 return -2;
1694         
1695         info.m_pid = program.audioStreams[i].pid;
1696
1697         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1698                 info.m_description = "MPEG";
1699         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1700                 info.m_description = "AC3";
1701         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1702                 info.m_description = "AAC";
1703         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1704                 info.m_description = "AAC-HE";
1705         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1706                 info.m_description = "DTS";
1707         else
1708                 info.m_description = "???";
1709
1710         if (program.audioStreams[i].component_tag != -1)
1711         {
1712                 ePtr<eServiceEvent> evt;
1713                 if (!m_event_handler.getEvent(evt, 0))
1714                 {
1715                         ePtr<eComponentData> data;
1716                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1717                                 info.m_language = data->getText();
1718                 }
1719         }
1720
1721         if (info.m_language.empty())
1722                 info.m_language = program.audioStreams[i].language_code;
1723         
1724         return 0;
1725 }
1726
1727 int eDVBServicePlay::selectAudioStream(int i)
1728 {
1729         eDVBServicePMTHandler::program program;
1730         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1731
1732         if (h.getProgramInfo(program))
1733                 return -1;
1734
1735         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1736                 return -2;
1737
1738         if (!m_decoder)
1739                 return -3;
1740
1741         int stream = i;
1742         if (stream == -1)
1743                 stream = program.defaultAudioStream;
1744
1745         int apid = -1, apidtype = -1;
1746
1747         if (((unsigned int)stream) < program.audioStreams.size())
1748         {
1749                 apid = program.audioStreams[stream].pid;
1750                 apidtype = program.audioStreams[stream].type;
1751         }
1752
1753         m_current_audio_pid = apid;
1754
1755         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1756         {
1757                 eDebug("set audio pid failed");
1758                 return -4;
1759         }
1760
1761         int rdsPid = apid;
1762
1763                 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1764         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1765         {
1766                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1767                 if (different_pid)
1768                         rdsPid = program.audioStreams[stream].rdsPid;
1769                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1770                 {
1771                         m_rds_decoder = 0;
1772                         ePtr<iDVBDemux> data_demux;
1773                         if (!h.getDataDemux(data_demux))
1774                         {
1775                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1776                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1777                                 m_rds_decoder->start(rdsPid);
1778                         }
1779                 }
1780         }
1781
1782                         /* store new pid as default only when:
1783                                 a.) we have an entry in the service db for the current service,
1784                                 b.) we are not playing back something,
1785                                 c.) we are not selecting the default entry. (we wouldn't change 
1786                                     anything in the best case, or destroy the default setting in
1787                                     case the real default is not yet available.)
1788                         */
1789         if (m_dvb_service && ((i != -1)
1790                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1791         {
1792                 if (apidtype == eDVBAudio::aMPEG)
1793                 {
1794                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1795                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1796                 }
1797                 else if (apidtype == eDVBAudio::aAC3)
1798                 {
1799                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1800                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1801                 }
1802                 else
1803                 {
1804                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1805                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1806                 }
1807         }
1808
1809         h.resetCachedProgram();
1810
1811         return 0;
1812 }
1813
1814 int eDVBServicePlay::getCurrentChannel()
1815 {
1816         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1817 }
1818
1819 RESULT eDVBServicePlay::selectChannel(int i)
1820 {
1821         if (i < LEFT || i > RIGHT || i == STEREO)
1822                 i = -1;  // Stereo
1823         if (m_dvb_service)
1824                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1825         if (m_decoder)
1826                 m_decoder->setAudioChannel(i);
1827         return 0;
1828 }
1829
1830 std::string eDVBServicePlay::getText(int x)
1831 {
1832         if (m_rds_decoder)
1833                 switch(x)
1834                 {
1835                         case RadioText:
1836                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1837                         case RtpText:
1838                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1839                 }
1840         return "";
1841 }
1842
1843 void eDVBServicePlay::rdsDecoderEvent(int what)
1844 {
1845         switch(what)
1846         {
1847                 case eDVBRdsDecoder::RadioTextChanged:
1848                         m_event((iPlayableService*)this, evUpdatedRadioText);
1849                         break;
1850                 case eDVBRdsDecoder::RtpTextChanged:
1851                         m_event((iPlayableService*)this, evUpdatedRtpText);
1852                         break;
1853                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1854                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1855                         break;
1856                 case eDVBRdsDecoder::RecvRassSlidePic:
1857                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1858                         break;
1859         }
1860 }
1861
1862 void eDVBServicePlay::showRassSlidePicture()
1863 {
1864         if (m_rds_decoder)
1865         {
1866                 if (m_decoder)
1867                 {
1868                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1869                         if (rass_slide_pic.length())
1870                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1871                         else
1872                                 eDebug("empty filename for rass slide picture received!!");
1873                 }
1874                 else
1875                         eDebug("no MPEG Decoder to show iframes avail");
1876         }
1877         else
1878                 eDebug("showRassSlidePicture called.. but not decoder");
1879 }
1880
1881 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1882 {
1883         if (m_rds_decoder)
1884         {
1885                 if (m_decoder)
1886                 {
1887                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1888                         if (rass_interactive_pic.length())
1889                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1890                         else
1891                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1892                 }
1893                 else
1894                         eDebug("no MPEG Decoder to show iframes avail");
1895         }
1896         else
1897                 eDebug("showRassInteractivePic called.. but not decoder");
1898 }
1899
1900 ePyObject eDVBServicePlay::getRassInteractiveMask()
1901 {
1902         if (m_rds_decoder)
1903                 return m_rds_decoder->getRassPictureMask();
1904         Py_RETURN_NONE;
1905 }
1906
1907 int eDVBServiceBase::getFrontendInfo(int w)
1908 {
1909         eUsePtr<iDVBChannel> channel;
1910         if(m_service_handler.getChannel(channel))
1911                 return 0;
1912         ePtr<iDVBFrontend> fe;
1913         if(channel->getFrontend(fe))
1914                 return 0;
1915         return fe->readFrontendData(w);
1916 }
1917
1918 PyObject *eDVBServiceBase::getFrontendData()
1919 {
1920         ePyObject ret = PyDict_New();
1921         if (ret)
1922         {
1923                 eUsePtr<iDVBChannel> channel;
1924                 if(!m_service_handler.getChannel(channel))
1925                 {
1926                         ePtr<iDVBFrontend> fe;
1927                         if(!channel->getFrontend(fe))
1928                                 fe->getFrontendData(ret);
1929                 }
1930         }
1931         else
1932                 Py_RETURN_NONE;
1933         return ret;
1934 }
1935
1936 PyObject *eDVBServiceBase::getFrontendStatus()
1937 {
1938         ePyObject ret = PyDict_New();
1939         if (ret)
1940         {
1941                 eUsePtr<iDVBChannel> channel;
1942                 if(!m_service_handler.getChannel(channel))
1943                 {
1944                         ePtr<iDVBFrontend> fe;
1945                         if(!channel->getFrontend(fe))
1946                                 fe->getFrontendStatus(ret);
1947                 }
1948         }
1949         else
1950                 Py_RETURN_NONE;
1951         return ret;
1952 }
1953
1954 PyObject *eDVBServiceBase::getTransponderData(bool original)
1955 {
1956         ePyObject ret = PyDict_New();
1957         if (ret)
1958         {
1959                 eUsePtr<iDVBChannel> channel;
1960                 if(!m_service_handler.getChannel(channel))
1961                 {
1962                         ePtr<iDVBFrontend> fe;
1963                         if(!channel->getFrontend(fe))
1964                                 fe->getTransponderData(ret, original);
1965                 }
1966         }
1967         else
1968                 Py_RETURN_NONE;
1969         return ret;
1970 }
1971
1972 PyObject *eDVBServiceBase::getAll(bool original)
1973 {
1974         ePyObject ret = getTransponderData(original);
1975         if (ret != Py_None)
1976         {
1977                 eUsePtr<iDVBChannel> channel;
1978                 if(!m_service_handler.getChannel(channel))
1979                 {
1980                         ePtr<iDVBFrontend> fe;
1981                         if(!channel->getFrontend(fe))
1982                         {
1983                                 fe->getFrontendData(ret);
1984                                 fe->getFrontendStatus(ret);
1985                         }
1986                 }
1987         }
1988         return ret;
1989 }
1990
1991 int eDVBServicePlay::getNumberOfSubservices()
1992 {
1993         ePtr<eServiceEvent> evt;
1994         if (!m_event_handler.getEvent(evt, 0))
1995                 return evt->getNumOfLinkageServices();
1996         return 0;
1997 }
1998
1999 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2000 {
2001         ePtr<eServiceEvent> evt;
2002         if (!m_event_handler.getEvent(evt, 0))
2003         {
2004                 if (!evt->getLinkageService(sub, m_reference, n))
2005                         return 0;
2006         }
2007         sub.type=eServiceReference::idInvalid;
2008         return -1;
2009 }
2010
2011 RESULT eDVBServicePlay::startTimeshift()
2012 {
2013         ePtr<iDVBDemux> demux;
2014         
2015         eDebug("Start timeshift!");
2016         
2017         if (m_timeshift_enabled)
2018                 return -1;
2019         
2020                 /* start recording with the data demux. */
2021         if (m_service_handler.getDataDemux(demux))
2022                 return -2;
2023
2024         demux->createTSRecorder(m_record);
2025         if (!m_record)
2026                 return -3;
2027
2028         std::string tspath;
2029         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2030                 eDebug("could not query ts path");
2031                 return -5;
2032         }
2033         tspath.append("/timeshift.XXXXXX");
2034         char* templ;
2035         templ = new char[tspath.length() + 1];
2036         strcpy(templ, tspath.c_str());
2037
2038         m_timeshift_fd = mkstemp(templ);
2039         m_timeshift_file = std::string(templ);
2040
2041         eDebug("recording to %s", templ);
2042
2043         delete [] templ;
2044
2045         if (m_timeshift_fd < 0)
2046         {
2047                 m_record = 0;
2048                 return -4;
2049         }
2050                 
2051         m_record->setTargetFD(m_timeshift_fd);
2052
2053         m_timeshift_enabled = 1;
2054         
2055         updateTimeshiftPids();
2056         m_record->start();
2057
2058         return 0;
2059 }
2060
2061 RESULT eDVBServicePlay::stopTimeshift()
2062 {
2063         if (!m_timeshift_enabled)
2064                 return -1;
2065         
2066         switchToLive();
2067         
2068         m_timeshift_enabled = 0;
2069         
2070         m_record->stop();
2071         m_record = 0;
2072         
2073         close(m_timeshift_fd);
2074         eDebug("remove timeshift file");
2075         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2076         
2077         return 0;
2078 }
2079
2080 int eDVBServicePlay::isTimeshiftActive()
2081 {
2082         return m_timeshift_enabled && m_timeshift_active;
2083 }
2084
2085 RESULT eDVBServicePlay::activateTimeshift()
2086 {
2087         if (!m_timeshift_enabled)
2088                 return -1;
2089         
2090         if (!m_timeshift_active)
2091         {
2092                 switchToTimeshift();
2093                 return 0;
2094         }
2095         
2096         return -2;
2097 }
2098
2099 PyObject *eDVBServicePlay::getCutList()
2100 {
2101         ePyObject list = PyList_New(0);
2102         
2103         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2104         {
2105                 ePyObject tuple = PyTuple_New(2);
2106                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2107                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2108                 PyList_Append(list, tuple);
2109                 Py_DECREF(tuple);
2110         }
2111         
2112         return list;
2113 }
2114
2115 void eDVBServicePlay::setCutList(ePyObject list)
2116 {
2117         if (!PyList_Check(list))
2118                 return;
2119         int size = PyList_Size(list);
2120         int i;
2121         
2122         m_cue_entries.clear();
2123         
2124         for (i=0; i<size; ++i)
2125         {
2126                 ePyObject tuple = PyList_GET_ITEM(list, i);
2127                 if (!PyTuple_Check(tuple))
2128                 {
2129                         eDebug("non-tuple in cutlist");
2130                         continue;
2131                 }
2132                 if (PyTuple_Size(tuple) != 2)
2133                 {
2134                         eDebug("cutlist entries need to be a 2-tuple");
2135                         continue;
2136                 }
2137                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2138                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2139                 {
2140                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2141                         continue;
2142                 }
2143                 pts_t pts = PyLong_AsLongLong(ppts);
2144                 int type = PyInt_AsLong(ptype);
2145                 m_cue_entries.insert(cueEntry(pts, type));
2146                 eDebug("adding %08llx, %d", pts, type);
2147         }
2148         m_cuesheet_changed = 1;
2149         
2150         cutlistToCuesheet();
2151         m_event((iPlayableService*)this, evCuesheetChanged);
2152 }
2153
2154 void eDVBServicePlay::setCutListEnable(int enable)
2155 {
2156         m_cutlist_enabled = enable;
2157         cutlistToCuesheet();
2158 }
2159
2160 void eDVBServicePlay::updateTimeshiftPids()
2161 {
2162         if (!m_record)
2163                 return;
2164         
2165         eDVBServicePMTHandler::program program;
2166         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2167
2168         if (h.getProgramInfo(program))
2169                 return;
2170         else
2171         {
2172                 std::set<int> pids_to_record;
2173                 pids_to_record.insert(0); // PAT
2174                 if (program.pmtPid != -1)
2175                         pids_to_record.insert(program.pmtPid); // PMT
2176
2177                 if (program.textPid != -1)
2178                         pids_to_record.insert(program.textPid); // Videotext
2179
2180                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2181                         i(program.videoStreams.begin()); 
2182                         i != program.videoStreams.end(); ++i)
2183                         pids_to_record.insert(i->pid);
2184
2185                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2186                         i(program.audioStreams.begin()); 
2187                         i != program.audioStreams.end(); ++i)
2188                                 pids_to_record.insert(i->pid);
2189
2190                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2191                         i(program.subtitleStreams.begin());
2192                         i != program.subtitleStreams.end(); ++i)
2193                                 pids_to_record.insert(i->pid);
2194
2195                 std::set<int> new_pids, obsolete_pids;
2196                 
2197                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2198                                 m_pids_active.begin(), m_pids_active.end(),
2199                                 std::inserter(new_pids, new_pids.begin()));
2200                 
2201                 std::set_difference(
2202                                 m_pids_active.begin(), m_pids_active.end(),
2203                                 pids_to_record.begin(), pids_to_record.end(), 
2204                                 std::inserter(new_pids, new_pids.begin())
2205                                 );
2206
2207                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2208                         m_record->addPID(*i);
2209
2210                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2211                         m_record->removePID(*i);
2212         }
2213 }
2214
2215 void eDVBServicePlay::switchToLive()
2216 {
2217         if (!m_timeshift_active)
2218                 return;
2219         
2220         eDebug("SwitchToLive");
2221         
2222         m_cue = 0;
2223         m_decoder = 0;
2224         m_decode_demux = 0;
2225         m_teletext_parser = 0;
2226         m_rds_decoder = 0;
2227         m_subtitle_parser = 0;
2228         m_new_dvb_subtitle_page_connection = 0;
2229         m_new_subtitle_page_connection = 0;
2230         m_rds_decoder_event_connection = 0;
2231         m_video_event_connection = 0;
2232         m_is_paused = m_skipmode = 0; /* not supported in live mode */
2233
2234                 /* free the timeshift service handler, we need the resources */
2235         m_service_handler_timeshift.free();
2236         m_timeshift_active = 0;
2237         m_timeshift_changed = 1;
2238
2239         m_event((iPlayableService*)this, evSeekableStatusChanged);
2240
2241         updateDecoder();
2242 }
2243
2244 void eDVBServicePlay::switchToTimeshift()
2245 {
2246         if (m_timeshift_active)
2247                 return;
2248
2249         m_decode_demux = 0;
2250         m_decoder = 0;
2251         m_teletext_parser = 0;
2252         m_rds_decoder = 0;
2253         m_subtitle_parser = 0;
2254         m_new_subtitle_page_connection = 0;
2255         m_new_dvb_subtitle_page_connection = 0;
2256         m_rds_decoder_event_connection = 0;
2257         m_video_event_connection = 0;
2258
2259         m_timeshift_active = 1;
2260         m_timeshift_changed = 1;
2261
2262         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2263         r.path = m_timeshift_file;
2264
2265         m_cue = new eCueSheet();
2266         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2267
2268         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2269         pause();
2270         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2271         
2272         m_event((iPlayableService*)this, evSeekableStatusChanged);
2273 }
2274
2275 void eDVBServicePlay::updateDecoder()
2276 {
2277         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2278
2279         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2280
2281         eDVBServicePMTHandler::program program;
2282         if (h.getProgramInfo(program))
2283                 eDebug("getting program info failed.");
2284         else
2285         {
2286                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2287                 if (!program.videoStreams.empty())
2288                 {
2289                         eDebugNoNewLine(" (");
2290                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2291                                 i(program.videoStreams.begin());
2292                                 i != program.videoStreams.end(); ++i)
2293                         {
2294                                 if (vpid == -1)
2295                                 {
2296                                         vpid = i->pid;
2297                                         vpidtype = i->type;
2298                                 }
2299                                 if (i != program.videoStreams.begin())
2300                                         eDebugNoNewLine(", ");
2301                                 eDebugNoNewLine("%04x", i->pid);
2302                         }
2303                         eDebugNoNewLine(")");
2304                 }
2305                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2306                 if (!program.audioStreams.empty())
2307                 {
2308                         eDebugNoNewLine(" (");
2309                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2310                                 i(program.audioStreams.begin());
2311                                 i != program.audioStreams.end(); ++i)
2312                         {
2313                                 if (i != program.audioStreams.begin())
2314                                         eDebugNoNewLine(", ");
2315                                 eDebugNoNewLine("%04x", i->pid);
2316                         }
2317                         eDebugNoNewLine(")");
2318                 }
2319                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2320                 pcrpid = program.pcrPid;
2321                 eDebug(", and the text pid is %04x", program.textPid);
2322                 tpid = program.textPid;
2323         }
2324
2325         if (!m_decoder)
2326         {
2327                 h.getDecodeDemux(m_decode_demux);
2328                 if (m_timeshift_changed)
2329                         m_decoder = 0;
2330                 if (m_decode_demux)
2331                 {
2332                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2333                         if (m_decoder)
2334                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2335                         if (m_is_primary)
2336                         {
2337                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2338                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2339                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2340                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2341                                 if (m_timeshift_changed)
2342                                 {
2343                                         ePyObject subs = getCachedSubtitle();
2344                                         if (subs != Py_None)
2345                                         {
2346                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2347                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2348                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2349                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2350                                                 if (type == 0) // dvb
2351                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2352                                                 else if (type == 1) // ttx
2353                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2354                                         }
2355                                         Py_DECREF(subs);
2356                                 }
2357                         }
2358                         m_decoder->play(); /* pids will be set later */
2359                 }
2360                 if (m_cue)
2361                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2362                 m_decoder->play(); /* pids will be set later. */
2363         }
2364
2365         m_timeshift_changed = 0;
2366
2367         if (m_decoder)
2368         {
2369                 if (m_dvb_service)
2370                 {
2371                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2372                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2373                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2374                 }
2375                 else // subservice
2376                 {
2377                         eServiceReferenceDVB ref;
2378                         m_service_handler.getServiceReference(ref);
2379                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2380                         if (!parent)
2381                                 parent = ref;
2382                         if (parent)
2383                         {
2384                                 ePtr<eDVBResourceManager> res_mgr;
2385                                 if (!eDVBResourceManager::getInstance(res_mgr))
2386                                 {
2387                                         ePtr<iDVBChannelList> db;
2388                                         if (!res_mgr->getChannelList(db))
2389                                         {
2390                                                 ePtr<eDVBService> origService;
2391                                                 if (!db->getService(parent, origService))
2392                                                 {
2393                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2394                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2395                                                 }
2396                                         }
2397                                 }
2398                         }
2399                 }
2400
2401                 std::string config_delay;
2402                 int config_delay_int = 0;
2403                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2404                         config_delay_int = atoi(config_delay.c_str());
2405                 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2406
2407                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2408                         config_delay_int = atoi(config_delay.c_str());
2409                 else
2410                         config_delay_int = 0;
2411                 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2412
2413                 m_decoder->setVideoPID(vpid, vpidtype);
2414                 selectAudioStream();
2415
2416                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2417                         m_decoder->setSyncPCR(pcrpid);
2418                 else
2419                         m_decoder->setSyncPCR(-1);
2420
2421                 if (m_is_primary)
2422                 {
2423                         m_decoder->setTextPID(tpid);
2424                         m_teletext_parser->start(program.textPid);
2425                 }
2426
2427                 if (vpid > 0 && vpid < 0x2000)
2428                         ;
2429                 else
2430                 {
2431                         std::string radio_pic;
2432                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2433                                 m_decoder->setRadioPic(radio_pic);
2434                 }
2435
2436                 m_decoder->set();
2437                 m_decoder->setAudioChannel(achannel);
2438
2439                 /* don't worry about non-existing services, nor pvr services */
2440                 if (m_dvb_service)
2441                 {
2442                                 /* (audio pid will be set in selectAudioTrack */
2443                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2444                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2445                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2446                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2447                 }
2448         }
2449         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2450 }
2451
2452 void eDVBServicePlay::loadCuesheet()
2453 {
2454         std::string filename = m_reference.path + ".cuts";
2455         
2456         m_cue_entries.clear();
2457
2458         FILE *f = fopen(filename.c_str(), "rb");
2459
2460         if (f)
2461         {
2462                 eDebug("loading cuts..");
2463                 while (1)
2464                 {
2465                         unsigned long long where;
2466                         unsigned int what;
2467                         
2468                         if (!fread(&where, sizeof(where), 1, f))
2469                                 break;
2470                         if (!fread(&what, sizeof(what), 1, f))
2471                                 break;
2472                         
2473 #if BYTE_ORDER == LITTLE_ENDIAN
2474                         where = bswap_64(where);
2475 #endif
2476                         what = ntohl(what);
2477                         
2478                         if (what > 3)
2479                                 break;
2480                         
2481                         m_cue_entries.insert(cueEntry(where, what));
2482                 }
2483                 fclose(f);
2484                 eDebug("%d entries", m_cue_entries.size());
2485         } else
2486                 eDebug("cutfile not found!");
2487         
2488         m_cuesheet_changed = 0;
2489         cutlistToCuesheet();
2490         m_event((iPlayableService*)this, evCuesheetChanged);
2491 }
2492
2493 void eDVBServicePlay::saveCuesheet()
2494 {
2495         std::string filename = m_reference.path + ".cuts";
2496         
2497         FILE *f = fopen(filename.c_str(), "wb");
2498
2499         if (f)
2500         {
2501                 unsigned long long where;
2502                 int what;
2503
2504                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2505                 {
2506 #if BYTE_ORDER == BIG_ENDIAN
2507                         where = i->where;
2508 #else
2509                         where = bswap_64(i->where);
2510 #endif
2511                         what = htonl(i->what);
2512                         fwrite(&where, sizeof(where), 1, f);
2513                         fwrite(&what, sizeof(what), 1, f);
2514                         
2515                 }
2516                 fclose(f);
2517         }
2518         
2519         m_cuesheet_changed = 0;
2520 }
2521
2522 void eDVBServicePlay::cutlistToCuesheet()
2523 {
2524         if (!m_cue)
2525         {
2526                 eDebug("no cue sheet");
2527                 return;
2528         }       
2529         m_cue->clear();
2530         
2531         if (!m_cutlist_enabled)
2532         {
2533                 m_cue->commitSpans();
2534                 eDebug("cutlists were disabled");
2535                 return;
2536         }
2537
2538         pts_t in = 0, out = 0, length = 0;
2539         
2540         getLength(length);
2541                 
2542         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2543         
2544         int have_any_span = 0;
2545         
2546         while (1)
2547         {
2548                 if (i == m_cue_entries.end())
2549                 {
2550                         if (!have_any_span)
2551                                 break;
2552                         out = length;
2553                 } else {
2554                         if (i->what == 0) /* in */
2555                         {
2556                                 in = i++->where;
2557                                 continue;
2558                         } else if (i->what == 1) /* out */
2559                                 out = i++->where;
2560                         else /* mark (2) or last play position (3) */
2561                         {
2562                                 i++;
2563                                 continue;
2564                         }
2565                 }
2566                 
2567                 if (in < 0)
2568                         in = 0;
2569                 if (out < 0)
2570                         out = 0;
2571                 if (in > length)
2572                         in = length;
2573                 if (out > length)
2574                         out = length;
2575                 
2576                 if (in < out)
2577                 {
2578                         have_any_span = 1;
2579                         m_cue->addSourceSpan(in, out);
2580                 }
2581                 
2582                 in = length;
2583                 
2584                 if (i == m_cue_entries.end())
2585                         break;
2586         }
2587         m_cue->commitSpans();
2588 }
2589
2590 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2591 {
2592         if (m_subtitle_widget)
2593                 disableSubtitles(parent);
2594
2595         ePyObject entry;
2596         int tuplesize = PyTuple_Size(tuple);
2597         int type = 0;
2598
2599         if (!PyTuple_Check(tuple))
2600                 goto error_out;
2601
2602         if (tuplesize < 1)
2603                 goto error_out;
2604
2605         entry = PyTuple_GET_ITEM(tuple, 0);
2606
2607         if (!PyInt_Check(entry))
2608                 goto error_out;
2609
2610         type = PyInt_AsLong(entry);
2611
2612         if (type == 1)  // teletext subtitles
2613         {
2614                 int page, magazine, pid;
2615                 if (tuplesize < 4)
2616                         goto error_out;
2617
2618                 if (!m_teletext_parser)
2619                 {
2620                         eDebug("enable teletext subtitles.. no parser !!!");
2621                         return -1;
2622                 }
2623
2624                 entry = PyTuple_GET_ITEM(tuple, 1);
2625                 if (!PyInt_Check(entry))
2626                         goto error_out;
2627                 pid = PyInt_AsLong(entry);
2628
2629                 entry = PyTuple_GET_ITEM(tuple, 2);
2630                 if (!PyInt_Check(entry))
2631                         goto error_out;
2632                 page = PyInt_AsLong(entry);
2633
2634                 entry = PyTuple_GET_ITEM(tuple, 3);
2635                 if (!PyInt_Check(entry))
2636                         goto error_out;
2637                 magazine = PyInt_AsLong(entry);
2638
2639                 m_subtitle_widget = new eSubtitleWidget(parent);
2640                 m_subtitle_widget->resize(parent->size()); /* full size */
2641                 m_teletext_parser->setPageAndMagazine(page, magazine);
2642                 if (m_dvb_service)
2643                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2644         }
2645         else if (type == 0)
2646         {
2647                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2648                 if (!m_subtitle_parser)
2649                 {
2650                         eDebug("enable dvb subtitles.. no parser !!!");
2651                         return -1;
2652                 }
2653                 if (tuplesize < 4)
2654                         goto error_out;
2655
2656                 entry = PyTuple_GET_ITEM(tuple, 1);
2657                 if (!PyInt_Check(entry))
2658                         goto error_out;
2659                 pid = PyInt_AsLong(entry);
2660
2661                 entry = PyTuple_GET_ITEM(tuple, 2);
2662                 if (!PyInt_Check(entry))
2663                         goto error_out;
2664                 composition_page_id = PyInt_AsLong(entry);
2665
2666                 entry = PyTuple_GET_ITEM(tuple, 3);
2667                 if (!PyInt_Check(entry))
2668                         goto error_out;
2669                 ancillary_page_id = PyInt_AsLong(entry);
2670
2671                 m_subtitle_widget = new eSubtitleWidget(parent);
2672                 m_subtitle_widget->resize(parent->size()); /* full size */
2673                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2674                 if (m_dvb_service)
2675                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2676         }
2677         else
2678                 goto error_out;
2679         return 0;
2680 error_out:
2681         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2682                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2683                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2684         return -1;
2685 }
2686
2687 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2688 {
2689         delete m_subtitle_widget;
2690         m_subtitle_widget = 0;
2691         if (m_subtitle_parser)
2692         {
2693                 m_subtitle_parser->stop();
2694                 m_dvb_subtitle_pages.clear();
2695         }
2696         if (m_teletext_parser)
2697         {
2698                 m_teletext_parser->setPageAndMagazine(-1, -1);
2699                 m_subtitle_pages.clear();
2700         }
2701         if (m_dvb_service)
2702                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2703         return 0;
2704 }
2705
2706 PyObject *eDVBServicePlay::getCachedSubtitle()
2707 {
2708         if (m_dvb_service)
2709         {
2710                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2711                 if (tmp != -1)
2712                 {
2713                         unsigned int data = (unsigned int)tmp;
2714                         int pid = (data&0xFFFF0000)>>16;
2715                         ePyObject tuple = PyTuple_New(4);
2716                         eDVBServicePMTHandler::program program;
2717                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2718                         if (!h.getProgramInfo(program))
2719                         {
2720                                 if (program.textPid==pid) // teletext
2721                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2722                                 else
2723                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2724                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2725                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2726                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2727                                 return tuple;
2728                         }
2729                 }
2730         }
2731         Py_RETURN_NONE;
2732 }
2733
2734 PyObject *eDVBServicePlay::getSubtitleList()
2735 {
2736         if (!m_teletext_parser)
2737                 Py_RETURN_NONE;
2738         
2739         ePyObject l = PyList_New(0);
2740         std::set<int> added_ttx_pages;
2741
2742         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2743                 m_teletext_parser->m_found_subtitle_pages;
2744
2745         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2746         eDVBServicePMTHandler::program program;
2747         if (h.getProgramInfo(program))
2748                 eDebug("getting program info failed.");
2749         else
2750         {
2751                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2752                         it != program.subtitleStreams.end(); ++it)
2753                 {
2754                         switch(it->subtitling_type)
2755                         {
2756                                 case 0x01: // ebu teletext subtitles
2757                                 {
2758                                         int page_number = it->teletext_page_number & 0xFF;
2759                                         int magazine_number = it->teletext_magazine_number & 7;
2760                                         int hash = magazine_number << 8 | page_number;
2761                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2762                                         {
2763                                                 ePyObject tuple = PyTuple_New(5);
2764                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2765                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2766                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2767                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2768                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2769                                                 PyList_Append(l, tuple);
2770                                                 Py_DECREF(tuple);
2771                                                 added_ttx_pages.insert(hash);
2772                                         }
2773                                         break;
2774                                 }
2775                                 case 0x10 ... 0x13:
2776                                 case 0x20 ... 0x23: // dvb subtitles
2777                                 {
2778                                         ePyObject tuple = PyTuple_New(5);
2779                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2780                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2781                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2782                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2783                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2784                                         PyList_Insert(l, 0, tuple);
2785                                         Py_DECREF(tuple);
2786                                         break;
2787                                 }
2788                         }
2789                 }
2790         }
2791
2792         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2793                 it != subs.end(); ++it)
2794         {
2795                 int page_number = it->teletext_page_number & 0xFF;
2796                 int magazine_number = it->teletext_magazine_number & 7;
2797                 int hash = magazine_number << 8 | page_number;
2798                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2799                 {
2800                         ePyObject tuple = PyTuple_New(5);
2801                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2802                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2803                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2804                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2805                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2806                         PyList_Append(l, tuple);
2807                         Py_DECREF(tuple);
2808                 }
2809         }
2810
2811         return l;
2812 }
2813
2814 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2815 {
2816         if (m_subtitle_widget)
2817         {
2818                 pts_t pos = 0;
2819                 if (m_decoder)
2820                         m_decoder->getPTS(0, pos);
2821                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2822                 m_subtitle_pages.push_back(page);
2823                 checkSubtitleTiming();
2824         }
2825 }
2826
2827 void eDVBServicePlay::checkSubtitleTiming()
2828 {
2829         eDebug("checkSubtitleTiming");
2830         if (!m_subtitle_widget)
2831                 return;
2832         while (1)
2833         {
2834                 enum { TELETEXT, DVB } type;
2835                 eDVBTeletextSubtitlePage page;
2836                 eDVBSubtitlePage dvb_page;
2837                 pts_t show_time;
2838                 if (!m_subtitle_pages.empty())
2839                 {
2840                         page = m_subtitle_pages.front();
2841                         type = TELETEXT;
2842                         show_time = page.m_pts;
2843                 }
2844                 else if (!m_dvb_subtitle_pages.empty())
2845                 {
2846                         dvb_page = m_dvb_subtitle_pages.front();
2847                         type = DVB;
2848                         show_time = dvb_page.m_show_time;
2849                 }
2850                 else
2851                         return;
2852         
2853                 pts_t pos = 0;
2854         
2855                 if (m_decoder)
2856                         m_decoder->getPTS(0, pos);
2857
2858                 eDebug("%lld %lld", pos, show_time);
2859                 int diff = show_time - pos;
2860                 if (type == TELETEXT && !page.m_have_pts)
2861                 {
2862                         eDebug("ttx subtitle page without pts... immediate show");
2863                         diff = 0;
2864                 }
2865                 if (diff < 0)
2866                 {
2867                         eDebug("[late (%d ms)]", -diff / 90);
2868                         diff = 0;
2869                 }
2870                 if (abs(diff) > 1800000)
2871                 {
2872                         eDebug("[invalid]... immediate show!");
2873                         diff = 0;
2874                 }
2875                 if ((diff/90)<20)
2876                 {
2877                         if (type == TELETEXT)
2878                         {
2879                                 eDebug("display teletext subtitle page %lld", show_time);
2880                                 m_subtitle_widget->setPage(page);
2881                                 m_subtitle_pages.pop_front();
2882                         }
2883                         else
2884                         {
2885                                 eDebug("display dvb subtitle Page %lld", show_time);
2886                                 m_subtitle_widget->setPage(dvb_page);
2887                                 m_dvb_subtitle_pages.pop_front();
2888                         }
2889                 } else
2890                 {
2891                         eDebug("start subtitle delay %d", diff / 90);
2892                         m_subtitle_sync_timer->start(diff / 90, 1);
2893                         break;
2894                 }
2895         }
2896 }
2897
2898 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2899 {
2900         if (m_subtitle_widget)
2901         {
2902                 pts_t pos = 0;
2903                 if (m_decoder)
2904                         m_decoder->getPTS(0, pos);
2905                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2906                 m_dvb_subtitle_pages.push_back(p);
2907                 checkSubtitleTiming();
2908         }
2909 }
2910
2911 int eDVBServicePlay::getAC3Delay()
2912 {
2913         if (m_dvb_service)
2914                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2915         else if (m_decoder)
2916                 return m_decoder->getAC3Delay();
2917         else
2918                 return 0;
2919 }
2920
2921 int eDVBServicePlay::getPCMDelay()
2922 {
2923         if (m_dvb_service)
2924                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2925         else if (m_decoder)
2926                 return m_decoder->getPCMDelay();
2927         else
2928                 return 0;
2929 }
2930
2931 void eDVBServicePlay::setAC3Delay(int delay)
2932 {
2933         if (m_dvb_service)
2934                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2935         if (m_decoder)
2936                 m_decoder->setAC3Delay(delay);
2937 }
2938
2939 void eDVBServicePlay::setPCMDelay(int delay)
2940 {
2941         if (m_dvb_service)
2942                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2943         if (m_decoder)
2944                 m_decoder->setPCMDelay(delay);
2945 }
2946
2947 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2948 {
2949         switch(event.type) {
2950                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2951                         m_event((iPlayableService*)this, evVideoSizeChanged);
2952                         break;
2953                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2954                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2955                         break;
2956                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2957                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2958                         break;
2959                 default:
2960                         break;
2961         }
2962 }
2963
2964 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2965 {
2966         ptr = this;
2967         return 0;
2968 }
2969
2970 PyObject *eDVBServicePlay::getStreamingData()
2971 {
2972         eDVBServicePMTHandler::program program;
2973         if (m_service_handler.getProgramInfo(program))
2974         {
2975                 Py_RETURN_NONE;
2976         }
2977
2978         ePyObject r = program.createPythonObject();
2979         ePtr<iDVBDemux> demux;
2980         if (!m_service_handler.getDataDemux(demux))
2981         {
2982                 uint8_t demux_id;
2983                 if (!demux->getCADemuxID(demux_id))
2984                         PutToDict(r, "demux", demux_id);
2985         }
2986
2987         return r;
2988 }
2989
2990
2991 DEFINE_REF(eDVBServicePlay)
2992
2993 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2994 {
2995         switch (w)
2996         {
2997         case iServiceInformation::sTransponderData:
2998                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2999         default:
3000                 break;
3001         }
3002         return iStaticServiceInformation::getInfoObject(ref, w);
3003 }
3004
3005 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");