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