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