Merge branch 'master' of /home/tmbinc/enigma2-git into tmbinc/FixTimingBugs
[enigma2.git] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
20
21                 /* for subtitles */
22 #include <lib/gui/esubtitle.h>
23
24 #include <sys/vfs.h>
25 #include <sys/stat.h>
26
27 #include <byteswap.h>
28 #include <netinet/in.h>
29
30 #ifndef BYTE_ORDER
31 #error no byte order defined!
32 #endif
33
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
35 {
36         DECLARE_REF(eStaticServiceDVBInformation);
37 public:
38         RESULT getName(const eServiceReference &ref, std::string &name);
39         int getLength(const eServiceReference &ref);
40         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41         PyObject *getInfoObject(const eServiceReference &ref, int);
42 };
43
44 DEFINE_REF(eStaticServiceDVBInformation);
45
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
47 {
48         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49         if ( !ref.name.empty() )
50         {
51                 if (service.getParentTransportStreamID().get()) // linkage subservice
52                 {
53                         ePtr<iServiceHandler> service_center;
54                         if (!eServiceCenter::getInstance(service_center))
55                         {
56                                 eServiceReferenceDVB parent = service;
57                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
58                                 parent.setServiceID( service.getParentServiceID() );
59                                 parent.setParentTransportStreamID(eTransportStreamID(0));
60                                 parent.setParentServiceID(eServiceID(0));
61                                 parent.name="";
62                                 ePtr<iStaticServiceInformation> service_info;
63                                 if (!service_center->info(parent, service_info))
64                                 {
65                                         if (!service_info->getName(parent, name))
66                                                 name=buildShortName(name) + " - ";
67                                 }
68                         }
69                 }
70                 else
71                         name="";
72                 name += ref.name;
73                 return 0;
74         }
75         else
76                 return -1;
77 }
78
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
80 {
81         return -1;
82 }
83
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
85 {
86         ePtr<eDVBResourceManager> res_mgr;
87         if ( eDVBResourceManager::getInstance( res_mgr ) )
88                 eDebug("isPlayable... no res manager!!");
89         else
90         {
91                 eDVBChannelID chid, chid_ignore;
92                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94                 return res_mgr->canAllocateChannel(chid, chid_ignore);
95         }
96         return false;
97 }
98
99 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
100 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
101 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
102
103 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
104 {
105         PutToDict(dict, "tuner_type", "DVB-S");
106         PutToDict(dict, "frequency", feparm.frequency);
107         PutToDict(dict, "symbol_rate", feparm.symbol_rate);
108         PutToDict(dict, "orbital_position", feparm.orbital_position);
109         PutToDict(dict, "inversion", feparm.inversion);
110         PutToDict(dict, "fec_inner", feparm.fec);
111         PutToDict(dict, "modulation", feparm.modulation);
112         PutToDict(dict, "polarization", feparm.polarisation);
113         if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
114         {
115                 PutToDict(dict, "rolloff", feparm.rolloff);
116                 PutToDict(dict, "pilot", feparm.pilot);
117         }
118         PutToDict(dict, "system", feparm.system);
119 }
120
121 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
122 {
123         PutToDict(dict, "tuner_type", "DVB-T");
124         PutToDict(dict, "frequency", feparm.frequency);
125         PutToDict(dict, "bandwidth", feparm.bandwidth);
126         PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
127         PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
128         PutToDict(dict, "constellation", feparm.modulation);
129         PutToDict(dict, "transmission_mode", feparm.transmission_mode);
130         PutToDict(dict, "guard_interval", feparm.guard_interval);
131         PutToDict(dict, "hierarchy_information", feparm.hierarchy);
132         PutToDict(dict, "inversion", feparm.inversion);
133 }
134
135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
136 {
137         PutToDict(dict, "tuner_type", "DVB-C");
138         PutToDict(dict, "frequency", feparm.frequency);
139         PutToDict(dict, "symbol_rate", feparm.symbol_rate);
140         PutToDict(dict, "modulation", feparm.modulation);
141         PutToDict(dict, "inversion", feparm.inversion);
142         PutToDict(dict, "fec_inner", feparm.fec_inner);
143 }
144
145 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
146 {
147         if (r.type == eServiceReference::idDVB)
148         {
149                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
150                 switch(what)
151                 {
152                         case iServiceInformation::sTransponderData:
153                         {
154                                 ePtr<eDVBResourceManager> res;
155                                 if (!eDVBResourceManager::getInstance(res))
156                                 {
157                                         ePtr<iDVBChannelList> db;
158                                         if (!res->getChannelList(db))
159                                         {
160                                                 eDVBChannelID chid;
161                                                 ref.getChannelID(chid);
162                                                 ePtr<iDVBFrontendParameters> feparm;
163                                                 if (!db->getChannelFrontendData(chid, feparm))
164                                                 {
165                                                         int system;
166                                                         if (!feparm->getSystem(system))
167                                                         {
168                                                                 ePyObject dict = PyDict_New();
169                                                                 switch(system)
170                                                                 {
171                                                                         case iDVBFrontend::feSatellite:
172                                                                         {
173                                                                                 eDVBFrontendParametersSatellite s;
174                                                                                 feparm->getDVBS(s);
175                                                                                 PutSatelliteDataToDict(dict, s);
176                                                                                 break;
177                                                                         }
178                                                                         case iDVBFrontend::feTerrestrial:
179                                                                         {
180                                                                                 eDVBFrontendParametersTerrestrial t;
181                                                                                 feparm->getDVBT(t);
182                                                                                 PutTerrestrialDataToDict(dict, t);
183                                                                                 break;
184                                                                         }
185                                                                         case iDVBFrontend::feCable:
186                                                                         {
187                                                                                 eDVBFrontendParametersCable c;
188                                                                                 feparm->getDVBC(c);
189                                                                                 PutCableDataToDict(dict, c);
190                                                                                 break;
191                                                                         }
192                                                                         default:
193                                                                                 eDebug("unknown frontend type %d", system);
194                                                                                 Py_DECREF(dict);
195                                                                                 break;
196                                                                 }
197                                                                 return dict;
198                                                         }
199                                                 }
200                                         }
201                                 }
202                         }
203                 }
204         }
205         Py_RETURN_NONE;
206 }
207
208 DEFINE_REF(eStaticServiceDVBBouquetInformation);
209
210 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
211 {
212         ePtr<iDVBChannelList> db;
213         ePtr<eDVBResourceManager> res;
214
215         int err;
216         if ((err = eDVBResourceManager::getInstance(res)) != 0)
217         {
218                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
219                 return err;
220         }
221         if ((err = res->getChannelList(db)) != 0)
222         {
223                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
224                 return err;
225         }
226
227         eBouquet *bouquet=0;
228         if ((err = db->getBouquet(ref, bouquet)) != 0)
229         {
230                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
231                 return -1;
232         }
233
234         if ( bouquet && bouquet->m_bouquet_name.length() )
235         {
236                 name = bouquet->m_bouquet_name;
237                 return 0;
238         }
239         else
240                 return -1;
241 }
242
243 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
244 {
245         if (ref.flags & eServiceReference::isGroup)
246         {
247                 ePtr<iDVBChannelList> db;
248                 ePtr<eDVBResourceManager> res;
249
250                 if (eDVBResourceManager::getInstance(res))
251                 {
252                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
253                         return 0;
254                 }
255
256                 if (res->getChannelList(db))
257                 {
258                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
259                         return 0;
260                 }
261
262                 eBouquet *bouquet=0;
263                 if (db->getBouquet(ref, bouquet))
264                 {
265                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
266                         return 0;
267                 }
268
269                 int prio_order = eDVBFrontend::getTypePriorityOrder();
270                 int cur=0;
271                 eDVBChannelID chid, chid_ignore;
272                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
273                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
274                 {
275                         static unsigned char prio_map[6][3] = {
276                                 { 3, 2, 1 }, // -S -C -T
277                                 { 3, 1, 2 }, // -S -T -C
278                                 { 2, 3, 1 }, // -C -S -T
279                                 { 1, 3, 2 }, // -C -T -S
280                                 { 1, 2, 3 }, // -T -C -S
281                                 { 2, 1, 3 }  // -T -S -C
282                         };
283                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
284                         int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
285                         switch(tmp)
286                         {
287                                 case 0:
288                                         break;
289                                 case 30000: // cached DVB-T channel
290                                 case 1: // DVB-T frontend
291                                         tmp = prio_map[prio_order][2];
292                                         break;
293                                 case 40000: // cached DVB-C channel
294                                 case 2:
295                                         tmp = prio_map[prio_order][1];
296                                         break;
297                                 default: // DVB-S
298                                         tmp = prio_map[prio_order][0];
299                                         break;
300                         }
301                         if (tmp > cur)
302                         {
303                                 m_playable_service = *it;
304                                 cur = tmp;
305                         }
306                 }
307                 if (cur)
308                         return cur;
309         }
310         m_playable_service = eServiceReference();
311         return 0;
312 }
313
314 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
315 {
316         return -1;
317 }
318
319 #include <lib/dvb/epgcache.h>
320
321 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
322 {
323         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
324 }
325
326 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
327 {
328         DECLARE_REF(eStaticServiceDVBPVRInformation);
329         eServiceReference m_ref;
330         eDVBMetaParser m_parser;
331 public:
332         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
333         RESULT getName(const eServiceReference &ref, std::string &name);
334         int getLength(const eServiceReference &ref);
335         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
336         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
337         int getInfo(const eServiceReference &ref, int w);
338         std::string getInfoString(const eServiceReference &ref,int w);
339 };
340
341 DEFINE_REF(eStaticServiceDVBPVRInformation);
342
343 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
344 {
345         m_ref = ref;
346         m_parser.parseFile(ref.path);
347 }
348
349 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
350 {
351         ASSERT(ref == m_ref);
352         if (m_parser.m_name.size())
353                 name = m_parser.m_name;
354         else
355         {
356                 name = ref.path;
357                 size_t n = name.rfind('/');
358                 if (n != std::string::npos)
359                         name = name.substr(n + 1);
360         }
361         return 0;
362 }
363
364 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
365 {
366         ASSERT(ref == m_ref);
367         
368         eDVBTSTools tstools;
369         
370         struct stat s;
371         stat(ref.path.c_str(), &s);
372
373         if (tstools.openFile(ref.path.c_str(), 1))
374                 return 0;
375
376                         /* check if cached data is still valid */
377         if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
378                 return m_parser.m_length / 90000;
379
380                         /* open again, this time with stream info */
381         if (tstools.openFile(ref.path.c_str()))
382                 return 0;
383
384                         /* otherwise, re-calc length and update meta file */
385         pts_t len;
386         if (tstools.calcLen(len))
387                 return 0;
388
389         m_parser.m_length = len;
390         m_parser.m_filesize = s.st_size;
391         m_parser.updateMeta(ref.path);
392         return m_parser.m_length / 90000;
393 }
394
395 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
396 {
397         switch (w)
398         {
399         case iServiceInformation::sDescription:
400                 return iServiceInformation::resIsString;
401         case iServiceInformation::sServiceref:
402                 return iServiceInformation::resIsString;
403         case iServiceInformation::sTimeCreate:
404                 if (m_parser.m_time_create)
405                         return m_parser.m_time_create;
406                 else
407                         return iServiceInformation::resNA;
408         default:
409                 return iServiceInformation::resNA;
410         }
411 }
412
413 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
414 {
415         switch (w)
416         {
417         case iServiceInformation::sDescription:
418                 return m_parser.m_description;
419         case iServiceInformation::sServiceref:
420                 return m_parser.m_ref.toString();
421         case iServiceInformation::sTags:
422                 return m_parser.m_tags;
423         default:
424                 return "";
425         }
426 }
427
428 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
429 {
430         if (!ref.path.empty())
431         {
432                 ePtr<eServiceEvent> event = new eServiceEvent;
433                 std::string filename = ref.path;
434                 filename.erase(filename.length()-2, 2);
435                 filename+="eit";
436                 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
437                 {
438                         evt = event;
439                         return 0;
440                 }
441         }
442         evt = 0;
443         return -1;
444 }
445
446 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
447 {
448         DECLARE_REF(eDVBPVRServiceOfflineOperations);
449         eServiceReferenceDVB m_ref;
450 public:
451         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
452         
453         RESULT deleteFromDisk(int simulate);
454         RESULT getListOfFilenames(std::list<std::string> &);
455 };
456
457 DEFINE_REF(eDVBPVRServiceOfflineOperations);
458
459 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
460 {
461 }
462
463 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
464 {
465         if (simulate)
466                 return 0;
467         else
468         {
469                 std::list<std::string> res;
470                 if (getListOfFilenames(res))
471                         return -1;
472                 
473                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
474                 if (!eraser)
475                         eDebug("FATAL !! can't get background file eraser");
476                 
477                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
478                 {
479                         eDebug("Removing %s...", i->c_str());
480                         if (eraser)
481                                 eraser->erase(i->c_str());
482                         else
483                                 ::unlink(i->c_str());
484                 }
485                 
486                 return 0;
487         }
488 }
489
490 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
491 {
492         res.clear();
493         res.push_back(m_ref.path);
494
495 // handling for old splitted recordings (enigma 1)
496         char buf[255];
497         int slice=1;
498         while(true)
499         {
500                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
501                 struct stat s;
502                 if (stat(buf, &s) < 0)
503                         break;
504                 res.push_back(buf);
505         }       
506
507         res.push_back(m_ref.path + ".meta");
508         res.push_back(m_ref.path + ".ap");
509         res.push_back(m_ref.path + ".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(); is done in caller*/
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                                 fe->getTransponderData(ret, original);
1881                 }
1882         }
1883         else
1884                 Py_RETURN_NONE;
1885         return ret;
1886 }
1887
1888 PyObject *eDVBServiceBase::getAll(bool original)
1889 {
1890         ePyObject ret = getTransponderData(original);
1891         if (ret != Py_None)
1892         {
1893                 eUsePtr<iDVBChannel> channel;
1894                 if(!m_service_handler.getChannel(channel))
1895                 {
1896                         ePtr<iDVBFrontend> fe;
1897                         if(!channel->getFrontend(fe))
1898                         {
1899                                 fe->getFrontendData(ret);
1900                                 fe->getFrontendStatus(ret);
1901                         }
1902                 }
1903         }
1904         return ret;
1905 }
1906
1907 int eDVBServicePlay::getNumberOfSubservices()
1908 {
1909         ePtr<eServiceEvent> evt;
1910         if (!m_event_handler.getEvent(evt, 0))
1911                 return evt->getNumOfLinkageServices();
1912         return 0;
1913 }
1914
1915 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1916 {
1917         ePtr<eServiceEvent> evt;
1918         if (!m_event_handler.getEvent(evt, 0))
1919         {
1920                 if (!evt->getLinkageService(sub, m_reference, n))
1921                         return 0;
1922         }
1923         sub.type=eServiceReference::idInvalid;
1924         return -1;
1925 }
1926
1927 RESULT eDVBServicePlay::startTimeshift()
1928 {
1929         ePtr<iDVBDemux> demux;
1930         
1931         eDebug("Start timeshift!");
1932         
1933         if (m_timeshift_enabled)
1934                 return -1;
1935         
1936                 /* start recording with the data demux. */
1937         if (m_service_handler.getDataDemux(demux))
1938                 return -2;
1939
1940         demux->createTSRecorder(m_record);
1941         if (!m_record)
1942                 return -3;
1943
1944         std::string tspath;
1945         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
1946                 eDebug("could not query ts path");
1947                 return -5;
1948         }
1949         tspath.append("/timeshift.XXXXXX");
1950         char* templ;
1951         templ = new char[tspath.length() + 1];
1952         strcpy(templ, tspath.c_str());
1953
1954         m_timeshift_fd = mkstemp(templ);
1955         m_timeshift_file = std::string(templ);
1956
1957         eDebug("recording to %s", templ);
1958
1959         delete [] templ;
1960
1961         if (m_timeshift_fd < 0)
1962         {
1963                 m_record = 0;
1964                 return -4;
1965         }
1966                 
1967         m_record->setTargetFD(m_timeshift_fd);
1968
1969         m_timeshift_enabled = 1;
1970         
1971         updateTimeshiftPids();
1972         m_record->start();
1973
1974         return 0;
1975 }
1976
1977 RESULT eDVBServicePlay::stopTimeshift()
1978 {
1979         if (!m_timeshift_enabled)
1980                 return -1;
1981         
1982         switchToLive();
1983         
1984         m_timeshift_enabled = 0;
1985         
1986         m_record->stop();
1987         m_record = 0;
1988         
1989         close(m_timeshift_fd);
1990         eDebug("remove timeshift file");
1991         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
1992         
1993         return 0;
1994 }
1995
1996 int eDVBServicePlay::isTimeshiftActive()
1997 {
1998         return m_timeshift_enabled && m_timeshift_active;
1999 }
2000
2001 RESULT eDVBServicePlay::activateTimeshift()
2002 {
2003         if (!m_timeshift_enabled)
2004                 return -1;
2005         
2006         if (!m_timeshift_active)
2007         {
2008                 switchToTimeshift();
2009                 return 0;
2010         }
2011         
2012         return -2;
2013 }
2014
2015 PyObject *eDVBServicePlay::getCutList()
2016 {
2017         ePyObject list = PyList_New(0);
2018         
2019         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2020         {
2021                 ePyObject tuple = PyTuple_New(2);
2022                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2023                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2024                 PyList_Append(list, tuple);
2025                 Py_DECREF(tuple);
2026         }
2027         
2028         return list;
2029 }
2030
2031 void eDVBServicePlay::setCutList(ePyObject list)
2032 {
2033         if (!PyList_Check(list))
2034                 return;
2035         int size = PyList_Size(list);
2036         int i;
2037         
2038         m_cue_entries.clear();
2039         
2040         for (i=0; i<size; ++i)
2041         {
2042                 ePyObject tuple = PyList_GET_ITEM(list, i);
2043                 if (!PyTuple_Check(tuple))
2044                 {
2045                         eDebug("non-tuple in cutlist");
2046                         continue;
2047                 }
2048                 if (PyTuple_Size(tuple) != 2)
2049                 {
2050                         eDebug("cutlist entries need to be a 2-tuple");
2051                         continue;
2052                 }
2053                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2054                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2055                 {
2056                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2057                         continue;
2058                 }
2059                 pts_t pts = PyLong_AsLongLong(ppts);
2060                 int type = PyInt_AsLong(ptype);
2061                 m_cue_entries.insert(cueEntry(pts, type));
2062                 eDebug("adding %08llx, %d", pts, type);
2063         }
2064         m_cuesheet_changed = 1;
2065         
2066         cutlistToCuesheet();
2067         m_event((iPlayableService*)this, evCuesheetChanged);
2068 }
2069
2070 void eDVBServicePlay::setCutListEnable(int enable)
2071 {
2072         m_cutlist_enabled = enable;
2073         cutlistToCuesheet();
2074 }
2075
2076 void eDVBServicePlay::updateTimeshiftPids()
2077 {
2078         if (!m_record)
2079                 return;
2080         
2081         eDVBServicePMTHandler::program program;
2082         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2083
2084         if (h.getProgramInfo(program))
2085                 return;
2086         else
2087         {
2088                 std::set<int> pids_to_record;
2089                 pids_to_record.insert(0); // PAT
2090                 if (program.pmtPid != -1)
2091                         pids_to_record.insert(program.pmtPid); // PMT
2092
2093                 if (program.textPid != -1)
2094                         pids_to_record.insert(program.textPid); // Videotext
2095
2096                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2097                         i(program.videoStreams.begin()); 
2098                         i != program.videoStreams.end(); ++i)
2099                         pids_to_record.insert(i->pid);
2100
2101                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2102                         i(program.audioStreams.begin()); 
2103                         i != program.audioStreams.end(); ++i)
2104                                 pids_to_record.insert(i->pid);
2105
2106                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2107                         i(program.subtitleStreams.begin());
2108                         i != program.subtitleStreams.end(); ++i)
2109                                 pids_to_record.insert(i->pid);
2110
2111                 std::set<int> new_pids, obsolete_pids;
2112                 
2113                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2114                                 m_pids_active.begin(), m_pids_active.end(),
2115                                 std::inserter(new_pids, new_pids.begin()));
2116                 
2117                 std::set_difference(
2118                                 m_pids_active.begin(), m_pids_active.end(),
2119                                 pids_to_record.begin(), pids_to_record.end(), 
2120                                 std::inserter(new_pids, new_pids.begin())
2121                                 );
2122
2123                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2124                         m_record->addPID(*i);
2125
2126                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2127                         m_record->removePID(*i);
2128         }
2129 }
2130
2131 void eDVBServicePlay::switchToLive()
2132 {
2133         if (!m_timeshift_active)
2134                 return;
2135         
2136         eDebug("SwitchToLive");
2137         
2138         m_cue = 0;
2139         m_decoder = 0;
2140         m_decode_demux = 0;
2141         m_teletext_parser = 0;
2142         m_rds_decoder = 0;
2143         m_subtitle_parser = 0;
2144         m_new_dvb_subtitle_page_connection = 0;
2145         m_new_subtitle_page_connection = 0;
2146         m_rds_decoder_event_connection = 0;
2147         m_video_event_connection = 0;
2148
2149                 /* free the timeshift service handler, we need the resources */
2150         m_service_handler_timeshift.free();
2151         m_timeshift_active = 0;
2152
2153         m_event((iPlayableService*)this, evSeekableStatusChanged);
2154
2155         updateDecoder();
2156 }
2157
2158 void eDVBServicePlay::switchToTimeshift()
2159 {
2160         if (m_timeshift_active)
2161                 return;
2162
2163         m_decode_demux = 0;
2164         m_decoder = 0;
2165         m_teletext_parser = 0;
2166         m_rds_decoder = 0;
2167         m_subtitle_parser = 0;
2168         m_new_subtitle_page_connection = 0;
2169         m_new_dvb_subtitle_page_connection = 0;
2170         m_rds_decoder_event_connection = 0;
2171         m_video_event_connection = 0;
2172
2173         m_timeshift_active = 1;
2174
2175         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2176         r.path = m_timeshift_file;
2177
2178         m_cue = new eCueSheet();
2179         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2180
2181         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2182         pause();
2183         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2184         
2185         m_event((iPlayableService*)this, evSeekableStatusChanged);
2186 }
2187
2188 void eDVBServicePlay::updateDecoder()
2189 {
2190         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2191
2192         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2193
2194         eDVBServicePMTHandler::program program;
2195         if (h.getProgramInfo(program))
2196                 eDebug("getting program info failed.");
2197         else
2198         {
2199                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2200                 if (!program.videoStreams.empty())
2201                 {
2202                         eDebugNoNewLine(" (");
2203                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2204                                 i(program.videoStreams.begin());
2205                                 i != program.videoStreams.end(); ++i)
2206                         {
2207                                 if (vpid == -1)
2208                                 {
2209                                         vpid = i->pid;
2210                                         vpidtype = i->type;
2211                                 }
2212                                 if (i != program.videoStreams.begin())
2213                                         eDebugNoNewLine(", ");
2214                                 eDebugNoNewLine("%04x", i->pid);
2215                         }
2216                         eDebugNoNewLine(")");
2217                 }
2218                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2219                 if (!program.audioStreams.empty())
2220                 {
2221                         eDebugNoNewLine(" (");
2222                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2223                                 i(program.audioStreams.begin());
2224                                 i != program.audioStreams.end(); ++i)
2225                         {
2226                                 if (i != program.audioStreams.begin())
2227                                         eDebugNoNewLine(", ");
2228                                 eDebugNoNewLine("%04x", i->pid);
2229                         }
2230                         eDebugNoNewLine(")");
2231                 }
2232                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2233                 pcrpid = program.pcrPid;
2234                 eDebug(", and the text pid is %04x", program.textPid);
2235                 tpid = program.textPid;
2236         }
2237
2238         if (!m_decoder)
2239         {
2240                 h.getDecodeDemux(m_decode_demux);
2241                 if (m_decode_demux)
2242                 {
2243                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2244                         if (m_decoder)
2245                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2246                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2247                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2248                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2249                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2250                 } else
2251                 {
2252                         m_teletext_parser = 0;
2253                         m_subtitle_parser = 0;
2254                 }
2255
2256                 if (m_cue)
2257                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2258         }
2259
2260         if (m_decoder)
2261         {
2262                 if (m_dvb_service)
2263                 {
2264                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2265                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2266                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2267                 }
2268                 else // subservice or recording
2269                 {
2270                         eServiceReferenceDVB ref;
2271                         m_service_handler.getServiceReference(ref);
2272                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2273                         if (!parent)
2274                                 parent = ref;
2275                         if (parent)
2276                         {
2277                                 ePtr<eDVBResourceManager> res_mgr;
2278                                 if (!eDVBResourceManager::getInstance(res_mgr))
2279                                 {
2280                                         ePtr<iDVBChannelList> db;
2281                                         if (!res_mgr->getChannelList(db))
2282                                         {
2283                                                 ePtr<eDVBService> origService;
2284                                                 if (!db->getService(parent, origService))
2285                                                 {
2286                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2287                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2288                                                 }
2289                                         }
2290                                 }
2291                         }
2292                 }
2293                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2294                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2295
2296                 m_decoder->setVideoPID(vpid, vpidtype);
2297                 selectAudioStream();
2298
2299                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2300                         m_decoder->setSyncPCR(pcrpid);
2301                 else
2302                         m_decoder->setSyncPCR(-1);
2303
2304                 m_decoder->setTextPID(tpid);
2305
2306                 m_teletext_parser->start(program.textPid);
2307
2308 /*              if (!m_is_primary)
2309                         m_decoder->setTrickmode();
2310                 else */ if (m_is_paused)
2311                         m_decoder->pause();
2312                 else
2313                         m_decoder->play();
2314
2315                 if (vpid > 0 && vpid < 0x2000)
2316                         ;
2317                 else
2318                 {
2319                         std::string radio_pic;
2320                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2321                                 m_decoder->setRadioPic(radio_pic);
2322                 }
2323
2324                 m_decoder->setAudioChannel(achannel);
2325
2326                 /* don't worry about non-existing services, nor pvr services */
2327                 if (m_dvb_service && !m_is_pvr)
2328                 {
2329                                 /* (audio pid will be set in selectAudioTrack */
2330                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2331                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2332                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2333                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2334                 }
2335         }
2336         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2337 }
2338
2339 void eDVBServicePlay::loadCuesheet()
2340 {
2341         std::string filename = m_reference.path + ".cuts";
2342         
2343         m_cue_entries.clear();
2344
2345         FILE *f = fopen(filename.c_str(), "rb");
2346
2347         if (f)
2348         {
2349                 eDebug("loading cuts..");
2350                 while (1)
2351                 {
2352                         unsigned long long where;
2353                         unsigned int what;
2354                         
2355                         if (!fread(&where, sizeof(where), 1, f))
2356                                 break;
2357                         if (!fread(&what, sizeof(what), 1, f))
2358                                 break;
2359                         
2360 #if BYTE_ORDER == LITTLE_ENDIAN
2361                         where = bswap_64(where);
2362 #endif
2363                         what = ntohl(what);
2364                         
2365                         if (what > 3)
2366                                 break;
2367                         
2368                         m_cue_entries.insert(cueEntry(where, what));
2369                 }
2370                 fclose(f);
2371                 eDebug("%d entries", m_cue_entries.size());
2372         } else
2373                 eDebug("cutfile not found!");
2374         
2375         m_cuesheet_changed = 0;
2376         cutlistToCuesheet();
2377         m_event((iPlayableService*)this, evCuesheetChanged);
2378 }
2379
2380 void eDVBServicePlay::saveCuesheet()
2381 {
2382         std::string filename = m_reference.path + ".cuts";
2383         
2384         FILE *f = fopen(filename.c_str(), "wb");
2385
2386         if (f)
2387         {
2388                 unsigned long long where;
2389                 int what;
2390
2391                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2392                 {
2393 #if BYTE_ORDER == BIG_ENDIAN
2394                         where = i->where;
2395 #else
2396                         where = bswap_64(i->where);
2397 #endif
2398                         what = htonl(i->what);
2399                         fwrite(&where, sizeof(where), 1, f);
2400                         fwrite(&what, sizeof(what), 1, f);
2401                         
2402                 }
2403                 fclose(f);
2404         }
2405         
2406         m_cuesheet_changed = 0;
2407 }
2408
2409 void eDVBServicePlay::cutlistToCuesheet()
2410 {
2411         if (!m_cue)
2412         {
2413                 eDebug("no cue sheet");
2414                 return;
2415         }       
2416         m_cue->clear();
2417         
2418         if (!m_cutlist_enabled)
2419         {
2420                 m_cue->commitSpans();
2421                 eDebug("cutlists were disabled");
2422                 return;
2423         }
2424
2425         pts_t in = 0, out = 0, length = 0;
2426         
2427         getLength(length);
2428                 
2429         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2430         
2431         while (1)
2432         {
2433                 if (i == m_cue_entries.end())
2434                         out = length;
2435                 else {
2436                         if (i->what == 0) /* in */
2437                         {
2438                                 in = i++->where;
2439                                 continue;
2440                         } else if (i->what == 1) /* out */
2441                                 out = i++->where;
2442                         else /* mark (2) or last play position (3) */
2443                         {
2444                                 i++;
2445                                 continue;
2446                         }
2447                 }
2448                 
2449                 if (in < 0)
2450                         in = 0;
2451                 if (out < 0)
2452                         out = 0;
2453                 if (in > length)
2454                         in = length;
2455                 if (out > length)
2456                         out = length;
2457                 
2458                 if (in < out)
2459                         m_cue->addSourceSpan(in, out);
2460                 
2461                 in = length;
2462                 
2463                 if (i == m_cue_entries.end())
2464                         break;
2465         }
2466         m_cue->commitSpans();
2467 }
2468
2469 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2470 {
2471         if (m_subtitle_widget)
2472                 disableSubtitles(parent);
2473
2474         ePyObject entry;
2475         int tuplesize = PyTuple_Size(tuple);
2476         int type = 0;
2477
2478         if (!PyTuple_Check(tuple))
2479                 goto error_out;
2480
2481         if (tuplesize < 1)
2482                 goto error_out;
2483
2484         entry = PyTuple_GET_ITEM(tuple, 0);
2485
2486         if (!PyInt_Check(entry))
2487                 goto error_out;
2488
2489         type = PyInt_AsLong(entry);
2490
2491         if (type == 1)  // teletext subtitles
2492         {
2493                 int page, magazine, pid;
2494                 if (tuplesize < 4)
2495                         goto error_out;
2496
2497                 if (!m_teletext_parser)
2498                 {
2499                         eDebug("enable teletext subtitles.. no parser !!!");
2500                         return -1;
2501                 }
2502
2503                 entry = PyTuple_GET_ITEM(tuple, 1);
2504                 if (!PyInt_Check(entry))
2505                         goto error_out;
2506                 pid = PyInt_AsLong(entry);
2507
2508                 entry = PyTuple_GET_ITEM(tuple, 2);
2509                 if (!PyInt_Check(entry))
2510                         goto error_out;
2511                 page = PyInt_AsLong(entry);
2512
2513                 entry = PyTuple_GET_ITEM(tuple, 3);
2514                 if (!PyInt_Check(entry))
2515                         goto error_out;
2516                 magazine = PyInt_AsLong(entry);
2517
2518                 m_subtitle_widget = new eSubtitleWidget(parent);
2519                 m_subtitle_widget->resize(parent->size()); /* full size */
2520                 m_teletext_parser->setPageAndMagazine(page, magazine);
2521                 if (m_dvb_service)
2522                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2523         }
2524         else if (type == 0)
2525         {
2526                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2527                 if (!m_subtitle_parser)
2528                 {
2529                         eDebug("enable dvb subtitles.. no parser !!!");
2530                         return -1;
2531                 }
2532                 if (tuplesize < 4)
2533                         goto error_out;
2534
2535                 entry = PyTuple_GET_ITEM(tuple, 1);
2536                 if (!PyInt_Check(entry))
2537                         goto error_out;
2538                 pid = PyInt_AsLong(entry);
2539
2540                 entry = PyTuple_GET_ITEM(tuple, 2);
2541                 if (!PyInt_Check(entry))
2542                         goto error_out;
2543                 composition_page_id = PyInt_AsLong(entry);
2544
2545                 entry = PyTuple_GET_ITEM(tuple, 3);
2546                 if (!PyInt_Check(entry))
2547                         goto error_out;
2548                 ancillary_page_id = PyInt_AsLong(entry);
2549
2550                 m_subtitle_widget = new eSubtitleWidget(parent);
2551                 m_subtitle_widget->resize(parent->size()); /* full size */
2552                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2553                 if (m_dvb_service)
2554                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2555         }
2556         else
2557                 goto error_out;
2558         return 0;
2559 error_out:
2560         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2561                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2562                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2563         return -1;
2564 }
2565
2566 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2567 {
2568         delete m_subtitle_widget;
2569         m_subtitle_widget = 0;
2570         if (m_subtitle_parser)
2571         {
2572                 m_subtitle_parser->stop();
2573                 m_dvb_subtitle_pages.clear();
2574         }
2575         if (m_teletext_parser)
2576         {
2577                 m_teletext_parser->setPageAndMagazine(-1, -1);
2578                 m_subtitle_pages.clear();
2579         }
2580         if (m_dvb_service)
2581                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2582         return 0;
2583 }
2584
2585 PyObject *eDVBServicePlay::getCachedSubtitle()
2586 {
2587         if (m_dvb_service)
2588         {
2589                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2590                 if (tmp != -1)
2591                 {
2592                         unsigned int data = (unsigned int)tmp;
2593                         int pid = (data&0xFFFF0000)>>16;
2594                         ePyObject tuple = PyTuple_New(4);
2595                         eDVBServicePMTHandler::program program;
2596                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2597                         if (!h.getProgramInfo(program))
2598                         {
2599                                 if (program.textPid==pid) // teletext
2600                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2601                                 else
2602                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2603                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2604                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2605                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2606                                 return tuple;
2607                         }
2608                 }
2609         }
2610         Py_RETURN_NONE;
2611 }
2612
2613 PyObject *eDVBServicePlay::getSubtitleList()
2614 {
2615         if (!m_teletext_parser)
2616                 Py_RETURN_NONE;
2617         
2618         ePyObject l = PyList_New(0);
2619         std::set<int> added_ttx_pages;
2620
2621         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2622                 m_teletext_parser->m_found_subtitle_pages;
2623
2624         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2625         eDVBServicePMTHandler::program program;
2626         if (h.getProgramInfo(program))
2627                 eDebug("getting program info failed.");
2628         else
2629         {
2630                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2631                         it != program.subtitleStreams.end(); ++it)
2632                 {
2633                         switch(it->subtitling_type)
2634                         {
2635                                 case 0x01: // ebu teletext subtitles
2636                                 {
2637                                         int page_number = it->teletext_page_number & 0xFF;
2638                                         int magazine_number = it->teletext_magazine_number & 7;
2639                                         int hash = magazine_number << 8 | page_number;
2640                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2641                                         {
2642                                                 ePyObject tuple = PyTuple_New(5);
2643                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2644                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2645                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2646                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2647                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2648                                                 PyList_Append(l, tuple);
2649                                                 Py_DECREF(tuple);
2650                                                 added_ttx_pages.insert(hash);
2651                                         }
2652                                         break;
2653                                 }
2654                                 case 0x10 ... 0x13:
2655                                 case 0x20 ... 0x23: // dvb subtitles
2656                                 {
2657                                         ePyObject tuple = PyTuple_New(5);
2658                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2659                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2660                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2661                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2662                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2663                                         PyList_Insert(l, 0, tuple);
2664                                         Py_DECREF(tuple);
2665                                         break;
2666                                 }
2667                         }
2668                 }
2669         }
2670
2671         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2672                 it != subs.end(); ++it)
2673         {
2674                 int page_number = it->teletext_page_number & 0xFF;
2675                 int magazine_number = it->teletext_magazine_number & 7;
2676                 int hash = magazine_number << 8 | page_number;
2677                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2678                 {
2679                         ePyObject tuple = PyTuple_New(5);
2680                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2681                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2682                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2683                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2684                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2685                         PyList_Append(l, tuple);
2686                         Py_DECREF(tuple);
2687                 }
2688         }
2689
2690         return l;
2691 }
2692
2693 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2694 {
2695         if (m_subtitle_widget)
2696         {
2697                 pts_t pos = 0;
2698                 if (m_decoder)
2699                         m_decoder->getPTS(0, pos);
2700                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2701                 m_subtitle_pages.push_back(page);
2702                 checkSubtitleTiming();
2703         }
2704 }
2705
2706 void eDVBServicePlay::checkSubtitleTiming()
2707 {
2708         eDebug("checkSubtitleTiming");
2709         if (!m_subtitle_widget)
2710                 return;
2711         while (1)
2712         {
2713                 enum { TELETEXT, DVB } type;
2714                 eDVBTeletextSubtitlePage page;
2715                 eDVBSubtitlePage dvb_page;
2716                 pts_t show_time;
2717                 if (!m_subtitle_pages.empty())
2718                 {
2719                         page = m_subtitle_pages.front();
2720                         type = TELETEXT;
2721                         show_time = page.m_pts;
2722                 }
2723                 else if (!m_dvb_subtitle_pages.empty())
2724                 {
2725                         dvb_page = m_dvb_subtitle_pages.front();
2726                         type = DVB;
2727                         show_time = dvb_page.m_show_time;
2728                 }
2729                 else
2730                         return;
2731         
2732                 pts_t pos = 0;
2733         
2734                 if (m_decoder)
2735                         m_decoder->getPTS(0, pos);
2736
2737                 eDebug("%lld %lld", pos, show_time);
2738                 int diff =  show_time - pos;
2739                 if (diff < 0)
2740                 {
2741                         eDebug("[late (%d ms)]", -diff / 90);
2742                         diff = 0;
2743                 }
2744 //              if (diff > 900000)
2745 //              {
2746 //                      eDebug("[invalid]");
2747 //                      diff = 0;
2748 //              }
2749         
2750                 if ((diff/90)<20)
2751                 {
2752                         if (type == TELETEXT)
2753                         {
2754                                 eDebug("display teletext subtitle page %lld", show_time);
2755                                 m_subtitle_widget->setPage(page);
2756                                 m_subtitle_pages.pop_front();
2757                         }
2758                         else
2759                         {
2760                                 eDebug("display dvb subtitle Page %lld", show_time);
2761                                 m_subtitle_widget->setPage(dvb_page);
2762                                 m_dvb_subtitle_pages.pop_front();
2763                         }
2764                 } else
2765                 {
2766                         eDebug("start subtitle delay %d", diff / 90);
2767                         m_subtitle_sync_timer->start(diff / 90, 1);
2768                         break;
2769                 }
2770         }
2771 }
2772
2773 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2774 {
2775         if (m_subtitle_widget)
2776         {
2777                 pts_t pos = 0;
2778                 if (m_decoder)
2779                         m_decoder->getPTS(0, pos);
2780                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2781                 m_dvb_subtitle_pages.push_back(p);
2782                 checkSubtitleTiming();
2783         }
2784 }
2785
2786 int eDVBServicePlay::getAC3Delay()
2787 {
2788         if (m_dvb_service)
2789                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2790         else if (m_decoder)
2791                 return m_decoder->getAC3Delay();
2792         else
2793                 return 0;
2794 }
2795
2796 int eDVBServicePlay::getPCMDelay()
2797 {
2798         if (m_dvb_service)
2799                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2800         else if (m_decoder)
2801                 return m_decoder->getPCMDelay();
2802         else
2803                 return 0;
2804 }
2805
2806 void eDVBServicePlay::setAC3Delay(int delay)
2807 {
2808         if (m_dvb_service)
2809                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2810         if (m_decoder)
2811                 m_decoder->setAC3Delay(delay);
2812 }
2813
2814 void eDVBServicePlay::setPCMDelay(int delay)
2815 {
2816         if (m_dvb_service)
2817                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2818         if (m_decoder)
2819                 m_decoder->setPCMDelay(delay);
2820 }
2821
2822 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2823 {
2824         switch(event.type) {
2825                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2826                         m_event((iPlayableService*)this, evVideoSizeChanged);
2827                         break;
2828                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2829                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2830                         break;
2831                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2832                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2833                         break;
2834                 default:
2835                         break;
2836         }
2837 }
2838
2839 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2840 {
2841         ptr = this;
2842         return 0;
2843 }
2844
2845 PyObject *eDVBServicePlay::getStreamingData()
2846 {
2847         eDVBServicePMTHandler::program program;
2848         if (m_service_handler.getProgramInfo(program))
2849         {
2850                 Py_RETURN_NONE;
2851         }
2852
2853         ePyObject r = program.createPythonObject();
2854         ePtr<iDVBDemux> demux;
2855         if (!m_service_handler.getDataDemux(demux))
2856         {
2857                 uint8_t demux_id;
2858                 if (!demux->getCADemuxID(demux_id))
2859                         PutToDict(r, "demux", demux_id);
2860         }
2861
2862         return r;
2863 }
2864
2865
2866 DEFINE_REF(eDVBServicePlay)
2867
2868 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2869 {
2870         switch (w)
2871         {
2872         case iServiceInformation::sTransponderData:
2873                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2874         default:
2875                 break;
2876         }
2877         return iStaticServiceInformation::getInfoObject(ref, w);
2878 }
2879
2880 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");