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