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