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