Merge branch 'master' of git.opendreambox.org:/git/enigma2
[vuplus_dvbapp] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
20
21                 /* for subtitles */
22 #include <lib/gui/esubtitle.h>
23
24 #include <sys/vfs.h>
25 #include <sys/stat.h>
26
27 #include <byteswap.h>
28 #include <netinet/in.h>
29
30 #ifndef BYTE_ORDER
31 #error no byte order defined!
32 #endif
33
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
35 {
36         DECLARE_REF(eStaticServiceDVBInformation);
37 public:
38         RESULT getName(const eServiceReference &ref, std::string &name);
39         int getLength(const eServiceReference &ref);
40         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41         PyObject *getInfoObject(const eServiceReference &ref, int);
42 };
43
44 DEFINE_REF(eStaticServiceDVBInformation);
45
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
47 {
48         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49         if ( !ref.name.empty() )
50         {
51                 if (service.getParentTransportStreamID().get()) // linkage subservice
52                 {
53                         ePtr<iServiceHandler> service_center;
54                         if (!eServiceCenter::getInstance(service_center))
55                         {
56                                 eServiceReferenceDVB parent = service;
57                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
58                                 parent.setServiceID( service.getParentServiceID() );
59                                 parent.setParentTransportStreamID(eTransportStreamID(0));
60                                 parent.setParentServiceID(eServiceID(0));
61                                 parent.name="";
62                                 ePtr<iStaticServiceInformation> service_info;
63                                 if (!service_center->info(parent, service_info))
64                                 {
65                                         if (!service_info->getName(parent, name))
66                                                 name=buildShortName(name) + " - ";
67                                 }
68                         }
69                 }
70                 else
71                         name="";
72                 name += ref.name;
73                 return 0;
74         }
75         else
76                 return -1;
77 }
78
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
80 {
81         return -1;
82 }
83
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
85 {
86         ePtr<eDVBResourceManager> res_mgr;
87         if ( eDVBResourceManager::getInstance( res_mgr ) )
88                 eDebug("isPlayable... no res manager!!");
89         else
90         {
91                 eDVBChannelID chid, chid_ignore;
92                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94                 return res_mgr->canAllocateChannel(chid, chid_ignore);
95         }
96         return false;
97 }
98
99 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
100 extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
101 extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
102
103 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
104 {
105         PutToDict(dict, "tuner_type", "DVB-S");
106         PutToDict(dict, "frequency", feparm.frequency);
107         PutToDict(dict, "symbol_rate", feparm.symbol_rate);
108         PutToDict(dict, "orbital_position", feparm.orbital_position);
109         PutToDict(dict, "inversion", feparm.inversion);
110         PutToDict(dict, "fec_inner", feparm.fec);
111         PutToDict(dict, "modulation", feparm.modulation);
112         PutToDict(dict, "polarization", feparm.polarisation);
113         if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
114         {
115                 PutToDict(dict, "rolloff", feparm.rolloff);
116                 PutToDict(dict, "pilot", feparm.pilot);
117         }
118         PutToDict(dict, "system", feparm.system);
119 }
120
121 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
122 {
123         PutToDict(dict, "tuner_type", "DVB-T");
124         PutToDict(dict, "frequency", feparm.frequency);
125         PutToDict(dict, "bandwidth", feparm.bandwidth);
126         PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
127         PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
128         PutToDict(dict, "constellation", feparm.modulation);
129         PutToDict(dict, "transmission_mode", feparm.transmission_mode);
130         PutToDict(dict, "guard_interval", feparm.guard_interval);
131         PutToDict(dict, "hierarchy_information", feparm.hierarchy);
132         PutToDict(dict, "inversion", feparm.inversion);
133 }
134
135 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
136 {
137         PutToDict(dict, "tuner_type", "DVB-C");
138         PutToDict(dict, "frequency", feparm.frequency);
139         PutToDict(dict, "symbol_rate", feparm.symbol_rate);
140         PutToDict(dict, "modulation", feparm.modulation);
141         PutToDict(dict, "inversion", feparm.inversion);
142         PutToDict(dict, "fec_inner", feparm.fec_inner);
143 }
144
145 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
146 {
147         if (r.type == eServiceReference::idDVB)
148         {
149                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
150                 switch(what)
151                 {
152                         case iServiceInformation::sTransponderData:
153                         {
154                                 ePtr<eDVBResourceManager> res;
155                                 if (!eDVBResourceManager::getInstance(res))
156                                 {
157                                         ePtr<iDVBChannelList> db;
158                                         if (!res->getChannelList(db))
159                                         {
160                                                 eDVBChannelID chid;
161                                                 ref.getChannelID(chid);
162                                                 ePtr<iDVBFrontendParameters> feparm;
163                                                 if (!db->getChannelFrontendData(chid, feparm))
164                                                 {
165                                                         int system;
166                                                         if (!feparm->getSystem(system))
167                                                         {
168                                                                 ePyObject dict = PyDict_New();
169                                                                 switch(system)
170                                                                 {
171                                                                         case iDVBFrontend::feSatellite:
172                                                                         {
173                                                                                 eDVBFrontendParametersSatellite s;
174                                                                                 feparm->getDVBS(s);
175                                                                                 PutSatelliteDataToDict(dict, s);
176                                                                                 break;
177                                                                         }
178                                                                         case iDVBFrontend::feTerrestrial:
179                                                                         {
180                                                                                 eDVBFrontendParametersTerrestrial t;
181                                                                                 feparm->getDVBT(t);
182                                                                                 PutTerrestrialDataToDict(dict, t);
183                                                                                 break;
184                                                                         }
185                                                                         case iDVBFrontend::feCable:
186                                                                         {
187                                                                                 eDVBFrontendParametersCable c;
188                                                                                 feparm->getDVBC(c);
189                                                                                 PutCableDataToDict(dict, c);
190                                                                                 break;
191                                                                         }
192                                                                         default:
193                                                                                 eDebug("unknown frontend type %d", system);
194                                                                                 Py_DECREF(dict);
195                                                                                 break;
196                                                                 }
197                                                                 return dict;
198                                                         }
199                                                 }
200                                         }
201                                 }
202                         }
203                 }
204         }
205         Py_RETURN_NONE;
206 }
207
208 DEFINE_REF(eStaticServiceDVBBouquetInformation);
209
210 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
211 {
212         ePtr<iDVBChannelList> db;
213         ePtr<eDVBResourceManager> res;
214
215         int err;
216         if ((err = eDVBResourceManager::getInstance(res)) != 0)
217         {
218                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
219                 return err;
220         }
221         if ((err = res->getChannelList(db)) != 0)
222         {
223                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
224                 return err;
225         }
226
227         eBouquet *bouquet=0;
228         if ((err = db->getBouquet(ref, bouquet)) != 0)
229         {
230                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
231                 return -1;
232         }
233
234         if ( bouquet && bouquet->m_bouquet_name.length() )
235         {
236                 name = bouquet->m_bouquet_name;
237                 return 0;
238         }
239         else
240                 return -1;
241 }
242
243 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
244 {
245         if (ref.flags & eServiceReference::isGroup)
246         {
247                 ePtr<iDVBChannelList> db;
248                 ePtr<eDVBResourceManager> res;
249
250                 if (eDVBResourceManager::getInstance(res))
251                 {
252                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
253                         return 0;
254                 }
255
256                 if (res->getChannelList(db))
257                 {
258                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
259                         return 0;
260                 }
261
262                 eBouquet *bouquet=0;
263                 if (db->getBouquet(ref, bouquet))
264                 {
265                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
266                         return 0;
267                 }
268
269                 int prio_order = eDVBFrontend::getTypePriorityOrder();
270                 int cur=0;
271                 eDVBChannelID chid, chid_ignore;
272                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
273                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
274                 {
275                         static unsigned char prio_map[6][3] = {
276                                 { 3, 2, 1 }, // -S -C -T
277                                 { 3, 1, 2 }, // -S -T -C
278                                 { 2, 3, 1 }, // -C -S -T
279                                 { 1, 3, 2 }, // -C -T -S
280                                 { 1, 2, 3 }, // -T -C -S
281                                 { 2, 1, 3 }  // -T -S -C
282                         };
283                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
284                         int tmp=res->canAllocateChannel(chid, chid_ignore, simulate);
285                         switch(tmp)
286                         {
287                                 case 0:
288                                         break;
289                                 case 30000: // cached DVB-T channel
290                                 case 1: // DVB-T frontend
291                                         tmp = prio_map[prio_order][2];
292                                         break;
293                                 case 40000: // cached DVB-C channel
294                                 case 2:
295                                         tmp = prio_map[prio_order][1];
296                                         break;
297                                 default: // DVB-S
298                                         tmp = prio_map[prio_order][0];
299                                         break;
300                         }
301                         if (tmp > cur)
302                         {
303                                 m_playable_service = *it;
304                                 cur = tmp;
305                         }
306                 }
307                 if (cur)
308                         return cur;
309         }
310         m_playable_service = eServiceReference();
311         return 0;
312 }
313
314 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
315 {
316         return -1;
317 }
318
319 #include <lib/dvb/epgcache.h>
320
321 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
322 {
323         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
324 }
325
326 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
327 {
328         DECLARE_REF(eStaticServiceDVBPVRInformation);
329         eServiceReference m_ref;
330         eDVBMetaParser m_parser;
331 public:
332         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
333         RESULT getName(const eServiceReference &ref, std::string &name);
334         int getLength(const eServiceReference &ref);
335         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
336         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
337         int getInfo(const eServiceReference &ref, int w);
338         std::string getInfoString(const eServiceReference &ref,int w);
339         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         int rdsPid = apid;
1762
1763                 /* 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 */
1764         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1765         {
1766                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1767                 if (different_pid)
1768                         rdsPid = program.audioStreams[stream].rdsPid;
1769                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1770                 {
1771                         m_rds_decoder = 0;
1772                         ePtr<iDVBDemux> data_demux;
1773                         if (!h.getDataDemux(data_demux))
1774                         {
1775                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1776                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1777                                 m_rds_decoder->start(rdsPid);
1778                         }
1779                 }
1780         }
1781
1782                         /* store new pid as default only when:
1783                                 a.) we have an entry in the service db for the current service,
1784                                 b.) we are not playing back something,
1785                                 c.) we are not selecting the default entry. (we wouldn't change 
1786                                     anything in the best case, or destroy the default setting in
1787                                     case the real default is not yet available.)
1788                         */
1789         if (m_dvb_service && ((i != -1)
1790                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1791         {
1792                 if (apidtype == eDVBAudio::aMPEG)
1793                 {
1794                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1795                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1796                 }
1797                 else if (apidtype == eDVBAudio::aAC3)
1798                 {
1799                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1800                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1801                 }
1802                 else
1803                 {
1804                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1805                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1806                 }
1807         }
1808
1809         h.resetCachedProgram();
1810
1811         return 0;
1812 }
1813
1814 int eDVBServicePlay::getCurrentChannel()
1815 {
1816         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1817 }
1818
1819 RESULT eDVBServicePlay::selectChannel(int i)
1820 {
1821         if (i < LEFT || i > RIGHT || i == STEREO)
1822                 i = -1;  // Stereo
1823         if (m_dvb_service)
1824                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1825         if (m_decoder)
1826                 m_decoder->setAudioChannel(i);
1827         return 0;
1828 }
1829
1830 std::string eDVBServicePlay::getText(int x)
1831 {
1832         if (m_rds_decoder)
1833                 switch(x)
1834                 {
1835                         case RadioText:
1836                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1837                         case RtpText:
1838                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1839                 }
1840         return "";
1841 }
1842
1843 void eDVBServicePlay::rdsDecoderEvent(int what)
1844 {
1845         switch(what)
1846         {
1847                 case eDVBRdsDecoder::RadioTextChanged:
1848                         m_event((iPlayableService*)this, evUpdatedRadioText);
1849                         break;
1850                 case eDVBRdsDecoder::RtpTextChanged:
1851                         m_event((iPlayableService*)this, evUpdatedRtpText);
1852                         break;
1853                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1854                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1855                         break;
1856                 case eDVBRdsDecoder::RecvRassSlidePic:
1857                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1858                         break;
1859         }
1860 }
1861
1862 void eDVBServicePlay::showRassSlidePicture()
1863 {
1864         if (m_rds_decoder)
1865         {
1866                 if (m_decoder)
1867                 {
1868                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1869                         if (rass_slide_pic.length())
1870                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1871                         else
1872                                 eDebug("empty filename for rass slide picture received!!");
1873                 }
1874                 else
1875                         eDebug("no MPEG Decoder to show iframes avail");
1876         }
1877         else
1878                 eDebug("showRassSlidePicture called.. but not decoder");
1879 }
1880
1881 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1882 {
1883         if (m_rds_decoder)
1884         {
1885                 if (m_decoder)
1886                 {
1887                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1888                         if (rass_interactive_pic.length())
1889                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1890                         else
1891                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1892                 }
1893                 else
1894                         eDebug("no MPEG Decoder to show iframes avail");
1895         }
1896         else
1897                 eDebug("showRassInteractivePic called.. but not decoder");
1898 }
1899
1900 ePyObject eDVBServicePlay::getRassInteractiveMask()
1901 {
1902         if (m_rds_decoder)
1903                 return m_rds_decoder->getRassPictureMask();
1904         Py_RETURN_NONE;
1905 }
1906
1907 int eDVBServiceBase::getFrontendInfo(int w)
1908 {
1909         eUsePtr<iDVBChannel> channel;
1910         if(m_service_handler.getChannel(channel))
1911                 return 0;
1912         ePtr<iDVBFrontend> fe;
1913         if(channel->getFrontend(fe))
1914                 return 0;
1915         return fe->readFrontendData(w);
1916 }
1917
1918 PyObject *eDVBServiceBase::getFrontendData()
1919 {
1920         ePyObject ret = PyDict_New();
1921         if (ret)
1922         {
1923                 eUsePtr<iDVBChannel> channel;
1924                 if(!m_service_handler.getChannel(channel))
1925                 {
1926                         ePtr<iDVBFrontend> fe;
1927                         if(!channel->getFrontend(fe))
1928                                 fe->getFrontendData(ret);
1929                 }
1930         }
1931         else
1932                 Py_RETURN_NONE;
1933         return ret;
1934 }
1935
1936 PyObject *eDVBServiceBase::getFrontendStatus()
1937 {
1938         ePyObject ret = PyDict_New();
1939         if (ret)
1940         {
1941                 eUsePtr<iDVBChannel> channel;
1942                 if(!m_service_handler.getChannel(channel))
1943                 {
1944                         ePtr<iDVBFrontend> fe;
1945                         if(!channel->getFrontend(fe))
1946                                 fe->getFrontendStatus(ret);
1947                 }
1948         }
1949         else
1950                 Py_RETURN_NONE;
1951         return ret;
1952 }
1953
1954 PyObject *eDVBServiceBase::getTransponderData(bool original)
1955 {
1956         ePyObject ret = PyDict_New();
1957         if (ret)
1958         {
1959                 eUsePtr<iDVBChannel> channel;
1960                 if(!m_service_handler.getChannel(channel))
1961                 {
1962                         ePtr<iDVBFrontend> fe;
1963                         if(!channel->getFrontend(fe))
1964                                 fe->getTransponderData(ret, original);
1965                 }
1966         }
1967         else
1968                 Py_RETURN_NONE;
1969         return ret;
1970 }
1971
1972 PyObject *eDVBServiceBase::getAll(bool original)
1973 {
1974         ePyObject ret = getTransponderData(original);
1975         if (ret != Py_None)
1976         {
1977                 eUsePtr<iDVBChannel> channel;
1978                 if(!m_service_handler.getChannel(channel))
1979                 {
1980                         ePtr<iDVBFrontend> fe;
1981                         if(!channel->getFrontend(fe))
1982                         {
1983                                 fe->getFrontendData(ret);
1984                                 fe->getFrontendStatus(ret);
1985                         }
1986                 }
1987         }
1988         return ret;
1989 }
1990
1991 int eDVBServicePlay::getNumberOfSubservices()
1992 {
1993         ePtr<eServiceEvent> evt;
1994         if (!m_event_handler.getEvent(evt, 0))
1995                 return evt->getNumOfLinkageServices();
1996         return 0;
1997 }
1998
1999 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2000 {
2001         ePtr<eServiceEvent> evt;
2002         if (!m_event_handler.getEvent(evt, 0))
2003         {
2004                 if (!evt->getLinkageService(sub, m_reference, n))
2005                         return 0;
2006         }
2007         sub.type=eServiceReference::idInvalid;
2008         return -1;
2009 }
2010
2011 RESULT eDVBServicePlay::startTimeshift()
2012 {
2013         ePtr<iDVBDemux> demux;
2014         
2015         eDebug("Start timeshift!");
2016         
2017         if (m_timeshift_enabled)
2018                 return -1;
2019         
2020                 /* start recording with the data demux. */
2021         if (m_service_handler.getDataDemux(demux))
2022                 return -2;
2023
2024         demux->createTSRecorder(m_record);
2025         if (!m_record)
2026                 return -3;
2027
2028         std::string tspath;
2029         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2030                 eDebug("could not query ts path");
2031                 return -5;
2032         }
2033         tspath.append("/timeshift.XXXXXX");
2034         char* templ;
2035         templ = new char[tspath.length() + 1];
2036         strcpy(templ, tspath.c_str());
2037
2038         m_timeshift_fd = mkstemp(templ);
2039         m_timeshift_file = std::string(templ);
2040
2041         eDebug("recording to %s", templ);
2042
2043         delete [] templ;
2044
2045         if (m_timeshift_fd < 0)
2046         {
2047                 m_record = 0;
2048                 return -4;
2049         }
2050                 
2051         m_record->setTargetFD(m_timeshift_fd);
2052
2053         m_timeshift_enabled = 1;
2054         
2055         updateTimeshiftPids();
2056         m_record->start();
2057
2058         return 0;
2059 }
2060
2061 RESULT eDVBServicePlay::stopTimeshift()
2062 {
2063         if (!m_timeshift_enabled)
2064                 return -1;
2065         
2066         switchToLive();
2067         
2068         m_timeshift_enabled = 0;
2069         
2070         m_record->stop();
2071         m_record = 0;
2072         
2073         close(m_timeshift_fd);
2074         eDebug("remove timeshift file");
2075         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2076         
2077         return 0;
2078 }
2079
2080 int eDVBServicePlay::isTimeshiftActive()
2081 {
2082         return m_timeshift_enabled && m_timeshift_active;
2083 }
2084
2085 RESULT eDVBServicePlay::activateTimeshift()
2086 {
2087         if (!m_timeshift_enabled)
2088                 return -1;
2089         
2090         if (!m_timeshift_active)
2091         {
2092                 switchToTimeshift();
2093                 return 0;
2094         }
2095         
2096         return -2;
2097 }
2098
2099 PyObject *eDVBServicePlay::getCutList()
2100 {
2101         ePyObject list = PyList_New(0);
2102         
2103         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2104         {
2105                 ePyObject tuple = PyTuple_New(2);
2106                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2107                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2108                 PyList_Append(list, tuple);
2109                 Py_DECREF(tuple);
2110         }
2111         
2112         return list;
2113 }
2114
2115 void eDVBServicePlay::setCutList(ePyObject list)
2116 {
2117         if (!PyList_Check(list))
2118                 return;
2119         int size = PyList_Size(list);
2120         int i;
2121         
2122         m_cue_entries.clear();
2123         
2124         for (i=0; i<size; ++i)
2125         {
2126                 ePyObject tuple = PyList_GET_ITEM(list, i);
2127                 if (!PyTuple_Check(tuple))
2128                 {
2129                         eDebug("non-tuple in cutlist");
2130                         continue;
2131                 }
2132                 if (PyTuple_Size(tuple) != 2)
2133                 {
2134                         eDebug("cutlist entries need to be a 2-tuple");
2135                         continue;
2136                 }
2137                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2138                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2139                 {
2140                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2141                         continue;
2142                 }
2143                 pts_t pts = PyLong_AsLongLong(ppts);
2144                 int type = PyInt_AsLong(ptype);
2145                 m_cue_entries.insert(cueEntry(pts, type));
2146                 eDebug("adding %08llx, %d", pts, type);
2147         }
2148         m_cuesheet_changed = 1;
2149         
2150         cutlistToCuesheet();
2151         m_event((iPlayableService*)this, evCuesheetChanged);
2152 }
2153
2154 void eDVBServicePlay::setCutListEnable(int enable)
2155 {
2156         m_cutlist_enabled = enable;
2157         cutlistToCuesheet();
2158 }
2159
2160 void eDVBServicePlay::updateTimeshiftPids()
2161 {
2162         if (!m_record)
2163                 return;
2164         
2165         eDVBServicePMTHandler::program program;
2166         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2167
2168         if (h.getProgramInfo(program))
2169                 return;
2170         else
2171         {
2172                 std::set<int> pids_to_record;
2173                 pids_to_record.insert(0); // PAT
2174                 if (program.pmtPid != -1)
2175                         pids_to_record.insert(program.pmtPid); // PMT
2176
2177                 if (program.textPid != -1)
2178                         pids_to_record.insert(program.textPid); // Videotext
2179
2180                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2181                         i(program.videoStreams.begin()); 
2182                         i != program.videoStreams.end(); ++i)
2183                         pids_to_record.insert(i->pid);
2184
2185                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2186                         i(program.audioStreams.begin()); 
2187                         i != program.audioStreams.end(); ++i)
2188                                 pids_to_record.insert(i->pid);
2189
2190                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2191                         i(program.subtitleStreams.begin());
2192                         i != program.subtitleStreams.end(); ++i)
2193                                 pids_to_record.insert(i->pid);
2194
2195                 std::set<int> new_pids, obsolete_pids;
2196                 
2197                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2198                                 m_pids_active.begin(), m_pids_active.end(),
2199                                 std::inserter(new_pids, new_pids.begin()));
2200                 
2201                 std::set_difference(
2202                                 m_pids_active.begin(), m_pids_active.end(),
2203                                 pids_to_record.begin(), pids_to_record.end(), 
2204                                 std::inserter(new_pids, new_pids.begin())
2205                                 );
2206
2207                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2208                         m_record->addPID(*i);
2209
2210                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2211                         m_record->removePID(*i);
2212         }
2213 }
2214
2215 void eDVBServicePlay::switchToLive()
2216 {
2217         if (!m_timeshift_active)
2218                 return;
2219         
2220         eDebug("SwitchToLive");
2221         
2222         m_cue = 0;
2223         m_decoder = 0;
2224         m_decode_demux = 0;
2225         m_teletext_parser = 0;
2226         m_rds_decoder = 0;
2227         m_subtitle_parser = 0;
2228         m_new_dvb_subtitle_page_connection = 0;
2229         m_new_subtitle_page_connection = 0;
2230         m_rds_decoder_event_connection = 0;
2231         m_video_event_connection = 0;
2232         m_is_paused = m_skipmode = 0; /* not supported in live mode */
2233
2234                 /* free the timeshift service handler, we need the resources */
2235         m_service_handler_timeshift.free();
2236         m_timeshift_active = 0;
2237         m_timeshift_changed = 1;
2238
2239         m_event((iPlayableService*)this, evSeekableStatusChanged);
2240
2241         updateDecoder();
2242 }
2243
2244 void eDVBServicePlay::switchToTimeshift()
2245 {
2246         if (m_timeshift_active)
2247                 return;
2248
2249         m_decode_demux = 0;
2250         m_decoder = 0;
2251         m_teletext_parser = 0;
2252         m_rds_decoder = 0;
2253         m_subtitle_parser = 0;
2254         m_new_subtitle_page_connection = 0;
2255         m_new_dvb_subtitle_page_connection = 0;
2256         m_rds_decoder_event_connection = 0;
2257         m_video_event_connection = 0;
2258
2259         m_timeshift_active = 1;
2260         m_timeshift_changed = 1;
2261
2262         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2263         r.path = m_timeshift_file;
2264
2265         m_cue = new eCueSheet();
2266         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2267
2268         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2269         pause();
2270         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2271         
2272         m_event((iPlayableService*)this, evSeekableStatusChanged);
2273 }
2274
2275 void eDVBServicePlay::updateDecoder()
2276 {
2277         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2278
2279         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2280
2281         eDVBServicePMTHandler::program program;
2282         if (h.getProgramInfo(program))
2283                 eDebug("getting program info failed.");
2284         else
2285         {
2286                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2287                 if (!program.videoStreams.empty())
2288                 {
2289                         eDebugNoNewLine(" (");
2290                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2291                                 i(program.videoStreams.begin());
2292                                 i != program.videoStreams.end(); ++i)
2293                         {
2294                                 if (vpid == -1)
2295                                 {
2296                                         vpid = i->pid;
2297                                         vpidtype = i->type;
2298                                 }
2299                                 if (i != program.videoStreams.begin())
2300                                         eDebugNoNewLine(", ");
2301                                 eDebugNoNewLine("%04x", i->pid);
2302                         }
2303                         eDebugNoNewLine(")");
2304                 }
2305                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2306                 if (!program.audioStreams.empty())
2307                 {
2308                         eDebugNoNewLine(" (");
2309                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2310                                 i(program.audioStreams.begin());
2311                                 i != program.audioStreams.end(); ++i)
2312                         {
2313                                 if (i != program.audioStreams.begin())
2314                                         eDebugNoNewLine(", ");
2315                                 eDebugNoNewLine("%04x", i->pid);
2316                         }
2317                         eDebugNoNewLine(")");
2318                 }
2319                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2320                 pcrpid = program.pcrPid;
2321                 eDebug(", and the text pid is %04x", program.textPid);
2322                 tpid = program.textPid;
2323         }
2324
2325         if (!m_decoder)
2326         {
2327                 h.getDecodeDemux(m_decode_demux);
2328                 if (m_timeshift_changed)
2329                         m_decoder = 0;
2330                 if (m_decode_demux)
2331                 {
2332                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2333                         if (m_decoder)
2334                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2335                         if (m_is_primary)
2336                         {
2337                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2338                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2339                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2340                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2341                                 if (m_timeshift_changed)
2342                                 {
2343                                         ePyObject subs = getCachedSubtitle();
2344                                         if (subs != Py_None)
2345                                         {
2346                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2347                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2348                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2349                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2350                                                 if (type == 0) // dvb
2351                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2352                                                 else if (type == 1) // ttx
2353                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2354                                         }
2355                                         Py_DECREF(subs);
2356                                 }
2357                         }
2358                         m_decoder->play(); /* pids will be set later */
2359                 }
2360                 if (m_cue)
2361                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2362         }
2363
2364         m_timeshift_changed = 0;
2365
2366         if (m_decoder)
2367         {
2368                 if (m_dvb_service)
2369                 {
2370                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2371                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2372                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2373                 }
2374                 else // subservice
2375                 {
2376                         eServiceReferenceDVB ref;
2377                         m_service_handler.getServiceReference(ref);
2378                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2379                         if (!parent)
2380                                 parent = ref;
2381                         if (parent)
2382                         {
2383                                 ePtr<eDVBResourceManager> res_mgr;
2384                                 if (!eDVBResourceManager::getInstance(res_mgr))
2385                                 {
2386                                         ePtr<iDVBChannelList> db;
2387                                         if (!res_mgr->getChannelList(db))
2388                                         {
2389                                                 ePtr<eDVBService> origService;
2390                                                 if (!db->getService(parent, origService))
2391                                                 {
2392                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2393                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2394                                                 }
2395                                         }
2396                                 }
2397                         }
2398                 }
2399
2400                 std::string config_delay;
2401                 int config_delay_int = 0;
2402                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2403                         config_delay_int = atoi(config_delay.c_str());
2404                 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2405
2406                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2407                         config_delay_int = atoi(config_delay.c_str());
2408                 else
2409                         config_delay_int = 0;
2410                 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2411
2412                 m_decoder->setVideoPID(vpid, vpidtype);
2413                 selectAudioStream();
2414
2415                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2416                         m_decoder->setSyncPCR(pcrpid);
2417                 else
2418                         m_decoder->setSyncPCR(-1);
2419
2420                 if (m_is_primary)
2421                 {
2422                         m_decoder->setTextPID(tpid);
2423                         m_teletext_parser->start(program.textPid);
2424                 }
2425
2426                 if (vpid > 0 && vpid < 0x2000)
2427                         ;
2428                 else
2429                 {
2430                         std::string radio_pic;
2431                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2432                                 m_decoder->setRadioPic(radio_pic);
2433                 }
2434
2435                 m_decoder->set();
2436                 m_decoder->setAudioChannel(achannel);
2437
2438                 /* don't worry about non-existing services, nor pvr services */
2439                 if (m_dvb_service)
2440                 {
2441                                 /* (audio pid will be set in selectAudioTrack */
2442                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2443                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2444                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2445                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2446                 }
2447         }
2448         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2449 }
2450
2451 void eDVBServicePlay::loadCuesheet()
2452 {
2453         std::string filename = m_reference.path + ".cuts";
2454         
2455         m_cue_entries.clear();
2456
2457         FILE *f = fopen(filename.c_str(), "rb");
2458
2459         if (f)
2460         {
2461                 eDebug("loading cuts..");
2462                 while (1)
2463                 {
2464                         unsigned long long where;
2465                         unsigned int what;
2466                         
2467                         if (!fread(&where, sizeof(where), 1, f))
2468                                 break;
2469                         if (!fread(&what, sizeof(what), 1, f))
2470                                 break;
2471                         
2472 #if BYTE_ORDER == LITTLE_ENDIAN
2473                         where = bswap_64(where);
2474 #endif
2475                         what = ntohl(what);
2476                         
2477                         if (what > 3)
2478                                 break;
2479                         
2480                         m_cue_entries.insert(cueEntry(where, what));
2481                 }
2482                 fclose(f);
2483                 eDebug("%d entries", m_cue_entries.size());
2484         } else
2485                 eDebug("cutfile not found!");
2486         
2487         m_cuesheet_changed = 0;
2488         cutlistToCuesheet();
2489         m_event((iPlayableService*)this, evCuesheetChanged);
2490 }
2491
2492 void eDVBServicePlay::saveCuesheet()
2493 {
2494         std::string filename = m_reference.path + ".cuts";
2495         
2496         FILE *f = fopen(filename.c_str(), "wb");
2497
2498         if (f)
2499         {
2500                 unsigned long long where;
2501                 int what;
2502
2503                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2504                 {
2505 #if BYTE_ORDER == BIG_ENDIAN
2506                         where = i->where;
2507 #else
2508                         where = bswap_64(i->where);
2509 #endif
2510                         what = htonl(i->what);
2511                         fwrite(&where, sizeof(where), 1, f);
2512                         fwrite(&what, sizeof(what), 1, f);
2513                         
2514                 }
2515                 fclose(f);
2516         }
2517         
2518         m_cuesheet_changed = 0;
2519 }
2520
2521 void eDVBServicePlay::cutlistToCuesheet()
2522 {
2523         if (!m_cue)
2524         {
2525                 eDebug("no cue sheet");
2526                 return;
2527         }       
2528         m_cue->clear();
2529         
2530         if (!m_cutlist_enabled)
2531         {
2532                 m_cue->commitSpans();
2533                 eDebug("cutlists were disabled");
2534                 return;
2535         }
2536
2537         pts_t in = 0, out = 0, length = 0;
2538         
2539         getLength(length);
2540                 
2541         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2542         
2543         int have_any_span = 0;
2544         
2545         while (1)
2546         {
2547                 if (i == m_cue_entries.end())
2548                 {
2549                         if (!have_any_span)
2550                                 break;
2551                         out = length;
2552                 } else {
2553                         if (i->what == 0) /* in */
2554                         {
2555                                 in = i++->where;
2556                                 continue;
2557                         } else if (i->what == 1) /* out */
2558                                 out = i++->where;
2559                         else /* mark (2) or last play position (3) */
2560                         {
2561                                 i++;
2562                                 continue;
2563                         }
2564                 }
2565                 
2566                 if (in < 0)
2567                         in = 0;
2568                 if (out < 0)
2569                         out = 0;
2570                 if (in > length)
2571                         in = length;
2572                 if (out > length)
2573                         out = length;
2574                 
2575                 if (in < out)
2576                 {
2577                         have_any_span = 1;
2578                         m_cue->addSourceSpan(in, out);
2579                 }
2580                 
2581                 in = length;
2582                 
2583                 if (i == m_cue_entries.end())
2584                         break;
2585         }
2586         m_cue->commitSpans();
2587 }
2588
2589 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2590 {
2591         if (m_subtitle_widget)
2592                 disableSubtitles(parent);
2593
2594         ePyObject entry;
2595         int tuplesize = PyTuple_Size(tuple);
2596         int type = 0;
2597
2598         if (!PyTuple_Check(tuple))
2599                 goto error_out;
2600
2601         if (tuplesize < 1)
2602                 goto error_out;
2603
2604         entry = PyTuple_GET_ITEM(tuple, 0);
2605
2606         if (!PyInt_Check(entry))
2607                 goto error_out;
2608
2609         type = PyInt_AsLong(entry);
2610
2611         if (type == 1)  // teletext subtitles
2612         {
2613                 int page, magazine, pid;
2614                 if (tuplesize < 4)
2615                         goto error_out;
2616
2617                 if (!m_teletext_parser)
2618                 {
2619                         eDebug("enable teletext subtitles.. no parser !!!");
2620                         return -1;
2621                 }
2622
2623                 entry = PyTuple_GET_ITEM(tuple, 1);
2624                 if (!PyInt_Check(entry))
2625                         goto error_out;
2626                 pid = PyInt_AsLong(entry);
2627
2628                 entry = PyTuple_GET_ITEM(tuple, 2);
2629                 if (!PyInt_Check(entry))
2630                         goto error_out;
2631                 page = PyInt_AsLong(entry);
2632
2633                 entry = PyTuple_GET_ITEM(tuple, 3);
2634                 if (!PyInt_Check(entry))
2635                         goto error_out;
2636                 magazine = PyInt_AsLong(entry);
2637
2638                 m_subtitle_widget = new eSubtitleWidget(parent);
2639                 m_subtitle_widget->resize(parent->size()); /* full size */
2640                 m_teletext_parser->setPageAndMagazine(page, magazine);
2641                 if (m_dvb_service)
2642                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2643         }
2644         else if (type == 0)
2645         {
2646                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2647                 if (!m_subtitle_parser)
2648                 {
2649                         eDebug("enable dvb subtitles.. no parser !!!");
2650                         return -1;
2651                 }
2652                 if (tuplesize < 4)
2653                         goto error_out;
2654
2655                 entry = PyTuple_GET_ITEM(tuple, 1);
2656                 if (!PyInt_Check(entry))
2657                         goto error_out;
2658                 pid = PyInt_AsLong(entry);
2659
2660                 entry = PyTuple_GET_ITEM(tuple, 2);
2661                 if (!PyInt_Check(entry))
2662                         goto error_out;
2663                 composition_page_id = PyInt_AsLong(entry);
2664
2665                 entry = PyTuple_GET_ITEM(tuple, 3);
2666                 if (!PyInt_Check(entry))
2667                         goto error_out;
2668                 ancillary_page_id = PyInt_AsLong(entry);
2669
2670                 m_subtitle_widget = new eSubtitleWidget(parent);
2671                 m_subtitle_widget->resize(parent->size()); /* full size */
2672                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2673                 if (m_dvb_service)
2674                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2675         }
2676         else
2677                 goto error_out;
2678         return 0;
2679 error_out:
2680         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2681                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2682                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2683         return -1;
2684 }
2685
2686 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2687 {
2688         delete m_subtitle_widget;
2689         m_subtitle_widget = 0;
2690         if (m_subtitle_parser)
2691         {
2692                 m_subtitle_parser->stop();
2693                 m_dvb_subtitle_pages.clear();
2694         }
2695         if (m_teletext_parser)
2696         {
2697                 m_teletext_parser->setPageAndMagazine(-1, -1);
2698                 m_subtitle_pages.clear();
2699         }
2700         if (m_dvb_service)
2701                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2702         return 0;
2703 }
2704
2705 PyObject *eDVBServicePlay::getCachedSubtitle()
2706 {
2707         if (m_dvb_service)
2708         {
2709                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2710                 if (tmp != -1)
2711                 {
2712                         unsigned int data = (unsigned int)tmp;
2713                         int pid = (data&0xFFFF0000)>>16;
2714                         ePyObject tuple = PyTuple_New(4);
2715                         eDVBServicePMTHandler::program program;
2716                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2717                         if (!h.getProgramInfo(program))
2718                         {
2719                                 if (program.textPid==pid) // teletext
2720                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2721                                 else
2722                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2723                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2724                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2725                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2726                                 return tuple;
2727                         }
2728                 }
2729         }
2730         Py_RETURN_NONE;
2731 }
2732
2733 PyObject *eDVBServicePlay::getSubtitleList()
2734 {
2735         if (!m_teletext_parser)
2736                 Py_RETURN_NONE;
2737         
2738         ePyObject l = PyList_New(0);
2739         std::set<int> added_ttx_pages;
2740
2741         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2742                 m_teletext_parser->m_found_subtitle_pages;
2743
2744         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2745         eDVBServicePMTHandler::program program;
2746         if (h.getProgramInfo(program))
2747                 eDebug("getting program info failed.");
2748         else
2749         {
2750                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2751                         it != program.subtitleStreams.end(); ++it)
2752                 {
2753                         switch(it->subtitling_type)
2754                         {
2755                                 case 0x01: // ebu teletext subtitles
2756                                 {
2757                                         int page_number = it->teletext_page_number & 0xFF;
2758                                         int magazine_number = it->teletext_magazine_number & 7;
2759                                         int hash = magazine_number << 8 | page_number;
2760                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2761                                         {
2762                                                 ePyObject tuple = PyTuple_New(5);
2763                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2764                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2765                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2766                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2767                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2768                                                 PyList_Append(l, tuple);
2769                                                 Py_DECREF(tuple);
2770                                                 added_ttx_pages.insert(hash);
2771                                         }
2772                                         break;
2773                                 }
2774                                 case 0x10 ... 0x13:
2775                                 case 0x20 ... 0x23: // dvb subtitles
2776                                 {
2777                                         ePyObject tuple = PyTuple_New(5);
2778                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2779                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2780                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2781                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2782                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2783                                         PyList_Insert(l, 0, tuple);
2784                                         Py_DECREF(tuple);
2785                                         break;
2786                                 }
2787                         }
2788                 }
2789         }
2790
2791         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2792                 it != subs.end(); ++it)
2793         {
2794                 int page_number = it->teletext_page_number & 0xFF;
2795                 int magazine_number = it->teletext_magazine_number & 7;
2796                 int hash = magazine_number << 8 | page_number;
2797                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2798                 {
2799                         ePyObject tuple = PyTuple_New(5);
2800                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2801                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2802                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2803                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2804                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2805                         PyList_Append(l, tuple);
2806                         Py_DECREF(tuple);
2807                 }
2808         }
2809
2810         return l;
2811 }
2812
2813 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2814 {
2815         if (m_subtitle_widget)
2816         {
2817                 pts_t pos = 0;
2818                 if (m_decoder)
2819                         m_decoder->getPTS(0, pos);
2820                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2821                 m_subtitle_pages.push_back(page);
2822                 checkSubtitleTiming();
2823         }
2824 }
2825
2826 void eDVBServicePlay::checkSubtitleTiming()
2827 {
2828         eDebug("checkSubtitleTiming");
2829         if (!m_subtitle_widget)
2830                 return;
2831         while (1)
2832         {
2833                 enum { TELETEXT, DVB } type;
2834                 eDVBTeletextSubtitlePage page;
2835                 eDVBSubtitlePage dvb_page;
2836                 pts_t show_time;
2837                 if (!m_subtitle_pages.empty())
2838                 {
2839                         page = m_subtitle_pages.front();
2840                         type = TELETEXT;
2841                         show_time = page.m_pts;
2842                 }
2843                 else if (!m_dvb_subtitle_pages.empty())
2844                 {
2845                         dvb_page = m_dvb_subtitle_pages.front();
2846                         type = DVB;
2847                         show_time = dvb_page.m_show_time;
2848                 }
2849                 else
2850                         return;
2851         
2852                 pts_t pos = 0;
2853         
2854                 if (m_decoder)
2855                         m_decoder->getPTS(0, pos);
2856
2857                 eDebug("%lld %lld", pos, show_time);
2858                 int diff = show_time - pos;
2859                 if (type == TELETEXT && !page.m_have_pts)
2860                 {
2861                         eDebug("ttx subtitle page without pts... immediate show");
2862                         diff = 0;
2863                 }
2864                 if (diff < 0)
2865                 {
2866                         eDebug("[late (%d ms)]", -diff / 90);
2867                         diff = 0;
2868                 }
2869                 if (abs(diff) > 1800000)
2870                 {
2871                         eDebug("[invalid]... immediate show!");
2872                         diff = 0;
2873                 }
2874                 if ((diff/90)<20)
2875                 {
2876                         if (type == TELETEXT)
2877                         {
2878                                 eDebug("display teletext subtitle page %lld", show_time);
2879                                 m_subtitle_widget->setPage(page);
2880                                 m_subtitle_pages.pop_front();
2881                         }
2882                         else
2883                         {
2884                                 eDebug("display dvb subtitle Page %lld", show_time);
2885                                 m_subtitle_widget->setPage(dvb_page);
2886                                 m_dvb_subtitle_pages.pop_front();
2887                         }
2888                 } else
2889                 {
2890                         eDebug("start subtitle delay %d", diff / 90);
2891                         m_subtitle_sync_timer->start(diff / 90, 1);
2892                         break;
2893                 }
2894         }
2895 }
2896
2897 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2898 {
2899         if (m_subtitle_widget)
2900         {
2901                 pts_t pos = 0;
2902                 if (m_decoder)
2903                         m_decoder->getPTS(0, pos);
2904                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2905                 m_dvb_subtitle_pages.push_back(p);
2906                 checkSubtitleTiming();
2907         }
2908 }
2909
2910 int eDVBServicePlay::getAC3Delay()
2911 {
2912         if (m_dvb_service)
2913                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2914         else if (m_decoder)
2915                 return m_decoder->getAC3Delay();
2916         else
2917                 return 0;
2918 }
2919
2920 int eDVBServicePlay::getPCMDelay()
2921 {
2922         if (m_dvb_service)
2923                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2924         else if (m_decoder)
2925                 return m_decoder->getPCMDelay();
2926         else
2927                 return 0;
2928 }
2929
2930 void eDVBServicePlay::setAC3Delay(int delay)
2931 {
2932         if (m_dvb_service)
2933                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2934         if (m_decoder)
2935                 m_decoder->setAC3Delay(delay);
2936 }
2937
2938 void eDVBServicePlay::setPCMDelay(int delay)
2939 {
2940         if (m_dvb_service)
2941                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2942         if (m_decoder)
2943                 m_decoder->setPCMDelay(delay);
2944 }
2945
2946 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2947 {
2948         switch(event.type) {
2949                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2950                         m_event((iPlayableService*)this, evVideoSizeChanged);
2951                         break;
2952                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2953                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2954                         break;
2955                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2956                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2957                         break;
2958                 default:
2959                         break;
2960         }
2961 }
2962
2963 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2964 {
2965         ptr = this;
2966         return 0;
2967 }
2968
2969 PyObject *eDVBServicePlay::getStreamingData()
2970 {
2971         eDVBServicePMTHandler::program program;
2972         if (m_service_handler.getProgramInfo(program))
2973         {
2974                 Py_RETURN_NONE;
2975         }
2976
2977         ePyObject r = program.createPythonObject();
2978         ePtr<iDVBDemux> demux;
2979         if (!m_service_handler.getDataDemux(demux))
2980         {
2981                 uint8_t demux_id;
2982                 if (!demux->getCADemuxID(demux_id))
2983                         PutToDict(r, "demux", demux_id);
2984         }
2985
2986         return r;
2987 }
2988
2989
2990 DEFINE_REF(eDVBServicePlay)
2991
2992 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2993 {
2994         switch (w)
2995         {
2996         case iServiceInformation::sTransponderData:
2997                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2998         default:
2999                 break;
3000         }
3001         return iStaticServiceInformation::getInfoObject(ref, w);
3002 }
3003
3004 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");