fixed single pat entry workaround, add delayed "no pat entry" handling to fix some...
[enigma2.git] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
20
21                 /* for subtitles */
22 #include <lib/gui/esubtitle.h>
23
24 #include <sys/vfs.h>
25 #include <sys/stat.h>
26
27 #include <byteswap.h>
28 #include <netinet/in.h>
29
30 #ifndef BYTE_ORDER
31 #error no byte order defined!
32 #endif
33
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
35 {
36         DECLARE_REF(eStaticServiceDVBInformation);
37 public:
38         RESULT getName(const eServiceReference &ref, std::string &name);
39         int getLength(const eServiceReference &ref);
40         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41         PyObject *getInfoObject(const eServiceReference &ref, int);
42 };
43
44 DEFINE_REF(eStaticServiceDVBInformation);
45
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
47 {
48         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49         if ( !ref.name.empty() )
50         {
51                 if (service.getParentTransportStreamID().get()) // linkage subservice
52                 {
53                         ePtr<iServiceHandler> service_center;
54                         if (!eServiceCenter::getInstance(service_center))
55                         {
56                                 eServiceReferenceDVB parent = service;
57                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
58                                 parent.setServiceID( service.getParentServiceID() );
59                                 parent.setParentTransportStreamID(eTransportStreamID(0));
60                                 parent.setParentServiceID(eServiceID(0));
61                                 parent.name="";
62                                 ePtr<iStaticServiceInformation> service_info;
63                                 if (!service_center->info(parent, service_info))
64                                 {
65                                         if (!service_info->getName(parent, name))
66                                                 name=buildShortName(name) + " - ";
67                                 }
68                         }
69                 }
70                 else
71                         name="";
72                 name += ref.name;
73                 return 0;
74         }
75         else
76                 return -1;
77 }
78
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
80 {
81         return -1;
82 }
83
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
85 {
86         ePtr<eDVBResourceManager> res_mgr;
87         if ( eDVBResourceManager::getInstance( res_mgr ) )
88                 eDebug("isPlayable... no res manager!!");
89         else
90         {
91                 eDVBChannelID chid, chid_ignore;
92                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94                 return res_mgr->canAllocateChannel(chid, chid_ignore);
95         }
96         return false;
97 }
98
99 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
100 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
101 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
102 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
103
104 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
105 {
106         if (r.type == eServiceReference::idDVB)
107         {
108                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
109                 switch(what)
110                 {
111                         case iServiceInformation::sTransponderData:
112                         {
113                                 ePtr<eDVBResourceManager> res;
114                                 if (!eDVBResourceManager::getInstance(res))
115                                 {
116                                         ePtr<iDVBChannelList> db;
117                                         if (!res->getChannelList(db))
118                                         {
119                                                 eDVBChannelID chid;
120                                                 ref.getChannelID(chid);
121                                                 ePtr<iDVBFrontendParameters> feparm;
122                                                 if (!db->getChannelFrontendData(chid, feparm))
123                                                 {
124                                                         int system;
125                                                         if (!feparm->getSystem(system))
126                                                         {
127                                                                 ePyObject dict = PyDict_New();
128                                                                 switch(system)
129                                                                 {
130                                                                         case iDVBFrontend::feSatellite:
131                                                                         {
132                                                                                 eDVBFrontendParametersSatellite s;
133                                                                                 feparm->getDVBS(s);
134                                                                                 PutSatelliteDataToDict(dict, s);
135                                                                                 break;
136                                                                         }
137                                                                         case iDVBFrontend::feTerrestrial:
138                                                                         {
139                                                                                 eDVBFrontendParametersTerrestrial t;
140                                                                                 feparm->getDVBT(t);
141                                                                                 PutTerrestrialDataToDict(dict, t);
142                                                                                 break;
143                                                                         }
144                                                                         case iDVBFrontend::feCable:
145                                                                         {
146                                                                                 eDVBFrontendParametersCable c;
147                                                                                 feparm->getDVBC(c);
148                                                                                 PutCableDataToDict(dict, c);
149                                                                                 break;
150                                                                         }
151                                                                         default:
152                                                                                 eDebug("unknown frontend type %d", system);
153                                                                                 Py_DECREF(dict);
154                                                                                 break;
155                                                                 }
156                                                                 return dict;
157                                                         }
158                                                 }
159                                         }
160                                 }
161                         }
162                 }
163         }
164         Py_RETURN_NONE;
165 }
166
167 DEFINE_REF(eStaticServiceDVBBouquetInformation);
168
169 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
170 {
171         ePtr<iDVBChannelList> db;
172         ePtr<eDVBResourceManager> res;
173
174         int err;
175         if ((err = eDVBResourceManager::getInstance(res)) != 0)
176         {
177                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
178                 return err;
179         }
180         if ((err = res->getChannelList(db)) != 0)
181         {
182                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
183                 return err;
184         }
185
186         eBouquet *bouquet=0;
187         if ((err = db->getBouquet(ref, bouquet)) != 0)
188         {
189                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
190                 return -1;
191         }
192
193         if ( bouquet && bouquet->m_bouquet_name.length() )
194         {
195                 name = bouquet->m_bouquet_name;
196                 return 0;
197         }
198         else
199                 return -1;
200 }
201
202 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
203 {
204         if (ref.flags & eServiceReference::isGroup)
205         {
206                 ePtr<iDVBChannelList> db;
207                 ePtr<eDVBResourceManager> res;
208
209                 if (eDVBResourceManager::getInstance(res))
210                 {
211                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
212                         return 0;
213                 }
214
215                 if (res->getChannelList(db))
216                 {
217                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
218                         return 0;
219                 }
220
221                 eBouquet *bouquet=0;
222                 if (db->getBouquet(ref, bouquet))
223                 {
224                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
225                         return 0;
226                 }
227
228                 int prio_order = eDVBFrontend::getTypePriorityOrder();
229                 int cur=0;
230                 eDVBChannelID chid, chid_ignore;
231                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
232                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
233                 {
234                         static unsigned char prio_map[6][3] = {
235                                 { 3, 2, 1 }, // -S -C -T
236                                 { 3, 1, 2 }, // -S -T -C
237                                 { 2, 3, 1 }, // -C -S -T
238                                 { 1, 3, 2 }, // -C -T -S
239                                 { 1, 2, 3 }, // -T -C -S
240                                 { 2, 1, 3 }  // -T -S -C
241                         };
242                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
243                         int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
244                         switch(tmp)
245                         {
246                                 case 0:
247                                         break;
248                                 case 30000: // cached DVB-T channel
249                                 case 1: // DVB-T frontend
250                                         tmp = prio_map[prio_order][2];
251                                         break;
252                                 case 40000: // cached DVB-C channel
253                                 case 2:
254                                         tmp = prio_map[prio_order][1];
255                                         break;
256                                 default: // DVB-S
257                                         tmp = prio_map[prio_order][0];
258                                         break;
259                         }
260                         if (tmp > cur)
261                         {
262                                 m_playable_service = *it;
263                                 cur = tmp;
264                         }
265                 }
266                 if (cur)
267                         return cur;
268         }
269         m_playable_service = eServiceReference();
270         return 0;
271 }
272
273 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
274 {
275         return -1;
276 }
277
278 #include <lib/dvb/epgcache.h>
279
280 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
281 {
282         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
283 }
284
285 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
286 {
287         DECLARE_REF(eStaticServiceDVBPVRInformation);
288         eServiceReference m_ref;
289         eDVBMetaParser m_parser;
290 public:
291         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
292         RESULT getName(const eServiceReference &ref, std::string &name);
293         int getLength(const eServiceReference &ref);
294         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
295         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
296         int getInfo(const eServiceReference &ref, int w);
297         std::string getInfoString(const eServiceReference &ref,int w);
298         PyObject *getInfoObject(const eServiceReference &r, int what);
299 };
300
301 DEFINE_REF(eStaticServiceDVBPVRInformation);
302
303 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
304 {
305         m_ref = ref;
306         m_parser.parseFile(ref.path);
307 }
308
309 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
310 {
311         ASSERT(ref == m_ref);
312         if (m_parser.m_name.size())
313                 name = m_parser.m_name;
314         else
315         {
316                 name = ref.path;
317                 size_t n = name.rfind('/');
318                 if (n != std::string::npos)
319                         name = name.substr(n + 1);
320         }
321         return 0;
322 }
323
324 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
325 {
326         ASSERT(ref == m_ref);
327         
328         eDVBTSTools tstools;
329         
330         struct stat s;
331         stat(ref.path.c_str(), &s);
332
333         if (tstools.openFile(ref.path.c_str(), 1))
334                 return 0;
335
336                         /* check if cached data is still valid */
337         if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
338                 return m_parser.m_length / 90000;
339
340                         /* open again, this time with stream info */
341         if (tstools.openFile(ref.path.c_str()))
342                 return 0;
343
344                         /* otherwise, re-calc length and update meta file */
345         pts_t len;
346         if (tstools.calcLen(len))
347                 return 0;
348
349         m_parser.m_length = len;
350         m_parser.m_filesize = s.st_size;
351         m_parser.updateMeta(ref.path);
352         return m_parser.m_length / 90000;
353 }
354
355 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
356 {
357         switch (w)
358         {
359         case iServiceInformation::sDescription:
360                 return iServiceInformation::resIsString;
361         case iServiceInformation::sServiceref:
362                 return iServiceInformation::resIsString;
363         case iServiceInformation::sFileSize:
364                 return m_parser.m_filesize;
365         case iServiceInformation::sTimeCreate:
366                 if (m_parser.m_time_create)
367                         return m_parser.m_time_create;
368                 else
369                         return iServiceInformation::resNA;
370         default:
371                 return iServiceInformation::resNA;
372         }
373 }
374
375 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
376 {
377         switch (w)
378         {
379         case iServiceInformation::sDescription:
380                 return m_parser.m_description;
381         case iServiceInformation::sServiceref:
382                 return m_parser.m_ref.toString();
383         case iServiceInformation::sTags:
384                 return m_parser.m_tags;
385         default:
386                 return "";
387         }
388 }
389
390 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
391 {
392         switch (what)
393         {
394         case iServiceInformation::sFileSize:
395                 return PyLong_FromLongLong(m_parser.m_filesize);
396         default:
397                 Py_RETURN_NONE;
398         }
399 }
400
401 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
402 {
403         if (!ref.path.empty())
404         {
405                 ePtr<eServiceEvent> event = new eServiceEvent;
406                 std::string filename = ref.path;
407                 filename.erase(filename.length()-2, 2);
408                 filename+="eit";
409                 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
410                 {
411                         evt = event;
412                         return 0;
413                 }
414         }
415         evt = 0;
416         return -1;
417 }
418
419 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
420 {
421         DECLARE_REF(eDVBPVRServiceOfflineOperations);
422         eServiceReferenceDVB m_ref;
423 public:
424         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
425         
426         RESULT deleteFromDisk(int simulate);
427         RESULT getListOfFilenames(std::list<std::string> &);
428         RESULT reindex();
429 };
430
431 DEFINE_REF(eDVBPVRServiceOfflineOperations);
432
433 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
434 {
435 }
436
437 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
438 {
439         if (simulate)
440                 return 0;
441         else
442         {
443                 std::list<std::string> res;
444                 if (getListOfFilenames(res))
445                         return -1;
446                 
447                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
448                 if (!eraser)
449                         eDebug("FATAL !! can't get background file eraser");
450                 
451                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
452                 {
453                         eDebug("Removing %s...", i->c_str());
454                         if (eraser)
455                                 eraser->erase(i->c_str());
456                         else
457                                 ::unlink(i->c_str());
458                 }
459                 
460                 return 0;
461         }
462 }
463
464 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
465 {
466         res.clear();
467         res.push_back(m_ref.path);
468
469 // handling for old splitted recordings (enigma 1)
470         char buf[255];
471         int slice=1;
472         while(true)
473         {
474                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
475                 struct stat s;
476                 if (stat(buf, &s) < 0)
477                         break;
478                 res.push_back(buf);
479         }       
480
481         res.push_back(m_ref.path + ".meta");
482         res.push_back(m_ref.path + ".ap");
483         res.push_back(m_ref.path + ".sc");
484         res.push_back(m_ref.path + ".cuts");
485         std::string tmp = m_ref.path;
486         tmp.erase(m_ref.path.length()-3);
487         res.push_back(tmp + ".eit");
488         return 0;
489 }
490
491 RESULT eDVBPVRServiceOfflineOperations::reindex()
492 {
493         const char *filename = m_ref.path.c_str();
494         eDebug("reindexing %s...", filename);
495
496         eMPEGStreamInformation info;
497         eMPEGStreamParserTS parser(info);
498         
499         info.startSave(filename);
500         
501         eRawFile f;
502         
503         int err = f.open(m_ref.path.c_str(), 0);
504         if (err < 0)
505                 return -1;
506
507         off_t offset = 0;
508         off_t length = f.length();
509         unsigned char buffer[188*256*4];
510         while (1)
511         {
512                 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
513                 int r = f.read(offset, buffer, sizeof(buffer));
514                 if (!r)
515                         break;
516                 if (r < 0)
517                         return r;
518                 offset += r;
519                 parser.parseData(offset, buffer, r);
520         }
521         
522         info.stopSave();
523         f.close();
524         
525         return 0;
526 }
527
528 DEFINE_REF(eServiceFactoryDVB)
529
530 eServiceFactoryDVB::eServiceFactoryDVB()
531 {
532         ePtr<eServiceCenter> sc;
533         
534         eServiceCenter::getPrivInstance(sc);
535         if (sc)
536         {
537                 std::list<std::string> extensions;
538                 extensions.push_back("ts");
539                 extensions.push_back("trp");
540                 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
541         }
542
543         m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
544         m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
545 }
546
547 eServiceFactoryDVB::~eServiceFactoryDVB()
548 {
549         ePtr<eServiceCenter> sc;
550         
551         eServiceCenter::getPrivInstance(sc);
552         if (sc)
553                 sc->removeServiceFactory(eServiceFactoryDVB::id);
554 }
555
556 DEFINE_REF(eDVBServiceList);
557
558 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
559 {
560 }
561
562 eDVBServiceList::~eDVBServiceList()
563 {
564 }
565
566 RESULT eDVBServiceList::startQuery()
567 {
568         ePtr<iDVBChannelList> db;
569         ePtr<eDVBResourceManager> res;
570         
571         int err;
572         if ((err = eDVBResourceManager::getInstance(res)) != 0)
573         {
574                 eDebug("no resource manager");
575                 return err;
576         }
577         if ((err = res->getChannelList(db)) != 0)
578         {
579                 eDebug("no channel list");
580                 return err;
581         }
582         
583         ePtr<eDVBChannelQuery> q;
584         
585         if (!m_parent.path.empty())
586         {
587                 eDVBChannelQuery::compile(q, m_parent.path);
588                 if (!q)
589                 {
590                         eDebug("compile query failed");
591                         return err;
592                 }
593         }
594         
595         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
596         {
597                 eDebug("startQuery failed");
598                 return err;
599         }
600
601         return 0;
602 }
603
604 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
605 {
606         eServiceReferenceDVB ref;
607         
608         if (!m_query)
609                 return -1;
610
611         while (!m_query->getNextResult(ref))
612                 list.push_back(ref);
613
614         if (sorted)
615                 list.sort(iListableServiceCompare(this));
616
617         return 0;
618 }
619
620 //   The first argument of this function is a format string to specify the order and
621 //   the content of the returned list
622 //   useable format options are
623 //   R = Service Reference (as swig object .. this is very slow)
624 //   S = Service Reference (as python string object .. same as ref.toString())
625 //   C = Service Reference (as python string object .. same as ref.toCompareString())
626 //   N = Service Name (as python string object)
627 //   n = Short Service Name (short name brakets used) (as python string object)
628 //   when exactly one return value per service is selected in the format string,
629 //   then each value is directly a list entry
630 //   when more than one value is returned per service, then the list is a list of
631 //   python tuples
632 //   unknown format string chars are returned as python None values !
633 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
634 {
635         ePyObject ret;
636         std::list<eServiceReference> tmplist;
637         int retcount=1;
638
639         if (!format || !(retcount=strlen(format)))
640                 format = "R"; // just return service reference swig object ...
641
642         if (!getContent(tmplist, sorted))
643         {
644                 int services=tmplist.size();
645                 ePtr<iStaticServiceInformation> sptr;
646                 eServiceCenterPtr service_center;
647
648                 if (strchr(format, 'N') || strchr(format, 'n'))
649                         eServiceCenter::getPrivInstance(service_center);
650
651                 ret = PyList_New(services);
652                 std::list<eServiceReference>::iterator it(tmplist.begin());
653
654                 for (int cnt=0; cnt < services; ++cnt)
655                 {
656                         eServiceReference &ref=*it++;
657                         ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
658                         for (int i=0; i < retcount; ++i)
659                         {
660                                 ePyObject tmp;
661                                 switch(format[i])
662                                 {
663                                 case 'R':  // service reference (swig)object
664                                         tmp = NEW_eServiceReference(ref);
665                                         break;
666                                 case 'C':  // service reference compare string
667                                         tmp = PyString_FromString(ref.toCompareString().c_str());
668                                         break;
669                                 case 'S':  // service reference string
670                                         tmp = PyString_FromString(ref.toString().c_str());
671                                         break;
672                                 case 'N':  // service name
673                                         if (service_center)
674                                         {
675                                                 service_center->info(ref, sptr);
676                                                 if (sptr)
677                                                 {
678                                                         std::string name;
679                                                         sptr->getName(ref, name);
680
681                                                         // filter short name brakets
682                                                         size_t pos;
683                                                         while((pos = name.find("\xc2\x86")) != std::string::npos)
684                                                                 name.erase(pos,2);
685                                                         while((pos = name.find("\xc2\x87")) != std::string::npos)
686                                                                 name.erase(pos,2);
687
688                                                         if (name.length())
689                                                                 tmp = PyString_FromString(name.c_str());
690                                                 }
691                                         }
692                                         if (!tmp)
693                                                 tmp = PyString_FromString("<n/a>");
694                                         break;
695                                 case 'n':  // short service name
696                                         if (service_center)
697                                         {
698                                                 service_center->info(ref, sptr);
699                                                 if (sptr)
700                                                 {
701                                                         std::string name;
702                                                         sptr->getName(ref, name);
703                                                         name = buildShortName(name);
704                                                         if (name.length())
705                                                                 tmp = PyString_FromString(name.c_str());
706                                                 }
707                                         }
708                                         if (!tmp)
709                                                 tmp = PyString_FromString("<n/a>");
710                                         break;
711                                 default:
712                                         if (tuple)
713                                         {
714                                                 tmp = Py_None;
715                                                 Py_INCREF(Py_None);
716                                         }
717                                         break;
718                                 }
719                                 if (tmp)
720                                 {
721                                         if (tuple)
722                                                 PyTuple_SET_ITEM(tuple, i, tmp);
723                                         else
724                                                 PyList_SET_ITEM(ret, cnt, tmp);
725                                 }
726                         }
727                         if (tuple)
728                                 PyList_SET_ITEM(ret, cnt, tuple);
729                 }
730         }
731         return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
732 }
733
734 RESULT eDVBServiceList::getNext(eServiceReference &ref)
735 {
736         if (!m_query)
737                 return -1;
738         
739         return m_query->getNextResult((eServiceReferenceDVB&)ref);
740 }
741
742 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
743 {
744         if (m_parent.flags & eServiceReference::canDescent) // bouquet
745         {
746                 ePtr<iDVBChannelList> db;
747                 ePtr<eDVBResourceManager> resm;
748
749                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
750                         return -1;
751
752                 if (db->getBouquet(m_parent, m_bouquet) != 0)
753                         return -1;
754
755                 res = this;
756                 
757                 return 0;
758         }
759         res = 0;
760         return -1;
761 }
762
763 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
764 {
765         if (!m_bouquet)
766                 return -1;
767         return m_bouquet->addService(ref, before);
768 }
769
770 RESULT eDVBServiceList::removeService(eServiceReference &ref)
771 {
772         if (!m_bouquet)
773                 return -1;
774         return m_bouquet->removeService(ref);
775 }
776
777 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
778 {
779         if (!m_bouquet)
780                 return -1;
781         return m_bouquet->moveService(ref, pos);
782 }
783
784 RESULT eDVBServiceList::flushChanges()
785 {
786         if (!m_bouquet)
787                 return -1;
788         return m_bouquet->flushChanges();
789 }
790
791 RESULT eDVBServiceList::setListName(const std::string &name)
792 {
793         if (!m_bouquet)
794                 return -1;
795         return m_bouquet->setListName(name);
796 }
797
798 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
799 {
800         ePtr<eDVBService> service;
801         int r = lookupService(service, ref);
802         if (r)
803                 service = 0;
804                 // check resources...
805         ptr = new eDVBServicePlay(ref, service);
806         return 0;
807 }
808
809 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
810 {
811         if (ref.path.empty())
812         {
813                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
814                 return 0;
815         } else
816         {
817                 ptr = 0;
818                 return -1;
819         }
820 }
821
822 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
823 {
824         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
825         if (list->startQuery())
826         {
827                 ptr = 0;
828                 return -1;
829         }
830         
831         ptr = list;
832         return 0;
833 }
834
835 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
836 {
837         /* is a listable service? */
838         if (ref.flags & eServiceReference::canDescent) // bouquet
839         {
840                 if ( !ref.name.empty() )  // satellites or providers list
841                         ptr = m_StaticServiceDVBInfo;
842                 else // a dvb bouquet
843                         ptr = m_StaticServiceDVBBouquetInfo;
844         }
845         else if (!ref.path.empty()) /* do we have a PVR service? */
846                 ptr = new eStaticServiceDVBPVRInformation(ref);
847         else // normal dvb service
848         {
849                 ePtr<eDVBService> service;
850                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
851                         ptr = m_StaticServiceDVBInfo;
852                 else
853                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
854                         ptr = service;
855         }
856         return 0;
857 }
858
859 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
860 {
861         if (ref.path.empty())
862         {
863                 ptr = 0;
864                 return -1;
865         } else
866         {
867                 ptr = new eDVBPVRServiceOfflineOperations(ref);
868                 return 0;
869         }
870 }
871
872 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
873 {
874         if (!ref.path.empty()) // playback
875         {
876                 eDVBMetaParser parser;
877                 int ret=parser.parseFile(ref.path);
878                 service = new eDVBService;
879                 if (!ret)
880                         eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
881         }
882         else
883         {
884                         // TODO: handle the listing itself
885                 // if (ref.... == -1) .. return "... bouquets ...";
886                 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
887                         // TODO: cache
888                 ePtr<iDVBChannelList> db;
889                 ePtr<eDVBResourceManager> res;
890         
891                 int err;
892                 if ((err = eDVBResourceManager::getInstance(res)) != 0)
893                 {
894                         eDebug("no resource manager");
895                         return err;
896                 }
897                 if ((err = res->getChannelList(db)) != 0)
898                 {
899                         eDebug("no channel list");
900                         return err;
901                 }
902         
903                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
904                 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
905                 {
906                         eDebug("getService failed!");
907                         return err;
908                 }
909         }
910
911         return 0;
912 }
913
914 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
915         m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
916 {
917         m_is_primary = 1;
918         m_is_pvr = !m_reference.path.empty();
919         
920         m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
921         m_skipmode = m_fastforward = m_slowmotion = 0;
922         
923         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
924         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
925         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
926
927         m_cuesheet_changed = 0;
928         m_cutlist_enabled = 1;
929         
930         m_subtitle_widget = 0;
931         
932         m_tune_state = -1;
933
934         m_subtitle_sync_timer = eTimer::create(eApp);
935
936         CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
937 }
938
939 eDVBServicePlay::~eDVBServicePlay()
940 {
941         if (m_is_pvr)
942         {
943                 eDVBMetaParser meta;
944                 int ret=meta.parseFile(m_reference.path);
945                 if (!ret)
946                 {
947                         char tmp[255];
948                         meta.m_service_data="";
949                         sprintf(tmp, "f:%x", m_dvb_service->m_flags);
950                         meta.m_service_data += tmp;
951                         // cached pids
952                         for (int x=0; x < eDVBService::cacheMax; ++x)
953                         {
954                                 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
955                                 if (entry != -1)
956                                 {
957                                         sprintf(tmp, ",c:%02d%04x", x, entry);
958                                         meta.m_service_data += tmp;
959                                 }
960                         }
961                         meta.updateMeta(m_reference.path);
962                 }
963         }
964         delete m_subtitle_widget;
965 }
966
967 void eDVBServicePlay::gotNewEvent()
968 {
969 #if 0
970                 // debug only
971         ePtr<eServiceEvent> m_event_now, m_event_next;
972         getEvent(m_event_now, 0);
973         getEvent(m_event_next, 1);
974
975         if (m_event_now)
976                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
977         if (m_event_next)
978                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
979 #endif
980         m_event((iPlayableService*)this, evUpdatedEventInfo);
981 }
982
983 void eDVBServicePlay::serviceEvent(int event)
984 {
985         m_tune_state = event;
986
987         switch (event)
988         {
989         case eDVBServicePMTHandler::eventTuned:
990         {
991                 ePtr<iDVBDemux> m_demux;
992                 if (!m_service_handler.getDataDemux(m_demux))
993                 {
994                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
995                         int sid = ref.getParentServiceID().get();
996                         if (!sid)
997                                 sid = ref.getServiceID().get();
998                         if ( ref.getParentTransportStreamID().get() &&
999                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1000                                 m_event_handler.startOther(m_demux, sid);
1001                         else
1002                                 m_event_handler.start(m_demux, sid);
1003                 }
1004                 m_event((iPlayableService*)this, evTunedIn);
1005                 break;
1006         }
1007         case eDVBServicePMTHandler::eventNoResources:
1008         case eDVBServicePMTHandler::eventNoPAT:
1009         case eDVBServicePMTHandler::eventNoPATEntry:
1010         case eDVBServicePMTHandler::eventNoPMT:
1011         case eDVBServicePMTHandler::eventTuneFailed:
1012         case eDVBServicePMTHandler::eventMisconfiguration:
1013         {
1014                 eDebug("DVB service failed to tune - error %d", event);
1015                 m_event((iPlayableService*)this, evTuneFailed);
1016                 break;
1017         }
1018         case eDVBServicePMTHandler::eventNewProgramInfo:
1019         {
1020                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1021                 if (m_timeshift_enabled)
1022                         updateTimeshiftPids();
1023                 if (!m_timeshift_active)
1024                         updateDecoder();
1025                 if (m_first_program_info & 1 && m_is_pvr)
1026                 {
1027                         m_first_program_info &= ~1;
1028                         seekTo(0);
1029                 }
1030                 if (!m_timeshift_active)
1031                         m_event((iPlayableService*)this, evUpdatedInfo);
1032                 break;
1033         }
1034         case eDVBServicePMTHandler::eventPreStart:
1035                 loadCuesheet();
1036                 break;
1037         case eDVBServicePMTHandler::eventEOF:
1038                 m_event((iPlayableService*)this, evEOF);
1039                 break;
1040         case eDVBServicePMTHandler::eventSOF:
1041                 m_event((iPlayableService*)this, evSOF);
1042                 break;
1043         }
1044 }
1045
1046 void eDVBServicePlay::serviceEventTimeshift(int event)
1047 {
1048         switch (event)
1049         {
1050         case eDVBServicePMTHandler::eventNewProgramInfo:
1051                 eDebug("eventNewProgramInfo TS");
1052                 if (m_timeshift_active)
1053                 {
1054                         updateDecoder();
1055                         if (m_first_program_info & 2)
1056                         {
1057                                 if (m_slowmotion)
1058                                 {
1059                                         eDebug("re-apply slowmotion after timeshift file change");
1060                                         m_decoder->setSlowMotion(m_slowmotion);
1061                                 }
1062                                 if (m_fastforward)
1063                                 {
1064                                         eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1065                                         if (m_skipmode)
1066                                                 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1067                                         if (m_fastforward != 1)
1068                                                 m_decoder->setFastForward(m_fastforward);
1069                                         else
1070                                                 m_decoder->setTrickmode();
1071                                 }
1072                                 else
1073                                         seekTo(0);
1074                                 m_first_program_info &= ~2;
1075                         }
1076                         m_event((iPlayableService*)this, evUpdatedInfo);
1077                 }
1078                 break;
1079         case eDVBServicePMTHandler::eventSOF:
1080 #if 0
1081                 if (!m_timeshift_file_next.empty())
1082                 {
1083                         eDebug("timeshift SOF, switch to next file");
1084                         m_decoder->pause();
1085
1086                         m_first_program_info |= 2;
1087
1088                         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1089                         r.path = m_timeshift_file_next;
1090
1091                         /* free the timeshift service handler, we need the resources */
1092                         m_service_handler_timeshift.free();
1093                         resetTimeshift(1);
1094
1095                         if (m_skipmode < 0)
1096                                 m_cue->seekTo(0, -1000);
1097                         ePtr<iTsSource> source = createTsSource(r);
1098                         m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1099
1100                         m_event((iPlayableService*)this, evUser+1);
1101                 }
1102                 else
1103 #endif
1104                         m_event((iPlayableService*)this, evSOF);
1105                 break;
1106         case eDVBServicePMTHandler::eventEOF:
1107                 if ((!m_is_paused) && (m_skipmode >= 0))
1108                 {
1109                         if (m_timeshift_file_next.empty())
1110                         {
1111                                 eDebug("timeshift EOF, so let's go live");
1112                                 switchToLive();
1113                         }
1114                         else
1115                         {
1116                                 eDebug("timeshift EOF, switch to next file");
1117
1118                                 m_first_program_info |= 2;
1119
1120                                 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1121                                 r.path = m_timeshift_file_next;
1122
1123                                 /* free the timeshift service handler, we need the resources */
1124                                 m_service_handler_timeshift.free();
1125                                 resetTimeshift(1);
1126
1127                                 ePtr<iTsSource> source = createTsSource(r);
1128                                 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 */
1129
1130                                 m_event((iPlayableService*)this, evUser+1);
1131                         }
1132                 }
1133                 break;
1134         }
1135 }
1136
1137 RESULT eDVBServicePlay::start()
1138 {
1139         eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1140
1141                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
1142                    two (one for decoding, one for data source), as we must be prepared
1143                    to start recording from the data demux. */
1144         if (m_is_pvr)
1145         {
1146                 eDVBMetaParser meta;
1147                 if (!meta.parseFile(m_reference.path))
1148                 {
1149                         service = meta.m_ref;
1150                         service.path = m_reference.path;
1151                 }
1152                 m_cue = new eCueSheet();
1153         }
1154         else
1155                 m_event(this, evStart);
1156
1157         m_first_program_info = 1;
1158         ePtr<iTsSource> source = createTsSource(service);
1159         m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service);
1160
1161         if (m_is_pvr)
1162         {
1163                 /* inject EIT if there is a stored one */
1164                 std::string filename = service.path;
1165                 filename.erase(filename.length()-2, 2);
1166                 filename+="eit";
1167                 ePtr<eServiceEvent> event = new eServiceEvent;
1168                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1169                 {
1170                         ePtr<eServiceEvent> empty;
1171                         m_event_handler.inject(event, 0);
1172                         m_event_handler.inject(empty, 1);
1173                 }
1174                 m_event(this, evStart);
1175         }
1176         return 0;
1177 }
1178
1179 RESULT eDVBServicePlay::stop()
1180 {
1181                 /* add bookmark for last play position */
1182         if (m_is_pvr)
1183         {
1184                 pts_t play_position, length;
1185                 if (!getPlayPosition(play_position))
1186                 {
1187                                 /* remove last position */
1188                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1189                         {
1190                                 if (i->what == 3) /* current play position */
1191                                 {
1192                                         m_cue_entries.erase(i);
1193                                         i = m_cue_entries.begin();
1194                                         continue;
1195                                 } else
1196                                         ++i;
1197                         }
1198                         
1199                         if (getLength(length))
1200                                 length = 0;
1201                         
1202                         if (length)
1203                         {
1204                                 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1205                         }
1206                         m_cuesheet_changed = 1;
1207                 }
1208         }
1209
1210         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1211
1212         m_service_handler_timeshift.free();
1213         m_service_handler.free();
1214         
1215         if (m_is_pvr && m_cuesheet_changed)
1216         {
1217                 struct stat s;
1218                                 /* save cuesheet only when main file is accessible. */
1219                 if (!::stat(m_reference.path.c_str(), &s))
1220                         saveCuesheet();
1221         }
1222         m_event((iPlayableService*)this, evStopped);
1223         return 0;
1224 }
1225
1226 RESULT eDVBServicePlay::setTarget(int target)
1227 {
1228         m_is_primary = !target;
1229         return 0;
1230 }
1231
1232 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1233 {
1234         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1235         return 0;
1236 }
1237
1238 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1239 {
1240                 /* note: we check for timeshift to be enabled,
1241                    not neccessary active. if you pause when timeshift
1242                    is not active, you should activate it when unpausing */
1243         if ((!m_is_pvr) && (!m_timeshift_enabled))
1244         {
1245                 ptr = 0;
1246                 return -1;
1247         }
1248
1249         ptr = this;
1250         return 0;
1251 }
1252
1253 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1254 {
1255         ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1256         eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1257         setFastForward_internal(0);
1258         if (m_decoder)
1259         {
1260                 m_slowmotion = ratio;
1261                 return m_decoder->setSlowMotion(ratio);
1262         }
1263         else
1264                 return -1;
1265 }
1266
1267 RESULT eDVBServicePlay::setFastForward(int ratio)
1268 {
1269         eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1270         ASSERT(ratio);
1271         return setFastForward_internal(ratio);
1272 }
1273
1274 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1275 {
1276         int skipmode, ffratio, ret = 0;
1277         pts_t pos=0;
1278
1279         if (ratio > 8)
1280         {
1281                 skipmode = ratio;
1282                 ffratio = 1;
1283         } else if (ratio > 0)
1284         {
1285                 skipmode = 0;
1286                 ffratio = ratio;
1287         } else if (!ratio)
1288         {
1289                 skipmode = 0;
1290                 ffratio = 0;
1291         } else // if (ratio < 0)
1292         {
1293                 skipmode = ratio;
1294                 ffratio = 1;
1295         }
1296
1297         if (m_skipmode != skipmode)
1298         {
1299                 eDebug("setting cue skipmode to %d", skipmode);
1300                 if (m_cue)
1301                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1302         }
1303
1304         m_skipmode = skipmode;
1305
1306         if (final_seek)
1307                 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1308
1309         m_fastforward = ffratio;
1310
1311         if (!m_decoder)
1312                 return -1;
1313
1314         if (ffratio == 0)
1315                 ; /* return m_decoder->play(); is done in caller*/
1316         else if (ffratio != 1)
1317                 ret = m_decoder->setFastForward(ffratio);
1318         else
1319                 ret = m_decoder->setTrickmode();
1320
1321         if (pos)
1322                 eDebug("final seek after trickplay ret %d", seekTo(pos));
1323
1324         return ret;
1325 }
1326
1327 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1328 {
1329         if (m_is_pvr || m_timeshift_enabled)
1330         {
1331                 ptr = this;
1332                 return 0;
1333         }
1334         
1335         ptr = 0;
1336         return -1;
1337 }
1338
1339         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1340 RESULT eDVBServicePlay::getLength(pts_t &len)
1341 {
1342         ePtr<iDVBPVRChannel> pvr_channel;
1343         
1344         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1345                 return -1;
1346         
1347         return pvr_channel->getLength(len);
1348 }
1349
1350 RESULT eDVBServicePlay::pause()
1351 {
1352         eDebug("eDVBServicePlay::pause");
1353         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1354         if (m_decoder)
1355         {
1356                 m_slowmotion = 0;
1357                 m_is_paused = 1;
1358                 return m_decoder->pause();
1359         } else
1360                 return -1;
1361 }
1362
1363 RESULT eDVBServicePlay::unpause()
1364 {
1365         eDebug("eDVBServicePlay::unpause");
1366         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1367         if (m_decoder)
1368         {
1369                 m_slowmotion = 0;
1370                 m_is_paused = 0;
1371                 return m_decoder->play();
1372         } else
1373                 return -1;
1374 }
1375
1376 RESULT eDVBServicePlay::seekTo(pts_t to)
1377 {
1378         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1379         
1380         if (!m_decode_demux)
1381                 return -1;
1382
1383         ePtr<iDVBPVRChannel> pvr_channel;
1384         
1385         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1386                 return -1;
1387         
1388         if (!m_cue)
1389                 return -1;
1390         
1391         m_cue->seekTo(0, to);
1392         m_dvb_subtitle_pages.clear();
1393         m_subtitle_pages.clear();
1394
1395         return 0;
1396 }
1397
1398 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1399 {
1400         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1401         
1402         if (!m_decode_demux)
1403                 return -1;
1404
1405         ePtr<iDVBPVRChannel> pvr_channel;
1406         
1407         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1408                 return -1;
1409         
1410         int mode = 1;
1411         
1412                         /* HACK until we have skip-AP api */
1413         if ((to > 0) && (to < 100))
1414                 mode = 2;
1415         
1416         to *= direction;
1417         
1418         if (!m_cue)
1419                 return 0;
1420         
1421         m_cue->seekTo(mode, to);
1422         m_dvb_subtitle_pages.clear();
1423         m_subtitle_pages.clear();
1424         return 0;
1425 }
1426
1427 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1428 {
1429         ePtr<iDVBPVRChannel> pvr_channel;
1430         
1431         if (!m_decode_demux)
1432                 return -1;
1433         
1434         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1435                 return -1;
1436         
1437         int r = 0;
1438
1439                 /* if there is a decoder, use audio or video PTS */
1440         if (m_decoder)
1441         {
1442                 r = m_decoder->getPTS(0, pos);
1443                 if (r)
1444                         return r;
1445         }
1446         
1447                 /* fixup */
1448         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1449 }
1450
1451 RESULT eDVBServicePlay::setTrickmode(int trick)
1452 {
1453                 /* currently unimplemented */
1454         return -1;
1455 }
1456
1457 RESULT eDVBServicePlay::isCurrentlySeekable()
1458 {
1459         int ret = 0;
1460         if (m_decoder)
1461         {
1462                 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1463                 if (m_decoder->getVideoProgressive() == -1)
1464                         ret &= ~2;
1465         }
1466         return ret;
1467 }
1468
1469 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1470 {
1471         ptr = this;
1472         return 0;
1473 }
1474
1475 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1476 {
1477         ptr = this;
1478         return 0;
1479 }
1480
1481 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1482 {
1483         ptr = this;
1484         return 0;
1485 }
1486
1487 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1488 {
1489         ptr = this;
1490         return 0;
1491 }
1492
1493 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1494 {
1495         ptr = this;
1496         return 0;
1497 }
1498
1499 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1500 {
1501         ptr = 0;
1502         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1503                 (m_timeshift_enabled || !m_is_pvr))
1504         {
1505                 if (!m_timeshift_enabled)
1506                 {
1507                         /* query config path */
1508                         std::string tspath;
1509                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1510                                 eDebug("could not query ts path from config");
1511                                 return -4;
1512                         }
1513                         tspath.append("/");
1514                         /* we need enough diskspace */
1515                         struct statfs fs;
1516                         if (statfs(tspath.c_str(), &fs) < 0)
1517                         {
1518                                 eDebug("statfs failed!");
1519                                 return -2;
1520                         }
1521                 
1522                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1523                         {
1524                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1525                                 return -3;
1526                         }
1527                 }
1528                 ptr = this;
1529                 return 0;
1530         }
1531         return -1;
1532 }
1533
1534 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1535 {
1536         if (m_is_pvr)
1537         {
1538                 ptr = this;
1539                 return 0;
1540         }
1541         ptr = 0;
1542         return -1;
1543 }
1544
1545 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1546 {
1547         ptr = this;
1548         return 0;
1549 }
1550
1551 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1552 {
1553         ptr = this;
1554         return 0;
1555 }
1556
1557 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1558 {
1559         ptr = this;
1560         return 0;
1561 }
1562
1563 RESULT eDVBServicePlay::getName(std::string &name)
1564 {
1565         if (m_is_pvr)
1566         {
1567                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1568                 return i->getName(m_reference, name);
1569         }
1570         else if (m_dvb_service)
1571         {
1572                 m_dvb_service->getName(m_reference, name);
1573                 if (name.empty())
1574                         name = "(...)";
1575         }
1576         else if (!m_reference.name.empty())
1577                 eStaticServiceDVBInformation().getName(m_reference, name);
1578         else
1579                 name = "DVB service";
1580         return 0;
1581 }
1582
1583 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1584 {
1585         return m_event_handler.getEvent(evt, nownext);
1586 }
1587
1588 int eDVBServicePlay::getInfo(int w)
1589 {
1590         eDVBServicePMTHandler::program program;
1591
1592         if (w == sCAIDs)
1593                 return resIsPyObject;
1594
1595         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1596
1597         int no_program_info = 0;
1598
1599         if (h.getProgramInfo(program))
1600                 no_program_info = 1;
1601
1602         switch (w)
1603         {
1604         case sVideoHeight:
1605                 if (m_decoder)
1606                         return m_decoder->getVideoHeight();
1607                 break;
1608         case sVideoWidth:
1609                 if (m_decoder)
1610                         return m_decoder->getVideoWidth();
1611                 break;
1612         case sFrameRate:
1613                 if (m_decoder)
1614                         return m_decoder->getVideoFrameRate();
1615                 break;
1616         case sProgressive:
1617                 if (m_decoder)
1618                         return m_decoder->getVideoProgressive();
1619                 break;
1620         case sAspect:
1621         {
1622                 int aspect = -1;
1623                 if (m_decoder)
1624                         aspect = m_decoder->getVideoAspect();
1625                 if (aspect == -1 && no_program_info)
1626                         break;
1627                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1628                 {
1629                         ePtr<eServiceEvent> evt;
1630                         if (!m_event_handler.getEvent(evt, 0))
1631                         {
1632                                 ePtr<eComponentData> data;
1633                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1634                                 {
1635                                         if ( data->getStreamContent() == 1 )
1636                                         {
1637                                                 switch(data->getComponentType())
1638                                                 {
1639                                                         // SD
1640                                                         case 1: // 4:3 SD PAL
1641                                                         case 2:
1642                                                         case 3: // 16:9 SD PAL
1643                                                         case 4: // > 16:9 PAL
1644                                                         case 5: // 4:3 SD NTSC
1645                                                         case 6: 
1646                                                         case 7: // 16:9 SD NTSC
1647                                                         case 8: // > 16:9 NTSC
1648
1649                                                         // HD
1650                                                         case 9: // 4:3 HD PAL
1651                                                         case 0xA:
1652                                                         case 0xB: // 16:9 HD PAL
1653                                                         case 0xC: // > 16:9 HD PAL
1654                                                         case 0xD: // 4:3 HD NTSC
1655                                                         case 0xE:
1656                                                         case 0xF: // 16:9 HD NTSC
1657                                                         case 0x10: // > 16:9 HD PAL
1658                                                                 return data->getComponentType();
1659                                                 }
1660                                         }
1661                                 }
1662                         }
1663                 }
1664                 else
1665                         return aspect;
1666                 break;
1667         }
1668         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1669         case sVideoPID:
1670                 if (m_dvb_service)
1671                 {
1672                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1673                         if (vpid != -1)
1674                                 return vpid;
1675                 }
1676                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1677         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1678         case sAudioPID:
1679                 if (m_dvb_service)
1680                 {
1681                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1682                         if (apid != -1)
1683                                 return apid;
1684                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1685                         if (apid != -1)
1686                                 return apid;
1687                 }
1688                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1689         case sPCRPID:
1690                 if (m_dvb_service)
1691                 {
1692                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1693                         if (pcrpid != -1)
1694                                 return pcrpid;
1695                 }
1696                 if (no_program_info) return -1; return program.pcrPid;
1697         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1698         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1699         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1700         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1701         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1702         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1703         case sProvider: if (!m_dvb_service) return -1; return -2;
1704         case sServiceref: return resIsString;
1705         case sDVBState: return m_tune_state;
1706         default:
1707                 break;
1708         }
1709         return -1;
1710 }
1711
1712 std::string eDVBServicePlay::getInfoString(int w)
1713 {
1714         switch (w)
1715         {
1716         case sProvider:
1717                 if (!m_dvb_service) return "";
1718                 return m_dvb_service->m_provider_name;
1719         case sServiceref:
1720                 return m_reference.toString();
1721         default:
1722                 break;
1723         }
1724         return iServiceInformation::getInfoString(w);
1725 }
1726
1727 PyObject *eDVBServicePlay::getInfoObject(int w)
1728 {
1729         switch (w)
1730         {
1731         case sCAIDs:
1732                 return m_service_handler.getCaIds();
1733         case sTransponderData:
1734                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1735         default:
1736                 break;
1737         }
1738         return iServiceInformation::getInfoObject(w);
1739 }
1740
1741 int eDVBServicePlay::getNumberOfTracks()
1742 {
1743         eDVBServicePMTHandler::program program;
1744         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1745         if (h.getProgramInfo(program))
1746                 return 0;
1747         return program.audioStreams.size();
1748 }
1749
1750 int eDVBServicePlay::getCurrentTrack()
1751 {
1752         eDVBServicePMTHandler::program program;
1753         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1754         if (h.getProgramInfo(program))
1755                 return 0;
1756
1757         int max = program.audioStreams.size();
1758         int i;
1759
1760         for (i = 0; i < max; ++i)
1761                 if (program.audioStreams[i].pid == m_current_audio_pid)
1762                         return i;
1763
1764         return 0;
1765 }
1766
1767 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1768 {
1769         int ret = selectAudioStream(i);
1770
1771         if (m_decoder->set())
1772                 return -5;
1773
1774         return ret;
1775 }
1776
1777 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1778 {
1779         eDVBServicePMTHandler::program program;
1780         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1781
1782         if (h.getProgramInfo(program))
1783                 return -1;
1784         
1785         if (i >= program.audioStreams.size())
1786                 return -2;
1787         
1788         info.m_pid = program.audioStreams[i].pid;
1789
1790         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1791                 info.m_description = "MPEG";
1792         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1793                 info.m_description = "AC3";
1794         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1795                 info.m_description = "AAC";
1796         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1797                 info.m_description = "AAC-HE";
1798         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1799                 info.m_description = "DTS";
1800         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1801                 info.m_description = "DTS-HD";
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))
3110         {
3111                 uint8_t demux_id;
3112                 if (!demux->getCADemuxID(demux_id))
3113                         PutToDict(r, "demux", demux_id);
3114         }
3115
3116         return r;
3117 }
3118
3119
3120 DEFINE_REF(eDVBServicePlay)
3121
3122 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3123 {
3124         switch (w)
3125         {
3126         case iServiceInformation::sTransponderData:
3127                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3128         default:
3129                 break;
3130         }
3131         return iStaticServiceInformation::getInfoObject(ref, w);
3132 }
3133
3134 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");