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