lib/service/servicedvb.cpp: add possibility to override servicename for pvr dvb services
[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)
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 sTransponderData:
1736                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1737         default:
1738                 break;
1739         }
1740         return iServiceInformation::getInfoObject(w);
1741 }
1742
1743 int eDVBServicePlay::getNumberOfTracks()
1744 {
1745         eDVBServicePMTHandler::program program;
1746         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1747         if (h.getProgramInfo(program))
1748                 return 0;
1749         return program.audioStreams.size();
1750 }
1751
1752 int eDVBServicePlay::getCurrentTrack()
1753 {
1754         eDVBServicePMTHandler::program program;
1755         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1756         if (h.getProgramInfo(program))
1757                 return 0;
1758
1759         int max = program.audioStreams.size();
1760         int i;
1761
1762         for (i = 0; i < max; ++i)
1763                 if (program.audioStreams[i].pid == m_current_audio_pid)
1764                         return i;
1765
1766         return 0;
1767 }
1768
1769 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1770 {
1771         int ret = selectAudioStream(i);
1772
1773         if (m_decoder->set())
1774                 return -5;
1775
1776         return ret;
1777 }
1778
1779 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1780 {
1781         eDVBServicePMTHandler::program program;
1782         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1783
1784         if (h.getProgramInfo(program))
1785                 return -1;
1786         
1787         if (i >= program.audioStreams.size())
1788                 return -2;
1789         
1790         info.m_pid = program.audioStreams[i].pid;
1791
1792         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1793                 info.m_description = "MPEG";
1794         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1795                 info.m_description = "AC3";
1796         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1797                 info.m_description = "AAC";
1798         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1799                 info.m_description = "AAC-HE";
1800         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1801                 info.m_description = "DTS";
1802         else
1803                 info.m_description = "???";
1804
1805         if (program.audioStreams[i].component_tag != -1)
1806         {
1807                 ePtr<eServiceEvent> evt;
1808                 if (!m_event_handler.getEvent(evt, 0))
1809                 {
1810                         ePtr<eComponentData> data;
1811                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1812                                 info.m_language = data->getText();
1813                 }
1814         }
1815
1816         if (info.m_language.empty())
1817                 info.m_language = program.audioStreams[i].language_code;
1818         
1819         return 0;
1820 }
1821
1822 int eDVBServicePlay::selectAudioStream(int i)
1823 {
1824         eDVBServicePMTHandler::program program;
1825         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1826         pts_t position = -1;
1827
1828         if (h.getProgramInfo(program))
1829                 return -1;
1830
1831         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1832                 return -2;
1833
1834         if (!m_decoder)
1835                 return -3;
1836
1837         int stream = i;
1838         if (stream == -1)
1839                 stream = program.defaultAudioStream;
1840
1841         int apid = -1, apidtype = -1;
1842
1843         if (((unsigned int)stream) < program.audioStreams.size())
1844         {
1845                 apid = program.audioStreams[stream].pid;
1846                 apidtype = program.audioStreams[stream].type;
1847         }
1848
1849         if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1850                 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1851
1852         m_current_audio_pid = apid;
1853
1854         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1855         {
1856                 eDebug("set audio pid failed");
1857                 return -4;
1858         }
1859
1860         if (position != -1)
1861                 eDebug("seekTo ret %d", seekTo(position));
1862
1863         int rdsPid = apid;
1864
1865                 /* 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 */
1866         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1867         {
1868                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1869                 if (different_pid)
1870                         rdsPid = program.audioStreams[stream].rdsPid;
1871                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1872                 {
1873                         m_rds_decoder = 0;
1874                         ePtr<iDVBDemux> data_demux;
1875                         if (!h.getDataDemux(data_demux))
1876                         {
1877                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1878                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1879                                 m_rds_decoder->start(rdsPid);
1880                         }
1881                 }
1882         }
1883
1884                         /* store new pid as default only when:
1885                                 a.) we have an entry in the service db for the current service,
1886                                 b.) we are not playing back something,
1887                                 c.) we are not selecting the default entry. (we wouldn't change 
1888                                     anything in the best case, or destroy the default setting in
1889                                     case the real default is not yet available.)
1890                         */
1891         if (m_dvb_service && ((i != -1)
1892                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1893         {
1894                 if (apidtype == eDVBAudio::aMPEG)
1895                 {
1896                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1897                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1898                 }
1899                 else if (apidtype == eDVBAudio::aAC3)
1900                 {
1901                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1902                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1903                 }
1904                 else
1905                 {
1906                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1907                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1908                 }
1909         }
1910
1911         h.resetCachedProgram();
1912
1913         return 0;
1914 }
1915
1916 int eDVBServicePlay::getCurrentChannel()
1917 {
1918         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1919 }
1920
1921 RESULT eDVBServicePlay::selectChannel(int i)
1922 {
1923         if (i < LEFT || i > RIGHT || i == STEREO)
1924                 i = -1;  // Stereo
1925         if (m_dvb_service)
1926                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1927         if (m_decoder)
1928                 m_decoder->setAudioChannel(i);
1929         return 0;
1930 }
1931
1932 std::string eDVBServicePlay::getText(int x)
1933 {
1934         if (m_rds_decoder)
1935                 switch(x)
1936                 {
1937                         case RadioText:
1938                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1939                         case RtpText:
1940                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1941                 }
1942         return "";
1943 }
1944
1945 void eDVBServicePlay::rdsDecoderEvent(int what)
1946 {
1947         switch(what)
1948         {
1949                 case eDVBRdsDecoder::RadioTextChanged:
1950                         m_event((iPlayableService*)this, evUpdatedRadioText);
1951                         break;
1952                 case eDVBRdsDecoder::RtpTextChanged:
1953                         m_event((iPlayableService*)this, evUpdatedRtpText);
1954                         break;
1955                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1956                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1957                         break;
1958                 case eDVBRdsDecoder::RecvRassSlidePic:
1959                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1960                         break;
1961         }
1962 }
1963
1964 void eDVBServicePlay::showRassSlidePicture()
1965 {
1966         if (m_rds_decoder)
1967         {
1968                 if (m_decoder)
1969                 {
1970                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1971                         if (rass_slide_pic.length())
1972                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1973                         else
1974                                 eDebug("empty filename for rass slide picture received!!");
1975                 }
1976                 else
1977                         eDebug("no MPEG Decoder to show iframes avail");
1978         }
1979         else
1980                 eDebug("showRassSlidePicture called.. but not decoder");
1981 }
1982
1983 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1984 {
1985         if (m_rds_decoder)
1986         {
1987                 if (m_decoder)
1988                 {
1989                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1990                         if (rass_interactive_pic.length())
1991                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1992                         else
1993                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1994                 }
1995                 else
1996                         eDebug("no MPEG Decoder to show iframes avail");
1997         }
1998         else
1999                 eDebug("showRassInteractivePic called.. but not decoder");
2000 }
2001
2002 ePyObject eDVBServicePlay::getRassInteractiveMask()
2003 {
2004         if (m_rds_decoder)
2005                 return m_rds_decoder->getRassPictureMask();
2006         Py_RETURN_NONE;
2007 }
2008
2009 int eDVBServiceBase::getFrontendInfo(int w)
2010 {
2011         eUsePtr<iDVBChannel> channel;
2012         if(m_service_handler.getChannel(channel))
2013                 return 0;
2014         ePtr<iDVBFrontend> fe;
2015         if(channel->getFrontend(fe))
2016                 return 0;
2017         return fe->readFrontendData(w);
2018 }
2019
2020 PyObject *eDVBServiceBase::getFrontendData()
2021 {
2022         ePyObject ret = PyDict_New();
2023         if (ret)
2024         {
2025                 eUsePtr<iDVBChannel> channel;
2026                 if(!m_service_handler.getChannel(channel))
2027                 {
2028                         ePtr<iDVBFrontend> fe;
2029                         if(!channel->getFrontend(fe))
2030                                 fe->getFrontendData(ret);
2031                 }
2032         }
2033         else
2034                 Py_RETURN_NONE;
2035         return ret;
2036 }
2037
2038 PyObject *eDVBServiceBase::getFrontendStatus()
2039 {
2040         ePyObject ret = PyDict_New();
2041         if (ret)
2042         {
2043                 eUsePtr<iDVBChannel> channel;
2044                 if(!m_service_handler.getChannel(channel))
2045                 {
2046                         ePtr<iDVBFrontend> fe;
2047                         if(!channel->getFrontend(fe))
2048                                 fe->getFrontendStatus(ret);
2049                 }
2050         }
2051         else
2052                 Py_RETURN_NONE;
2053         return ret;
2054 }
2055
2056 PyObject *eDVBServiceBase::getTransponderData(bool original)
2057 {
2058         ePyObject ret = PyDict_New();
2059         if (ret)
2060         {
2061                 eUsePtr<iDVBChannel> channel;
2062                 if(!m_service_handler.getChannel(channel))
2063                 {
2064                         ePtr<iDVBFrontend> fe;
2065                         if(!channel->getFrontend(fe))
2066                                 fe->getTransponderData(ret, original);
2067                 }
2068         }
2069         else
2070                 Py_RETURN_NONE;
2071         return ret;
2072 }
2073
2074 PyObject *eDVBServiceBase::getAll(bool original)
2075 {
2076         ePyObject ret = getTransponderData(original);
2077         if (ret != Py_None)
2078         {
2079                 eUsePtr<iDVBChannel> channel;
2080                 if(!m_service_handler.getChannel(channel))
2081                 {
2082                         ePtr<iDVBFrontend> fe;
2083                         if(!channel->getFrontend(fe))
2084                         {
2085                                 fe->getFrontendData(ret);
2086                                 fe->getFrontendStatus(ret);
2087                         }
2088                 }
2089         }
2090         return ret;
2091 }
2092
2093 int eDVBServicePlay::getNumberOfSubservices()
2094 {
2095         ePtr<eServiceEvent> evt;
2096         if (!m_event_handler.getEvent(evt, 0))
2097                 return evt->getNumOfLinkageServices();
2098         return 0;
2099 }
2100
2101 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2102 {
2103         ePtr<eServiceEvent> evt;
2104         if (!m_event_handler.getEvent(evt, 0))
2105         {
2106                 if (!evt->getLinkageService(sub, m_reference, n))
2107                         return 0;
2108         }
2109         sub.type=eServiceReference::idInvalid;
2110         return -1;
2111 }
2112
2113 RESULT eDVBServicePlay::startTimeshift()
2114 {
2115         ePtr<iDVBDemux> demux;
2116         
2117         eDebug("Start timeshift!");
2118         
2119         if (m_timeshift_enabled)
2120                 return -1;
2121         
2122                 /* start recording with the data demux. */
2123         if (m_service_handler.getDataDemux(demux))
2124                 return -2;
2125
2126         demux->createTSRecorder(m_record);
2127         if (!m_record)
2128                 return -3;
2129
2130         std::string tspath;
2131         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2132                 eDebug("could not query ts path");
2133                 return -5;
2134         }
2135         tspath.append("/timeshift.XXXXXX");
2136         char* templ;
2137         templ = new char[tspath.length() + 1];
2138         strcpy(templ, tspath.c_str());
2139
2140         m_timeshift_fd = mkstemp(templ);
2141         m_timeshift_file = std::string(templ);
2142
2143         eDebug("recording to %s", templ);
2144
2145         delete [] templ;
2146
2147         if (m_timeshift_fd < 0)
2148         {
2149                 m_record = 0;
2150                 return -4;
2151         }
2152                 
2153         m_record->setTargetFD(m_timeshift_fd);
2154
2155         m_timeshift_enabled = 1;
2156         
2157         updateTimeshiftPids();
2158         m_record->start();
2159
2160         return 0;
2161 }
2162
2163 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2164 {
2165         if (!m_timeshift_enabled)
2166                 return -1;
2167         
2168         if (swToLive)
2169                 switchToLive();
2170         
2171         m_timeshift_enabled = 0;
2172         
2173         m_record->stop();
2174         m_record = 0;
2175         
2176         close(m_timeshift_fd);
2177         eDebug("remove timeshift file");
2178         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2179         
2180         return 0;
2181 }
2182
2183 int eDVBServicePlay::isTimeshiftActive()
2184 {
2185         return m_timeshift_enabled && m_timeshift_active;
2186 }
2187
2188 RESULT eDVBServicePlay::activateTimeshift()
2189 {
2190         if (!m_timeshift_enabled)
2191                 return -1;
2192         
2193         if (!m_timeshift_active)
2194         {
2195                 switchToTimeshift();
2196                 return 0;
2197         }
2198         
2199         return -2;
2200 }
2201
2202 PyObject *eDVBServicePlay::getCutList()
2203 {
2204         ePyObject list = PyList_New(0);
2205         
2206         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2207         {
2208                 ePyObject tuple = PyTuple_New(2);
2209                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2210                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2211                 PyList_Append(list, tuple);
2212                 Py_DECREF(tuple);
2213         }
2214         
2215         return list;
2216 }
2217
2218 void eDVBServicePlay::setCutList(ePyObject list)
2219 {
2220         if (!PyList_Check(list))
2221                 return;
2222         int size = PyList_Size(list);
2223         int i;
2224         
2225         m_cue_entries.clear();
2226         
2227         for (i=0; i<size; ++i)
2228         {
2229                 ePyObject tuple = PyList_GET_ITEM(list, i);
2230                 if (!PyTuple_Check(tuple))
2231                 {
2232                         eDebug("non-tuple in cutlist");
2233                         continue;
2234                 }
2235                 if (PyTuple_Size(tuple) != 2)
2236                 {
2237                         eDebug("cutlist entries need to be a 2-tuple");
2238                         continue;
2239                 }
2240                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2241                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2242                 {
2243                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2244                         continue;
2245                 }
2246                 pts_t pts = PyLong_AsLongLong(ppts);
2247                 int type = PyInt_AsLong(ptype);
2248                 m_cue_entries.insert(cueEntry(pts, type));
2249                 eDebug("adding %08llx, %d", pts, type);
2250         }
2251         m_cuesheet_changed = 1;
2252         
2253         cutlistToCuesheet();
2254         m_event((iPlayableService*)this, evCuesheetChanged);
2255 }
2256
2257 void eDVBServicePlay::setCutListEnable(int enable)
2258 {
2259         m_cutlist_enabled = enable;
2260         cutlistToCuesheet();
2261 }
2262
2263 void eDVBServicePlay::updateTimeshiftPids()
2264 {
2265         if (!m_record)
2266                 return;
2267         
2268         eDVBServicePMTHandler::program program;
2269         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2270
2271         if (h.getProgramInfo(program))
2272                 return;
2273         else
2274         {
2275                 std::set<int> pids_to_record;
2276                 pids_to_record.insert(0); // PAT
2277                 if (program.pmtPid != -1)
2278                         pids_to_record.insert(program.pmtPid); // PMT
2279
2280                 if (program.textPid != -1)
2281                         pids_to_record.insert(program.textPid); // Videotext
2282
2283                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2284                         i(program.videoStreams.begin()); 
2285                         i != program.videoStreams.end(); ++i)
2286                         pids_to_record.insert(i->pid);
2287
2288                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2289                         i(program.audioStreams.begin()); 
2290                         i != program.audioStreams.end(); ++i)
2291                                 pids_to_record.insert(i->pid);
2292
2293                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2294                         i(program.subtitleStreams.begin());
2295                         i != program.subtitleStreams.end(); ++i)
2296                                 pids_to_record.insert(i->pid);
2297
2298                 std::set<int> new_pids, obsolete_pids;
2299                 
2300                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2301                                 m_pids_active.begin(), m_pids_active.end(),
2302                                 std::inserter(new_pids, new_pids.begin()));
2303                 
2304                 std::set_difference(
2305                                 m_pids_active.begin(), m_pids_active.end(),
2306                                 pids_to_record.begin(), pids_to_record.end(), 
2307                                 std::inserter(new_pids, new_pids.begin())
2308                                 );
2309
2310                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2311                         m_record->addPID(*i);
2312
2313                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2314                         m_record->removePID(*i);
2315         }
2316 }
2317
2318 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2319 {
2320         m_timeshift_file_next = f;
2321         return 0;
2322 }
2323
2324 void eDVBServicePlay::switchToLive()
2325 {
2326         if (!m_timeshift_active)
2327                 return;
2328
2329         eDebug("SwitchToLive");
2330
2331         resetTimeshift(0);
2332
2333         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2334
2335         /* free the timeshift service handler, we need the resources */
2336         m_service_handler_timeshift.free();
2337
2338         updateDecoder(true);
2339 }
2340
2341 void eDVBServicePlay::resetTimeshift(int start)
2342 {
2343         m_cue = 0;
2344         m_decode_demux = 0;
2345         m_decoder = 0;
2346         m_teletext_parser = 0;
2347         m_rds_decoder = 0;
2348         m_subtitle_parser = 0;
2349         m_new_subtitle_page_connection = 0;
2350         m_new_dvb_subtitle_page_connection = 0;
2351         m_rds_decoder_event_connection = 0;
2352         m_video_event_connection = 0;
2353         m_timeshift_changed = 1;
2354         m_timeshift_file_next.clear();
2355
2356         if (start)
2357         {
2358                 m_cue = new eCueSheet();
2359                 m_timeshift_active = 1;
2360         }
2361         else
2362                 m_timeshift_active = 0;
2363 }
2364
2365 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2366 {
2367         eRawFile *f = new eRawFile();
2368         f->open(ref.path.c_str());
2369         return ePtr<iTsSource>(f);
2370 }
2371
2372 void eDVBServicePlay::switchToTimeshift()
2373 {
2374         if (m_timeshift_active)
2375                 return;
2376
2377         resetTimeshift(1);
2378
2379         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2380         r.path = m_timeshift_file;
2381
2382         m_cue->seekTo(0, -1000);
2383
2384         ePtr<iTsSource> source = createTsSource(r);
2385         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 */
2386
2387         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2388         pause();
2389         updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2390 }
2391
2392 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2393 {
2394         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2395         bool mustPlay = false;
2396
2397         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2398
2399         eDVBServicePMTHandler::program program;
2400         if (h.getProgramInfo(program))
2401                 eDebug("getting program info failed.");
2402         else
2403         {
2404                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2405                 if (!program.videoStreams.empty())
2406                 {
2407                         eDebugNoNewLine(" (");
2408                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2409                                 i(program.videoStreams.begin());
2410                                 i != program.videoStreams.end(); ++i)
2411                         {
2412                                 if (vpid == -1)
2413                                 {
2414                                         vpid = i->pid;
2415                                         vpidtype = i->type;
2416                                 }
2417                                 if (i != program.videoStreams.begin())
2418                                         eDebugNoNewLine(", ");
2419                                 eDebugNoNewLine("%04x", i->pid);
2420                         }
2421                         eDebugNoNewLine(")");
2422                 }
2423                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2424                 if (!program.audioStreams.empty())
2425                 {
2426                         eDebugNoNewLine(" (");
2427                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2428                                 i(program.audioStreams.begin());
2429                                 i != program.audioStreams.end(); ++i)
2430                         {
2431                                 if (i != program.audioStreams.begin())
2432                                         eDebugNoNewLine(", ");
2433                                 eDebugNoNewLine("%04x", i->pid);
2434                         }
2435                         eDebugNoNewLine(")");
2436                 }
2437                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2438                 pcrpid = program.pcrPid;
2439                 eDebug(", and the text pid is %04x", program.textPid);
2440                 tpid = program.textPid;
2441         }
2442
2443         if (!m_decoder)
2444         {
2445                 h.getDecodeDemux(m_decode_demux);
2446                 if (m_decode_demux)
2447                 {
2448                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2449                         if (m_decoder)
2450                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2451                         if (m_is_primary)
2452                         {
2453                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2454                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2455                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2456                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2457                                 if (m_timeshift_changed)
2458                                 {
2459                                         ePyObject subs = getCachedSubtitle();
2460                                         if (subs != Py_None)
2461                                         {
2462                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2463                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2464                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2465                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2466                                                 if (type == 0) // dvb
2467                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2468                                                 else if (type == 1) // ttx
2469                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2470                                         }
2471                                         Py_DECREF(subs);
2472                                 }
2473                         }
2474                 }
2475                 if (m_cue)
2476                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2477                 mustPlay = true;
2478         }
2479
2480         m_timeshift_changed = 0;
2481
2482         if (m_decoder)
2483         {
2484                 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2485                 if (m_dvb_service)
2486                 {
2487                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2488                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2489                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2490                 }
2491                 else // subservice
2492                 {
2493                         eServiceReferenceDVB ref;
2494                         m_service_handler.getServiceReference(ref);
2495                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2496                         if (!parent)
2497                                 parent = ref;
2498                         if (parent)
2499                         {
2500                                 ePtr<eDVBResourceManager> res_mgr;
2501                                 if (!eDVBResourceManager::getInstance(res_mgr))
2502                                 {
2503                                         ePtr<iDVBChannelList> db;
2504                                         if (!res_mgr->getChannelList(db))
2505                                         {
2506                                                 ePtr<eDVBService> origService;
2507                                                 if (!db->getService(parent, origService))
2508                                                 {
2509                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2510                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2511                                                 }
2512                                         }
2513                                 }
2514                         }
2515                 }
2516
2517                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2518                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2519
2520                 m_decoder->setVideoPID(vpid, vpidtype);
2521                 selectAudioStream();
2522
2523                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2524                         m_decoder->setSyncPCR(pcrpid);
2525                 else
2526                         m_decoder->setSyncPCR(-1);
2527
2528                 if (m_is_primary)
2529                 {
2530                         m_decoder->setTextPID(tpid);
2531                         m_teletext_parser->start(program.textPid);
2532                 }
2533
2534                 if (vpid > 0 && vpid < 0x2000)
2535                         ;
2536                 else
2537                 {
2538                         std::string radio_pic;
2539                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2540                                 m_decoder->setRadioPic(radio_pic);
2541                 }
2542
2543                 if (mustPlay)
2544                         m_decoder->play();
2545                 else
2546                         m_decoder->set();
2547
2548                 m_decoder->setAudioChannel(achannel);
2549
2550                 /* don't worry about non-existing services, nor pvr services */
2551                 if (m_dvb_service)
2552                 {
2553                                 /* (audio pid will be set in selectAudioTrack */
2554                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2555                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2556                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2557                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2558                 }
2559                 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2560                         sendSeekableStateChanged = true;
2561         }
2562         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2563
2564         if (sendSeekableStateChanged)
2565                 m_event((iPlayableService*)this, evSeekableStatusChanged);
2566 }
2567
2568 void eDVBServicePlay::loadCuesheet()
2569 {
2570         std::string filename = m_reference.path + ".cuts";
2571         
2572         m_cue_entries.clear();
2573
2574         FILE *f = fopen(filename.c_str(), "rb");
2575
2576         if (f)
2577         {
2578                 eDebug("loading cuts..");
2579                 while (1)
2580                 {
2581                         unsigned long long where;
2582                         unsigned int what;
2583                         
2584                         if (!fread(&where, sizeof(where), 1, f))
2585                                 break;
2586                         if (!fread(&what, sizeof(what), 1, f))
2587                                 break;
2588                         
2589 #if BYTE_ORDER == LITTLE_ENDIAN
2590                         where = bswap_64(where);
2591 #endif
2592                         what = ntohl(what);
2593                         
2594                         if (what > 3)
2595                                 break;
2596                         
2597                         m_cue_entries.insert(cueEntry(where, what));
2598                 }
2599                 fclose(f);
2600                 eDebug("%d entries", m_cue_entries.size());
2601         } else
2602                 eDebug("cutfile not found!");
2603         
2604         m_cuesheet_changed = 0;
2605         cutlistToCuesheet();
2606         m_event((iPlayableService*)this, evCuesheetChanged);
2607 }
2608
2609 void eDVBServicePlay::saveCuesheet()
2610 {
2611         std::string filename = m_reference.path + ".cuts";
2612         
2613         FILE *f = fopen(filename.c_str(), "wb");
2614
2615         if (f)
2616         {
2617                 unsigned long long where;
2618                 int what;
2619
2620                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2621                 {
2622 #if BYTE_ORDER == BIG_ENDIAN
2623                         where = i->where;
2624 #else
2625                         where = bswap_64(i->where);
2626 #endif
2627                         what = htonl(i->what);
2628                         fwrite(&where, sizeof(where), 1, f);
2629                         fwrite(&what, sizeof(what), 1, f);
2630                         
2631                 }
2632                 fclose(f);
2633         }
2634         
2635         m_cuesheet_changed = 0;
2636 }
2637
2638 void eDVBServicePlay::cutlistToCuesheet()
2639 {
2640         if (!m_cue)
2641         {
2642                 eDebug("no cue sheet");
2643                 return;
2644         }       
2645         m_cue->clear();
2646         
2647         if (!m_cutlist_enabled)
2648         {
2649                 m_cue->commitSpans();
2650                 eDebug("cutlists were disabled");
2651                 return;
2652         }
2653
2654         pts_t in = 0, out = 0, length = 0;
2655         
2656         getLength(length);
2657                 
2658         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2659         
2660         int have_any_span = 0;
2661         
2662         while (1)
2663         {
2664                 if (i == m_cue_entries.end())
2665                 {
2666                         if (!have_any_span && !in)
2667                                 break;
2668                         out = length;
2669                 } else {
2670                         if (i->what == 0) /* in */
2671                         {
2672                                 in = i++->where;
2673                                 continue;
2674                         } else if (i->what == 1) /* out */
2675                                 out = i++->where;
2676                         else /* mark (2) or last play position (3) */
2677                         {
2678                                 i++;
2679                                 continue;
2680                         }
2681                 }
2682                 
2683                 if (in < 0)
2684                         in = 0;
2685                 if (out < 0)
2686                         out = 0;
2687                 if (in > length)
2688                         in = length;
2689                 if (out > length)
2690                         out = length;
2691                 
2692                 if (in < out)
2693                 {
2694                         have_any_span = 1;
2695                         m_cue->addSourceSpan(in, out);
2696                         in = out = 0;
2697                 }
2698                 
2699                 in = length;
2700                 
2701                 if (i == m_cue_entries.end())
2702                         break;
2703         }
2704         m_cue->commitSpans();
2705 }
2706
2707 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2708 {
2709         if (m_subtitle_widget)
2710                 disableSubtitles(parent);
2711
2712         ePyObject entry;
2713         int tuplesize = PyTuple_Size(tuple);
2714         int type = 0;
2715
2716         if (!PyTuple_Check(tuple))
2717                 goto error_out;
2718
2719         if (tuplesize < 1)
2720                 goto error_out;
2721
2722         entry = PyTuple_GET_ITEM(tuple, 0);
2723
2724         if (!PyInt_Check(entry))
2725                 goto error_out;
2726
2727         type = PyInt_AsLong(entry);
2728
2729         if (type == 1)  // teletext subtitles
2730         {
2731                 int page, magazine, pid;
2732                 if (tuplesize < 4)
2733                         goto error_out;
2734
2735                 if (!m_teletext_parser)
2736                 {
2737                         eDebug("enable teletext subtitles.. no parser !!!");
2738                         return -1;
2739                 }
2740
2741                 entry = PyTuple_GET_ITEM(tuple, 1);
2742                 if (!PyInt_Check(entry))
2743                         goto error_out;
2744                 pid = PyInt_AsLong(entry);
2745
2746                 entry = PyTuple_GET_ITEM(tuple, 2);
2747                 if (!PyInt_Check(entry))
2748                         goto error_out;
2749                 page = PyInt_AsLong(entry);
2750
2751                 entry = PyTuple_GET_ITEM(tuple, 3);
2752                 if (!PyInt_Check(entry))
2753                         goto error_out;
2754                 magazine = PyInt_AsLong(entry);
2755
2756                 m_subtitle_widget = new eSubtitleWidget(parent);
2757                 m_subtitle_widget->resize(parent->size()); /* full size */
2758                 m_teletext_parser->setPageAndMagazine(page, magazine);
2759                 if (m_dvb_service)
2760                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2761         }
2762         else if (type == 0)
2763         {
2764                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2765                 if (!m_subtitle_parser)
2766                 {
2767                         eDebug("enable dvb subtitles.. no parser !!!");
2768                         return -1;
2769                 }
2770                 if (tuplesize < 4)
2771                         goto error_out;
2772
2773                 entry = PyTuple_GET_ITEM(tuple, 1);
2774                 if (!PyInt_Check(entry))
2775                         goto error_out;
2776                 pid = PyInt_AsLong(entry);
2777
2778                 entry = PyTuple_GET_ITEM(tuple, 2);
2779                 if (!PyInt_Check(entry))
2780                         goto error_out;
2781                 composition_page_id = PyInt_AsLong(entry);
2782
2783                 entry = PyTuple_GET_ITEM(tuple, 3);
2784                 if (!PyInt_Check(entry))
2785                         goto error_out;
2786                 ancillary_page_id = PyInt_AsLong(entry);
2787
2788                 m_subtitle_widget = new eSubtitleWidget(parent);
2789                 m_subtitle_widget->resize(parent->size()); /* full size */
2790                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2791                 if (m_dvb_service)
2792                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2793         }
2794         else
2795                 goto error_out;
2796         return 0;
2797 error_out:
2798         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2799                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2800                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2801         return -1;
2802 }
2803
2804 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2805 {
2806         delete m_subtitle_widget;
2807         m_subtitle_widget = 0;
2808         if (m_subtitle_parser)
2809         {
2810                 m_subtitle_parser->stop();
2811                 m_dvb_subtitle_pages.clear();
2812         }
2813         if (m_teletext_parser)
2814         {
2815                 m_teletext_parser->setPageAndMagazine(-1, -1);
2816                 m_subtitle_pages.clear();
2817         }
2818         if (m_dvb_service)
2819                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2820         return 0;
2821 }
2822
2823 PyObject *eDVBServicePlay::getCachedSubtitle()
2824 {
2825         if (m_dvb_service)
2826         {
2827                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2828                 if (tmp != -1)
2829                 {
2830                         unsigned int data = (unsigned int)tmp;
2831                         int pid = (data&0xFFFF0000)>>16;
2832                         ePyObject tuple = PyTuple_New(4);
2833                         eDVBServicePMTHandler::program program;
2834                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2835                         if (!h.getProgramInfo(program))
2836                         {
2837                                 if (program.textPid==pid) // teletext
2838                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2839                                 else
2840                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2841                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2842                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2843                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2844                                 return tuple;
2845                         }
2846                 }
2847         }
2848         Py_RETURN_NONE;
2849 }
2850
2851 PyObject *eDVBServicePlay::getSubtitleList()
2852 {
2853         if (!m_teletext_parser)
2854                 Py_RETURN_NONE;
2855         
2856         ePyObject l = PyList_New(0);
2857         std::set<int> added_ttx_pages;
2858
2859         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2860                 m_teletext_parser->m_found_subtitle_pages;
2861
2862         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2863         eDVBServicePMTHandler::program program;
2864         if (h.getProgramInfo(program))
2865                 eDebug("getting program info failed.");
2866         else
2867         {
2868                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2869                         it != program.subtitleStreams.end(); ++it)
2870                 {
2871                         switch(it->subtitling_type)
2872                         {
2873                                 case 0x01: // ebu teletext subtitles
2874                                 {
2875                                         int page_number = it->teletext_page_number & 0xFF;
2876                                         int magazine_number = it->teletext_magazine_number & 7;
2877                                         int hash = magazine_number << 8 | page_number;
2878                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2879                                         {
2880                                                 ePyObject tuple = PyTuple_New(5);
2881                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2882                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2883                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2884                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2885                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2886                                                 PyList_Append(l, tuple);
2887                                                 Py_DECREF(tuple);
2888                                                 added_ttx_pages.insert(hash);
2889                                         }
2890                                         break;
2891                                 }
2892                                 case 0x10 ... 0x13:
2893                                 case 0x20 ... 0x23: // dvb subtitles
2894                                 {
2895                                         ePyObject tuple = PyTuple_New(5);
2896                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2897                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2898                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2899                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2900                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2901                                         PyList_Insert(l, 0, tuple);
2902                                         Py_DECREF(tuple);
2903                                         break;
2904                                 }
2905                         }
2906                 }
2907         }
2908
2909         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2910                 it != subs.end(); ++it)
2911         {
2912                 int page_number = it->teletext_page_number & 0xFF;
2913                 int magazine_number = it->teletext_magazine_number & 7;
2914                 int hash = magazine_number << 8 | page_number;
2915                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2916                 {
2917                         ePyObject tuple = PyTuple_New(5);
2918                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2919                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2920                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2921                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2922                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2923                         PyList_Append(l, tuple);
2924                         Py_DECREF(tuple);
2925                 }
2926         }
2927
2928         return l;
2929 }
2930
2931 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2932 {
2933         if (m_subtitle_widget)
2934         {
2935                 pts_t pos = 0;
2936                 if (m_decoder)
2937                         m_decoder->getPTS(0, pos);
2938                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2939                 m_subtitle_pages.push_back(page);
2940                 checkSubtitleTiming();
2941         }
2942 }
2943
2944 void eDVBServicePlay::checkSubtitleTiming()
2945 {
2946         eDebug("checkSubtitleTiming");
2947         if (!m_subtitle_widget)
2948                 return;
2949         while (1)
2950         {
2951                 enum { TELETEXT, DVB } type;
2952                 eDVBTeletextSubtitlePage page;
2953                 eDVBSubtitlePage dvb_page;
2954                 pts_t show_time;
2955                 if (!m_subtitle_pages.empty())
2956                 {
2957                         page = m_subtitle_pages.front();
2958                         type = TELETEXT;
2959                         show_time = page.m_pts;
2960                 }
2961                 else if (!m_dvb_subtitle_pages.empty())
2962                 {
2963                         dvb_page = m_dvb_subtitle_pages.front();
2964                         type = DVB;
2965                         show_time = dvb_page.m_show_time;
2966                 }
2967                 else
2968                         return;
2969         
2970                 pts_t pos = 0;
2971         
2972                 if (m_decoder)
2973                         m_decoder->getPTS(0, pos);
2974
2975                 eDebug("%lld %lld", pos, show_time);
2976                 int diff = show_time - pos;
2977                 if (type == TELETEXT && !page.m_have_pts)
2978                 {
2979                         eDebug("ttx subtitle page without pts... immediate show");
2980                         diff = 0;
2981                 }
2982                 if (diff < 0)
2983                 {
2984                         eDebug("[late (%d ms)]", -diff / 90);
2985                         diff = 0;
2986                 }
2987                 if (abs(diff) > 1800000)
2988                 {
2989                         eDebug("[invalid]... immediate show!");
2990                         diff = 0;
2991                 }
2992                 if ((diff/90)<20)
2993                 {
2994                         if (type == TELETEXT)
2995                         {
2996                                 eDebug("display teletext subtitle page %lld", show_time);
2997                                 m_subtitle_widget->setPage(page);
2998                                 m_subtitle_pages.pop_front();
2999                         }
3000                         else
3001                         {
3002                                 eDebug("display dvb subtitle Page %lld", show_time);
3003                                 m_subtitle_widget->setPage(dvb_page);
3004                                 m_dvb_subtitle_pages.pop_front();
3005                         }
3006                 } else
3007                 {
3008                         eDebug("start subtitle delay %d", diff / 90);
3009                         m_subtitle_sync_timer->start(diff / 90, 1);
3010                         break;
3011                 }
3012         }
3013 }
3014
3015 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3016 {
3017         if (m_subtitle_widget)
3018         {
3019                 pts_t pos = 0;
3020                 if (m_decoder)
3021                         m_decoder->getPTS(0, pos);
3022                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3023                 m_dvb_subtitle_pages.push_back(p);
3024                 checkSubtitleTiming();
3025         }
3026 }
3027
3028 int eDVBServicePlay::getAC3Delay()
3029 {
3030         if (m_dvb_service)
3031                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3032         else if (m_decoder)
3033                 return m_decoder->getAC3Delay();
3034         else
3035                 return 0;
3036 }
3037
3038 int eDVBServicePlay::getPCMDelay()
3039 {
3040         if (m_dvb_service)
3041                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3042         else if (m_decoder)
3043                 return m_decoder->getPCMDelay();
3044         else
3045                 return 0;
3046 }
3047
3048 void eDVBServicePlay::setAC3Delay(int delay)
3049 {
3050         if (m_dvb_service)
3051                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3052         if (m_decoder) {
3053                 std::string config_delay;
3054                 int config_delay_int = 0;
3055                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3056                         config_delay_int = atoi(config_delay.c_str());
3057                 m_decoder->setAC3Delay(delay + config_delay_int);
3058         }
3059 }
3060
3061 void eDVBServicePlay::setPCMDelay(int delay)
3062 {
3063         if (m_dvb_service)
3064                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3065         if (m_decoder) {
3066                 std::string config_delay;
3067                 int config_delay_int = 0;
3068                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3069                         config_delay_int = atoi(config_delay.c_str());
3070                 else
3071                         config_delay_int = 0;
3072                 m_decoder->setPCMDelay(delay + config_delay_int);
3073         }
3074 }
3075
3076 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3077 {
3078         switch(event.type) {
3079                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3080                         m_event((iPlayableService*)this, evVideoSizeChanged);
3081                         break;
3082                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3083                         m_event((iPlayableService*)this, evVideoFramerateChanged);
3084                         break;
3085                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3086                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
3087                         break;
3088                 default:
3089                         break;
3090         }
3091 }
3092
3093 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3094 {
3095         ptr = this;
3096         return 0;
3097 }
3098
3099 PyObject *eDVBServicePlay::getStreamingData()
3100 {
3101         eDVBServicePMTHandler::program program;
3102         if (m_service_handler.getProgramInfo(program))
3103         {
3104                 Py_RETURN_NONE;
3105         }
3106
3107         ePyObject r = program.createPythonObject();
3108         ePtr<iDVBDemux> demux;
3109         if (!m_service_handler.getDataDemux(demux))