servicedvb.cpp: also disable fast winding for only audio ts files
[vuplus_dvbapp] / 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         int ret = 0;
1374         if (m_decoder)
1375         {
1376                 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1377                 if (m_decoder->getVideoWidth() == -1)
1378                         ret &= ~2;
1379         }
1380         return ret;
1381 }
1382
1383 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1384 {
1385         ptr = this;
1386         return 0;
1387 }
1388
1389 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1390 {
1391         ptr = this;
1392         return 0;
1393 }
1394
1395 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1396 {
1397         ptr = this;
1398         return 0;
1399 }
1400
1401 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1402 {
1403         ptr = this;
1404         return 0;
1405 }
1406
1407 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1408 {
1409         ptr = this;
1410         return 0;
1411 }
1412
1413 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1414 {
1415         ptr = 0;
1416         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1417                 (m_timeshift_enabled || !m_is_pvr))
1418         {
1419                 if (!m_timeshift_enabled)
1420                 {
1421                         /* query config path */
1422                         std::string tspath;
1423                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1424                                 eDebug("could not query ts path from config");
1425                                 return -4;
1426                         }
1427                         tspath.append("/");
1428                         /* we need enough diskspace */
1429                         struct statfs fs;
1430                         if (statfs(tspath.c_str(), &fs) < 0)
1431                         {
1432                                 eDebug("statfs failed!");
1433                                 return -2;
1434                         }
1435                 
1436                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1437                         {
1438                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1439                                 return -3;
1440                         }
1441                 }
1442                 ptr = this;
1443                 return 0;
1444         }
1445         return -1;
1446 }
1447
1448 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1449 {
1450         if (m_is_pvr)
1451         {
1452                 ptr = this;
1453                 return 0;
1454         }
1455         ptr = 0;
1456         return -1;
1457 }
1458
1459 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1460 {
1461         ptr = this;
1462         return 0;
1463 }
1464
1465 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1466 {
1467         ptr = this;
1468         return 0;
1469 }
1470
1471 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1472 {
1473         ptr = this;
1474         return 0;
1475 }
1476
1477 RESULT eDVBServicePlay::getName(std::string &name)
1478 {
1479         if (m_is_pvr)
1480         {
1481                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1482                 return i->getName(m_reference, name);
1483         }
1484         else if (m_dvb_service)
1485         {
1486                 m_dvb_service->getName(m_reference, name);
1487                 if (name.empty())
1488                         name = "(...)";
1489         }
1490         else if (!m_reference.name.empty())
1491                 eStaticServiceDVBInformation().getName(m_reference, name);
1492         else
1493                 name = "DVB service";
1494         return 0;
1495 }
1496
1497 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1498 {
1499         return m_event_handler.getEvent(evt, nownext);
1500 }
1501
1502 int eDVBServicePlay::getInfo(int w)
1503 {
1504         eDVBServicePMTHandler::program program;
1505
1506         if (w == sCAIDs)
1507                 return resIsPyObject;
1508
1509         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1510
1511         int no_program_info = 0;
1512
1513         if (h.getProgramInfo(program))
1514                 no_program_info = 1;
1515
1516         switch (w)
1517         {
1518         case sVideoHeight:
1519                 if (m_decoder)
1520                         return m_decoder->getVideoHeight();
1521                 break;
1522         case sVideoWidth:
1523                 if (m_decoder)
1524                         return m_decoder->getVideoWidth();
1525                 break;
1526         case sFrameRate:
1527                 if (m_decoder)
1528                         return m_decoder->getVideoFrameRate();
1529                 break;
1530         case sProgressive:
1531                 if (m_decoder)
1532                         return m_decoder->getVideoProgressive();
1533                 break;
1534         case sAspect:
1535         {
1536                 int aspect = -1;
1537                 if (m_decoder)
1538                         aspect = m_decoder->getVideoAspect();
1539                 if (aspect == -1 && no_program_info)
1540                         break;
1541                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1542                 {
1543                         ePtr<eServiceEvent> evt;
1544                         if (!m_event_handler.getEvent(evt, 0))
1545                         {
1546                                 ePtr<eComponentData> data;
1547                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1548                                 {
1549                                         if ( data->getStreamContent() == 1 )
1550                                         {
1551                                                 switch(data->getComponentType())
1552                                                 {
1553                                                         // SD
1554                                                         case 1: // 4:3 SD PAL
1555                                                         case 2:
1556                                                         case 3: // 16:9 SD PAL
1557                                                         case 4: // > 16:9 PAL
1558                                                         case 5: // 4:3 SD NTSC
1559                                                         case 6: 
1560                                                         case 7: // 16:9 SD NTSC
1561                                                         case 8: // > 16:9 NTSC
1562
1563                                                         // HD
1564                                                         case 9: // 4:3 HD PAL
1565                                                         case 0xA:
1566                                                         case 0xB: // 16:9 HD PAL
1567                                                         case 0xC: // > 16:9 HD PAL
1568                                                         case 0xD: // 4:3 HD NTSC
1569                                                         case 0xE:
1570                                                         case 0xF: // 16:9 HD NTSC
1571                                                         case 0x10: // > 16:9 HD PAL
1572                                                                 return data->getComponentType();
1573                                                 }
1574                                         }
1575                                 }
1576                         }
1577                 }
1578                 else
1579                         return aspect;
1580                 break;
1581         }
1582         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1583         case sVideoPID:
1584                 if (m_dvb_service)
1585                 {
1586                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1587                         if (vpid != -1)
1588                                 return vpid;
1589                 }
1590                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1591         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1592         case sAudioPID:
1593                 if (m_dvb_service)
1594                 {
1595                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1596                         if (apid != -1)
1597                                 return apid;
1598                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1599                         if (apid != -1)
1600                                 return apid;
1601                 }
1602                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1603         case sPCRPID:
1604                 if (m_dvb_service)
1605                 {
1606                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1607                         if (pcrpid != -1)
1608                                 return pcrpid;
1609                 }
1610                 if (no_program_info) return -1; return program.pcrPid;
1611         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1612         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1613         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1614         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1615         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1616         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1617         case sProvider: if (!m_dvb_service) return -1; return -2;
1618         case sServiceref: return resIsString;
1619         case sDVBState: return m_tune_state;
1620         default:
1621                 break;
1622         }
1623         return -1;
1624 }
1625
1626 std::string eDVBServicePlay::getInfoString(int w)
1627 {
1628         switch (w)
1629         {
1630         case sProvider:
1631                 if (!m_dvb_service) return "";
1632                 return m_dvb_service->m_provider_name;
1633         case sServiceref:
1634                 return m_reference.toString();
1635         default:
1636                 break;
1637         }
1638         return iServiceInformation::getInfoString(w);
1639 }
1640
1641 PyObject *eDVBServicePlay::getInfoObject(int w)
1642 {
1643         switch (w)
1644         {
1645         case sCAIDs:
1646                 return m_service_handler.getCaIds();
1647         case sTransponderData:
1648                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1649         default:
1650                 break;
1651         }
1652         return iServiceInformation::getInfoObject(w);
1653 }
1654
1655 int eDVBServicePlay::getNumberOfTracks()
1656 {
1657         eDVBServicePMTHandler::program program;
1658         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1659         if (h.getProgramInfo(program))
1660                 return 0;
1661         return program.audioStreams.size();
1662 }
1663
1664 int eDVBServicePlay::getCurrentTrack()
1665 {
1666         eDVBServicePMTHandler::program program;
1667         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1668         if (h.getProgramInfo(program))
1669                 return 0;
1670
1671         int max = program.audioStreams.size();
1672         int i;
1673
1674         for (i = 0; i < max; ++i)
1675                 if (program.audioStreams[i].pid == m_current_audio_pid)
1676                         return i;
1677
1678         return 0;
1679 }
1680
1681 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1682 {
1683         int ret = selectAudioStream(i);
1684
1685         if (m_decoder->set())
1686                 return -5;
1687
1688         return ret;
1689 }
1690
1691 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1692 {
1693         eDVBServicePMTHandler::program program;
1694         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1695
1696         if (h.getProgramInfo(program))
1697                 return -1;
1698         
1699         if (i >= program.audioStreams.size())
1700                 return -2;
1701         
1702         info.m_pid = program.audioStreams[i].pid;
1703
1704         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1705                 info.m_description = "MPEG";
1706         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1707                 info.m_description = "AC3";
1708         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1709                 info.m_description = "AAC";
1710         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1711                 info.m_description = "AAC-HE";
1712         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1713                 info.m_description = "DTS";
1714         else
1715                 info.m_description = "???";
1716
1717         if (program.audioStreams[i].component_tag != -1)
1718         {
1719                 ePtr<eServiceEvent> evt;
1720                 if (!m_event_handler.getEvent(evt, 0))
1721                 {
1722                         ePtr<eComponentData> data;
1723                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1724                                 info.m_language = data->getText();
1725                 }
1726         }
1727
1728         if (info.m_language.empty())
1729                 info.m_language = program.audioStreams[i].language_code;
1730         
1731         return 0;
1732 }
1733
1734 int eDVBServicePlay::selectAudioStream(int i)
1735 {
1736         eDVBServicePMTHandler::program program;
1737         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1738
1739         if (h.getProgramInfo(program))
1740                 return -1;
1741
1742         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1743                 return -2;
1744
1745         if (!m_decoder)
1746                 return -3;
1747
1748         int stream = i;
1749         if (stream == -1)
1750                 stream = program.defaultAudioStream;
1751
1752         int apid = -1, apidtype = -1;
1753
1754         if (((unsigned int)stream) < program.audioStreams.size())
1755         {
1756                 apid = program.audioStreams[stream].pid;
1757                 apidtype = program.audioStreams[stream].type;
1758         }
1759
1760         m_current_audio_pid = apid;
1761
1762         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1763         {
1764                 eDebug("set audio pid failed");
1765                 return -4;
1766         }
1767
1768         int rdsPid = apid;
1769
1770                 /* 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 */
1771         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1772         {
1773                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1774                 if (different_pid)
1775                         rdsPid = program.audioStreams[stream].rdsPid;
1776                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1777                 {
1778                         m_rds_decoder = 0;
1779                         ePtr<iDVBDemux> data_demux;
1780                         if (!h.getDataDemux(data_demux))
1781                         {
1782                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1783                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1784                                 m_rds_decoder->start(rdsPid);
1785                         }
1786                 }
1787         }
1788
1789                         /* store new pid as default only when:
1790                                 a.) we have an entry in the service db for the current service,
1791                                 b.) we are not playing back something,
1792                                 c.) we are not selecting the default entry. (we wouldn't change 
1793                                     anything in the best case, or destroy the default setting in
1794                                     case the real default is not yet available.)
1795                         */
1796         if (m_dvb_service && ((i != -1)
1797                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1798         {
1799                 if (apidtype == eDVBAudio::aMPEG)
1800                 {
1801                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1802                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1803                 }
1804                 else if (apidtype == eDVBAudio::aAC3)
1805                 {
1806                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1807                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1808                 }
1809                 else
1810                 {
1811                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1812                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1813                 }
1814         }
1815
1816         h.resetCachedProgram();
1817
1818         return 0;
1819 }
1820
1821 int eDVBServicePlay::getCurrentChannel()
1822 {
1823         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1824 }
1825
1826 RESULT eDVBServicePlay::selectChannel(int i)
1827 {
1828         if (i < LEFT || i > RIGHT || i == STEREO)
1829                 i = -1;  // Stereo
1830         if (m_dvb_service)
1831                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1832         if (m_decoder)
1833                 m_decoder->setAudioChannel(i);
1834         return 0;
1835 }
1836
1837 std::string eDVBServicePlay::getText(int x)
1838 {
1839         if (m_rds_decoder)
1840                 switch(x)
1841                 {
1842                         case RadioText:
1843                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1844                         case RtpText:
1845                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1846                 }
1847         return "";
1848 }
1849
1850 void eDVBServicePlay::rdsDecoderEvent(int what)
1851 {
1852         switch(what)
1853         {
1854                 case eDVBRdsDecoder::RadioTextChanged:
1855                         m_event((iPlayableService*)this, evUpdatedRadioText);
1856                         break;
1857                 case eDVBRdsDecoder::RtpTextChanged:
1858                         m_event((iPlayableService*)this, evUpdatedRtpText);
1859                         break;
1860                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1861                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1862                         break;
1863                 case eDVBRdsDecoder::RecvRassSlidePic:
1864                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1865                         break;
1866         }
1867 }
1868
1869 void eDVBServicePlay::showRassSlidePicture()
1870 {
1871         if (m_rds_decoder)
1872         {
1873                 if (m_decoder)
1874                 {
1875                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1876                         if (rass_slide_pic.length())
1877                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1878                         else
1879                                 eDebug("empty filename for rass slide picture received!!");
1880                 }
1881                 else
1882                         eDebug("no MPEG Decoder to show iframes avail");
1883         }
1884         else
1885                 eDebug("showRassSlidePicture called.. but not decoder");
1886 }
1887
1888 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1889 {
1890         if (m_rds_decoder)
1891         {
1892                 if (m_decoder)
1893                 {
1894                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1895                         if (rass_interactive_pic.length())
1896                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1897                         else
1898                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1899                 }
1900                 else
1901                         eDebug("no MPEG Decoder to show iframes avail");
1902         }
1903         else
1904                 eDebug("showRassInteractivePic called.. but not decoder");
1905 }
1906
1907 ePyObject eDVBServicePlay::getRassInteractiveMask()
1908 {
1909         if (m_rds_decoder)
1910                 return m_rds_decoder->getRassPictureMask();
1911         Py_RETURN_NONE;
1912 }
1913
1914 int eDVBServiceBase::getFrontendInfo(int w)
1915 {
1916         eUsePtr<iDVBChannel> channel;
1917         if(m_service_handler.getChannel(channel))
1918                 return 0;
1919         ePtr<iDVBFrontend> fe;
1920         if(channel->getFrontend(fe))
1921                 return 0;
1922         return fe->readFrontendData(w);
1923 }
1924
1925 PyObject *eDVBServiceBase::getFrontendData()
1926 {
1927         ePyObject ret = PyDict_New();
1928         if (ret)
1929         {
1930                 eUsePtr<iDVBChannel> channel;
1931                 if(!m_service_handler.getChannel(channel))
1932                 {
1933                         ePtr<iDVBFrontend> fe;
1934                         if(!channel->getFrontend(fe))
1935                                 fe->getFrontendData(ret);
1936                 }
1937         }
1938         else
1939                 Py_RETURN_NONE;
1940         return ret;
1941 }
1942
1943 PyObject *eDVBServiceBase::getFrontendStatus()
1944 {
1945         ePyObject ret = PyDict_New();
1946         if (ret)
1947         {
1948                 eUsePtr<iDVBChannel> channel;
1949                 if(!m_service_handler.getChannel(channel))
1950                 {
1951                         ePtr<iDVBFrontend> fe;
1952                         if(!channel->getFrontend(fe))
1953                                 fe->getFrontendStatus(ret);
1954                 }
1955         }
1956         else
1957                 Py_RETURN_NONE;
1958         return ret;
1959 }
1960
1961 PyObject *eDVBServiceBase::getTransponderData(bool original)
1962 {
1963         ePyObject ret = PyDict_New();
1964         if (ret)
1965         {
1966                 eUsePtr<iDVBChannel> channel;
1967                 if(!m_service_handler.getChannel(channel))
1968                 {
1969                         ePtr<iDVBFrontend> fe;
1970                         if(!channel->getFrontend(fe))
1971                                 fe->getTransponderData(ret, original);
1972                 }
1973         }
1974         else
1975                 Py_RETURN_NONE;
1976         return ret;
1977 }
1978
1979 PyObject *eDVBServiceBase::getAll(bool original)
1980 {
1981         ePyObject ret = getTransponderData(original);
1982         if (ret != Py_None)
1983         {
1984                 eUsePtr<iDVBChannel> channel;
1985                 if(!m_service_handler.getChannel(channel))
1986                 {
1987                         ePtr<iDVBFrontend> fe;
1988                         if(!channel->getFrontend(fe))
1989                         {
1990                                 fe->getFrontendData(ret);
1991                                 fe->getFrontendStatus(ret);
1992                         }
1993                 }
1994         }
1995         return ret;
1996 }
1997
1998 int eDVBServicePlay::getNumberOfSubservices()
1999 {
2000         ePtr<eServiceEvent> evt;
2001         if (!m_event_handler.getEvent(evt, 0))
2002                 return evt->getNumOfLinkageServices();
2003         return 0;
2004 }
2005
2006 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2007 {
2008         ePtr<eServiceEvent> evt;
2009         if (!m_event_handler.getEvent(evt, 0))
2010         {
2011                 if (!evt->getLinkageService(sub, m_reference, n))
2012                         return 0;
2013         }
2014         sub.type=eServiceReference::idInvalid;
2015         return -1;
2016 }
2017
2018 RESULT eDVBServicePlay::startTimeshift()
2019 {
2020         ePtr<iDVBDemux> demux;
2021         
2022         eDebug("Start timeshift!");
2023         
2024         if (m_timeshift_enabled)
2025                 return -1;
2026         
2027                 /* start recording with the data demux. */
2028         if (m_service_handler.getDataDemux(demux))
2029                 return -2;
2030
2031         demux->createTSRecorder(m_record);
2032         if (!m_record)
2033                 return -3;
2034
2035         std::string tspath;
2036         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2037                 eDebug("could not query ts path");
2038                 return -5;
2039         }
2040         tspath.append("/timeshift.XXXXXX");
2041         char* templ;
2042         templ = new char[tspath.length() + 1];
2043         strcpy(templ, tspath.c_str());
2044
2045         m_timeshift_fd = mkstemp(templ);
2046         m_timeshift_file = std::string(templ);
2047
2048         eDebug("recording to %s", templ);
2049
2050         delete [] templ;
2051
2052         if (m_timeshift_fd < 0)
2053         {
2054                 m_record = 0;
2055                 return -4;
2056         }
2057                 
2058         m_record->setTargetFD(m_timeshift_fd);
2059
2060         m_timeshift_enabled = 1;
2061         
2062         updateTimeshiftPids();
2063         m_record->start();
2064
2065         return 0;
2066 }
2067
2068 RESULT eDVBServicePlay::stopTimeshift()
2069 {
2070         if (!m_timeshift_enabled)
2071                 return -1;
2072         
2073         switchToLive();
2074         
2075         m_timeshift_enabled = 0;
2076         
2077         m_record->stop();
2078         m_record = 0;
2079         
2080         close(m_timeshift_fd);
2081         eDebug("remove timeshift file");
2082         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2083         
2084         return 0;
2085 }
2086
2087 int eDVBServicePlay::isTimeshiftActive()
2088 {
2089         return m_timeshift_enabled && m_timeshift_active;
2090 }
2091
2092 RESULT eDVBServicePlay::activateTimeshift()
2093 {
2094         if (!m_timeshift_enabled)
2095                 return -1;
2096         
2097         if (!m_timeshift_active)
2098         {
2099                 switchToTimeshift();
2100                 return 0;
2101         }
2102         
2103         return -2;
2104 }
2105
2106 PyObject *eDVBServicePlay::getCutList()
2107 {
2108         ePyObject list = PyList_New(0);
2109         
2110         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2111         {
2112                 ePyObject tuple = PyTuple_New(2);
2113                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2114                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2115                 PyList_Append(list, tuple);
2116                 Py_DECREF(tuple);
2117         }
2118         
2119         return list;
2120 }
2121
2122 void eDVBServicePlay::setCutList(ePyObject list)
2123 {
2124         if (!PyList_Check(list))
2125                 return;
2126         int size = PyList_Size(list);
2127         int i;
2128         
2129         m_cue_entries.clear();
2130         
2131         for (i=0; i<size; ++i)
2132         {
2133                 ePyObject tuple = PyList_GET_ITEM(list, i);
2134                 if (!PyTuple_Check(tuple))
2135                 {
2136                         eDebug("non-tuple in cutlist");
2137                         continue;
2138                 }
2139                 if (PyTuple_Size(tuple) != 2)
2140                 {
2141                         eDebug("cutlist entries need to be a 2-tuple");
2142                         continue;
2143                 }
2144                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2145                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2146                 {
2147                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2148                         continue;
2149                 }
2150                 pts_t pts = PyLong_AsLongLong(ppts);
2151                 int type = PyInt_AsLong(ptype);
2152                 m_cue_entries.insert(cueEntry(pts, type));
2153                 eDebug("adding %08llx, %d", pts, type);
2154         }
2155         m_cuesheet_changed = 1;
2156         
2157         cutlistToCuesheet();
2158         m_event((iPlayableService*)this, evCuesheetChanged);
2159 }
2160
2161 void eDVBServicePlay::setCutListEnable(int enable)
2162 {
2163         m_cutlist_enabled = enable;
2164         cutlistToCuesheet();
2165 }
2166
2167 void eDVBServicePlay::updateTimeshiftPids()
2168 {
2169         if (!m_record)
2170                 return;
2171         
2172         eDVBServicePMTHandler::program program;
2173         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2174
2175         if (h.getProgramInfo(program))
2176                 return;
2177         else
2178         {
2179                 std::set<int> pids_to_record;
2180                 pids_to_record.insert(0); // PAT
2181                 if (program.pmtPid != -1)
2182                         pids_to_record.insert(program.pmtPid); // PMT
2183
2184                 if (program.textPid != -1)
2185                         pids_to_record.insert(program.textPid); // Videotext
2186
2187                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2188                         i(program.videoStreams.begin()); 
2189                         i != program.videoStreams.end(); ++i)
2190                         pids_to_record.insert(i->pid);
2191
2192                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2193                         i(program.audioStreams.begin()); 
2194                         i != program.audioStreams.end(); ++i)
2195                                 pids_to_record.insert(i->pid);
2196
2197                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2198                         i(program.subtitleStreams.begin());
2199                         i != program.subtitleStreams.end(); ++i)
2200                                 pids_to_record.insert(i->pid);
2201
2202                 std::set<int> new_pids, obsolete_pids;
2203                 
2204                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2205                                 m_pids_active.begin(), m_pids_active.end(),
2206                                 std::inserter(new_pids, new_pids.begin()));
2207                 
2208                 std::set_difference(
2209                                 m_pids_active.begin(), m_pids_active.end(),
2210                                 pids_to_record.begin(), pids_to_record.end(), 
2211                                 std::inserter(new_pids, new_pids.begin())
2212                                 );
2213
2214                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2215                         m_record->addPID(*i);
2216
2217                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2218                         m_record->removePID(*i);
2219         }
2220 }
2221
2222 void eDVBServicePlay::switchToLive()
2223 {
2224         if (!m_timeshift_active)
2225                 return;
2226         
2227         eDebug("SwitchToLive");
2228         
2229         m_cue = 0;
2230         m_decoder = 0;
2231         m_decode_demux = 0;
2232         m_teletext_parser = 0;
2233         m_rds_decoder = 0;
2234         m_subtitle_parser = 0;
2235         m_new_dvb_subtitle_page_connection = 0;
2236         m_new_subtitle_page_connection = 0;
2237         m_rds_decoder_event_connection = 0;
2238         m_video_event_connection = 0;
2239         m_is_paused = m_skipmode = 0; /* not supported in live mode */
2240
2241                 /* free the timeshift service handler, we need the resources */
2242         m_service_handler_timeshift.free();
2243         m_timeshift_active = 0;
2244         m_timeshift_changed = 1;
2245
2246         m_event((iPlayableService*)this, evSeekableStatusChanged);
2247
2248         updateDecoder();
2249 }
2250
2251 void eDVBServicePlay::switchToTimeshift()
2252 {
2253         if (m_timeshift_active)
2254                 return;
2255
2256         m_decode_demux = 0;
2257         m_decoder = 0;
2258         m_teletext_parser = 0;
2259         m_rds_decoder = 0;
2260         m_subtitle_parser = 0;
2261         m_new_subtitle_page_connection = 0;
2262         m_new_dvb_subtitle_page_connection = 0;
2263         m_rds_decoder_event_connection = 0;
2264         m_video_event_connection = 0;
2265
2266         m_timeshift_active = 1;
2267         m_timeshift_changed = 1;
2268
2269         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2270         r.path = m_timeshift_file;
2271
2272         m_cue = new eCueSheet();
2273         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2274
2275         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2276         pause();
2277         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2278         
2279         m_event((iPlayableService*)this, evSeekableStatusChanged);
2280 }
2281
2282 void eDVBServicePlay::updateDecoder()
2283 {
2284         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2285
2286         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2287
2288         eDVBServicePMTHandler::program program;
2289         if (h.getProgramInfo(program))
2290                 eDebug("getting program info failed.");
2291         else
2292         {
2293                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2294                 if (!program.videoStreams.empty())
2295                 {
2296                         eDebugNoNewLine(" (");
2297                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2298                                 i(program.videoStreams.begin());
2299                                 i != program.videoStreams.end(); ++i)
2300                         {
2301                                 if (vpid == -1)
2302                                 {
2303                                         vpid = i->pid;
2304                                         vpidtype = i->type;
2305                                 }
2306                                 if (i != program.videoStreams.begin())
2307                                         eDebugNoNewLine(", ");
2308                                 eDebugNoNewLine("%04x", i->pid);
2309                         }
2310                         eDebugNoNewLine(")");
2311                 }
2312                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2313                 if (!program.audioStreams.empty())
2314                 {
2315                         eDebugNoNewLine(" (");
2316                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2317                                 i(program.audioStreams.begin());
2318                                 i != program.audioStreams.end(); ++i)
2319                         {
2320                                 if (i != program.audioStreams.begin())
2321                                         eDebugNoNewLine(", ");
2322                                 eDebugNoNewLine("%04x", i->pid);
2323                         }
2324                         eDebugNoNewLine(")");
2325                 }
2326                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2327                 pcrpid = program.pcrPid;
2328                 eDebug(", and the text pid is %04x", program.textPid);
2329                 tpid = program.textPid;
2330         }
2331
2332         if (!m_decoder)
2333         {
2334                 h.getDecodeDemux(m_decode_demux);
2335                 if (m_timeshift_changed)
2336                         m_decoder = 0;
2337                 if (m_decode_demux)
2338                 {
2339                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2340                         if (m_decoder)
2341                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2342                         if (m_is_primary)
2343                         {
2344                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2345                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2346                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2347                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2348                                 if (m_timeshift_changed)
2349                                 {
2350                                         ePyObject subs = getCachedSubtitle();
2351                                         if (subs != Py_None)
2352                                         {
2353                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2354                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2355                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2356                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2357                                                 if (type == 0) // dvb
2358                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2359                                                 else if (type == 1) // ttx
2360                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2361                                         }
2362                                         Py_DECREF(subs);
2363                                 }
2364                         }
2365                         m_decoder->play(); /* pids will be set later */
2366                 }
2367                 if (m_cue)
2368                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2369                 m_decoder->play(); /* pids will be set later. */
2370         }
2371
2372         m_timeshift_changed = 0;
2373
2374         if (m_decoder)
2375         {
2376                 if (m_dvb_service)
2377                 {
2378                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2379                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2380                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2381                 }
2382                 else // subservice
2383                 {
2384                         eServiceReferenceDVB ref;
2385                         m_service_handler.getServiceReference(ref);
2386                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2387                         if (!parent)
2388                                 parent = ref;
2389                         if (parent)
2390                         {
2391                                 ePtr<eDVBResourceManager> res_mgr;
2392                                 if (!eDVBResourceManager::getInstance(res_mgr))
2393                                 {
2394                                         ePtr<iDVBChannelList> db;
2395                                         if (!res_mgr->getChannelList(db))
2396                                         {
2397                                                 ePtr<eDVBService> origService;
2398                                                 if (!db->getService(parent, origService))
2399                                                 {
2400                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2401                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2402                                                 }
2403                                         }
2404                                 }
2405                         }
2406                 }
2407
2408                 std::string config_delay;
2409                 int config_delay_int = 0;
2410                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2411                         config_delay_int = atoi(config_delay.c_str());
2412                 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2413
2414                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2415                         config_delay_int = atoi(config_delay.c_str());
2416                 else
2417                         config_delay_int = 0;
2418                 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2419
2420                 m_decoder->setVideoPID(vpid, vpidtype);
2421                 selectAudioStream();
2422
2423                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2424                         m_decoder->setSyncPCR(pcrpid);
2425                 else
2426                         m_decoder->setSyncPCR(-1);
2427
2428                 if (m_is_primary)
2429                 {
2430                         m_decoder->setTextPID(tpid);
2431                         m_teletext_parser->start(program.textPid);
2432                 }
2433
2434                 if (vpid > 0 && vpid < 0x2000)
2435                         ;
2436                 else
2437                 {
2438                         std::string radio_pic;
2439                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2440                                 m_decoder->setRadioPic(radio_pic);
2441                 }
2442
2443                 m_decoder->set();
2444                 m_decoder->setAudioChannel(achannel);
2445
2446                 /* don't worry about non-existing services, nor pvr services */
2447                 if (m_dvb_service)
2448                 {
2449                                 /* (audio pid will be set in selectAudioTrack */
2450                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2451                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2452                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2453                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2454                 }
2455         }
2456         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2457 }
2458
2459 void eDVBServicePlay::loadCuesheet()
2460 {
2461         std::string filename = m_reference.path + ".cuts";
2462         
2463         m_cue_entries.clear();
2464
2465         FILE *f = fopen(filename.c_str(), "rb");
2466
2467         if (f)
2468         {
2469                 eDebug("loading cuts..");
2470                 while (1)
2471                 {
2472                         unsigned long long where;
2473                         unsigned int what;
2474                         
2475                         if (!fread(&where, sizeof(where), 1, f))
2476                                 break;
2477                         if (!fread(&what, sizeof(what), 1, f))
2478                                 break;
2479                         
2480 #if BYTE_ORDER == LITTLE_ENDIAN
2481                         where = bswap_64(where);
2482 #endif
2483                         what = ntohl(what);
2484                         
2485                         if (what > 3)
2486                                 break;
2487                         
2488                         m_cue_entries.insert(cueEntry(where, what));
2489                 }
2490                 fclose(f);
2491                 eDebug("%d entries", m_cue_entries.size());
2492         } else
2493                 eDebug("cutfile not found!");
2494         
2495         m_cuesheet_changed = 0;
2496         cutlistToCuesheet();
2497         m_event((iPlayableService*)this, evCuesheetChanged);
2498 }
2499
2500 void eDVBServicePlay::saveCuesheet()
2501 {
2502         std::string filename = m_reference.path + ".cuts";
2503         
2504         FILE *f = fopen(filename.c_str(), "wb");
2505
2506         if (f)
2507         {
2508                 unsigned long long where;
2509                 int what;
2510
2511                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2512                 {
2513 #if BYTE_ORDER == BIG_ENDIAN
2514                         where = i->where;
2515 #else
2516                         where = bswap_64(i->where);
2517 #endif
2518                         what = htonl(i->what);
2519                         fwrite(&where, sizeof(where), 1, f);
2520                         fwrite(&what, sizeof(what), 1, f);
2521                         
2522                 }
2523                 fclose(f);
2524         }
2525         
2526         m_cuesheet_changed = 0;
2527 }
2528
2529 void eDVBServicePlay::cutlistToCuesheet()
2530 {
2531         if (!m_cue)
2532         {
2533                 eDebug("no cue sheet");
2534                 return;
2535         }       
2536         m_cue->clear();
2537         
2538         if (!m_cutlist_enabled)
2539         {
2540                 m_cue->commitSpans();
2541                 eDebug("cutlists were disabled");
2542                 return;
2543         }
2544
2545         pts_t in = 0, out = 0, length = 0;
2546         
2547         getLength(length);
2548                 
2549         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2550         
2551         int have_any_span = 0;
2552         
2553         while (1)
2554         {
2555                 if (i == m_cue_entries.end())
2556                 {
2557                         if (!have_any_span)
2558                                 break;
2559                         out = length;
2560                 } else {
2561                         if (i->what == 0) /* in */
2562                         {
2563                                 in = i++->where;
2564                                 continue;
2565                         } else if (i->what == 1) /* out */
2566                                 out = i++->where;
2567                         else /* mark (2) or last play position (3) */
2568                         {
2569                                 i++;
2570                                 continue;
2571                         }
2572                 }
2573                 
2574                 if (in < 0)
2575                         in = 0;
2576                 if (out < 0)
2577                         out = 0;
2578                 if (in > length)
2579                         in = length;
2580                 if (out > length)
2581                         out = length;
2582                 
2583                 if (in < out)
2584                 {
2585                         have_any_span = 1;
2586                         m_cue->addSourceSpan(in, out);
2587                 }
2588                 
2589                 in = length;
2590                 
2591                 if (i == m_cue_entries.end())
2592                         break;
2593         }
2594         m_cue->commitSpans();
2595 }
2596
2597 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2598 {
2599         if (m_subtitle_widget)
2600                 disableSubtitles(parent);
2601
2602         ePyObject entry;
2603         int tuplesize = PyTuple_Size(tuple);
2604         int type = 0;
2605
2606         if (!PyTuple_Check(tuple))
2607                 goto error_out;
2608
2609         if (tuplesize < 1)
2610                 goto error_out;
2611
2612         entry = PyTuple_GET_ITEM(tuple, 0);
2613
2614         if (!PyInt_Check(entry))
2615                 goto error_out;
2616
2617         type = PyInt_AsLong(entry);
2618
2619         if (type == 1)  // teletext subtitles
2620         {
2621                 int page, magazine, pid;
2622                 if (tuplesize < 4)
2623                         goto error_out;
2624
2625                 if (!m_teletext_parser)
2626                 {
2627                         eDebug("enable teletext subtitles.. no parser !!!");
2628                         return -1;
2629                 }
2630
2631                 entry = PyTuple_GET_ITEM(tuple, 1);
2632                 if (!PyInt_Check(entry))
2633                         goto error_out;
2634                 pid = PyInt_AsLong(entry);
2635
2636                 entry = PyTuple_GET_ITEM(tuple, 2);
2637                 if (!PyInt_Check(entry))
2638                         goto error_out;
2639                 page = PyInt_AsLong(entry);
2640
2641                 entry = PyTuple_GET_ITEM(tuple, 3);
2642                 if (!PyInt_Check(entry))
2643                         goto error_out;
2644                 magazine = PyInt_AsLong(entry);
2645
2646                 m_subtitle_widget = new eSubtitleWidget(parent);
2647                 m_subtitle_widget->resize(parent->size()); /* full size */
2648                 m_teletext_parser->setPageAndMagazine(page, magazine);
2649                 if (m_dvb_service)
2650                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2651         }
2652         else if (type == 0)
2653         {
2654                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2655                 if (!m_subtitle_parser)
2656                 {
2657                         eDebug("enable dvb subtitles.. no parser !!!");
2658                         return -1;
2659                 }
2660                 if (tuplesize < 4)
2661                         goto error_out;
2662
2663                 entry = PyTuple_GET_ITEM(tuple, 1);
2664                 if (!PyInt_Check(entry))
2665                         goto error_out;
2666                 pid = PyInt_AsLong(entry);
2667
2668                 entry = PyTuple_GET_ITEM(tuple, 2);
2669                 if (!PyInt_Check(entry))
2670                         goto error_out;
2671                 composition_page_id = PyInt_AsLong(entry);
2672
2673                 entry = PyTuple_GET_ITEM(tuple, 3);
2674                 if (!PyInt_Check(entry))
2675                         goto error_out;
2676                 ancillary_page_id = PyInt_AsLong(entry);
2677
2678                 m_subtitle_widget = new eSubtitleWidget(parent);
2679                 m_subtitle_widget->resize(parent->size()); /* full size */
2680                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2681                 if (m_dvb_service)
2682                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2683         }
2684         else
2685                 goto error_out;
2686         return 0;
2687 error_out:
2688         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2689                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2690                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2691         return -1;
2692 }
2693
2694 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2695 {
2696         delete m_subtitle_widget;
2697         m_subtitle_widget = 0;
2698         if (m_subtitle_parser)
2699         {
2700                 m_subtitle_parser->stop();
2701                 m_dvb_subtitle_pages.clear();
2702         }
2703         if (m_teletext_parser)
2704         {
2705                 m_teletext_parser->setPageAndMagazine(-1, -1);
2706                 m_subtitle_pages.clear();
2707         }
2708         if (m_dvb_service)
2709                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2710         return 0;
2711 }
2712
2713 PyObject *eDVBServicePlay::getCachedSubtitle()
2714 {
2715         if (m_dvb_service)
2716         {
2717                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2718                 if (tmp != -1)
2719                 {
2720                         unsigned int data = (unsigned int)tmp;
2721                         int pid = (data&0xFFFF0000)>>16;
2722                         ePyObject tuple = PyTuple_New(4);
2723                         eDVBServicePMTHandler::program program;
2724                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2725                         if (!h.getProgramInfo(program))
2726                         {
2727                                 if (program.textPid==pid) // teletext
2728                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2729                                 else
2730                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2731                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2732                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2733                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2734                                 return tuple;
2735                         }
2736                 }
2737         }
2738         Py_RETURN_NONE;
2739 }
2740
2741 PyObject *eDVBServicePlay::getSubtitleList()
2742 {
2743         if (!m_teletext_parser)
2744                 Py_RETURN_NONE;
2745         
2746         ePyObject l = PyList_New(0);
2747         std::set<int> added_ttx_pages;
2748
2749         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2750                 m_teletext_parser->m_found_subtitle_pages;
2751
2752         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2753         eDVBServicePMTHandler::program program;
2754         if (h.getProgramInfo(program))
2755                 eDebug("getting program info failed.");
2756         else
2757         {
2758                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2759                         it != program.subtitleStreams.end(); ++it)
2760                 {
2761                         switch(it->subtitling_type)
2762                         {
2763                                 case 0x01: // ebu teletext subtitles
2764                                 {
2765                                         int page_number = it->teletext_page_number & 0xFF;
2766                                         int magazine_number = it->teletext_magazine_number & 7;
2767                                         int hash = magazine_number << 8 | page_number;
2768                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2769                                         {
2770                                                 ePyObject tuple = PyTuple_New(5);
2771                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2772                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2773                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2774                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2775                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2776                                                 PyList_Append(l, tuple);
2777                                                 Py_DECREF(tuple);
2778                                                 added_ttx_pages.insert(hash);
2779                                         }
2780                                         break;
2781                                 }
2782                                 case 0x10 ... 0x13:
2783                                 case 0x20 ... 0x23: // dvb subtitles
2784                                 {
2785                                         ePyObject tuple = PyTuple_New(5);
2786                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2787                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2788                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2789                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2790                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2791                                         PyList_Insert(l, 0, tuple);
2792                                         Py_DECREF(tuple);
2793                                         break;
2794                                 }
2795                         }
2796                 }
2797         }
2798
2799         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2800                 it != subs.end(); ++it)
2801         {
2802                 int page_number = it->teletext_page_number & 0xFF;
2803                 int magazine_number = it->teletext_magazine_number & 7;
2804                 int hash = magazine_number << 8 | page_number;
2805                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2806                 {
2807                         ePyObject tuple = PyTuple_New(5);
2808                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2809                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2810                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2811                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2812                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2813                         PyList_Append(l, tuple);
2814                         Py_DECREF(tuple);
2815                 }
2816         }
2817
2818         return l;
2819 }
2820
2821 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2822 {
2823         if (m_subtitle_widget)
2824         {
2825                 pts_t pos = 0;
2826                 if (m_decoder)
2827                         m_decoder->getPTS(0, pos);
2828                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2829                 m_subtitle_pages.push_back(page);
2830                 checkSubtitleTiming();
2831         }
2832 }
2833
2834 void eDVBServicePlay::checkSubtitleTiming()
2835 {
2836         eDebug("checkSubtitleTiming");
2837         if (!m_subtitle_widget)
2838                 return;
2839         while (1)
2840         {
2841                 enum { TELETEXT, DVB } type;
2842                 eDVBTeletextSubtitlePage page;
2843                 eDVBSubtitlePage dvb_page;
2844                 pts_t show_time;
2845                 if (!m_subtitle_pages.empty())
2846                 {
2847                         page = m_subtitle_pages.front();
2848                         type = TELETEXT;
2849                         show_time = page.m_pts;
2850                 }
2851                 else if (!m_dvb_subtitle_pages.empty())
2852                 {
2853                         dvb_page = m_dvb_subtitle_pages.front();
2854                         type = DVB;
2855                         show_time = dvb_page.m_show_time;
2856                 }
2857                 else
2858                         return;
2859         
2860                 pts_t pos = 0;
2861         
2862                 if (m_decoder)
2863                         m_decoder->getPTS(0, pos);
2864
2865                 eDebug("%lld %lld", pos, show_time);
2866                 int diff = show_time - pos;
2867                 if (type == TELETEXT && !page.m_have_pts)
2868                 {
2869                         eDebug("ttx subtitle page without pts... immediate show");
2870                         diff = 0;
2871                 }
2872                 if (diff < 0)
2873                 {
2874                         eDebug("[late (%d ms)]", -diff / 90);
2875                         diff = 0;
2876                 }
2877                 if (abs(diff) > 1800000)
2878                 {
2879                         eDebug("[invalid]... immediate show!");
2880                         diff = 0;
2881                 }
2882                 if ((diff/90)<20)
2883                 {
2884                         if (type == TELETEXT)
2885                         {
2886                                 eDebug("display teletext subtitle page %lld", show_time);
2887                                 m_subtitle_widget->setPage(page);
2888                                 m_subtitle_pages.pop_front();
2889                         }
2890                         else
2891                         {
2892                                 eDebug("display dvb subtitle Page %lld", show_time);
2893                                 m_subtitle_widget->setPage(dvb_page);
2894                                 m_dvb_subtitle_pages.pop_front();
2895                         }
2896                 } else
2897                 {
2898                         eDebug("start subtitle delay %d", diff / 90);
2899                         m_subtitle_sync_timer->start(diff / 90, 1);
2900                         break;
2901                 }
2902         }
2903 }
2904
2905 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2906 {
2907         if (m_subtitle_widget)
2908         {
2909                 pts_t pos = 0;
2910                 if (m_decoder)
2911                         m_decoder->getPTS(0, pos);
2912                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2913                 m_dvb_subtitle_pages.push_back(p);
2914                 checkSubtitleTiming();
2915         }
2916 }
2917
2918 int eDVBServicePlay::getAC3Delay()
2919 {
2920         if (m_dvb_service)
2921                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2922         else if (m_decoder)
2923                 return m_decoder->getAC3Delay();
2924         else
2925                 return 0;
2926 }
2927
2928 int eDVBServicePlay::getPCMDelay()
2929 {
2930         if (m_dvb_service)
2931                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2932         else if (m_decoder)
2933                 return m_decoder->getPCMDelay();
2934         else
2935                 return 0;
2936 }
2937
2938 void eDVBServicePlay::setAC3Delay(int delay)
2939 {
2940         if (m_dvb_service)
2941                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2942         if (m_decoder)
2943                 m_decoder->setAC3Delay(delay);
2944 }
2945
2946 void eDVBServicePlay::setPCMDelay(int delay)
2947 {
2948         if (m_dvb_service)
2949                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2950         if (m_decoder)
2951                 m_decoder->setPCMDelay(delay);
2952 }
2953
2954 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2955 {
2956         switch(event.type) {
2957                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2958                         m_event((iPlayableService*)this, evVideoSizeChanged);
2959                         break;
2960                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2961                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2962                         break;
2963                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2964                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2965                         break;
2966                 default:
2967                         break;
2968         }
2969 }
2970
2971 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2972 {
2973         ptr = this;
2974         return 0;
2975 }
2976
2977 PyObject *eDVBServicePlay::getStreamingData()
2978 {
2979         eDVBServicePMTHandler::program program;
2980         if (m_service_handler.getProgramInfo(program))
2981         {
2982                 Py_RETURN_NONE;
2983         }
2984
2985         ePyObject r = program.createPythonObject();
2986         ePtr<iDVBDemux> demux;
2987         if (!m_service_handler.getDataDemux(demux))
2988         {
2989                 uint8_t demux_id;
2990                 if (!demux->getCADemuxID(demux_id))
2991                         PutToDict(r, "demux", demux_id);
2992         }
2993
2994         return r;
2995 }
2996
2997
2998 DEFINE_REF(eDVBServicePlay)
2999
3000 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3001 {
3002         switch (w)
3003         {
3004         case iServiceInformation::sTransponderData:
3005                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3006         default:
3007                 break;
3008         }
3009         return iStaticServiceInformation::getInfoObject(ref, w);
3010 }
3011
3012 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");