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