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