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