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