get audio / video pid from pid cache (for serviceinfo dialog)
[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_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
2213                 /* free the timeshift service handler, we need the resources */
2214         m_service_handler_timeshift.free();
2215         m_timeshift_active = 0;
2216
2217         m_event((iPlayableService*)this, evSeekableStatusChanged);
2218
2219         updateDecoder();
2220 }
2221
2222 void eDVBServicePlay::switchToTimeshift()
2223 {
2224         if (m_timeshift_active)
2225                 return;
2226
2227         m_decode_demux = 0;
2228         m_decoder = 0;
2229         m_teletext_parser = 0;
2230         m_rds_decoder = 0;
2231         m_subtitle_parser = 0;
2232         m_new_subtitle_page_connection = 0;
2233         m_new_dvb_subtitle_page_connection = 0;
2234         m_rds_decoder_event_connection = 0;
2235         m_video_event_connection = 0;
2236
2237         m_timeshift_active = 1;
2238
2239         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2240         r.path = m_timeshift_file;
2241
2242         m_cue = new eCueSheet();
2243         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2244
2245         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2246         pause();
2247         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2248         
2249         m_event((iPlayableService*)this, evSeekableStatusChanged);
2250 }
2251
2252 void eDVBServicePlay::updateDecoder()
2253 {
2254         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2255
2256         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2257
2258         eDVBServicePMTHandler::program program;
2259         if (h.getProgramInfo(program))
2260                 eDebug("getting program info failed.");
2261         else
2262         {
2263                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2264                 if (!program.videoStreams.empty())
2265                 {
2266                         eDebugNoNewLine(" (");
2267                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2268                                 i(program.videoStreams.begin());
2269                                 i != program.videoStreams.end(); ++i)
2270                         {
2271                                 if (vpid == -1)
2272                                 {
2273                                         vpid = i->pid;
2274                                         vpidtype = i->type;
2275                                 }
2276                                 if (i != program.videoStreams.begin())
2277                                         eDebugNoNewLine(", ");
2278                                 eDebugNoNewLine("%04x", i->pid);
2279                         }
2280                         eDebugNoNewLine(")");
2281                 }
2282                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2283                 if (!program.audioStreams.empty())
2284                 {
2285                         eDebugNoNewLine(" (");
2286                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2287                                 i(program.audioStreams.begin());
2288                                 i != program.audioStreams.end(); ++i)
2289                         {
2290                                 if (i != program.audioStreams.begin())
2291                                         eDebugNoNewLine(", ");
2292                                 eDebugNoNewLine("%04x", i->pid);
2293                         }
2294                         eDebugNoNewLine(")");
2295                 }
2296                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2297                 pcrpid = program.pcrPid;
2298                 eDebug(", and the text pid is %04x", program.textPid);
2299                 tpid = program.textPid;
2300         }
2301
2302         if (!m_decoder)
2303         {
2304                 h.getDecodeDemux(m_decode_demux);
2305                 if (m_decode_demux)
2306                 {
2307                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2308                         if (m_decoder)
2309                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2310                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2311                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2312                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2313                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2314                 } else
2315                 {
2316                         m_teletext_parser = 0;
2317                         m_subtitle_parser = 0;
2318                 }
2319
2320                 if (m_cue)
2321                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2322         }
2323
2324         if (m_decoder)
2325         {
2326                 if (m_dvb_service)
2327                 {
2328                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2329                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2330                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2331                 }
2332                 else // subservice
2333                 {
2334                         eServiceReferenceDVB ref;
2335                         m_service_handler.getServiceReference(ref);
2336                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2337                         if (!parent)
2338                                 parent = ref;
2339                         if (parent)
2340                         {
2341                                 ePtr<eDVBResourceManager> res_mgr;
2342                                 if (!eDVBResourceManager::getInstance(res_mgr))
2343                                 {
2344                                         ePtr<iDVBChannelList> db;
2345                                         if (!res_mgr->getChannelList(db))
2346                                         {
2347                                                 ePtr<eDVBService> origService;
2348                                                 if (!db->getService(parent, origService))
2349                                                 {
2350                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2351                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2352                                                 }
2353                                         }
2354                                 }
2355                         }
2356                 }
2357
2358                 std::string config_delay;
2359                 int config_delay_int = 0;
2360                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2361                         config_delay_int = atoi(config_delay.c_str());
2362                 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2363
2364                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2365                         config_delay_int = atoi(config_delay.c_str());
2366                 else
2367                         config_delay_int = 0;
2368                 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2369
2370                 m_decoder->setVideoPID(vpid, vpidtype);
2371                 selectAudioStream();
2372
2373                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2374                         m_decoder->setSyncPCR(pcrpid);
2375                 else
2376                         m_decoder->setSyncPCR(-1);
2377
2378                 m_decoder->setTextPID(tpid);
2379
2380                 m_teletext_parser->start(program.textPid);
2381
2382                 if (vpid > 0 && vpid < 0x2000)
2383                         ;
2384                 else
2385                 {
2386                         std::string radio_pic;
2387                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2388                                 m_decoder->setRadioPic(radio_pic);
2389                 }
2390
2391 /*              if (!m_is_primary)
2392                         m_decoder->setTrickmode();
2393                 else */ if (m_is_paused)
2394                         m_decoder->pause();
2395                 else
2396                         m_decoder->play();
2397
2398                 m_decoder->setAudioChannel(achannel);
2399
2400                 /* don't worry about non-existing services, nor pvr services */
2401                 if (m_dvb_service)
2402                 {
2403                                 /* (audio pid will be set in selectAudioTrack */
2404                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2405                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2406                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2407                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2408                 }
2409         }
2410         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2411 }
2412
2413 void eDVBServicePlay::loadCuesheet()
2414 {
2415         std::string filename = m_reference.path + ".cuts";
2416         
2417         m_cue_entries.clear();
2418
2419         FILE *f = fopen(filename.c_str(), "rb");
2420
2421         if (f)
2422         {
2423                 eDebug("loading cuts..");
2424                 while (1)
2425                 {
2426                         unsigned long long where;
2427                         unsigned int what;
2428                         
2429                         if (!fread(&where, sizeof(where), 1, f))
2430                                 break;
2431                         if (!fread(&what, sizeof(what), 1, f))
2432                                 break;
2433                         
2434 #if BYTE_ORDER == LITTLE_ENDIAN
2435                         where = bswap_64(where);
2436 #endif
2437                         what = ntohl(what);
2438                         
2439                         if (what > 3)
2440                                 break;
2441                         
2442                         m_cue_entries.insert(cueEntry(where, what));
2443                 }
2444                 fclose(f);
2445                 eDebug("%d entries", m_cue_entries.size());
2446         } else
2447                 eDebug("cutfile not found!");
2448         
2449         m_cuesheet_changed = 0;
2450         cutlistToCuesheet();
2451         m_event((iPlayableService*)this, evCuesheetChanged);
2452 }
2453
2454 void eDVBServicePlay::saveCuesheet()
2455 {
2456         std::string filename = m_reference.path + ".cuts";
2457         
2458         FILE *f = fopen(filename.c_str(), "wb");
2459
2460         if (f)
2461         {
2462                 unsigned long long where;
2463                 int what;
2464
2465                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2466                 {
2467 #if BYTE_ORDER == BIG_ENDIAN
2468                         where = i->where;
2469 #else
2470                         where = bswap_64(i->where);
2471 #endif
2472                         what = htonl(i->what);
2473                         fwrite(&where, sizeof(where), 1, f);
2474                         fwrite(&what, sizeof(what), 1, f);
2475                         
2476                 }
2477                 fclose(f);
2478         }
2479         
2480         m_cuesheet_changed = 0;
2481 }
2482
2483 void eDVBServicePlay::cutlistToCuesheet()
2484 {
2485         if (!m_cue)
2486         {
2487                 eDebug("no cue sheet");
2488                 return;
2489         }       
2490         m_cue->clear();
2491         
2492         if (!m_cutlist_enabled)
2493         {
2494                 m_cue->commitSpans();
2495                 eDebug("cutlists were disabled");
2496                 return;
2497         }
2498
2499         pts_t in = 0, out = 0, length = 0;
2500         
2501         getLength(length);
2502                 
2503         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2504         
2505         int have_any_span = 0;
2506         
2507         while (1)
2508         {
2509                 if (i == m_cue_entries.end())
2510                 {
2511                         if (!have_any_span)
2512                                 break;
2513                         out = length;
2514                 } else {
2515                         if (i->what == 0) /* in */
2516                         {
2517                                 in = i++->where;
2518                                 continue;
2519                         } else if (i->what == 1) /* out */
2520                                 out = i++->where;
2521                         else /* mark (2) or last play position (3) */
2522                         {
2523                                 i++;
2524                                 continue;
2525                         }
2526                 }
2527                 
2528                 if (in < 0)
2529                         in = 0;
2530                 if (out < 0)
2531                         out = 0;
2532                 if (in > length)
2533                         in = length;
2534                 if (out > length)
2535                         out = length;
2536                 
2537                 if (in < out)
2538                 {
2539                         have_any_span = 1;
2540                         m_cue->addSourceSpan(in, out);
2541                 }
2542                 
2543                 in = length;
2544                 
2545                 if (i == m_cue_entries.end())
2546                         break;
2547         }
2548         m_cue->commitSpans();
2549 }
2550
2551 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2552 {
2553         if (m_subtitle_widget)
2554                 disableSubtitles(parent);
2555
2556         ePyObject entry;
2557         int tuplesize = PyTuple_Size(tuple);
2558         int type = 0;
2559
2560         if (!PyTuple_Check(tuple))
2561                 goto error_out;
2562
2563         if (tuplesize < 1)
2564                 goto error_out;
2565
2566         entry = PyTuple_GET_ITEM(tuple, 0);
2567
2568         if (!PyInt_Check(entry))
2569                 goto error_out;
2570
2571         type = PyInt_AsLong(entry);
2572
2573         if (type == 1)  // teletext subtitles
2574         {
2575                 int page, magazine, pid;
2576                 if (tuplesize < 4)
2577                         goto error_out;
2578
2579                 if (!m_teletext_parser)
2580                 {
2581                         eDebug("enable teletext subtitles.. no parser !!!");
2582                         return -1;
2583                 }
2584
2585                 entry = PyTuple_GET_ITEM(tuple, 1);
2586                 if (!PyInt_Check(entry))
2587                         goto error_out;
2588                 pid = PyInt_AsLong(entry);
2589
2590                 entry = PyTuple_GET_ITEM(tuple, 2);
2591                 if (!PyInt_Check(entry))
2592                         goto error_out;
2593                 page = PyInt_AsLong(entry);
2594
2595                 entry = PyTuple_GET_ITEM(tuple, 3);
2596                 if (!PyInt_Check(entry))
2597                         goto error_out;
2598                 magazine = PyInt_AsLong(entry);
2599
2600                 m_subtitle_widget = new eSubtitleWidget(parent);
2601                 m_subtitle_widget->resize(parent->size()); /* full size */
2602                 m_teletext_parser->setPageAndMagazine(page, magazine);
2603                 if (m_dvb_service)
2604                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2605         }
2606         else if (type == 0)
2607         {
2608                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2609                 if (!m_subtitle_parser)
2610                 {
2611                         eDebug("enable dvb subtitles.. no parser !!!");
2612                         return -1;
2613                 }
2614                 if (tuplesize < 4)
2615                         goto error_out;
2616
2617                 entry = PyTuple_GET_ITEM(tuple, 1);
2618                 if (!PyInt_Check(entry))
2619                         goto error_out;
2620                 pid = PyInt_AsLong(entry);
2621
2622                 entry = PyTuple_GET_ITEM(tuple, 2);
2623                 if (!PyInt_Check(entry))
2624                         goto error_out;
2625                 composition_page_id = PyInt_AsLong(entry);
2626
2627                 entry = PyTuple_GET_ITEM(tuple, 3);
2628                 if (!PyInt_Check(entry))
2629                         goto error_out;
2630                 ancillary_page_id = PyInt_AsLong(entry);
2631
2632                 m_subtitle_widget = new eSubtitleWidget(parent);
2633                 m_subtitle_widget->resize(parent->size()); /* full size */
2634                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2635                 if (m_dvb_service)
2636                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2637         }
2638         else
2639                 goto error_out;
2640         return 0;
2641 error_out:
2642         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2643                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2644                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2645         return -1;
2646 }
2647
2648 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2649 {
2650         delete m_subtitle_widget;
2651         m_subtitle_widget = 0;
2652         if (m_subtitle_parser)
2653         {
2654                 m_subtitle_parser->stop();
2655                 m_dvb_subtitle_pages.clear();
2656         }
2657         if (m_teletext_parser)
2658         {
2659                 m_teletext_parser->setPageAndMagazine(-1, -1);
2660                 m_subtitle_pages.clear();
2661         }
2662         if (m_dvb_service)
2663                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2664         return 0;
2665 }
2666
2667 PyObject *eDVBServicePlay::getCachedSubtitle()
2668 {
2669         if (m_dvb_service)
2670         {
2671                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2672                 if (tmp != -1)
2673                 {
2674                         unsigned int data = (unsigned int)tmp;
2675                         int pid = (data&0xFFFF0000)>>16;
2676                         ePyObject tuple = PyTuple_New(4);
2677                         eDVBServicePMTHandler::program program;
2678                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2679                         if (!h.getProgramInfo(program))
2680                         {
2681                                 if (program.textPid==pid) // teletext
2682                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2683                                 else
2684                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2685                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2686                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2687                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2688                                 return tuple;
2689                         }
2690                 }
2691         }
2692         Py_RETURN_NONE;
2693 }
2694
2695 PyObject *eDVBServicePlay::getSubtitleList()
2696 {
2697         if (!m_teletext_parser)
2698                 Py_RETURN_NONE;
2699         
2700         ePyObject l = PyList_New(0);
2701         std::set<int> added_ttx_pages;
2702
2703         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2704                 m_teletext_parser->m_found_subtitle_pages;
2705
2706         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2707         eDVBServicePMTHandler::program program;
2708         if (h.getProgramInfo(program))
2709                 eDebug("getting program info failed.");
2710         else
2711         {
2712                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2713                         it != program.subtitleStreams.end(); ++it)
2714                 {
2715                         switch(it->subtitling_type)
2716                         {
2717                                 case 0x01: // ebu teletext subtitles
2718                                 {
2719                                         int page_number = it->teletext_page_number & 0xFF;
2720                                         int magazine_number = it->teletext_magazine_number & 7;
2721                                         int hash = magazine_number << 8 | page_number;
2722                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2723                                         {
2724                                                 ePyObject tuple = PyTuple_New(5);
2725                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2726                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2727                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2728                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2729                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2730                                                 PyList_Append(l, tuple);
2731                                                 Py_DECREF(tuple);
2732                                                 added_ttx_pages.insert(hash);
2733                                         }
2734                                         break;
2735                                 }
2736                                 case 0x10 ... 0x13:
2737                                 case 0x20 ... 0x23: // dvb subtitles
2738                                 {
2739                                         ePyObject tuple = PyTuple_New(5);
2740                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2741                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2742                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2743                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2744                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2745                                         PyList_Insert(l, 0, tuple);
2746                                         Py_DECREF(tuple);
2747                                         break;
2748                                 }
2749                         }
2750                 }
2751         }
2752
2753         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2754                 it != subs.end(); ++it)
2755         {
2756                 int page_number = it->teletext_page_number & 0xFF;
2757                 int magazine_number = it->teletext_magazine_number & 7;
2758                 int hash = magazine_number << 8 | page_number;
2759                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2760                 {
2761                         ePyObject tuple = PyTuple_New(5);
2762                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2763                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2764                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2765                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2766                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2767                         PyList_Append(l, tuple);
2768                         Py_DECREF(tuple);
2769                 }
2770         }
2771
2772         return l;
2773 }
2774
2775 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2776 {
2777         if (m_subtitle_widget)
2778         {
2779                 pts_t pos = 0;
2780                 if (m_decoder)
2781                         m_decoder->getPTS(0, pos);
2782                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2783                 m_subtitle_pages.push_back(page);
2784                 checkSubtitleTiming();
2785         }
2786 }
2787
2788 void eDVBServicePlay::checkSubtitleTiming()
2789 {
2790         eDebug("checkSubtitleTiming");
2791         if (!m_subtitle_widget)
2792                 return;
2793         while (1)
2794         {
2795                 enum { TELETEXT, DVB } type;
2796                 eDVBTeletextSubtitlePage page;
2797                 eDVBSubtitlePage dvb_page;
2798                 pts_t show_time;
2799                 if (!m_subtitle_pages.empty())
2800                 {
2801                         page = m_subtitle_pages.front();
2802                         type = TELETEXT;
2803                         show_time = page.m_pts;
2804                 }
2805                 else if (!m_dvb_subtitle_pages.empty())
2806                 {
2807                         dvb_page = m_dvb_subtitle_pages.front();
2808                         type = DVB;
2809                         show_time = dvb_page.m_show_time;
2810                 }
2811                 else
2812                         return;
2813         
2814                 pts_t pos = 0;
2815         
2816                 if (m_decoder)
2817                         m_decoder->getPTS(0, pos);
2818
2819                 eDebug("%lld %lld", pos, show_time);
2820                 int diff =  show_time - pos;
2821                 if (diff < 0)
2822                 {
2823                         eDebug("[late (%d ms)]", -diff / 90);
2824                         diff = 0;
2825                 }
2826 //              if (diff > 900000)
2827 //              {
2828 //                      eDebug("[invalid]");
2829 //                      diff = 0;
2830 //              }
2831         
2832                 if ((diff/90)<20)
2833                 {
2834                         if (type == TELETEXT)
2835                         {
2836                                 eDebug("display teletext subtitle page %lld", show_time);
2837                                 m_subtitle_widget->setPage(page);
2838                                 m_subtitle_pages.pop_front();
2839                         }
2840                         else
2841                         {
2842                                 eDebug("display dvb subtitle Page %lld", show_time);
2843                                 m_subtitle_widget->setPage(dvb_page);
2844                                 m_dvb_subtitle_pages.pop_front();
2845                         }
2846                 } else
2847                 {
2848                         eDebug("start subtitle delay %d", diff / 90);
2849                         m_subtitle_sync_timer->start(diff / 90, 1);
2850                         break;
2851                 }
2852         }
2853 }
2854
2855 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2856 {
2857         if (m_subtitle_widget)
2858         {
2859                 pts_t pos = 0;
2860                 if (m_decoder)
2861                         m_decoder->getPTS(0, pos);
2862                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2863                 m_dvb_subtitle_pages.push_back(p);
2864                 checkSubtitleTiming();
2865         }
2866 }
2867
2868 int eDVBServicePlay::getAC3Delay()
2869 {
2870         if (m_dvb_service)
2871                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2872         else if (m_decoder)
2873                 return m_decoder->getAC3Delay();
2874         else
2875                 return 0;
2876 }
2877
2878 int eDVBServicePlay::getPCMDelay()
2879 {
2880         if (m_dvb_service)
2881                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2882         else if (m_decoder)
2883                 return m_decoder->getPCMDelay();
2884         else
2885                 return 0;
2886 }
2887
2888 void eDVBServicePlay::setAC3Delay(int delay)
2889 {
2890         if (m_dvb_service)
2891                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2892         if (m_decoder)
2893                 m_decoder->setAC3Delay(delay);
2894 }
2895
2896 void eDVBServicePlay::setPCMDelay(int delay)
2897 {
2898         if (m_dvb_service)
2899                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2900         if (m_decoder)
2901                 m_decoder->setPCMDelay(delay);
2902 }
2903
2904 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2905 {
2906         switch(event.type) {
2907                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2908                         m_event((iPlayableService*)this, evVideoSizeChanged);
2909                         break;
2910                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2911                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2912                         break;
2913                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2914                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2915                         break;
2916                 default:
2917                         break;
2918         }
2919 }
2920
2921 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2922 {
2923         ptr = this;
2924         return 0;
2925 }
2926
2927 PyObject *eDVBServicePlay::getStreamingData()
2928 {
2929         eDVBServicePMTHandler::program program;
2930         if (m_service_handler.getProgramInfo(program))
2931         {
2932                 Py_RETURN_NONE;
2933         }
2934
2935         ePyObject r = program.createPythonObject();
2936         ePtr<iDVBDemux> demux;
2937         if (!m_service_handler.getDataDemux(demux))
2938         {
2939                 uint8_t demux_id;
2940                 if (!demux->getCADemuxID(demux_id))
2941                         PutToDict(r, "demux", demux_id);
2942         }
2943
2944         return r;
2945 }
2946
2947
2948 DEFINE_REF(eDVBServicePlay)
2949
2950 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2951 {
2952         switch (w)
2953         {
2954         case iServiceInformation::sTransponderData:
2955                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2956         default:
2957                 break;
2958         }
2959         return iStaticServiceInformation::getInfoObject(ref, w);
2960 }
2961
2962 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");