servicedvb.cpp: compile fix for bug 411
[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                                 int perc = play_position * 100LL / length;
1132                         
1133                                         /* only store last play position when between 1% and 99% */
1134                                 if ((1 < perc) && (perc < 99))
1135                                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1136                         }
1137                         m_cuesheet_changed = 1;
1138                 }
1139         }
1140
1141         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1142
1143         m_service_handler_timeshift.free();
1144         m_service_handler.free();
1145         
1146         if (m_is_pvr && m_cuesheet_changed)
1147         {
1148                 struct stat s;
1149                                 /* save cuesheet only when main file is accessible. */
1150                 if (!::stat(m_reference.path.c_str(), &s))
1151                         saveCuesheet();
1152         }
1153         m_event((iPlayableService*)this, evStopped);
1154         return 0;
1155 }
1156
1157 RESULT eDVBServicePlay::setTarget(int target)
1158 {
1159         m_is_primary = !target;
1160         return 0;
1161 }
1162
1163 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1164 {
1165         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1166         return 0;
1167 }
1168
1169 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1170 {
1171                 /* note: we check for timeshift to be enabled,
1172                    not neccessary active. if you pause when timeshift
1173                    is not active, you should activate it when unpausing */
1174         if ((!m_is_pvr) && (!m_timeshift_enabled))
1175         {
1176                 ptr = 0;
1177                 return -1;
1178         }
1179
1180         ptr = this;
1181         return 0;
1182 }
1183
1184 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1185 {
1186         ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1187         eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1188         setFastForward_internal(0);
1189         if (m_decoder)
1190         {
1191                 m_slowmotion = ratio;
1192                 return m_decoder->setSlowMotion(ratio);
1193         }
1194         else
1195                 return -1;
1196 }
1197
1198 RESULT eDVBServicePlay::setFastForward(int ratio)
1199 {
1200         eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1201         ASSERT(ratio);
1202         return setFastForward_internal(ratio);
1203 }
1204
1205 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1206 {
1207         int skipmode, ffratio, ret = 0;
1208         pts_t pos=0;
1209
1210         if (ratio > 8)
1211         {
1212                 skipmode = ratio;
1213                 ffratio = 1;
1214         } else if (ratio > 0)
1215         {
1216                 skipmode = 0;
1217                 ffratio = ratio;
1218         } else if (!ratio)
1219         {
1220                 skipmode = 0;
1221                 ffratio = 0;
1222         } else // if (ratio < 0)
1223         {
1224                 skipmode = ratio;
1225                 ffratio = 1;
1226         }
1227
1228         if (m_skipmode != skipmode)
1229         {
1230                 eDebug("setting cue skipmode to %d", skipmode);
1231                 if (m_cue)
1232                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1233         }
1234
1235         m_skipmode = skipmode;
1236
1237         if (final_seek)
1238                 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1239
1240         m_fastforward = ffratio;
1241
1242         if (!m_decoder)
1243                 return -1;
1244
1245         if (ffratio == 0)
1246                 ; /* return m_decoder->play(); is done in caller*/
1247         else if (ffratio != 1)
1248                 ret = m_decoder->setFastForward(ffratio);
1249         else
1250                 ret = m_decoder->setTrickmode();
1251
1252         if (pos)
1253                 eDebug("final seek after trickplay ret %d", seekTo(pos));
1254
1255         return ret;
1256 }
1257
1258 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1259 {
1260         if (m_is_pvr || m_timeshift_enabled)
1261         {
1262                 ptr = this;
1263                 return 0;
1264         }
1265         
1266         ptr = 0;
1267         return -1;
1268 }
1269
1270         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1271 RESULT eDVBServicePlay::getLength(pts_t &len)
1272 {
1273         ePtr<iDVBPVRChannel> pvr_channel;
1274         
1275         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1276                 return -1;
1277         
1278         return pvr_channel->getLength(len);
1279 }
1280
1281 RESULT eDVBServicePlay::pause()
1282 {
1283         eDebug("eDVBServicePlay::pause");
1284         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1285         if (m_decoder)
1286         {
1287                 m_slowmotion = 0;
1288                 m_is_paused = 1;
1289                 return m_decoder->pause();
1290         } else
1291                 return -1;
1292 }
1293
1294 RESULT eDVBServicePlay::unpause()
1295 {
1296         eDebug("eDVBServicePlay::unpause");
1297         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1298         if (m_decoder)
1299         {
1300                 m_slowmotion = 0;
1301                 m_is_paused = 0;
1302                 return m_decoder->play();
1303         } else
1304                 return -1;
1305 }
1306
1307 RESULT eDVBServicePlay::seekTo(pts_t to)
1308 {
1309         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1310         
1311         if (!m_decode_demux)
1312                 return -1;
1313
1314         ePtr<iDVBPVRChannel> pvr_channel;
1315         
1316         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1317                 return -1;
1318         
1319         if (!m_cue)
1320                 return -1;
1321         
1322         m_cue->seekTo(0, to);
1323         m_dvb_subtitle_pages.clear();
1324         m_subtitle_pages.clear();
1325
1326         return 0;
1327 }
1328
1329 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1330 {
1331         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1332         
1333         if (!m_decode_demux)
1334                 return -1;
1335
1336         ePtr<iDVBPVRChannel> pvr_channel;
1337         
1338         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1339                 return -1;
1340         
1341         int mode = 1;
1342         
1343                         /* HACK until we have skip-AP api */
1344         if ((to > 0) && (to < 100))
1345                 mode = 2;
1346         
1347         to *= direction;
1348         
1349         if (!m_cue)
1350                 return 0;
1351         
1352         m_cue->seekTo(mode, to);
1353         m_dvb_subtitle_pages.clear();
1354         m_subtitle_pages.clear();
1355         return 0;
1356 }
1357
1358 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1359 {
1360         ePtr<iDVBPVRChannel> pvr_channel;
1361         
1362         if (!m_decode_demux)
1363                 return -1;
1364         
1365         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1366                 return -1;
1367         
1368         int r = 0;
1369
1370                 /* if there is a decoder, use audio or video PTS */
1371         if (m_decoder)
1372         {
1373                 r = m_decoder->getPTS(0, pos);
1374                 if (r)
1375                         return r;
1376         }
1377         
1378                 /* fixup */
1379         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1380 }
1381
1382 RESULT eDVBServicePlay::setTrickmode(int trick)
1383 {
1384                 /* currently unimplemented */
1385         return -1;
1386 }
1387
1388 RESULT eDVBServicePlay::isCurrentlySeekable()
1389 {
1390         int ret = 0;
1391         if (m_decoder)
1392         {
1393                 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1394                 if (m_decoder->getVideoProgressive() == -1)
1395                         ret &= ~2;
1396         }
1397         return ret;
1398 }
1399
1400 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1401 {
1402         ptr = this;
1403         return 0;
1404 }
1405
1406 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1407 {
1408         ptr = this;
1409         return 0;
1410 }
1411
1412 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1413 {
1414         ptr = this;
1415         return 0;
1416 }
1417
1418 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1419 {
1420         ptr = this;
1421         return 0;
1422 }
1423
1424 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1425 {
1426         ptr = this;
1427         return 0;
1428 }
1429
1430 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1431 {
1432         ptr = 0;
1433         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1434                 (m_timeshift_enabled || !m_is_pvr))
1435         {
1436                 if (!m_timeshift_enabled)
1437                 {
1438                         /* query config path */
1439                         std::string tspath;
1440                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1441                                 eDebug("could not query ts path from config");
1442                                 return -4;
1443                         }
1444                         tspath.append("/");
1445                         /* we need enough diskspace */
1446                         struct statfs fs;
1447                         if (statfs(tspath.c_str(), &fs) < 0)
1448                         {
1449                                 eDebug("statfs failed!");
1450                                 return -2;
1451                         }
1452                 
1453                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1454                         {
1455                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1456                                 return -3;
1457                         }
1458                 }
1459                 ptr = this;
1460                 return 0;
1461         }
1462         return -1;
1463 }
1464
1465 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1466 {
1467         if (m_is_pvr)
1468         {
1469                 ptr = this;
1470                 return 0;
1471         }
1472         ptr = 0;
1473         return -1;
1474 }
1475
1476 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1477 {
1478         ptr = this;
1479         return 0;
1480 }
1481
1482 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1483 {
1484         ptr = this;
1485         return 0;
1486 }
1487
1488 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1489 {
1490         ptr = this;
1491         return 0;
1492 }
1493
1494 RESULT eDVBServicePlay::getName(std::string &name)
1495 {
1496         if (m_is_pvr)
1497         {
1498                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1499                 return i->getName(m_reference, name);
1500         }
1501         else if (m_dvb_service)
1502         {
1503                 m_dvb_service->getName(m_reference, name);
1504                 if (name.empty())
1505                         name = "(...)";
1506         }
1507         else if (!m_reference.name.empty())
1508                 eStaticServiceDVBInformation().getName(m_reference, name);
1509         else
1510                 name = "DVB service";
1511         return 0;
1512 }
1513
1514 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1515 {
1516         return m_event_handler.getEvent(evt, nownext);
1517 }
1518
1519 int eDVBServicePlay::getInfo(int w)
1520 {
1521         eDVBServicePMTHandler::program program;
1522
1523         if (w == sCAIDs)
1524                 return resIsPyObject;
1525
1526         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1527
1528         int no_program_info = 0;
1529
1530         if (h.getProgramInfo(program))
1531                 no_program_info = 1;
1532
1533         switch (w)
1534         {
1535         case sVideoHeight:
1536                 if (m_decoder)
1537                         return m_decoder->getVideoHeight();
1538                 break;
1539         case sVideoWidth:
1540                 if (m_decoder)
1541                         return m_decoder->getVideoWidth();
1542                 break;
1543         case sFrameRate:
1544                 if (m_decoder)
1545                         return m_decoder->getVideoFrameRate();
1546                 break;
1547         case sProgressive:
1548                 if (m_decoder)
1549                         return m_decoder->getVideoProgressive();
1550                 break;
1551         case sAspect:
1552         {
1553                 int aspect = -1;
1554                 if (m_decoder)
1555                         aspect = m_decoder->getVideoAspect();
1556                 if (aspect == -1 && no_program_info)
1557                         break;
1558                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1559                 {
1560                         ePtr<eServiceEvent> evt;
1561                         if (!m_event_handler.getEvent(evt, 0))
1562                         {
1563                                 ePtr<eComponentData> data;
1564                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1565                                 {
1566                                         if ( data->getStreamContent() == 1 )
1567                                         {
1568                                                 switch(data->getComponentType())
1569                                                 {
1570                                                         // SD
1571                                                         case 1: // 4:3 SD PAL
1572                                                         case 2:
1573                                                         case 3: // 16:9 SD PAL
1574                                                         case 4: // > 16:9 PAL
1575                                                         case 5: // 4:3 SD NTSC
1576                                                         case 6: 
1577                                                         case 7: // 16:9 SD NTSC
1578                                                         case 8: // > 16:9 NTSC
1579
1580                                                         // HD
1581                                                         case 9: // 4:3 HD PAL
1582                                                         case 0xA:
1583                                                         case 0xB: // 16:9 HD PAL
1584                                                         case 0xC: // > 16:9 HD PAL
1585                                                         case 0xD: // 4:3 HD NTSC
1586                                                         case 0xE:
1587                                                         case 0xF: // 16:9 HD NTSC
1588                                                         case 0x10: // > 16:9 HD PAL
1589                                                                 return data->getComponentType();
1590                                                 }
1591                                         }
1592                                 }
1593                         }
1594                 }
1595                 else
1596                         return aspect;
1597                 break;
1598         }
1599         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1600         case sVideoPID:
1601                 if (m_dvb_service)
1602                 {
1603                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1604                         if (vpid != -1)
1605                                 return vpid;
1606                 }
1607                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1608         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1609         case sAudioPID:
1610                 if (m_dvb_service)
1611                 {
1612                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1613                         if (apid != -1)
1614                                 return apid;
1615                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1616                         if (apid != -1)
1617                                 return apid;
1618                 }
1619                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1620         case sPCRPID:
1621                 if (m_dvb_service)
1622                 {
1623                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1624                         if (pcrpid != -1)
1625                                 return pcrpid;
1626                 }
1627                 if (no_program_info) return -1; return program.pcrPid;
1628         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1629         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1630         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1631         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1632         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1633         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1634         case sProvider: if (!m_dvb_service) return -1; return -2;
1635         case sServiceref: return resIsString;
1636         case sDVBState: return m_tune_state;
1637         default:
1638                 break;
1639         }
1640         return -1;
1641 }
1642
1643 std::string eDVBServicePlay::getInfoString(int w)
1644 {
1645         switch (w)
1646         {
1647         case sProvider:
1648                 if (!m_dvb_service) return "";
1649                 return m_dvb_service->m_provider_name;
1650         case sServiceref:
1651                 return m_reference.toString();
1652         default:
1653                 break;
1654         }
1655         return iServiceInformation::getInfoString(w);
1656 }
1657
1658 PyObject *eDVBServicePlay::getInfoObject(int w)
1659 {
1660         switch (w)
1661         {
1662         case sCAIDs:
1663                 return m_service_handler.getCaIds();
1664         case sTransponderData:
1665                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1666         default:
1667                 break;
1668         }
1669         return iServiceInformation::getInfoObject(w);
1670 }
1671
1672 int eDVBServicePlay::getNumberOfTracks()
1673 {
1674         eDVBServicePMTHandler::program program;
1675         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1676         if (h.getProgramInfo(program))
1677                 return 0;
1678         return program.audioStreams.size();
1679 }
1680
1681 int eDVBServicePlay::getCurrentTrack()
1682 {
1683         eDVBServicePMTHandler::program program;
1684         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1685         if (h.getProgramInfo(program))
1686                 return 0;
1687
1688         int max = program.audioStreams.size();
1689         int i;
1690
1691         for (i = 0; i < max; ++i)
1692                 if (program.audioStreams[i].pid == m_current_audio_pid)
1693                         return i;
1694
1695         return 0;
1696 }
1697
1698 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1699 {
1700         int ret = selectAudioStream(i);
1701
1702         if (m_decoder->set())
1703                 return -5;
1704
1705         return ret;
1706 }
1707
1708 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1709 {
1710         eDVBServicePMTHandler::program program;
1711         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1712
1713         if (h.getProgramInfo(program))
1714                 return -1;
1715         
1716         if (i >= program.audioStreams.size())
1717                 return -2;
1718         
1719         info.m_pid = program.audioStreams[i].pid;
1720
1721         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1722                 info.m_description = "MPEG";
1723         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1724                 info.m_description = "AC3";
1725         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1726                 info.m_description = "AAC";
1727         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1728                 info.m_description = "AAC-HE";
1729         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1730                 info.m_description = "DTS";
1731         else
1732                 info.m_description = "???";
1733
1734         if (program.audioStreams[i].component_tag != -1)
1735         {
1736                 ePtr<eServiceEvent> evt;
1737                 if (!m_event_handler.getEvent(evt, 0))
1738                 {
1739                         ePtr<eComponentData> data;
1740                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1741                                 info.m_language = data->getText();
1742                 }
1743         }
1744
1745         if (info.m_language.empty())
1746                 info.m_language = program.audioStreams[i].language_code;
1747         
1748         return 0;
1749 }
1750
1751 int eDVBServicePlay::selectAudioStream(int i)
1752 {
1753         eDVBServicePMTHandler::program program;
1754         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1755         pts_t position = -1;
1756
1757         if (h.getProgramInfo(program))
1758                 return -1;
1759
1760         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1761                 return -2;
1762
1763         if (!m_decoder)
1764                 return -3;
1765
1766         int stream = i;
1767         if (stream == -1)
1768                 stream = program.defaultAudioStream;
1769
1770         int apid = -1, apidtype = -1;
1771
1772         if (((unsigned int)stream) < program.audioStreams.size())
1773         {
1774                 apid = program.audioStreams[stream].pid;
1775                 apidtype = program.audioStreams[stream].type;
1776         }
1777
1778         if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1779                 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1780
1781         m_current_audio_pid = apid;
1782
1783         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1784         {
1785                 eDebug("set audio pid failed");
1786                 return -4;
1787         }
1788
1789         if (position != -1)
1790                 eDebug("seekTo ret %d", seekTo(position));
1791
1792         int rdsPid = apid;
1793
1794                 /* 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 */
1795         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1796         {
1797                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1798                 if (different_pid)
1799                         rdsPid = program.audioStreams[stream].rdsPid;
1800                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1801                 {
1802                         m_rds_decoder = 0;
1803                         ePtr<iDVBDemux> data_demux;
1804                         if (!h.getDataDemux(data_demux))
1805                         {
1806                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1807                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1808                                 m_rds_decoder->start(rdsPid);
1809                         }
1810                 }
1811         }
1812
1813                         /* store new pid as default only when:
1814                                 a.) we have an entry in the service db for the current service,
1815                                 b.) we are not playing back something,
1816                                 c.) we are not selecting the default entry. (we wouldn't change 
1817                                     anything in the best case, or destroy the default setting in
1818                                     case the real default is not yet available.)
1819                         */
1820         if (m_dvb_service && ((i != -1)
1821                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1822         {
1823                 if (apidtype == eDVBAudio::aMPEG)
1824                 {
1825                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1826                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1827                 }
1828                 else if (apidtype == eDVBAudio::aAC3)
1829                 {
1830                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1831                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1832                 }
1833                 else
1834                 {
1835                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1836                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1837                 }
1838         }
1839
1840         h.resetCachedProgram();
1841
1842         return 0;
1843 }
1844
1845 int eDVBServicePlay::getCurrentChannel()
1846 {
1847         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1848 }
1849
1850 RESULT eDVBServicePlay::selectChannel(int i)
1851 {
1852         if (i < LEFT || i > RIGHT || i == STEREO)
1853                 i = -1;  // Stereo
1854         if (m_dvb_service)
1855                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1856         if (m_decoder)
1857                 m_decoder->setAudioChannel(i);
1858         return 0;
1859 }
1860
1861 std::string eDVBServicePlay::getText(int x)
1862 {
1863         if (m_rds_decoder)
1864                 switch(x)
1865                 {
1866                         case RadioText:
1867                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1868                         case RtpText:
1869                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1870                 }
1871         return "";
1872 }
1873
1874 void eDVBServicePlay::rdsDecoderEvent(int what)
1875 {
1876         switch(what)
1877         {
1878                 case eDVBRdsDecoder::RadioTextChanged:
1879                         m_event((iPlayableService*)this, evUpdatedRadioText);
1880                         break;
1881                 case eDVBRdsDecoder::RtpTextChanged:
1882                         m_event((iPlayableService*)this, evUpdatedRtpText);
1883                         break;
1884                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1885                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1886                         break;
1887                 case eDVBRdsDecoder::RecvRassSlidePic:
1888                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1889                         break;
1890         }
1891 }
1892
1893 void eDVBServicePlay::showRassSlidePicture()
1894 {
1895         if (m_rds_decoder)
1896         {
1897                 if (m_decoder)
1898                 {
1899                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1900                         if (rass_slide_pic.length())
1901                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1902                         else
1903                                 eDebug("empty filename for rass slide picture received!!");
1904                 }
1905                 else
1906                         eDebug("no MPEG Decoder to show iframes avail");
1907         }
1908         else
1909                 eDebug("showRassSlidePicture called.. but not decoder");
1910 }
1911
1912 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1913 {
1914         if (m_rds_decoder)
1915         {
1916                 if (m_decoder)
1917                 {
1918                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1919                         if (rass_interactive_pic.length())
1920                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1921                         else
1922                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1923                 }
1924                 else
1925                         eDebug("no MPEG Decoder to show iframes avail");
1926         }
1927         else
1928                 eDebug("showRassInteractivePic called.. but not decoder");
1929 }
1930
1931 ePyObject eDVBServicePlay::getRassInteractiveMask()
1932 {
1933         if (m_rds_decoder)
1934                 return m_rds_decoder->getRassPictureMask();
1935         Py_RETURN_NONE;
1936 }
1937
1938 int eDVBServiceBase::getFrontendInfo(int w)
1939 {
1940         eUsePtr<iDVBChannel> channel;
1941         if(m_service_handler.getChannel(channel))
1942                 return 0;
1943         ePtr<iDVBFrontend> fe;
1944         if(channel->getFrontend(fe))
1945                 return 0;
1946         return fe->readFrontendData(w);
1947 }
1948
1949 PyObject *eDVBServiceBase::getFrontendData()
1950 {
1951         ePyObject ret = PyDict_New();
1952         if (ret)
1953         {
1954                 eUsePtr<iDVBChannel> channel;
1955                 if(!m_service_handler.getChannel(channel))
1956                 {
1957                         ePtr<iDVBFrontend> fe;
1958                         if(!channel->getFrontend(fe))
1959                                 fe->getFrontendData(ret);
1960                 }
1961         }
1962         else
1963                 Py_RETURN_NONE;
1964         return ret;
1965 }
1966
1967 PyObject *eDVBServiceBase::getFrontendStatus()
1968 {
1969         ePyObject ret = PyDict_New();
1970         if (ret)
1971         {
1972                 eUsePtr<iDVBChannel> channel;
1973                 if(!m_service_handler.getChannel(channel))
1974                 {
1975                         ePtr<iDVBFrontend> fe;
1976                         if(!channel->getFrontend(fe))
1977                                 fe->getFrontendStatus(ret);
1978                 }
1979         }
1980         else
1981                 Py_RETURN_NONE;
1982         return ret;
1983 }
1984
1985 PyObject *eDVBServiceBase::getTransponderData(bool original)
1986 {
1987         ePyObject ret = PyDict_New();
1988         if (ret)
1989         {
1990                 eUsePtr<iDVBChannel> channel;
1991                 if(!m_service_handler.getChannel(channel))
1992                 {
1993                         ePtr<iDVBFrontend> fe;
1994                         if(!channel->getFrontend(fe))
1995                                 fe->getTransponderData(ret, original);
1996                 }
1997         }
1998         else
1999                 Py_RETURN_NONE;
2000         return ret;
2001 }
2002
2003 PyObject *eDVBServiceBase::getAll(bool original)
2004 {
2005         ePyObject ret = getTransponderData(original);
2006         if (ret != Py_None)
2007         {
2008                 eUsePtr<iDVBChannel> channel;
2009                 if(!m_service_handler.getChannel(channel))
2010                 {
2011                         ePtr<iDVBFrontend> fe;
2012                         if(!channel->getFrontend(fe))
2013                         {
2014                                 fe->getFrontendData(ret);
2015                                 fe->getFrontendStatus(ret);
2016                         }
2017                 }
2018         }
2019         return ret;
2020 }
2021
2022 int eDVBServicePlay::getNumberOfSubservices()
2023 {
2024         ePtr<eServiceEvent> evt;
2025         if (!m_event_handler.getEvent(evt, 0))
2026                 return evt->getNumOfLinkageServices();
2027         return 0;
2028 }
2029
2030 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2031 {
2032         ePtr<eServiceEvent> evt;
2033         if (!m_event_handler.getEvent(evt, 0))
2034         {
2035                 if (!evt->getLinkageService(sub, m_reference, n))
2036                         return 0;
2037         }
2038         sub.type=eServiceReference::idInvalid;
2039         return -1;
2040 }
2041
2042 RESULT eDVBServicePlay::startTimeshift()
2043 {
2044         ePtr<iDVBDemux> demux;
2045         
2046         eDebug("Start timeshift!");
2047         
2048         if (m_timeshift_enabled)
2049                 return -1;
2050         
2051                 /* start recording with the data demux. */
2052         if (m_service_handler.getDataDemux(demux))
2053                 return -2;
2054
2055         demux->createTSRecorder(m_record);
2056         if (!m_record)
2057                 return -3;
2058
2059         std::string tspath;
2060         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2061                 eDebug("could not query ts path");
2062                 return -5;
2063         }
2064         tspath.append("/timeshift.XXXXXX");
2065         char* templ;
2066         templ = new char[tspath.length() + 1];
2067         strcpy(templ, tspath.c_str());
2068
2069         m_timeshift_fd = mkstemp(templ);
2070         m_timeshift_file = std::string(templ);
2071
2072         eDebug("recording to %s", templ);
2073
2074         delete [] templ;
2075
2076         if (m_timeshift_fd < 0)
2077         {
2078                 m_record = 0;
2079                 return -4;
2080         }
2081                 
2082         m_record->setTargetFD(m_timeshift_fd);
2083
2084         m_timeshift_enabled = 1;
2085         
2086         updateTimeshiftPids();
2087         m_record->start();
2088
2089         return 0;
2090 }
2091
2092 RESULT eDVBServicePlay::stopTimeshift(bool switchToLive)
2093 {
2094         if (!m_timeshift_enabled)
2095                 return -1;
2096         
2097         if (switchToLive)
2098                 switchToLive();
2099         
2100         m_timeshift_enabled = 0;
2101         
2102         m_record->stop();
2103         m_record = 0;
2104         
2105         close(m_timeshift_fd);
2106         eDebug("remove timeshift file");
2107         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2108         
2109         return 0;
2110 }
2111
2112 int eDVBServicePlay::isTimeshiftActive()
2113 {
2114         return m_timeshift_enabled && m_timeshift_active;
2115 }
2116
2117 RESULT eDVBServicePlay::activateTimeshift()
2118 {
2119         if (!m_timeshift_enabled)
2120                 return -1;
2121         
2122         if (!m_timeshift_active)
2123         {
2124                 switchToTimeshift();
2125                 return 0;
2126         }
2127         
2128         return -2;
2129 }
2130
2131 PyObject *eDVBServicePlay::getCutList()
2132 {
2133         ePyObject list = PyList_New(0);
2134         
2135         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2136         {
2137                 ePyObject tuple = PyTuple_New(2);
2138                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2139                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2140                 PyList_Append(list, tuple);
2141                 Py_DECREF(tuple);
2142         }
2143         
2144         return list;
2145 }
2146
2147 void eDVBServicePlay::setCutList(ePyObject list)
2148 {
2149         if (!PyList_Check(list))
2150                 return;
2151         int size = PyList_Size(list);
2152         int i;
2153         
2154         m_cue_entries.clear();
2155         
2156         for (i=0; i<size; ++i)
2157         {
2158                 ePyObject tuple = PyList_GET_ITEM(list, i);
2159                 if (!PyTuple_Check(tuple))
2160                 {
2161                         eDebug("non-tuple in cutlist");
2162                         continue;
2163                 }
2164                 if (PyTuple_Size(tuple) != 2)
2165                 {
2166                         eDebug("cutlist entries need to be a 2-tuple");
2167                         continue;
2168                 }
2169                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2170                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2171                 {
2172                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2173                         continue;
2174                 }
2175                 pts_t pts = PyLong_AsLongLong(ppts);
2176                 int type = PyInt_AsLong(ptype);
2177                 m_cue_entries.insert(cueEntry(pts, type));
2178                 eDebug("adding %08llx, %d", pts, type);
2179         }
2180         m_cuesheet_changed = 1;
2181         
2182         cutlistToCuesheet();
2183         m_event((iPlayableService*)this, evCuesheetChanged);
2184 }
2185
2186 void eDVBServicePlay::setCutListEnable(int enable)
2187 {
2188         m_cutlist_enabled = enable;
2189         cutlistToCuesheet();
2190 }
2191
2192 void eDVBServicePlay::updateTimeshiftPids()
2193 {
2194         if (!m_record)
2195                 return;
2196         
2197         eDVBServicePMTHandler::program program;
2198         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2199
2200         if (h.getProgramInfo(program))
2201                 return;
2202         else
2203         {
2204                 std::set<int> pids_to_record;
2205                 pids_to_record.insert(0); // PAT
2206                 if (program.pmtPid != -1)
2207                         pids_to_record.insert(program.pmtPid); // PMT
2208
2209                 if (program.textPid != -1)
2210                         pids_to_record.insert(program.textPid); // Videotext
2211
2212                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2213                         i(program.videoStreams.begin()); 
2214                         i != program.videoStreams.end(); ++i)
2215                         pids_to_record.insert(i->pid);
2216
2217                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2218                         i(program.audioStreams.begin()); 
2219                         i != program.audioStreams.end(); ++i)
2220                                 pids_to_record.insert(i->pid);
2221
2222                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2223                         i(program.subtitleStreams.begin());
2224                         i != program.subtitleStreams.end(); ++i)
2225                                 pids_to_record.insert(i->pid);
2226
2227                 std::set<int> new_pids, obsolete_pids;
2228                 
2229                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2230                                 m_pids_active.begin(), m_pids_active.end(),
2231                                 std::inserter(new_pids, new_pids.begin()));
2232                 
2233                 std::set_difference(
2234                                 m_pids_active.begin(), m_pids_active.end(),
2235                                 pids_to_record.begin(), pids_to_record.end(), 
2236                                 std::inserter(new_pids, new_pids.begin())
2237                                 );
2238
2239                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2240                         m_record->addPID(*i);
2241
2242                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2243                         m_record->removePID(*i);
2244         }
2245 }
2246
2247 void eDVBServicePlay::switchToLive()
2248 {
2249         if (!m_timeshift_active)
2250                 return;
2251         
2252         eDebug("SwitchToLive");
2253         
2254         m_cue = 0;
2255         m_decoder = 0;
2256         m_decode_demux = 0;
2257         m_teletext_parser = 0;
2258         m_rds_decoder = 0;
2259         m_subtitle_parser = 0;
2260         m_new_dvb_subtitle_page_connection = 0;
2261         m_new_subtitle_page_connection = 0;
2262         m_rds_decoder_event_connection = 0;
2263         m_video_event_connection = 0;
2264         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2265
2266                 /* free the timeshift service handler, we need the resources */
2267         m_service_handler_timeshift.free();
2268         m_timeshift_active = 0;
2269         m_timeshift_changed = 1;
2270
2271         updateDecoder(true);
2272 }
2273
2274 void eDVBServicePlay::switchToTimeshift()
2275 {
2276         if (m_timeshift_active)
2277                 return;
2278
2279         m_decode_demux = 0;
2280         m_decoder = 0;
2281         m_teletext_parser = 0;
2282         m_rds_decoder = 0;
2283         m_subtitle_parser = 0;
2284         m_new_subtitle_page_connection = 0;
2285         m_new_dvb_subtitle_page_connection = 0;
2286         m_rds_decoder_event_connection = 0;
2287         m_video_event_connection = 0;
2288
2289         m_timeshift_active = 1;
2290         m_timeshift_changed = 1;
2291
2292         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2293         r.path = m_timeshift_file;
2294
2295         m_cue = new eCueSheet();
2296         m_cue->seekTo(0, -1000);
2297         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2298
2299         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2300         pause();
2301         updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2302 }
2303
2304 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2305 {
2306         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2307         bool mustPlay = false;
2308
2309         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2310
2311         eDVBServicePMTHandler::program program;
2312         if (h.getProgramInfo(program))
2313                 eDebug("getting program info failed.");
2314         else
2315         {
2316                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2317                 if (!program.videoStreams.empty())
2318                 {
2319                         eDebugNoNewLine(" (");
2320                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2321                                 i(program.videoStreams.begin());
2322                                 i != program.videoStreams.end(); ++i)
2323                         {
2324                                 if (vpid == -1)
2325                                 {
2326                                         vpid = i->pid;
2327                                         vpidtype = i->type;
2328                                 }
2329                                 if (i != program.videoStreams.begin())
2330                                         eDebugNoNewLine(", ");
2331                                 eDebugNoNewLine("%04x", i->pid);
2332                         }
2333                         eDebugNoNewLine(")");
2334                 }
2335                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2336                 if (!program.audioStreams.empty())
2337                 {
2338                         eDebugNoNewLine(" (");
2339                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2340                                 i(program.audioStreams.begin());
2341                                 i != program.audioStreams.end(); ++i)
2342                         {
2343                                 if (i != program.audioStreams.begin())
2344                                         eDebugNoNewLine(", ");
2345                                 eDebugNoNewLine("%04x", i->pid);
2346                         }
2347                         eDebugNoNewLine(")");
2348                 }
2349                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2350                 pcrpid = program.pcrPid;
2351                 eDebug(", and the text pid is %04x", program.textPid);
2352                 tpid = program.textPid;
2353         }
2354
2355         if (!m_decoder)
2356         {
2357                 h.getDecodeDemux(m_decode_demux);
2358                 if (m_timeshift_changed)
2359                         m_decoder = 0;
2360                 if (m_decode_demux)
2361                 {
2362                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2363                         if (m_decoder)
2364                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2365                         if (m_is_primary)
2366                         {
2367                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2368                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2369                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2370                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2371                                 if (m_timeshift_changed)
2372                                 {
2373                                         ePyObject subs = getCachedSubtitle();
2374                                         if (subs != Py_None)
2375                                         {
2376                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2377                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2378                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2379                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2380                                                 if (type == 0) // dvb
2381                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2382                                                 else if (type == 1) // ttx
2383                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2384                                         }
2385                                         Py_DECREF(subs);
2386                                 }
2387                         }
2388                 }
2389                 if (m_cue)
2390                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2391                 mustPlay = true;
2392         }
2393
2394         m_timeshift_changed = 0;
2395
2396         if (m_decoder)
2397         {
2398                 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2399                 if (m_dvb_service)
2400                 {
2401                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2402                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2403                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2404                 }
2405                 else // subservice
2406                 {
2407                         eServiceReferenceDVB ref;
2408                         m_service_handler.getServiceReference(ref);
2409                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2410                         if (!parent)
2411                                 parent = ref;
2412                         if (parent)
2413                         {
2414                                 ePtr<eDVBResourceManager> res_mgr;
2415                                 if (!eDVBResourceManager::getInstance(res_mgr))
2416                                 {
2417                                         ePtr<iDVBChannelList> db;
2418                                         if (!res_mgr->getChannelList(db))
2419                                         {
2420                                                 ePtr<eDVBService> origService;
2421                                                 if (!db->getService(parent, origService))
2422                                                 {
2423                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2424                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2425                                                 }
2426                                         }
2427                                 }
2428                         }
2429                 }
2430
2431                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2432                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2433
2434                 m_decoder->setVideoPID(vpid, vpidtype);
2435                 selectAudioStream();
2436
2437                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2438                         m_decoder->setSyncPCR(pcrpid);
2439                 else
2440                         m_decoder->setSyncPCR(-1);
2441
2442                 if (m_is_primary)
2443                 {
2444                         m_decoder->setTextPID(tpid);
2445                         m_teletext_parser->start(program.textPid);
2446                 }
2447
2448                 if (vpid > 0 && vpid < 0x2000)
2449                         ;
2450                 else
2451                 {
2452                         std::string radio_pic;
2453                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2454                                 m_decoder->setRadioPic(radio_pic);
2455                 }
2456
2457                 if (mustPlay)
2458                         m_decoder->play();
2459                 else
2460                         m_decoder->set();
2461
2462                 m_decoder->setAudioChannel(achannel);
2463
2464                 /* don't worry about non-existing services, nor pvr services */
2465                 if (m_dvb_service)
2466                 {
2467                                 /* (audio pid will be set in selectAudioTrack */
2468                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2469                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2470                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2471                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2472                 }
2473                 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2474                         sendSeekableStateChanged = true;
2475         }
2476         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2477
2478         if (sendSeekableStateChanged)
2479                 m_event((iPlayableService*)this, evSeekableStatusChanged);
2480 }
2481
2482 void eDVBServicePlay::loadCuesheet()
2483 {
2484         std::string filename = m_reference.path + ".cuts";
2485         
2486         m_cue_entries.clear();
2487
2488         FILE *f = fopen(filename.c_str(), "rb");
2489
2490         if (f)
2491         {
2492                 eDebug("loading cuts..");
2493                 while (1)
2494                 {
2495                         unsigned long long where;
2496                         unsigned int what;
2497                         
2498                         if (!fread(&where, sizeof(where), 1, f))
2499                                 break;
2500                         if (!fread(&what, sizeof(what), 1, f))
2501                                 break;
2502                         
2503 #if BYTE_ORDER == LITTLE_ENDIAN
2504                         where = bswap_64(where);
2505 #endif
2506                         what = ntohl(what);
2507                         
2508                         if (what > 3)
2509                                 break;
2510                         
2511                         m_cue_entries.insert(cueEntry(where, what));
2512                 }
2513                 fclose(f);
2514                 eDebug("%d entries", m_cue_entries.size());
2515         } else
2516                 eDebug("cutfile not found!");
2517         
2518         m_cuesheet_changed = 0;
2519         cutlistToCuesheet();
2520         m_event((iPlayableService*)this, evCuesheetChanged);
2521 }
2522
2523 void eDVBServicePlay::saveCuesheet()
2524 {
2525         std::string filename = m_reference.path + ".cuts";
2526         
2527         FILE *f = fopen(filename.c_str(), "wb");
2528
2529         if (f)
2530         {
2531                 unsigned long long where;
2532                 int what;
2533
2534                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2535                 {
2536 #if BYTE_ORDER == BIG_ENDIAN
2537                         where = i->where;
2538 #else
2539                         where = bswap_64(i->where);
2540 #endif
2541                         what = htonl(i->what);
2542                         fwrite(&where, sizeof(where), 1, f);
2543                         fwrite(&what, sizeof(what), 1, f);
2544                         
2545                 }
2546                 fclose(f);
2547         }
2548         
2549         m_cuesheet_changed = 0;
2550 }
2551
2552 void eDVBServicePlay::cutlistToCuesheet()
2553 {
2554         if (!m_cue)
2555         {
2556                 eDebug("no cue sheet");
2557                 return;
2558         }       
2559         m_cue->clear();
2560         
2561         if (!m_cutlist_enabled)
2562         {
2563                 m_cue->commitSpans();
2564                 eDebug("cutlists were disabled");
2565                 return;
2566         }
2567
2568         pts_t in = 0, out = 0, length = 0;
2569         
2570         getLength(length);
2571                 
2572         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2573         
2574         int have_any_span = 0;
2575         
2576         while (1)
2577         {
2578                 if (i == m_cue_entries.end())
2579                 {
2580                         if (!have_any_span && !in)
2581                                 break;
2582                         out = length;
2583                 } else {
2584                         if (i->what == 0) /* in */
2585                         {
2586                                 in = i++->where;
2587                                 continue;
2588                         } else if (i->what == 1) /* out */
2589                                 out = i++->where;
2590                         else /* mark (2) or last play position (3) */
2591                         {
2592                                 i++;
2593                                 continue;
2594                         }
2595                 }
2596                 
2597                 if (in < 0)
2598                         in = 0;
2599                 if (out < 0)
2600                         out = 0;
2601                 if (in > length)
2602                         in = length;
2603                 if (out > length)
2604                         out = length;
2605                 
2606                 if (in < out)
2607                 {
2608                         have_any_span = 1;
2609                         m_cue->addSourceSpan(in, out);
2610                         in = out = 0;
2611                 }
2612                 
2613                 in = length;
2614                 
2615                 if (i == m_cue_entries.end())
2616                         break;
2617         }
2618         m_cue->commitSpans();
2619 }
2620
2621 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2622 {
2623         if (m_subtitle_widget)
2624                 disableSubtitles(parent);
2625
2626         ePyObject entry;
2627         int tuplesize = PyTuple_Size(tuple);
2628         int type = 0;
2629
2630         if (!PyTuple_Check(tuple))
2631                 goto error_out;
2632
2633         if (tuplesize < 1)
2634                 goto error_out;
2635
2636         entry = PyTuple_GET_ITEM(tuple, 0);
2637
2638         if (!PyInt_Check(entry))
2639                 goto error_out;
2640
2641         type = PyInt_AsLong(entry);
2642
2643         if (type == 1)  // teletext subtitles
2644         {
2645                 int page, magazine, pid;
2646                 if (tuplesize < 4)
2647                         goto error_out;
2648
2649                 if (!m_teletext_parser)
2650                 {
2651                         eDebug("enable teletext subtitles.. no parser !!!");
2652                         return -1;
2653                 }
2654
2655                 entry = PyTuple_GET_ITEM(tuple, 1);
2656                 if (!PyInt_Check(entry))
2657                         goto error_out;
2658                 pid = PyInt_AsLong(entry);
2659
2660                 entry = PyTuple_GET_ITEM(tuple, 2);
2661                 if (!PyInt_Check(entry))
2662                         goto error_out;
2663                 page = PyInt_AsLong(entry);
2664
2665                 entry = PyTuple_GET_ITEM(tuple, 3);
2666                 if (!PyInt_Check(entry))
2667                         goto error_out;
2668                 magazine = PyInt_AsLong(entry);
2669
2670                 m_subtitle_widget = new eSubtitleWidget(parent);
2671                 m_subtitle_widget->resize(parent->size()); /* full size */
2672                 m_teletext_parser->setPageAndMagazine(page, magazine);
2673                 if (m_dvb_service)
2674                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2675         }
2676         else if (type == 0)
2677         {
2678                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2679                 if (!m_subtitle_parser)
2680                 {
2681                         eDebug("enable dvb subtitles.. no parser !!!");
2682                         return -1;
2683                 }
2684                 if (tuplesize < 4)
2685                         goto error_out;
2686
2687                 entry = PyTuple_GET_ITEM(tuple, 1);
2688                 if (!PyInt_Check(entry))
2689                         goto error_out;
2690                 pid = PyInt_AsLong(entry);
2691
2692                 entry = PyTuple_GET_ITEM(tuple, 2);
2693                 if (!PyInt_Check(entry))
2694                         goto error_out;
2695                 composition_page_id = PyInt_AsLong(entry);
2696
2697                 entry = PyTuple_GET_ITEM(tuple, 3);
2698                 if (!PyInt_Check(entry))
2699                         goto error_out;
2700                 ancillary_page_id = PyInt_AsLong(entry);
2701
2702                 m_subtitle_widget = new eSubtitleWidget(parent);
2703                 m_subtitle_widget->resize(parent->size()); /* full size */
2704                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2705                 if (m_dvb_service)
2706                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2707         }
2708         else
2709                 goto error_out;
2710         return 0;
2711 error_out:
2712         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2713                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2714                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2715         return -1;
2716 }
2717
2718 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2719 {
2720         delete m_subtitle_widget;
2721         m_subtitle_widget = 0;
2722         if (m_subtitle_parser)
2723         {
2724                 m_subtitle_parser->stop();
2725                 m_dvb_subtitle_pages.clear();
2726         }
2727         if (m_teletext_parser)
2728         {
2729                 m_teletext_parser->setPageAndMagazine(-1, -1);
2730                 m_subtitle_pages.clear();
2731         }
2732         if (m_dvb_service)
2733                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2734         return 0;
2735 }
2736
2737 PyObject *eDVBServicePlay::getCachedSubtitle()
2738 {
2739         if (m_dvb_service)
2740         {
2741                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2742                 if (tmp != -1)
2743                 {
2744                         unsigned int data = (unsigned int)tmp;
2745                         int pid = (data&0xFFFF0000)>>16;
2746                         ePyObject tuple = PyTuple_New(4);
2747                         eDVBServicePMTHandler::program program;
2748                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2749                         if (!h.getProgramInfo(program))
2750                         {
2751                                 if (program.textPid==pid) // teletext
2752                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2753                                 else
2754                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2755                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2756                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2757                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2758                                 return tuple;
2759                         }
2760                 }
2761         }
2762         Py_RETURN_NONE;
2763 }
2764
2765 PyObject *eDVBServicePlay::getSubtitleList()
2766 {
2767         if (!m_teletext_parser)
2768                 Py_RETURN_NONE;
2769         
2770         ePyObject l = PyList_New(0);
2771         std::set<int> added_ttx_pages;
2772
2773         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2774                 m_teletext_parser->m_found_subtitle_pages;
2775
2776         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2777         eDVBServicePMTHandler::program program;
2778         if (h.getProgramInfo(program))
2779                 eDebug("getting program info failed.");
2780         else
2781         {
2782                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2783                         it != program.subtitleStreams.end(); ++it)
2784                 {
2785                         switch(it->subtitling_type)
2786                         {
2787                                 case 0x01: // ebu teletext subtitles
2788                                 {
2789                                         int page_number = it->teletext_page_number & 0xFF;
2790                                         int magazine_number = it->teletext_magazine_number & 7;
2791                                         int hash = magazine_number << 8 | page_number;
2792                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2793                                         {
2794                                                 ePyObject tuple = PyTuple_New(5);
2795                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2796                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2797                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2798                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2799                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2800                                                 PyList_Append(l, tuple);
2801                                                 Py_DECREF(tuple);
2802                                                 added_ttx_pages.insert(hash);
2803                                         }
2804                                         break;
2805                                 }
2806                                 case 0x10 ... 0x13:
2807                                 case 0x20 ... 0x23: // dvb subtitles
2808                                 {
2809                                         ePyObject tuple = PyTuple_New(5);
2810                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2811                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2812                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2813                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2814                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2815                                         PyList_Insert(l, 0, tuple);
2816                                         Py_DECREF(tuple);
2817                                         break;
2818                                 }
2819                         }
2820                 }
2821         }
2822
2823         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2824                 it != subs.end(); ++it)
2825         {
2826                 int page_number = it->teletext_page_number & 0xFF;
2827                 int magazine_number = it->teletext_magazine_number & 7;
2828                 int hash = magazine_number << 8 | page_number;
2829                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2830                 {
2831                         ePyObject tuple = PyTuple_New(5);
2832                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2833                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2834                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2835                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2836                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2837                         PyList_Append(l, tuple);
2838                         Py_DECREF(tuple);
2839                 }
2840         }
2841
2842         return l;
2843 }
2844
2845 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2846 {
2847         if (m_subtitle_widget)
2848         {
2849                 pts_t pos = 0;
2850                 if (m_decoder)
2851                         m_decoder->getPTS(0, pos);
2852                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2853                 m_subtitle_pages.push_back(page);
2854                 checkSubtitleTiming();
2855         }
2856 }
2857
2858 void eDVBServicePlay::checkSubtitleTiming()
2859 {
2860         eDebug("checkSubtitleTiming");
2861         if (!m_subtitle_widget)
2862                 return;
2863         while (1)
2864         {
2865                 enum { TELETEXT, DVB } type;
2866                 eDVBTeletextSubtitlePage page;
2867                 eDVBSubtitlePage dvb_page;
2868                 pts_t show_time;
2869                 if (!m_subtitle_pages.empty())
2870                 {
2871                         page = m_subtitle_pages.front();
2872                         type = TELETEXT;
2873                         show_time = page.m_pts;
2874                 }
2875                 else if (!m_dvb_subtitle_pages.empty())
2876                 {
2877                         dvb_page = m_dvb_subtitle_pages.front();
2878                         type = DVB;
2879                         show_time = dvb_page.m_show_time;
2880                 }
2881                 else
2882                         return;
2883         
2884                 pts_t pos = 0;
2885         
2886                 if (m_decoder)
2887                         m_decoder->getPTS(0, pos);
2888
2889                 eDebug("%lld %lld", pos, show_time);
2890                 int diff = show_time - pos;
2891                 if (type == TELETEXT && !page.m_have_pts)
2892                 {
2893                         eDebug("ttx subtitle page without pts... immediate show");
2894                         diff = 0;
2895                 }
2896                 if (diff < 0)
2897                 {
2898                         eDebug("[late (%d ms)]", -diff / 90);
2899                         diff = 0;
2900                 }
2901                 if (abs(diff) > 1800000)
2902                 {
2903                         eDebug("[invalid]... immediate show!");
2904                         diff = 0;
2905                 }
2906                 if ((diff/90)<20)
2907                 {
2908                         if (type == TELETEXT)
2909                         {
2910                                 eDebug("display teletext subtitle page %lld", show_time);
2911                                 m_subtitle_widget->setPage(page);
2912                                 m_subtitle_pages.pop_front();
2913                         }
2914                         else
2915                         {
2916                                 eDebug("display dvb subtitle Page %lld", show_time);
2917                                 m_subtitle_widget->setPage(dvb_page);
2918                                 m_dvb_subtitle_pages.pop_front();
2919                         }
2920                 } else
2921                 {
2922                         eDebug("start subtitle delay %d", diff / 90);
2923                         m_subtitle_sync_timer->start(diff / 90, 1);
2924                         break;
2925                 }
2926         }
2927 }
2928
2929 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2930 {
2931         if (m_subtitle_widget)
2932         {
2933                 pts_t pos = 0;
2934                 if (m_decoder)
2935                         m_decoder->getPTS(0, pos);
2936                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2937                 m_dvb_subtitle_pages.push_back(p);
2938                 checkSubtitleTiming();
2939         }
2940 }
2941
2942 int eDVBServicePlay::getAC3Delay()
2943 {
2944         if (m_dvb_service)
2945                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2946         else if (m_decoder)
2947                 return m_decoder->getAC3Delay();
2948         else
2949                 return 0;
2950 }
2951
2952 int eDVBServicePlay::getPCMDelay()
2953 {
2954         if (m_dvb_service)
2955                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2956         else if (m_decoder)
2957                 return m_decoder->getPCMDelay();
2958         else
2959                 return 0;
2960 }
2961
2962 void eDVBServicePlay::setAC3Delay(int delay)
2963 {
2964         if (m_dvb_service)
2965                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2966         if (m_decoder) {
2967                 std::string config_delay;
2968                 int config_delay_int = 0;
2969                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2970                         config_delay_int = atoi(config_delay.c_str());
2971                 m_decoder->setAC3Delay(delay + config_delay_int);
2972         }
2973 }
2974
2975 void eDVBServicePlay::setPCMDelay(int delay)
2976 {
2977         if (m_dvb_service)
2978                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2979         if (m_decoder) {
2980                 std::string config_delay;
2981                 int config_delay_int = 0;
2982                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2983                         config_delay_int = atoi(config_delay.c_str());
2984                 else
2985                         config_delay_int = 0;
2986                 m_decoder->setPCMDelay(delay + config_delay_int);
2987         }
2988 }
2989
2990 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2991 {
2992         switch(event.type) {
2993                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2994                         m_event((iPlayableService*)this, evVideoSizeChanged);
2995                         break;
2996                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2997                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2998                         break;
2999                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3000                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
3001                         break;
3002                 default:
3003                         break;
3004         }
3005 }
3006
3007 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3008 {
3009         ptr = this;
3010         return 0;
3011 }
3012
3013 PyObject *eDVBServicePlay::getStreamingData()
3014 {
3015         eDVBServicePMTHandler::program program;
3016         if (m_service_handler.getProgramInfo(program))
3017         {
3018                 Py_RETURN_NONE;
3019         }
3020
3021         ePyObject r = program.createPythonObject();
3022         ePtr<iDVBDemux> demux;
3023         if (!m_service_handler.getDataDemux(demux))
3024         {
3025                 uint8_t demux_id;
3026                 if (!demux->getCADemuxID(demux_id))
3027                         PutToDict(r, "demux", demux_id);
3028         }
3029
3030         return r;
3031 }
3032
3033
3034 DEFINE_REF(eDVBServicePlay)
3035
3036 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3037 {
3038         switch (w)
3039         {
3040         case iServiceInformation::sTransponderData:
3041                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3042         default:
3043                 break;
3044         }
3045         return iStaticServiceInformation::getInfoObject(ref, w);
3046 }
3047
3048 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");