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