Merge branch 'master' of /home/tmbinc/enigma2-git
[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:
1562                 if (m_dvb_service)
1563                 {
1564                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1565                         if (vpid != -1)
1566                                 return vpid;
1567                 }
1568                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1569         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1570         case sAudioPID:
1571                 if (m_dvb_service)
1572                 {
1573                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1574                         if (apid != -1)
1575                                 return apid;
1576                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1577                         if (apid != -1)
1578                                 return apid;
1579                 }
1580                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1581         case sPCRPID:
1582                 if (m_dvb_service)
1583                 {
1584                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1585                         if (pcrpid != -1)
1586                                 return pcrpid;
1587                 }
1588                 if (no_program_info) return -1; return program.pcrPid;
1589         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1590         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1591         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1592         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1593         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1594         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1595         case sProvider: if (!m_dvb_service) return -1; return -2;
1596         case sServiceref: return resIsString;
1597         case sDVBState: return m_tune_state;
1598         default:
1599                 break;
1600         }
1601         return -1;
1602 }
1603
1604 std::string eDVBServicePlay::getInfoString(int w)
1605 {
1606         switch (w)
1607         {
1608         case sProvider:
1609                 if (!m_dvb_service) return "";
1610                 return m_dvb_service->m_provider_name;
1611         case sServiceref:
1612                 return m_reference.toString();
1613         default:
1614                 break;
1615         }
1616         return iServiceInformation::getInfoString(w);
1617 }
1618
1619 PyObject *eDVBServicePlay::getInfoObject(int w)
1620 {
1621         switch (w)
1622         {
1623         case sCAIDs:
1624                 return m_service_handler.getCaIds();
1625         case sTransponderData:
1626                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1627         default:
1628                 break;
1629         }
1630         return iServiceInformation::getInfoObject(w);
1631 }
1632
1633 int eDVBServicePlay::getNumberOfTracks()
1634 {
1635         eDVBServicePMTHandler::program program;
1636         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1637         if (h.getProgramInfo(program))
1638                 return 0;
1639         return program.audioStreams.size();
1640 }
1641
1642 int eDVBServicePlay::getCurrentTrack()
1643 {
1644         eDVBServicePMTHandler::program program;
1645         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1646         if (h.getProgramInfo(program))
1647                 return 0;
1648
1649         int max = program.audioStreams.size();
1650         int i;
1651
1652         for (i = 0; i < max; ++i)
1653                 if (program.audioStreams[i].pid == m_current_audio_pid)
1654                         return i;
1655
1656         return 0;
1657 }
1658
1659 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1660 {
1661         int ret = selectAudioStream(i);
1662
1663         if (m_decoder->set())
1664                 return -5;
1665
1666         return ret;
1667 }
1668
1669 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1670 {
1671         eDVBServicePMTHandler::program program;
1672         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1673
1674         if (h.getProgramInfo(program))
1675                 return -1;
1676         
1677         if (i >= program.audioStreams.size())
1678                 return -2;
1679         
1680         info.m_pid = program.audioStreams[i].pid;
1681
1682         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1683                 info.m_description = "MPEG";
1684         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1685                 info.m_description = "AC3";
1686         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1687                 info.m_description = "AAC";
1688         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1689                 info.m_description = "AAC-HE";
1690         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1691                 info.m_description = "DTS";
1692         else
1693                 info.m_description = "???";
1694
1695         if (program.audioStreams[i].component_tag != -1)
1696         {
1697                 ePtr<eServiceEvent> evt;
1698                 if (!m_event_handler.getEvent(evt, 0))
1699                 {
1700                         ePtr<eComponentData> data;
1701                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1702                                 info.m_language = data->getText();
1703                 }
1704         }
1705
1706         if (info.m_language.empty())
1707                 info.m_language = program.audioStreams[i].language_code;
1708         
1709         return 0;
1710 }
1711
1712 int eDVBServicePlay::selectAudioStream(int i)
1713 {
1714         eDVBServicePMTHandler::program program;
1715         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1716
1717         if (h.getProgramInfo(program))
1718                 return -1;
1719
1720         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1721                 return -2;
1722
1723         if (!m_decoder)
1724                 return -3;
1725
1726         int stream = i;
1727         if (stream == -1)
1728                 stream = program.defaultAudioStream;
1729
1730         int apid = -1, apidtype = -1;
1731
1732         if (((unsigned int)stream) < program.audioStreams.size())
1733         {
1734                 apid = program.audioStreams[stream].pid;
1735                 apidtype = program.audioStreams[stream].type;
1736         }
1737
1738         m_current_audio_pid = apid;
1739
1740         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1741         {
1742                 eDebug("set audio pid failed");
1743                 return -4;
1744         }
1745
1746                 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1747         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1748                 if (!m_rds_decoder)
1749                 {
1750                         ePtr<iDVBDemux> data_demux;
1751                         if (!h.getDataDemux(data_demux))
1752                         {
1753                                 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1754                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1755                         }
1756                 }
1757
1758                 /* if we decided that we need one, update the pid */
1759         if (m_rds_decoder)
1760                 m_rds_decoder->start(apid);
1761
1762                         /* store new pid as default only when:
1763                                 a.) we have an entry in the service db for the current service,
1764                                 b.) we are not playing back something,
1765                                 c.) we are not selecting the default entry. (we wouldn't change 
1766                                     anything in the best case, or destroy the default setting in
1767                                     case the real default is not yet available.)
1768                         */
1769         if (m_dvb_service && ((i != -1)
1770                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1771         {
1772                 if (apidtype == eDVBAudio::aMPEG)
1773                 {
1774                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1775                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1776                 }
1777                 else if (apidtype == eDVBAudio::aAC3)
1778                 {
1779                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1780                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1781                 }
1782                 else
1783                 {
1784                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1785                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1786                 }
1787         }
1788
1789         h.resetCachedProgram();
1790
1791         return 0;
1792 }
1793
1794 int eDVBServicePlay::getCurrentChannel()
1795 {
1796         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1797 }
1798
1799 RESULT eDVBServicePlay::selectChannel(int i)
1800 {
1801         if (i < LEFT || i > RIGHT || i == STEREO)
1802                 i = -1;  // Stereo
1803         if (m_dvb_service)
1804                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1805         if (m_decoder)
1806                 m_decoder->setAudioChannel(i);
1807         return 0;
1808 }
1809
1810 std::string eDVBServicePlay::getText(int x)
1811 {
1812         if (m_rds_decoder)
1813                 switch(x)
1814                 {
1815                         case RadioText:
1816                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1817                         case RtpText:
1818                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1819                 }
1820         return "";
1821 }
1822
1823 void eDVBServicePlay::rdsDecoderEvent(int what)
1824 {
1825         switch(what)
1826         {
1827                 case eDVBRdsDecoder::RadioTextChanged:
1828                         m_event((iPlayableService*)this, evUpdatedRadioText);
1829                         break;
1830                 case eDVBRdsDecoder::RtpTextChanged:
1831                         m_event((iPlayableService*)this, evUpdatedRtpText);
1832                         break;
1833                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1834                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1835                         break;
1836                 case eDVBRdsDecoder::RecvRassSlidePic:
1837                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1838                         break;
1839         }
1840 }
1841
1842 void eDVBServicePlay::showRassSlidePicture()
1843 {
1844         if (m_rds_decoder)
1845         {
1846                 if (m_decoder)
1847                 {
1848                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1849                         if (rass_slide_pic.length())
1850                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1851                         else
1852                                 eDebug("empty filename for rass slide picture received!!");
1853                 }
1854                 else
1855                         eDebug("no MPEG Decoder to show iframes avail");
1856         }
1857         else
1858                 eDebug("showRassSlidePicture called.. but not decoder");
1859 }
1860
1861 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1862 {
1863         if (m_rds_decoder)
1864         {
1865                 if (m_decoder)
1866                 {
1867                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1868                         if (rass_interactive_pic.length())
1869                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1870                         else
1871                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1872                 }
1873                 else
1874                         eDebug("no MPEG Decoder to show iframes avail");
1875         }
1876         else
1877                 eDebug("showRassInteractivePic called.. but not decoder");
1878 }
1879
1880 ePyObject eDVBServicePlay::getRassInteractiveMask()
1881 {
1882         if (m_rds_decoder)
1883                 return m_rds_decoder->getRassPictureMask();
1884         Py_RETURN_NONE;
1885 }
1886
1887 int eDVBServiceBase::getFrontendInfo(int w)
1888 {
1889         eUsePtr<iDVBChannel> channel;
1890         if(m_service_handler.getChannel(channel))
1891                 return 0;
1892         ePtr<iDVBFrontend> fe;
1893         if(channel->getFrontend(fe))
1894                 return 0;
1895         return fe->readFrontendData(w);
1896 }
1897
1898 PyObject *eDVBServiceBase::getFrontendData()
1899 {
1900         ePyObject ret = PyDict_New();
1901         if (ret)
1902         {
1903                 eUsePtr<iDVBChannel> channel;
1904                 if(!m_service_handler.getChannel(channel))
1905                 {
1906                         ePtr<iDVBFrontend> fe;
1907                         if(!channel->getFrontend(fe))
1908                                 fe->getFrontendData(ret);
1909                 }
1910         }
1911         else
1912                 Py_RETURN_NONE;
1913         return ret;
1914 }
1915
1916 PyObject *eDVBServiceBase::getFrontendStatus()
1917 {
1918         ePyObject ret = PyDict_New();
1919         if (ret)
1920         {
1921                 eUsePtr<iDVBChannel> channel;
1922                 if(!m_service_handler.getChannel(channel))
1923                 {
1924                         ePtr<iDVBFrontend> fe;
1925                         if(!channel->getFrontend(fe))
1926                                 fe->getFrontendStatus(ret);
1927                 }
1928         }
1929         else
1930                 Py_RETURN_NONE;
1931         return ret;
1932 }
1933
1934 PyObject *eDVBServiceBase::getTransponderData(bool original)
1935 {
1936         ePyObject ret = PyDict_New();
1937         if (ret)
1938         {
1939                 eUsePtr<iDVBChannel> channel;
1940                 if(!m_service_handler.getChannel(channel))
1941                 {
1942                         ePtr<iDVBFrontend> fe;
1943                         if(!channel->getFrontend(fe))
1944                                 fe->getTransponderData(ret, original);
1945                 }
1946         }
1947         else
1948                 Py_RETURN_NONE;
1949         return ret;
1950 }
1951
1952 PyObject *eDVBServiceBase::getAll(bool original)
1953 {
1954         ePyObject ret = getTransponderData(original);
1955         if (ret != Py_None)
1956         {
1957                 eUsePtr<iDVBChannel> channel;
1958                 if(!m_service_handler.getChannel(channel))
1959                 {
1960                         ePtr<iDVBFrontend> fe;
1961                         if(!channel->getFrontend(fe))
1962                         {
1963                                 fe->getFrontendData(ret);
1964                                 fe->getFrontendStatus(ret);
1965                         }
1966                 }
1967         }
1968         return ret;
1969 }
1970
1971 int eDVBServicePlay::getNumberOfSubservices()
1972 {
1973         ePtr<eServiceEvent> evt;
1974         if (!m_event_handler.getEvent(evt, 0))
1975                 return evt->getNumOfLinkageServices();
1976         return 0;
1977 }
1978
1979 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1980 {
1981         ePtr<eServiceEvent> evt;
1982         if (!m_event_handler.getEvent(evt, 0))
1983         {
1984                 if (!evt->getLinkageService(sub, m_reference, n))
1985                         return 0;
1986         }
1987         sub.type=eServiceReference::idInvalid;
1988         return -1;
1989 }
1990
1991 RESULT eDVBServicePlay::startTimeshift()
1992 {
1993         ePtr<iDVBDemux> demux;
1994         
1995         eDebug("Start timeshift!");
1996         
1997         if (m_timeshift_enabled)
1998                 return -1;
1999         
2000                 /* start recording with the data demux. */
2001         if (m_service_handler.getDataDemux(demux))
2002                 return -2;
2003
2004         demux->createTSRecorder(m_record);
2005         if (!m_record)
2006                 return -3;
2007
2008         std::string tspath;
2009         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2010                 eDebug("could not query ts path");
2011                 return -5;
2012         }
2013         tspath.append("/timeshift.XXXXXX");
2014         char* templ;
2015         templ = new char[tspath.length() + 1];
2016         strcpy(templ, tspath.c_str());
2017
2018         m_timeshift_fd = mkstemp(templ);
2019         m_timeshift_file = std::string(templ);
2020
2021         eDebug("recording to %s", templ);
2022
2023         delete [] templ;
2024
2025         if (m_timeshift_fd < 0)
2026         {
2027                 m_record = 0;
2028                 return -4;
2029         }
2030                 
2031         m_record->setTargetFD(m_timeshift_fd);
2032
2033         m_timeshift_enabled = 1;
2034         
2035         updateTimeshiftPids();
2036         m_record->start();
2037
2038         return 0;
2039 }
2040
2041 RESULT eDVBServicePlay::stopTimeshift()
2042 {
2043         if (!m_timeshift_enabled)
2044                 return -1;
2045         
2046         switchToLive();
2047         
2048         m_timeshift_enabled = 0;
2049         
2050         m_record->stop();
2051         m_record = 0;
2052         
2053         close(m_timeshift_fd);
2054         eDebug("remove timeshift file");
2055         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2056         
2057         return 0;
2058 }
2059
2060 int eDVBServicePlay::isTimeshiftActive()
2061 {
2062         return m_timeshift_enabled && m_timeshift_active;
2063 }
2064
2065 RESULT eDVBServicePlay::activateTimeshift()
2066 {
2067         if (!m_timeshift_enabled)
2068                 return -1;
2069         
2070         if (!m_timeshift_active)
2071         {
2072                 switchToTimeshift();
2073                 return 0;
2074         }
2075         
2076         return -2;
2077 }
2078
2079 PyObject *eDVBServicePlay::getCutList()
2080 {
2081         ePyObject list = PyList_New(0);
2082         
2083         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2084         {
2085                 ePyObject tuple = PyTuple_New(2);
2086                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2087                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2088                 PyList_Append(list, tuple);
2089                 Py_DECREF(tuple);
2090         }
2091         
2092         return list;
2093 }
2094
2095 void eDVBServicePlay::setCutList(ePyObject list)
2096 {
2097         if (!PyList_Check(list))
2098                 return;
2099         int size = PyList_Size(list);
2100         int i;
2101         
2102         m_cue_entries.clear();
2103         
2104         for (i=0; i<size; ++i)
2105         {
2106                 ePyObject tuple = PyList_GET_ITEM(list, i);
2107                 if (!PyTuple_Check(tuple))
2108                 {
2109                         eDebug("non-tuple in cutlist");
2110                         continue;
2111                 }
2112                 if (PyTuple_Size(tuple) != 2)
2113                 {
2114                         eDebug("cutlist entries need to be a 2-tuple");
2115                         continue;
2116                 }
2117                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2118                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2119                 {
2120                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2121                         continue;
2122                 }
2123                 pts_t pts = PyLong_AsLongLong(ppts);
2124                 int type = PyInt_AsLong(ptype);
2125                 m_cue_entries.insert(cueEntry(pts, type));
2126                 eDebug("adding %08llx, %d", pts, type);
2127         }
2128         m_cuesheet_changed = 1;
2129         
2130         cutlistToCuesheet();
2131         m_event((iPlayableService*)this, evCuesheetChanged);
2132 }
2133
2134 void eDVBServicePlay::setCutListEnable(int enable)
2135 {
2136         m_cutlist_enabled = enable;
2137         cutlistToCuesheet();
2138 }
2139
2140 void eDVBServicePlay::updateTimeshiftPids()
2141 {
2142         if (!m_record)
2143                 return;
2144         
2145         eDVBServicePMTHandler::program program;
2146         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2147
2148         if (h.getProgramInfo(program))
2149                 return;
2150         else
2151         {
2152                 std::set<int> pids_to_record;
2153                 pids_to_record.insert(0); // PAT
2154                 if (program.pmtPid != -1)
2155                         pids_to_record.insert(program.pmtPid); // PMT
2156
2157                 if (program.textPid != -1)
2158                         pids_to_record.insert(program.textPid); // Videotext
2159
2160                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2161                         i(program.videoStreams.begin()); 
2162                         i != program.videoStreams.end(); ++i)
2163                         pids_to_record.insert(i->pid);
2164
2165                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2166                         i(program.audioStreams.begin()); 
2167                         i != program.audioStreams.end(); ++i)
2168                                 pids_to_record.insert(i->pid);
2169
2170                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2171                         i(program.subtitleStreams.begin());
2172                         i != program.subtitleStreams.end(); ++i)
2173                                 pids_to_record.insert(i->pid);
2174
2175                 std::set<int> new_pids, obsolete_pids;
2176                 
2177                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2178                                 m_pids_active.begin(), m_pids_active.end(),
2179                                 std::inserter(new_pids, new_pids.begin()));
2180                 
2181                 std::set_difference(
2182                                 m_pids_active.begin(), m_pids_active.end(),
2183                                 pids_to_record.begin(), pids_to_record.end(), 
2184                                 std::inserter(new_pids, new_pids.begin())
2185                                 );
2186
2187                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2188                         m_record->addPID(*i);
2189
2190                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2191                         m_record->removePID(*i);
2192         }
2193 }
2194
2195 void eDVBServicePlay::switchToLive()
2196 {
2197         if (!m_timeshift_active)
2198                 return;
2199         
2200         eDebug("SwitchToLive");
2201         
2202         m_cue = 0;
2203         m_decoder = 0;
2204         m_decode_demux = 0;
2205         m_teletext_parser = 0;
2206         m_rds_decoder = 0;
2207         m_subtitle_parser = 0;
2208         m_new_dvb_subtitle_page_connection = 0;
2209         m_new_subtitle_page_connection = 0;
2210         m_rds_decoder_event_connection = 0;
2211         m_video_event_connection = 0;
2212
2213                 /* free the timeshift service handler, we need the resources */
2214         m_service_handler_timeshift.free();
2215         m_timeshift_active = 0;
2216
2217         m_event((iPlayableService*)this, evSeekableStatusChanged);
2218
2219         updateDecoder();
2220 }
2221
2222 void eDVBServicePlay::switchToTimeshift()
2223 {
2224         if (m_timeshift_active)
2225                 return;
2226
2227         m_decode_demux = 0;
2228         m_decoder = 0;
2229         m_teletext_parser = 0;
2230         m_rds_decoder = 0;
2231         m_subtitle_parser = 0;
2232         m_new_subtitle_page_connection = 0;
2233         m_new_dvb_subtitle_page_connection = 0;
2234         m_rds_decoder_event_connection = 0;
2235         m_video_event_connection = 0;
2236
2237         m_timeshift_active = 1;
2238
2239         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2240         r.path = m_timeshift_file;
2241
2242         m_cue = new eCueSheet();
2243         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2244
2245         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2246         pause();
2247         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2248         
2249         m_event((iPlayableService*)this, evSeekableStatusChanged);
2250 }
2251
2252 void eDVBServicePlay::updateDecoder()
2253 {
2254         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2255
2256         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2257
2258         eDVBServicePMTHandler::program program;
2259         if (h.getProgramInfo(program))
2260                 eDebug("getting program info failed.");
2261         else
2262         {
2263                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2264                 if (!program.videoStreams.empty())
2265                 {
2266                         eDebugNoNewLine(" (");
2267                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2268                                 i(program.videoStreams.begin());
2269                                 i != program.videoStreams.end(); ++i)
2270                         {
2271                                 if (vpid == -1)
2272                                 {
2273                                         vpid = i->pid;
2274                                         vpidtype = i->type;
2275                                 }
2276                                 if (i != program.videoStreams.begin())
2277                                         eDebugNoNewLine(", ");
2278                                 eDebugNoNewLine("%04x", i->pid);
2279                         }
2280                         eDebugNoNewLine(")");
2281                 }
2282                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2283                 if (!program.audioStreams.empty())
2284                 {
2285                         eDebugNoNewLine(" (");
2286                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2287                                 i(program.audioStreams.begin());
2288                                 i != program.audioStreams.end(); ++i)
2289                         {
2290                                 if (i != program.audioStreams.begin())
2291                                         eDebugNoNewLine(", ");
2292                                 eDebugNoNewLine("%04x", i->pid);
2293                         }
2294                         eDebugNoNewLine(")");
2295                 }
2296                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2297                 pcrpid = program.pcrPid;
2298                 eDebug(", and the text pid is %04x", program.textPid);
2299                 tpid = program.textPid;
2300         }
2301
2302         if (!m_decoder)
2303         {
2304                 h.getDecodeDemux(m_decode_demux);
2305                 if (m_decode_demux)
2306                 {
2307                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2308                         if (m_decoder)
2309                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2310                 }
2311                 if (m_decode_demux && m_is_primary)
2312                 {
2313                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2314                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2315                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2316                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2317                 } else
2318                 {
2319                         m_teletext_parser = 0;
2320                         m_subtitle_parser = 0;
2321                 }
2322
2323                 if (m_cue)
2324                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2325         }
2326
2327         if (m_decoder)
2328         {
2329                 if (m_dvb_service)
2330                 {
2331                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2332                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2333                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2334                 }
2335                 else // subservice
2336                 {
2337                         eServiceReferenceDVB ref;
2338                         m_service_handler.getServiceReference(ref);
2339                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2340                         if (!parent)
2341                                 parent = ref;
2342                         if (parent)
2343                         {
2344                                 ePtr<eDVBResourceManager> res_mgr;
2345                                 if (!eDVBResourceManager::getInstance(res_mgr))
2346                                 {
2347                                         ePtr<iDVBChannelList> db;
2348                                         if (!res_mgr->getChannelList(db))
2349                                         {
2350                                                 ePtr<eDVBService> origService;
2351                                                 if (!db->getService(parent, origService))
2352                                                 {
2353                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2354                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2355                                                 }
2356                                         }
2357                                 }
2358                         }
2359                 }
2360
2361                 std::string config_delay;
2362                 int config_delay_int = 0;
2363                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2364                         config_delay_int = atoi(config_delay.c_str());
2365                 m_decoder->setAC3Delay(ac3_delay == -1 ? config_delay_int : ac3_delay + config_delay_int);
2366
2367                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2368                         config_delay_int = atoi(config_delay.c_str());
2369                 else
2370                         config_delay_int = 0;
2371                 m_decoder->setPCMDelay(pcm_delay == -1 ? config_delay_int : pcm_delay + config_delay_int);
2372
2373                 m_decoder->setVideoPID(vpid, vpidtype);
2374                 selectAudioStream();
2375
2376                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2377                         m_decoder->setSyncPCR(pcrpid);
2378                 else
2379                         m_decoder->setSyncPCR(-1);
2380
2381                 if (m_is_primary)
2382                 {
2383                         m_decoder->setTextPID(tpid);
2384                         m_teletext_parser->start(program.textPid);
2385                 }
2386
2387                 if (vpid > 0 && vpid < 0x2000)
2388                         ;
2389                 else
2390                 {
2391                         std::string radio_pic;
2392                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2393                                 m_decoder->setRadioPic(radio_pic);
2394                 }
2395
2396 /*              if (!m_is_primary)
2397                         m_decoder->setTrickmode();
2398                 else */ if (m_is_paused)
2399                         m_decoder->pause();
2400                 else
2401                         m_decoder->play();
2402
2403                 m_decoder->setAudioChannel(achannel);
2404
2405                 /* don't worry about non-existing services, nor pvr services */
2406                 if (m_dvb_service)
2407                 {
2408                                 /* (audio pid will be set in selectAudioTrack */
2409                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2410                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2411                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2412                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2413                 }
2414         }
2415         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2416 }
2417
2418 void eDVBServicePlay::loadCuesheet()
2419 {
2420         std::string filename = m_reference.path + ".cuts";
2421         
2422         m_cue_entries.clear();
2423
2424         FILE *f = fopen(filename.c_str(), "rb");
2425
2426         if (f)
2427         {
2428                 eDebug("loading cuts..");
2429                 while (1)
2430                 {
2431                         unsigned long long where;
2432                         unsigned int what;
2433                         
2434                         if (!fread(&where, sizeof(where), 1, f))
2435                                 break;
2436                         if (!fread(&what, sizeof(what), 1, f))
2437                                 break;
2438                         
2439 #if BYTE_ORDER == LITTLE_ENDIAN
2440                         where = bswap_64(where);
2441 #endif
2442                         what = ntohl(what);
2443                         
2444                         if (what > 3)
2445                                 break;
2446                         
2447                         m_cue_entries.insert(cueEntry(where, what));
2448                 }
2449                 fclose(f);
2450                 eDebug("%d entries", m_cue_entries.size());
2451         } else
2452                 eDebug("cutfile not found!");
2453         
2454         m_cuesheet_changed = 0;
2455         cutlistToCuesheet();
2456         m_event((iPlayableService*)this, evCuesheetChanged);
2457 }
2458
2459 void eDVBServicePlay::saveCuesheet()
2460 {
2461         std::string filename = m_reference.path + ".cuts";
2462         
2463         FILE *f = fopen(filename.c_str(), "wb");
2464
2465         if (f)
2466         {
2467                 unsigned long long where;
2468                 int what;
2469
2470                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2471                 {
2472 #if BYTE_ORDER == BIG_ENDIAN
2473                         where = i->where;
2474 #else
2475                         where = bswap_64(i->where);
2476 #endif
2477                         what = htonl(i->what);
2478                         fwrite(&where, sizeof(where), 1, f);
2479                         fwrite(&what, sizeof(what), 1, f);
2480                         
2481                 }
2482                 fclose(f);
2483         }
2484         
2485         m_cuesheet_changed = 0;
2486 }
2487
2488 void eDVBServicePlay::cutlistToCuesheet()
2489 {
2490         if (!m_cue)
2491         {
2492                 eDebug("no cue sheet");
2493                 return;
2494         }       
2495         m_cue->clear();
2496         
2497         if (!m_cutlist_enabled)
2498         {
2499                 m_cue->commitSpans();
2500                 eDebug("cutlists were disabled");
2501                 return;
2502         }
2503
2504         pts_t in = 0, out = 0, length = 0;
2505         
2506         getLength(length);
2507                 
2508         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2509         
2510         int have_any_span = 0;
2511         
2512         while (1)
2513         {
2514                 if (i == m_cue_entries.end())
2515                 {
2516                         if (!have_any_span)
2517                                 break;
2518                         out = length;
2519                 } else {
2520                         if (i->what == 0) /* in */
2521                         {
2522                                 in = i++->where;
2523                                 continue;
2524                         } else if (i->what == 1) /* out */
2525                                 out = i++->where;
2526                         else /* mark (2) or last play position (3) */
2527                         {
2528                                 i++;
2529                                 continue;
2530                         }
2531                 }
2532                 
2533                 if (in < 0)
2534                         in = 0;
2535                 if (out < 0)
2536                         out = 0;
2537                 if (in > length)
2538                         in = length;
2539                 if (out > length)
2540                         out = length;
2541                 
2542                 if (in < out)
2543                 {
2544                         have_any_span = 1;
2545                         m_cue->addSourceSpan(in, out);
2546                 }
2547                 
2548                 in = length;
2549                 
2550                 if (i == m_cue_entries.end())
2551                         break;
2552         }
2553         m_cue->commitSpans();
2554 }
2555
2556 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2557 {
2558         if (m_subtitle_widget)
2559                 disableSubtitles(parent);
2560
2561         ePyObject entry;
2562         int tuplesize = PyTuple_Size(tuple);
2563         int type = 0;
2564
2565         if (!PyTuple_Check(tuple))
2566                 goto error_out;
2567
2568         if (tuplesize < 1)
2569                 goto error_out;
2570
2571         entry = PyTuple_GET_ITEM(tuple, 0);
2572
2573         if (!PyInt_Check(entry))
2574                 goto error_out;
2575
2576         type = PyInt_AsLong(entry);
2577
2578         if (type == 1)  // teletext subtitles
2579         {
2580                 int page, magazine, pid;
2581                 if (tuplesize < 4)
2582                         goto error_out;
2583
2584                 if (!m_teletext_parser)
2585                 {
2586                         eDebug("enable teletext subtitles.. no parser !!!");
2587                         return -1;
2588                 }
2589
2590                 entry = PyTuple_GET_ITEM(tuple, 1);
2591                 if (!PyInt_Check(entry))
2592                         goto error_out;
2593                 pid = PyInt_AsLong(entry);
2594
2595                 entry = PyTuple_GET_ITEM(tuple, 2);
2596                 if (!PyInt_Check(entry))
2597                         goto error_out;
2598                 page = PyInt_AsLong(entry);
2599
2600                 entry = PyTuple_GET_ITEM(tuple, 3);
2601                 if (!PyInt_Check(entry))
2602                         goto error_out;
2603                 magazine = PyInt_AsLong(entry);
2604
2605                 m_subtitle_widget = new eSubtitleWidget(parent);
2606                 m_subtitle_widget->resize(parent->size()); /* full size */
2607                 m_teletext_parser->setPageAndMagazine(page, magazine);
2608                 if (m_dvb_service)
2609                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2610         }
2611         else if (type == 0)
2612         {
2613                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2614                 if (!m_subtitle_parser)
2615                 {
2616                         eDebug("enable dvb subtitles.. no parser !!!");
2617                         return -1;
2618                 }
2619                 if (tuplesize < 4)
2620                         goto error_out;
2621
2622                 entry = PyTuple_GET_ITEM(tuple, 1);
2623                 if (!PyInt_Check(entry))
2624                         goto error_out;
2625                 pid = PyInt_AsLong(entry);
2626
2627                 entry = PyTuple_GET_ITEM(tuple, 2);
2628                 if (!PyInt_Check(entry))
2629                         goto error_out;
2630                 composition_page_id = PyInt_AsLong(entry);
2631
2632                 entry = PyTuple_GET_ITEM(tuple, 3);
2633                 if (!PyInt_Check(entry))
2634                         goto error_out;
2635                 ancillary_page_id = PyInt_AsLong(entry);
2636
2637                 m_subtitle_widget = new eSubtitleWidget(parent);
2638                 m_subtitle_widget->resize(parent->size()); /* full size */
2639                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2640                 if (m_dvb_service)
2641                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2642         }
2643         else
2644                 goto error_out;
2645         return 0;
2646 error_out:
2647         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2648                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2649                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2650         return -1;
2651 }
2652
2653 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2654 {
2655         delete m_subtitle_widget;
2656         m_subtitle_widget = 0;
2657         if (m_subtitle_parser)
2658         {
2659                 m_subtitle_parser->stop();
2660                 m_dvb_subtitle_pages.clear();
2661         }
2662         if (m_teletext_parser)
2663         {
2664                 m_teletext_parser->setPageAndMagazine(-1, -1);
2665                 m_subtitle_pages.clear();
2666         }
2667         if (m_dvb_service)
2668                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2669         return 0;
2670 }
2671
2672 PyObject *eDVBServicePlay::getCachedSubtitle()
2673 {
2674         if (m_dvb_service)
2675         {
2676                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2677                 if (tmp != -1)
2678                 {
2679                         unsigned int data = (unsigned int)tmp;
2680                         int pid = (data&0xFFFF0000)>>16;
2681                         ePyObject tuple = PyTuple_New(4);
2682                         eDVBServicePMTHandler::program program;
2683                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2684                         if (!h.getProgramInfo(program))
2685                         {
2686                                 if (program.textPid==pid) // teletext
2687                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2688                                 else
2689                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2690                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2691                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2692                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2693                                 return tuple;
2694                         }
2695                 }
2696         }
2697         Py_RETURN_NONE;
2698 }
2699
2700 PyObject *eDVBServicePlay::getSubtitleList()
2701 {
2702         if (!m_teletext_parser)
2703                 Py_RETURN_NONE;
2704         
2705         ePyObject l = PyList_New(0);
2706         std::set<int> added_ttx_pages;
2707
2708         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2709                 m_teletext_parser->m_found_subtitle_pages;
2710
2711         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2712         eDVBServicePMTHandler::program program;
2713         if (h.getProgramInfo(program))
2714                 eDebug("getting program info failed.");
2715         else
2716         {
2717                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2718                         it != program.subtitleStreams.end(); ++it)
2719                 {
2720                         switch(it->subtitling_type)
2721                         {
2722                                 case 0x01: // ebu teletext subtitles
2723                                 {
2724                                         int page_number = it->teletext_page_number & 0xFF;
2725                                         int magazine_number = it->teletext_magazine_number & 7;
2726                                         int hash = magazine_number << 8 | page_number;
2727                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2728                                         {
2729                                                 ePyObject tuple = PyTuple_New(5);
2730                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2731                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2732                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2733                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2734                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2735                                                 PyList_Append(l, tuple);
2736                                                 Py_DECREF(tuple);
2737                                                 added_ttx_pages.insert(hash);
2738                                         }
2739                                         break;
2740                                 }
2741                                 case 0x10 ... 0x13:
2742                                 case 0x20 ... 0x23: // dvb subtitles
2743                                 {
2744                                         ePyObject tuple = PyTuple_New(5);
2745                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2746                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2747                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2748                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2749                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2750                                         PyList_Insert(l, 0, tuple);
2751                                         Py_DECREF(tuple);
2752                                         break;
2753                                 }
2754                         }
2755                 }
2756         }
2757
2758         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2759                 it != subs.end(); ++it)
2760         {
2761                 int page_number = it->teletext_page_number & 0xFF;
2762                 int magazine_number = it->teletext_magazine_number & 7;
2763                 int hash = magazine_number << 8 | page_number;
2764                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2765                 {
2766                         ePyObject tuple = PyTuple_New(5);
2767                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2768                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2769                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2770                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2771                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2772                         PyList_Append(l, tuple);
2773                         Py_DECREF(tuple);
2774                 }
2775         }
2776
2777         return l;
2778 }
2779
2780 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2781 {
2782         if (m_subtitle_widget)
2783         {
2784                 pts_t pos = 0;
2785                 if (m_decoder)
2786                         m_decoder->getPTS(0, pos);
2787                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2788                 m_subtitle_pages.push_back(page);
2789                 checkSubtitleTiming();
2790         }
2791 }
2792
2793 void eDVBServicePlay::checkSubtitleTiming()
2794 {
2795         eDebug("checkSubtitleTiming");
2796         if (!m_subtitle_widget)
2797                 return;
2798         while (1)
2799         {
2800                 enum { TELETEXT, DVB } type;
2801                 eDVBTeletextSubtitlePage page;
2802                 eDVBSubtitlePage dvb_page;
2803                 pts_t show_time;
2804                 if (!m_subtitle_pages.empty())
2805                 {
2806                         page = m_subtitle_pages.front();
2807                         type = TELETEXT;
2808                         show_time = page.m_pts;
2809                 }
2810                 else if (!m_dvb_subtitle_pages.empty())
2811                 {
2812                         dvb_page = m_dvb_subtitle_pages.front();
2813                         type = DVB;
2814                         show_time = dvb_page.m_show_time;
2815                 }
2816                 else
2817                         return;
2818         
2819                 pts_t pos = 0;
2820         
2821                 if (m_decoder)
2822                         m_decoder->getPTS(0, pos);
2823
2824                 eDebug("%lld %lld", pos, show_time);
2825                 int diff =  show_time - pos;
2826                 if (diff < 0)
2827                 {
2828                         eDebug("[late (%d ms)]", -diff / 90);
2829                         diff = 0;
2830                 }
2831 //              if (diff > 900000)
2832 //              {
2833 //                      eDebug("[invalid]");
2834 //                      diff = 0;
2835 //              }
2836         
2837                 if ((diff/90)<20)
2838                 {
2839                         if (type == TELETEXT)
2840                         {
2841                                 eDebug("display teletext subtitle page %lld", show_time);
2842                                 m_subtitle_widget->setPage(page);
2843                                 m_subtitle_pages.pop_front();
2844                         }
2845                         else
2846                         {
2847                                 eDebug("display dvb subtitle Page %lld", show_time);
2848                                 m_subtitle_widget->setPage(dvb_page);
2849                                 m_dvb_subtitle_pages.pop_front();
2850                         }
2851                 } else
2852                 {
2853                         eDebug("start subtitle delay %d", diff / 90);
2854                         m_subtitle_sync_timer->start(diff / 90, 1);
2855                         break;
2856                 }
2857         }
2858 }
2859
2860 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2861 {
2862         if (m_subtitle_widget)
2863         {
2864                 pts_t pos = 0;
2865                 if (m_decoder)
2866                         m_decoder->getPTS(0, pos);
2867                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2868                 m_dvb_subtitle_pages.push_back(p);
2869                 checkSubtitleTiming();
2870         }
2871 }
2872
2873 int eDVBServicePlay::getAC3Delay()
2874 {
2875         if (m_dvb_service)
2876                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2877         else if (m_decoder)
2878                 return m_decoder->getAC3Delay();
2879         else
2880                 return 0;
2881 }
2882
2883 int eDVBServicePlay::getPCMDelay()
2884 {
2885         if (m_dvb_service)
2886                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2887         else if (m_decoder)
2888                 return m_decoder->getPCMDelay();
2889         else
2890                 return 0;
2891 }
2892
2893 void eDVBServicePlay::setAC3Delay(int delay)
2894 {
2895         if (m_dvb_service)
2896                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2897         if (m_decoder)
2898                 m_decoder->setAC3Delay(delay);
2899 }
2900
2901 void eDVBServicePlay::setPCMDelay(int delay)
2902 {
2903         if (m_dvb_service)
2904                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2905         if (m_decoder)
2906                 m_decoder->setPCMDelay(delay);
2907 }
2908
2909 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2910 {
2911         switch(event.type) {
2912                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2913                         m_event((iPlayableService*)this, evVideoSizeChanged);
2914                         break;
2915                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2916                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2917                         break;
2918                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2919                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2920                         break;
2921                 default:
2922                         break;
2923         }
2924 }
2925
2926 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2927 {
2928         ptr = this;
2929         return 0;
2930 }
2931
2932 PyObject *eDVBServicePlay::getStreamingData()
2933 {
2934         eDVBServicePMTHandler::program program;
2935         if (m_service_handler.getProgramInfo(program))
2936         {
2937                 Py_RETURN_NONE;
2938         }
2939
2940         ePyObject r = program.createPythonObject();
2941         ePtr<iDVBDemux> demux;
2942         if (!m_service_handler.getDataDemux(demux))
2943         {
2944                 uint8_t demux_id;
2945                 if (!demux->getCADemuxID(demux_id))
2946                         PutToDict(r, "demux", demux_id);
2947         }
2948
2949         return r;
2950 }
2951
2952
2953 DEFINE_REF(eDVBServicePlay)
2954
2955 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2956 {
2957         switch (w)
2958         {
2959         case iServiceInformation::sTransponderData:
2960                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2961         default:
2962                 break;
2963         }
2964         return iStaticServiceInformation::getInfoObject(ref, w);
2965 }
2966
2967 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");