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