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