initialize teletext subtitles with page -1 and magazine -1
[vuplus_dvbapp] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
13
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
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 #define TSPATH "/media/hdd"
35
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
37 {
38         DECLARE_REF(eStaticServiceDVBInformation);
39 public:
40         RESULT getName(const eServiceReference &ref, std::string &name);
41         int getLength(const eServiceReference &ref);
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                                         {
67                                                 // just show short name
68                                                 unsigned int pos = name.find("\xc2\x86");
69                                                 if ( pos != std::string::npos )
70                                                         name.erase(0, pos+2);
71                                                 pos = name.find("\xc2\x87");
72                                                 if ( pos != std::string::npos )
73                                                         name.erase(pos);
74                                                 name+=" - ";
75                                         }
76                                 }
77                         }
78                 }
79                 else
80                         name="";
81                 name += ref.name;
82                 return 0;
83         }
84         else
85                 return -1;
86 }
87
88 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
89 {
90         return -1;
91 }
92
93 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
94 {
95         DECLARE_REF(eStaticServiceDVBBouquetInformation);
96 public:
97         RESULT getName(const eServiceReference &ref, std::string &name);
98         int getLength(const eServiceReference &ref);
99 };
100
101 DEFINE_REF(eStaticServiceDVBBouquetInformation);
102
103 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
104 {
105         ePtr<iDVBChannelList> db;
106         ePtr<eDVBResourceManager> res;
107
108         int err;
109         if ((err = eDVBResourceManager::getInstance(res)) != 0)
110         {
111                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
112                 return err;
113         }
114         if ((err = res->getChannelList(db)) != 0)
115         {
116                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
117                 return err;
118         }
119
120         eBouquet *bouquet=0;
121         if ((err = db->getBouquet(ref, bouquet)) != 0)
122         {
123                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
124                 return -1;
125         }
126
127         if ( bouquet && bouquet->m_bouquet_name.length() )
128         {
129                 name = bouquet->m_bouquet_name;
130                 return 0;
131         }
132         else
133                 return -1;
134 }
135
136 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
137 {
138         return -1;
139 }
140
141 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
142 {
143         DECLARE_REF(eStaticServiceDVBPVRInformation);
144         eServiceReference m_ref;
145         eDVBMetaParser m_parser;
146 public:
147         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
148         RESULT getName(const eServiceReference &ref, std::string &name);
149         int getLength(const eServiceReference &ref);
150         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
151
152         int getInfo(const eServiceReference &ref, int w);
153         std::string getInfoString(const eServiceReference &ref,int w);
154 };
155
156 DEFINE_REF(eStaticServiceDVBPVRInformation);
157
158 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
159 {
160         m_ref = ref;
161         m_parser.parseFile(ref.path);
162 }
163
164 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
165 {
166         ASSERT(ref == m_ref);
167         name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
168         return 0;
169 }
170
171 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
172 {
173         ASSERT(ref == m_ref);
174         
175         eDVBTSTools tstools;
176         
177         if (tstools.openFile(ref.path.c_str()))
178                 return 0;
179
180         pts_t len;
181         if (tstools.calcLen(len))
182                 return 0;
183
184         return len / 90000;
185 }
186
187 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
188 {
189         switch (w)
190         {
191         case iServiceInformation::sDescription:
192                 return iServiceInformation::resIsString;
193         case iServiceInformation::sServiceref:
194                 return iServiceInformation::resIsString;
195         case iServiceInformation::sTimeCreate:
196                 if (m_parser.m_time_create)
197                         return m_parser.m_time_create;
198                 else
199                         return iServiceInformation::resNA;
200         default:
201                 return iServiceInformation::resNA;
202         }
203 }
204
205 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
206 {
207         switch (w)
208         {
209         case iServiceInformation::sDescription:
210                 return m_parser.m_description;
211         case iServiceInformation::sServiceref:
212                 return m_parser.m_ref.toString();
213         case iServiceInformation::sTags:
214                 return m_parser.m_tags;
215         default:
216                 return "";
217         }
218 }
219
220 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
221 {
222         if (!ref.path.empty())
223         {
224                 ePtr<eServiceEvent> event = new eServiceEvent;
225                 std::string filename = ref.path;
226                 filename.erase(filename.length()-2, 2);
227                 filename+="eit";
228                 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
229                 {
230                         evt = event;
231                         return 0;
232                 }
233         }
234         evt = 0;
235         return -1;
236 }
237
238 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
239 {
240         DECLARE_REF(eDVBPVRServiceOfflineOperations);
241         eServiceReferenceDVB m_ref;
242 public:
243         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
244         
245         RESULT deleteFromDisk(int simulate);
246         RESULT getListOfFilenames(std::list<std::string> &);
247 };
248
249 DEFINE_REF(eDVBPVRServiceOfflineOperations);
250
251 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
252 {
253 }
254
255 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
256 {
257         if (simulate)
258                 return 0;
259         else
260         {
261                 std::list<std::string> res;
262                 if (getListOfFilenames(res))
263                         return -1;
264                 
265                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
266                 if (!eraser)
267                         eDebug("FATAL !! can't get background file eraser");
268                 
269                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
270                 {
271                         eDebug("Removing %s...", i->c_str());
272                         if (eraser)
273                                 eraser->erase(i->c_str());
274                         else
275                                 ::unlink(i->c_str());
276                 }
277                 
278                 return 0;
279         }
280 }
281
282 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
283 {
284         res.clear();
285         res.push_back(m_ref.path);
286
287 // handling for old splitted recordings (enigma 1)
288         char buf[255];
289         int slice=1;
290         while(true)
291         {
292                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
293                 struct stat s;
294                 if (stat(buf, &s) < 0)
295                         break;
296                 res.push_back(buf);
297         }       
298
299         res.push_back(m_ref.path + ".meta");
300         res.push_back(m_ref.path + ".ap");
301         res.push_back(m_ref.path + ".cuts");
302         std::string tmp = m_ref.path;
303         tmp.erase(m_ref.path.length()-3);
304         res.push_back(tmp + ".eit");
305         return 0;
306 }
307
308 DEFINE_REF(eServiceFactoryDVB)
309
310 eServiceFactoryDVB::eServiceFactoryDVB()
311 {
312         ePtr<eServiceCenter> sc;
313         
314         eServiceCenter::getPrivInstance(sc);
315         if (sc)
316                 sc->addServiceFactory(eServiceFactoryDVB::id, this);
317
318         m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
319         m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
320 }
321
322 eServiceFactoryDVB::~eServiceFactoryDVB()
323 {
324         ePtr<eServiceCenter> sc;
325         
326         eServiceCenter::getPrivInstance(sc);
327         if (sc)
328                 sc->removeServiceFactory(eServiceFactoryDVB::id);
329 }
330
331 DEFINE_REF(eDVBServiceList);
332
333 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
334 {
335 }
336
337 eDVBServiceList::~eDVBServiceList()
338 {
339 }
340
341 RESULT eDVBServiceList::startQuery()
342 {
343         ePtr<iDVBChannelList> db;
344         ePtr<eDVBResourceManager> res;
345         
346         int err;
347         if ((err = eDVBResourceManager::getInstance(res)) != 0)
348         {
349                 eDebug("no resource manager");
350                 return err;
351         }
352         if ((err = res->getChannelList(db)) != 0)
353         {
354                 eDebug("no channel list");
355                 return err;
356         }
357         
358         ePtr<eDVBChannelQuery> q;
359         
360         if (!m_parent.path.empty())
361         {
362                 eDVBChannelQuery::compile(q, m_parent.path);
363                 if (!q)
364                 {
365                         eDebug("compile query failed");
366                         return err;
367                 }
368         }
369         
370         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
371         {
372                 eDebug("startQuery failed");
373                 return err;
374         }
375
376         return 0;
377 }
378
379 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
380 {
381         eServiceReferenceDVB ref;
382         
383         if (!m_query)
384                 return -1;
385         
386         while (!m_query->getNextResult(ref))
387                 list.push_back(ref);
388
389         if (sorted)
390                 list.sort(iListableServiceCompare(this));
391
392         return 0;
393 }
394
395 //   The first argument of this function is a format string to specify the order and
396 //   the content of the returned list
397 //   useable format options are
398 //   R = Service Reference (as swig object .. this is very slow)
399 //   S = Service Reference (as python string object .. same as ref.toString())
400 //   C = Service Reference (as python string object .. same as ref.toCompareString())
401 //   N = Service Name (as python string object)
402 //   when exactly one return value per service is selected in the format string,
403 //   then each value is directly a list entry
404 //   when more than one value is returned per service, then the list is a list of
405 //   python tuples
406 //   unknown format string chars are returned as python None values !
407 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
408 {
409         PyObject *ret=0;
410         std::list<eServiceReference> tmplist;
411         int retcount=1;
412
413         if (!format || !(retcount=strlen(format)))
414                 format = "R"; // just return service reference swig object ...
415
416         if (!getContent(tmplist, sorted))
417         {
418                 int services=tmplist.size();
419                 ePtr<iStaticServiceInformation> sptr;
420                 eServiceCenterPtr service_center;
421
422                 if (strchr(format, 'N'))
423                         eServiceCenter::getPrivInstance(service_center);
424
425                 ret = PyList_New(services);
426                 std::list<eServiceReference>::iterator it(tmplist.begin());
427
428                 for (int cnt=0; cnt < services; ++cnt)
429                 {
430                         eServiceReference &ref=*it++;
431                         PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
432                         for (int i=0; i < retcount; ++i)
433                         {
434                                 PyObject *tmp=0;
435                                 switch(format[i])
436                                 {
437                                 case 'R':  // service reference (swig)object
438                                         tmp = New_eServiceReference(ref);
439                                         break;
440                                 case 'C':  // service reference compare string
441                                         tmp = PyString_FromString(ref.toCompareString().c_str());
442                                         break;
443                                 case 'S':  // service reference string
444                                         tmp = PyString_FromString(ref.toString().c_str());
445                                         break;
446                                 case 'N':  // service name
447                                         if (service_center)
448                                         {
449                                                 service_center->info(ref, sptr);
450                                                 if (sptr)
451                                                 {
452                                                         std::string name;
453                                                         sptr->getName(ref, name);
454                                                         if (name.length())
455                                                                 tmp = PyString_FromString(name.c_str());
456                                                 }
457                                         }
458                                         if (!tmp)
459                                                 tmp = PyString_FromString("<n/a>");
460                                         break;
461                                 default:
462                                         if (tuple)
463                                         {
464                                                 tmp = Py_None;
465                                                 Py_INCREF(Py_None);
466                                         }
467                                         break;
468                                 }
469                                 if (tmp)
470                                 {
471                                         if (tuple)
472                                                 PyTuple_SET_ITEM(tuple, i, tmp);
473                                         else
474                                                 PyList_SET_ITEM(ret, cnt, tmp);
475                                 }
476                         }
477                         if (tuple)
478                                 PyList_SET_ITEM(ret, cnt, tuple);
479                 }
480         }
481         return ret ? ret : PyList_New(0);
482 }
483
484 RESULT eDVBServiceList::getNext(eServiceReference &ref)
485 {
486         if (!m_query)
487                 return -1;
488         
489         return m_query->getNextResult((eServiceReferenceDVB&)ref);
490 }
491
492 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
493 {
494         return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
495 }
496
497 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
498 {
499         if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
500         {
501                 ePtr<iDVBChannelList> db;
502                 ePtr<eDVBResourceManager> resm;
503
504                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
505                         return -1;
506
507                 if (db->getBouquet(m_parent, m_bouquet) != 0)
508                         return -1;
509
510                 res = this;
511                 
512                 return 0;
513         }
514         res = 0;
515         return -1;
516 }
517
518 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
519 {
520         if (!m_bouquet)
521                 return -1;
522         return m_bouquet->addService(ref, before);
523 }
524
525 RESULT eDVBServiceList::removeService(eServiceReference &ref)
526 {
527         if (!m_bouquet)
528                 return -1;
529         return m_bouquet->removeService(ref);
530 }
531
532 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
533 {
534         if (!m_bouquet)
535                 return -1;
536         return m_bouquet->moveService(ref, pos);
537 }
538
539 RESULT eDVBServiceList::flushChanges()
540 {
541         if (!m_bouquet)
542                 return -1;
543         return m_bouquet->flushChanges();
544 }
545
546 RESULT eDVBServiceList::setListName(const std::string &name)
547 {
548         if (!m_bouquet)
549                 return -1;
550         return m_bouquet->setListName(name);
551 }
552
553 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
554 {
555         ePtr<eDVBService> service;
556         int r = lookupService(service, ref);
557         if (r)
558                 service = 0;
559                 // check resources...
560         ptr = new eDVBServicePlay(ref, service);
561         return 0;
562 }
563
564 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
565 {
566         if (ref.path.empty())
567         {
568                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
569                 return 0;
570         } else
571         {
572                 ptr = 0;
573                 return -1;
574         }
575 }
576
577 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
578 {
579         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
580         if (list->startQuery())
581         {
582                 ptr = 0;
583                 return -1;
584         }
585         
586         ptr = list;
587         return 0;
588 }
589
590 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
591 {
592         /* is a listable service? */
593         if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
594         {
595                 if ( !ref.name.empty() )  // satellites or providers list
596                         ptr = m_StaticServiceDVBInfo;
597                 else // a dvb bouquet
598                         ptr = m_StaticServiceDVBBouquetInfo;
599         }
600         else if (!ref.path.empty()) /* do we have a PVR service? */
601                 ptr = new eStaticServiceDVBPVRInformation(ref);
602         else // normal dvb service
603         {
604                 ePtr<eDVBService> service;
605                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
606                         ptr = m_StaticServiceDVBInfo;
607                 else
608                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
609                         ptr = service;
610         }
611         return 0;
612 }
613
614 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
615 {
616         if (ref.path.empty())
617         {
618                 ptr = 0;
619                 return -1;
620         } else
621         {
622                 ptr = new eDVBPVRServiceOfflineOperations(ref);
623                 return 0;
624         }
625 }
626
627 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
628 {
629                         // TODO: handle the listing itself
630         // if (ref.... == -1) .. return "... bouquets ...";
631         // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
632                         // TODO: cache
633         ePtr<iDVBChannelList> db;
634         ePtr<eDVBResourceManager> res;
635         
636         int err;
637         if ((err = eDVBResourceManager::getInstance(res)) != 0)
638         {
639                 eDebug("no resource manager");
640                 return err;
641         }
642         if ((err = res->getChannelList(db)) != 0)
643         {
644                 eDebug("no channel list");
645                 return err;
646         }
647         
648                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
649         if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
650         {
651                 eDebug("getService failed!");
652                 return err;
653         }
654
655         return 0;
656 }
657
658 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
659         m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
660 {
661         m_is_primary = 1;
662         m_is_pvr = !m_reference.path.empty();
663         
664         m_timeshift_enabled = m_timeshift_active = 0;
665         m_skipmode = 0;
666         
667         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
668         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
669         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
670
671         m_cuesheet_changed = 0;
672         m_cutlist_enabled = 1;
673         
674         m_subtitle_widget = 0;
675         
676         CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
677 }
678
679 eDVBServicePlay::~eDVBServicePlay()
680 {
681         delete m_subtitle_widget;
682 }
683
684 void eDVBServicePlay::gotNewEvent()
685 {
686 #if 0
687                 // debug only
688         ePtr<eServiceEvent> m_event_now, m_event_next;
689         getEvent(m_event_now, 0);
690         getEvent(m_event_next, 1);
691
692         if (m_event_now)
693                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
694         if (m_event_next)
695                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
696 #endif
697         m_event((iPlayableService*)this, evUpdatedEventInfo);
698 }
699
700 void eDVBServicePlay::serviceEvent(int event)
701 {
702         switch (event)
703         {
704         case eDVBServicePMTHandler::eventTuned:
705         {
706                 ePtr<iDVBDemux> m_demux;
707                 if (!m_service_handler.getDataDemux(m_demux))
708                 {
709                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
710                         int sid = ref.getParentServiceID().get();
711                         if (!sid)
712                                 sid = ref.getServiceID().get();
713                         if ( ref.getParentTransportStreamID().get() &&
714                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
715                                 m_event_handler.startOther(m_demux, sid);
716                         else
717                                 m_event_handler.start(m_demux, sid);
718                 }
719                 break;
720         }
721         case eDVBServicePMTHandler::eventTuneFailed:
722         {
723                 eDebug("DVB service failed to tune");
724                 m_event((iPlayableService*)this, evTuneFailed);
725                 break;
726         }
727         case eDVBServicePMTHandler::eventNewProgramInfo:
728         {
729                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
730                 if (m_timeshift_enabled)
731                         updateTimeshiftPids();
732                 if (!m_timeshift_active)
733                         updateDecoder();
734                 if (m_first_program_info && m_is_pvr)
735                 {
736                         m_first_program_info = 0;
737                         seekTo(0);
738                 }
739                 m_event((iPlayableService*)this, evUpdatedInfo);
740                 break;
741         }
742         case eDVBServicePMTHandler::eventEOF:
743                 m_event((iPlayableService*)this, evEOF);
744                 break;
745         case eDVBServicePMTHandler::eventSOF:
746                 m_event((iPlayableService*)this, evSOF);
747                 break;
748         }
749 }
750
751 void eDVBServicePlay::serviceEventTimeshift(int event)
752 {
753         switch (event)
754         {
755         case eDVBServicePMTHandler::eventNewProgramInfo:
756                 if (m_timeshift_active)
757                         updateDecoder();
758                 break;
759         case eDVBServicePMTHandler::eventSOF:
760                 m_event((iPlayableService*)this, evSOF);
761                 break;
762         case eDVBServicePMTHandler::eventEOF:
763                 switchToLive();
764                 break;
765         }
766 }
767
768 RESULT eDVBServicePlay::start()
769 {
770         int r;
771                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
772                    two (one for decoding, one for data source), as we must be prepared
773                    to start recording from the data demux. */
774         if (m_is_pvr)
775                 m_cue = new eCueSheet();
776
777         m_first_program_info = 1;
778         eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
779         r = m_service_handler.tune(service, m_is_pvr, m_cue);
780
781                 /* inject EIT if there is a stored one */
782         if (m_is_pvr)
783         {
784                 std::string filename = service.path;
785                 filename.erase(filename.length()-2, 2);
786                 filename+="eit";
787                 ePtr<eServiceEvent> event = new eServiceEvent;
788                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
789                 {
790                         ePtr<eServiceEvent> empty;
791                         m_event_handler.inject(event, 0);
792                         m_event_handler.inject(empty, 1);
793                 }
794         }
795
796         if (m_is_pvr)
797                 loadCuesheet();
798
799         m_event(this, evStart);
800         m_event((iPlayableService*)this, evSeekableStatusChanged);
801         return 0;
802 }
803
804 RESULT eDVBServicePlay::stop()
805 {
806                 /* add bookmark for last play position */
807         if (m_is_pvr)
808         {
809                 pts_t play_position;
810                 if (!getPlayPosition(play_position))
811                 {
812                                 /* remove last position */
813                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
814                         {
815                                 if (i->what == 3) /* current play position */
816                                 {
817                                         m_cue_entries.erase(i);
818                                         i = m_cue_entries.begin();
819                                         continue;
820                                 } else
821                                         ++i;
822                         }
823                         
824                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
825                         m_cuesheet_changed = 1;
826                 }
827         }
828
829         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
830
831         m_service_handler_timeshift.free();
832         m_service_handler.free();
833         
834         if (m_is_pvr && m_cuesheet_changed)
835         {
836                 struct stat s;
837                                 /* save cuesheet only when main file is accessible. */
838                 if (!::stat(m_reference.path.c_str(), &s))
839                         saveCuesheet();
840         }
841         
842         return 0;
843 }
844
845 RESULT eDVBServicePlay::setTarget(int target)
846 {
847         m_is_primary = !target;
848         return 0;
849 }
850
851 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
852 {
853         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
854         return 0;
855 }
856
857 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
858 {
859                 /* note: we check for timeshift to be enabled,
860                    not neccessary active. if you pause when timeshift
861                    is not active, you should activate it when unpausing */
862         if ((!m_is_pvr) && (!m_timeshift_enabled))
863         {
864                 ptr = 0;
865                 return -1;
866         }
867
868         ptr = this;
869         return 0;
870 }
871
872 RESULT eDVBServicePlay::setSlowMotion(int ratio)
873 {
874         if (m_decoder)
875                 return m_decoder->setSlowMotion(ratio);
876         else
877                 return -1;
878 }
879
880 RESULT eDVBServicePlay::setFastForward(int ratio)
881 {
882         int skipmode, ffratio;
883         
884         if (ratio > 8)
885         {
886                 skipmode = ratio;
887                 ffratio = 1;
888         } else if (ratio > 0)
889         {
890                 skipmode = 0;
891                 ffratio = ratio;
892         } else if (!ratio)
893         {
894                 skipmode = 0;
895                 ffratio = 0;
896         } else // if (ratio < 0)
897         {
898                 skipmode = ratio;
899                 ffratio = 1;
900         }
901
902         if (m_skipmode != skipmode)
903         {
904                 eDebug("setting cue skipmode to %d", skipmode);
905                 if (m_cue)
906                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
907         }
908         
909         m_skipmode = skipmode;
910         
911         if (!m_decoder)
912                 return -1;
913
914         return m_decoder->setFastForward(ffratio);
915 }
916     
917 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
918 {
919         if (m_is_pvr || m_timeshift_enabled)
920         {
921                 ptr = this;
922                 return 0;
923         }
924         
925         ptr = 0;
926         return -1;
927 }
928
929         /* TODO: when timeshift is enabled but not active, this doesn't work. */
930 RESULT eDVBServicePlay::getLength(pts_t &len)
931 {
932         ePtr<iDVBPVRChannel> pvr_channel;
933         
934         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
935                 return -1;
936         
937         return pvr_channel->getLength(len);
938 }
939
940 RESULT eDVBServicePlay::pause()
941 {
942         if (!m_is_paused && m_decoder)
943         {
944                 m_is_paused = 1;
945                 return m_decoder->freeze(0);
946         } else
947                 return -1;
948 }
949
950 RESULT eDVBServicePlay::unpause()
951 {
952         if (m_is_paused && m_decoder)
953         {
954                 m_is_paused = 0;
955                 return m_decoder->unfreeze();
956         } else
957                 return -1;
958 }
959
960 RESULT eDVBServicePlay::seekTo(pts_t to)
961 {
962         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
963         
964         if (!m_decode_demux)
965                 return -1;
966
967         ePtr<iDVBPVRChannel> pvr_channel;
968         
969         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
970                 return -1;
971         
972         if (!m_cue)
973                 return -1;
974         
975         m_cue->seekTo(0, to);
976         return 0;
977 }
978
979 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
980 {
981         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
982         
983         if (!m_decode_demux)
984                 return -1;
985
986         ePtr<iDVBPVRChannel> pvr_channel;
987         
988         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
989                 return -1;
990         
991         int mode = 1;
992         
993                         /* HACK until we have skip-AP api */
994         if ((to > 0) && (to < 100))
995                 mode = 2;
996         
997         to *= direction;
998         
999         if (!m_cue)
1000                 return 0;
1001         
1002         m_cue->seekTo(mode, to);
1003         return 0;
1004 }
1005
1006 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1007 {
1008         ePtr<iDVBPVRChannel> pvr_channel;
1009         
1010         if (!m_decode_demux)
1011                 return -1;
1012         
1013         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1014                 return -1;
1015         
1016         int r = 0;
1017
1018                 /* if there is a decoder, use audio or video PTS */
1019         if (m_decoder)
1020         {
1021                 r = m_decoder->getPTS(0, pos);
1022                 if (r)
1023                         return r;
1024         }
1025         
1026                 /* fixup */
1027         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1028 }
1029
1030 RESULT eDVBServicePlay::setTrickmode(int trick)
1031 {
1032         if (m_decoder)
1033                 m_decoder->setTrickmode(trick);
1034         return 0;
1035 }
1036
1037 RESULT eDVBServicePlay::isCurrentlySeekable()
1038 {
1039         return m_is_pvr || m_timeshift_active;
1040 }
1041
1042 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1043 {
1044         ptr = this;
1045         return 0;
1046 }
1047
1048 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1049 {
1050         ptr = this;
1051         return 0;
1052 }
1053
1054 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1055 {
1056         ptr = this;
1057         return 0;
1058 }
1059
1060 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1061 {
1062         ptr = this;
1063         return 0;
1064 }
1065
1066 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1067 {
1068         ptr = this;
1069         return 0;
1070 }
1071
1072 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1073 {
1074         ptr = 0;
1075         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1076                 (m_timeshift_enabled || !m_is_pvr))
1077         {
1078                 if (!m_timeshift_enabled)
1079                 {
1080                                 /* we need enough diskspace */
1081                         struct statfs fs;
1082                         if (statfs(TSPATH "/.", &fs) < 0)
1083                         {
1084                                 eDebug("statfs failed!");
1085                                 return -2;
1086                         }
1087                 
1088                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1089                         {
1090                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1091                                 return -3;
1092                         }
1093                 }
1094                 ptr = this;
1095                 return 0;
1096         }
1097         return -1;
1098 }
1099
1100 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1101 {
1102         if (m_is_pvr)
1103         {
1104                 ptr = this;
1105                 return 0;
1106         }
1107         ptr = 0;
1108         return -1;
1109 }
1110
1111 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1112 {
1113         ptr = this;
1114         return 0;
1115 }
1116
1117 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1118 {
1119         ptr = this;
1120         return 0;
1121 }
1122
1123 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1124 {
1125         ptr = this;
1126         return 0;
1127 }
1128
1129 RESULT eDVBServicePlay::getName(std::string &name)
1130 {
1131         if (m_is_pvr)
1132         {
1133                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1134                 return i->getName(m_reference, name);
1135         }
1136         if (m_dvb_service)
1137         {
1138                 m_dvb_service->getName(m_reference, name);
1139                 if (name.empty())
1140                         name = "(...)";
1141         }
1142         else if (!m_reference.name.empty())
1143                 eStaticServiceDVBInformation().getName(m_reference, name);
1144         else
1145                 name = "DVB service";
1146         return 0;
1147 }
1148
1149 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1150 {
1151         return m_event_handler.getEvent(evt, nownext);
1152 }
1153
1154 int eDVBServicePlay::getInfo(int w)
1155 {
1156         eDVBServicePMTHandler::program program;
1157
1158         if (w == sCAIDs)
1159                 return resIsPyObject;
1160
1161         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1162         
1163         if (h.getProgramInfo(program))
1164                 return -1;
1165         
1166         switch (w)
1167         {
1168         case sAspect:
1169                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1170                 {
1171                         ePtr<eServiceEvent> evt;
1172                         if (!m_event_handler.getEvent(evt, 0))
1173                         {
1174                                 ePtr<eComponentData> data;
1175                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1176                                 {
1177                                         if ( data->getStreamContent() == 1 )
1178                                         {
1179                                                 switch(data->getComponentType())
1180                                                 {
1181                                                         // SD
1182                                                         case 1: // 4:3 SD PAL
1183                                                         case 2:
1184                                                         case 3: // 16:9 SD PAL
1185                                                         case 4: // > 16:9 PAL
1186                                                         case 5: // 4:3 SD NTSC
1187                                                         case 6: 
1188                                                         case 7: // 16:9 SD NTSC
1189                                                         case 8: // > 16:9 NTSC
1190
1191                                                         // HD
1192                                                         case 9: // 4:3 HD PAL
1193                                                         case 0xA:
1194                                                         case 0xB: // 16:9 HD PAL
1195                                                         case 0xC: // > 16:9 HD PAL
1196                                                         case 0xD: // 4:3 HD NTSC
1197                                                         case 0xE:
1198                                                         case 0xF: // 16:9 HD NTSC
1199                                                         case 0x10: // > 16:9 HD PAL
1200                                                                 return data->getComponentType();
1201                                                 }
1202                                         }
1203                                 }
1204                         }
1205                 }
1206                 return -1;
1207         case sIsCrypted: return program.isCrypted();
1208         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1209         case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1210         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1211         case sPCRPID: return program.pcrPid;
1212         case sPMTPID: return program.pmtPid;
1213         case sTXTPID: return program.textPid;
1214         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1215         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1216         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1217         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1218         case sProvider: if (!m_dvb_service) return -1; return -2;
1219         default:
1220                 return -1;
1221         }
1222 }
1223
1224 std::string eDVBServicePlay::getInfoString(int w)
1225 {
1226         switch (w)
1227         {
1228         case sProvider:
1229                 if (!m_dvb_service) return "";
1230                 return m_dvb_service->m_provider_name;
1231         default:
1232                 break;
1233         }
1234         return iServiceInformation::getInfoString(w);
1235 }
1236
1237 PyObject *eDVBServicePlay::getInfoObject(int w)
1238 {
1239         switch (w)
1240         {
1241         case sCAIDs:
1242                 return m_service_handler.getCaIds();
1243         default:
1244                 break;
1245         }
1246         return iServiceInformation::getInfoObject(w);
1247 }
1248
1249 int eDVBServicePlay::getNumberOfTracks()
1250 {
1251         eDVBServicePMTHandler::program program;
1252         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1253         if (h.getProgramInfo(program))
1254                 return 0;
1255         return program.audioStreams.size();
1256 }
1257
1258 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1259 {
1260         int ret = selectAudioStream(i);
1261
1262         if (m_decoder->start())
1263                 return -5;
1264
1265         return ret;
1266 }
1267
1268 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1269 {
1270         eDVBServicePMTHandler::program program;
1271         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1272
1273         if (h.getProgramInfo(program))
1274                 return -1;
1275         
1276         if (i >= program.audioStreams.size())
1277                 return -2;
1278         
1279         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1280                 info.m_description = "MPEG";
1281         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1282                 info.m_description = "AC3";
1283         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1284                 info.m_description = "AAC";
1285         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1286                 info.m_description = "DTS";
1287         else
1288                 info.m_description = "???";
1289
1290         if (program.audioStreams[i].component_tag != -1)
1291         {
1292                 ePtr<eServiceEvent> evt;
1293                 if (!m_event_handler.getEvent(evt, 0))
1294                 {
1295                         ePtr<eComponentData> data;
1296                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1297                                 info.m_language = data->getText();
1298                 }
1299         }
1300
1301         if (info.m_language.empty())
1302                 info.m_language = program.audioStreams[i].language_code;
1303         
1304         return 0;
1305 }
1306
1307 int eDVBServicePlay::selectAudioStream(int i)
1308 {
1309         eDVBServicePMTHandler::program program;
1310         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1311
1312         if (h.getProgramInfo(program))
1313                 return -1;
1314         
1315         if ((unsigned int)i >= program.audioStreams.size())
1316                 return -2;
1317         
1318         if (!m_decoder)
1319                 return -3;
1320         
1321         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1322                 return -4;
1323
1324         if (m_radiotext_parser)
1325                 m_radiotext_parser->start(program.audioStreams[i].pid);
1326
1327         if (m_dvb_service && !m_is_pvr)
1328         {
1329                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1330                 {
1331                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1332                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1333                 }
1334                 else
1335                 {
1336                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1337                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1338                 }
1339         }
1340
1341         h.resetCachedProgram();
1342
1343         return 0;
1344 }
1345
1346 int eDVBServicePlay::getCurrentChannel()
1347 {
1348         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1349 }
1350
1351 RESULT eDVBServicePlay::selectChannel(int i)
1352 {
1353         if (i < LEFT || i > RIGHT || i == STEREO)
1354                 i = -1;  // Stereo
1355         if (m_dvb_service)
1356                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1357         if (m_decoder)
1358                 m_decoder->setAudioChannel(i);
1359         return 0;
1360 }
1361
1362 std::string eDVBServicePlay::getRadioText(int x)
1363 {
1364         if (m_radiotext_parser)
1365                 switch(x)
1366                 {
1367                         case 0:
1368                                 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1369                 }
1370         return "";
1371 }
1372
1373 void eDVBServicePlay::radioTextUpdated()
1374 {
1375         m_event((iPlayableService*)this, evUpdatedRadioText);
1376 }
1377
1378 int eDVBServiceBase::getFrontendInfo(int w)
1379 {
1380         eUsePtr<iDVBChannel> channel;
1381         if(m_service_handler.getChannel(channel))
1382                 return 0;
1383         ePtr<iDVBFrontend> fe;
1384         if(channel->getFrontend(fe))
1385                 return 0;
1386         return fe->readFrontendData(w);
1387 }
1388
1389 PyObject *eDVBServiceBase::getFrontendData(bool original)
1390 {
1391         PyObject *ret=0;
1392
1393         eUsePtr<iDVBChannel> channel;
1394         if(!m_service_handler.getChannel(channel))
1395         {
1396                 ePtr<iDVBFrontend> fe;
1397                 if(!channel->getFrontend(fe))
1398                 {
1399                         ret = fe->readTransponderData(original);
1400                         if (ret)
1401                         {
1402                                 ePtr<iDVBFrontendParameters> feparm;
1403                                 channel->getCurrentFrontendParameters(feparm);
1404                                 if (feparm)
1405                                 {
1406                                         eDVBFrontendParametersSatellite osat;
1407                                         if (!feparm->getDVBS(osat))
1408                                         {
1409                                                 void PutToDict(PyObject *, const char*, long);
1410                                                 void PutToDict(PyObject *, const char*, const char*);
1411                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1412                                                 const char *tmp = "UNKNOWN";
1413                                                 switch(osat.polarisation)
1414                                                 {
1415                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1416                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1417                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1418                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1419                                                         default:break;
1420                                                 }
1421                                                 PutToDict(ret, "polarization", tmp);
1422                                         }
1423                                 }
1424                         }
1425                 }
1426         }
1427         if (!ret)
1428         {
1429                 ret = Py_None;
1430                 Py_INCREF(ret);
1431         }
1432         return ret;
1433 }
1434
1435 int eDVBServicePlay::getNumberOfSubservices()
1436 {
1437         ePtr<eServiceEvent> evt;
1438         if (!m_event_handler.getEvent(evt, 0))
1439                 return evt->getNumOfLinkageServices();
1440         return 0;
1441 }
1442
1443 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1444 {
1445         ePtr<eServiceEvent> evt;
1446         if (!m_event_handler.getEvent(evt, 0))
1447         {
1448                 if (!evt->getLinkageService(sub, m_reference, n))
1449                         return 0;
1450         }
1451         sub.type=eServiceReference::idInvalid;
1452         return -1;
1453 }
1454
1455 RESULT eDVBServicePlay::startTimeshift()
1456 {
1457         ePtr<iDVBDemux> demux;
1458         
1459         eDebug("Start timeshift!");
1460         
1461         if (m_timeshift_enabled)
1462                 return -1;
1463         
1464                 /* start recording with the data demux. */
1465         if (m_service_handler.getDataDemux(demux))
1466                 return -2;
1467
1468         demux->createTSRecorder(m_record);
1469         if (!m_record)
1470                 return -3;
1471
1472         char templ[]=TSPATH "/timeshift.XXXXXX";
1473         m_timeshift_fd = mkstemp(templ);
1474         m_timeshift_file = templ;
1475         
1476         eDebug("recording to %s", templ);
1477         
1478         if (m_timeshift_fd < 0)
1479         {
1480                 m_record = 0;
1481                 return -4;
1482         }
1483                 
1484         m_record->setTargetFD(m_timeshift_fd);
1485
1486         m_timeshift_enabled = 1;
1487         
1488         updateTimeshiftPids();
1489         m_record->start();
1490
1491         return 0;
1492 }
1493
1494 RESULT eDVBServicePlay::stopTimeshift()
1495 {
1496         if (!m_timeshift_enabled)
1497                 return -1;
1498         
1499         switchToLive();
1500         
1501         m_timeshift_enabled = 0;
1502         
1503         m_record->stop();
1504         m_record = 0;
1505         
1506         close(m_timeshift_fd);
1507         eDebug("remove timeshift file");
1508         remove(m_timeshift_file.c_str());
1509         
1510         return 0;
1511 }
1512
1513 int eDVBServicePlay::isTimeshiftActive()
1514 {
1515         return m_timeshift_enabled && m_timeshift_active;
1516 }
1517
1518 RESULT eDVBServicePlay::activateTimeshift()
1519 {
1520         if (!m_timeshift_enabled)
1521                 return -1;
1522         
1523         if (!m_timeshift_active)
1524         {
1525                 switchToTimeshift();
1526                 return 0;
1527         }
1528         
1529         return -2;
1530 }
1531
1532 PyObject *eDVBServicePlay::getCutList()
1533 {
1534         PyObject *list = PyList_New(0);
1535         
1536         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1537         {
1538                 PyObject *tuple = PyTuple_New(2);
1539                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1540                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1541                 PyList_Append(list, tuple);
1542                 Py_DECREF(tuple);
1543         }
1544         
1545         return list;
1546 }
1547
1548 void eDVBServicePlay::setCutList(PyObject *list)
1549 {
1550         if (!PyList_Check(list))
1551                 return;
1552         int size = PyList_Size(list);
1553         int i;
1554         
1555         m_cue_entries.clear();
1556         
1557         for (i=0; i<size; ++i)
1558         {
1559                 PyObject *tuple = PyList_GetItem(list, i);
1560                 if (!PyTuple_Check(tuple))
1561                 {
1562                         eDebug("non-tuple in cutlist");
1563                         continue;
1564                 }
1565                 if (PyTuple_Size(tuple) != 2)
1566                 {
1567                         eDebug("cutlist entries need to be a 2-tuple");
1568                         continue;
1569                 }
1570                 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1571                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1572                 {
1573                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1574                         continue;
1575                 }
1576                 pts_t pts = PyLong_AsLongLong(ppts);
1577                 int type = PyInt_AsLong(ptype);
1578                 m_cue_entries.insert(cueEntry(pts, type));
1579                 eDebug("adding %08llx, %d", pts, type);
1580         }
1581         m_cuesheet_changed = 1;
1582         
1583         cutlistToCuesheet();
1584         m_event((iPlayableService*)this, evCuesheetChanged);
1585 }
1586
1587 void eDVBServicePlay::setCutListEnable(int enable)
1588 {
1589         m_cutlist_enabled = enable;
1590         cutlistToCuesheet();
1591 }
1592
1593 void eDVBServicePlay::updateTimeshiftPids()
1594 {
1595         if (!m_record)
1596                 return;
1597         
1598         eDVBServicePMTHandler::program program;
1599         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1600
1601         if (h.getProgramInfo(program))
1602                 return;
1603         else
1604         {
1605                 std::set<int> pids_to_record;
1606                 pids_to_record.insert(0); // PAT
1607                 if (program.pmtPid != -1)
1608                         pids_to_record.insert(program.pmtPid); // PMT
1609
1610                 if (program.textPid != -1)
1611                         pids_to_record.insert(program.textPid); // Videotext
1612
1613                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1614                         i(program.videoStreams.begin()); 
1615                         i != program.videoStreams.end(); ++i)
1616                         pids_to_record.insert(i->pid);
1617
1618                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1619                         i(program.audioStreams.begin()); 
1620                         i != program.audioStreams.end(); ++i)
1621                                 pids_to_record.insert(i->pid);
1622
1623                 std::set<int> new_pids, obsolete_pids;
1624                 
1625                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1626                                 m_pids_active.begin(), m_pids_active.end(),
1627                                 std::inserter(new_pids, new_pids.begin()));
1628                 
1629                 std::set_difference(
1630                                 m_pids_active.begin(), m_pids_active.end(),
1631                                 pids_to_record.begin(), pids_to_record.end(), 
1632                                 std::inserter(new_pids, new_pids.begin())
1633                                 );
1634
1635                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1636                         m_record->addPID(*i);
1637
1638                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1639                         m_record->removePID(*i);
1640         }
1641 }
1642
1643 void eDVBServicePlay::switchToLive()
1644 {
1645         if (!m_timeshift_active)
1646                 return;
1647         
1648         m_cue = 0;
1649         m_decoder = 0;
1650         m_decode_demux = 0;
1651         m_teletext_parser = 0;
1652         m_radiotext_parser = 0;
1653         m_subtitle_parser = 0;
1654         m_new_dvb_subtitle_page_connection = 0;
1655         m_new_subtitle_page_connection = 0;
1656         m_radiotext_updated_connection = 0;
1657
1658                 /* free the timeshift service handler, we need the resources */
1659         m_service_handler_timeshift.free();
1660         m_timeshift_active = 0;
1661
1662         m_event((iPlayableService*)this, evSeekableStatusChanged);
1663
1664         updateDecoder();
1665 }
1666
1667 void eDVBServicePlay::switchToTimeshift()
1668 {
1669         if (m_timeshift_active)
1670                 return;
1671
1672         m_decode_demux = 0;
1673         m_decoder = 0;
1674         m_teletext_parser = 0;
1675         m_radiotext_parser = 0;
1676         m_subtitle_parser = 0;
1677         m_new_subtitle_page_connection = 0;
1678         m_new_dvb_subtitle_page_connection = 0;
1679         m_radiotext_updated_connection = 0;
1680
1681         m_timeshift_active = 1;
1682
1683         m_event((iPlayableService*)this, evSeekableStatusChanged);
1684
1685         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1686         r.path = m_timeshift_file;
1687
1688         m_cue = new eCueSheet();
1689         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1690         updateDecoder(); /* mainly to switch off PCR */
1691 }
1692
1693 void eDVBServicePlay::updateDecoder()
1694 {
1695         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1696
1697         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1698
1699         bool defaultac3=false;
1700         std::string default_ac3;
1701
1702         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1703                 defaultac3 = default_ac3 == "True";
1704
1705         eDVBServicePMTHandler::program program;
1706         if (h.getProgramInfo(program))
1707                 eDebug("getting program info failed.");
1708         else
1709         {
1710                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1711                 if (!program.videoStreams.empty())
1712                 {
1713                         eDebugNoNewLine(" (");
1714                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1715                                 i(program.videoStreams.begin());
1716                                 i != program.videoStreams.end(); ++i)
1717                         {
1718                                 if (vpid == -1)
1719                                 {
1720                                         vpid = i->pid;
1721                                         vpidtype = i->type;
1722                                 }
1723                                 if (i != program.videoStreams.begin())
1724                                         eDebugNoNewLine(", ");
1725                                 eDebugNoNewLine("%04x", i->pid);
1726                         }
1727                         eDebugNoNewLine(")");
1728                 }
1729                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1730                 if (!program.audioStreams.empty())
1731                 {
1732                         eDebugNoNewLine(" (");
1733                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1734                                 i(program.audioStreams.begin());
1735                                 i != program.audioStreams.end(); ++i)
1736                         {
1737                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1738                                 {
1739                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1740                                         {
1741                                                 apid = i->pid;
1742                                                 apidtype = i->type;
1743                                         }
1744                                 }
1745                                 if (i != program.audioStreams.begin())
1746                                         eDebugNoNewLine(", ");
1747                                 eDebugNoNewLine("%04x", i->pid);
1748                         }
1749                         eDebugNoNewLine(")");
1750                 }
1751                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1752                 pcrpid = program.pcrPid;
1753                 eDebug(", and the text pid is %04x", program.textPid);
1754                 tpid = program.textPid;
1755         }
1756
1757         if (!m_decoder)
1758         {
1759                 h.getDecodeDemux(m_decode_demux);
1760                 if (m_decode_demux)
1761                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1762                 if (m_cue)
1763                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1764                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1765                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1766                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1767                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1768         }
1769
1770         if (m_decoder)
1771         {
1772                 if (m_dvb_service)
1773                 {
1774                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1775                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1776                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1777                 }
1778                 else // subservice or recording
1779                 {
1780                         eServiceReferenceDVB ref;
1781                         m_service_handler.getServiceReference(ref);
1782                         eServiceReferenceDVB parent = ref.getParentServiceReference();
1783                         if (!parent)
1784                                 parent = ref;
1785                         if (parent)
1786                         {
1787                                 ePtr<eDVBResourceManager> res_mgr;
1788                                 if (!eDVBResourceManager::getInstance(res_mgr))
1789                                 {
1790                                         ePtr<iDVBChannelList> db;
1791                                         if (!res_mgr->getChannelList(db))
1792                                         {
1793                                                 ePtr<eDVBService> origService;
1794                                                 if (!db->getService(parent, origService))
1795                                                 {
1796                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1797                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1798                                                 }
1799                                         }
1800                                 }
1801                         }
1802                 }
1803                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1804                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1805
1806                 m_decoder->setVideoPID(vpid, vpidtype);
1807                 m_decoder->setAudioPID(apid, apidtype);
1808                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1809                 {
1810                         m_decoder->setSyncPCR(pcrpid);
1811                         if (apid != -1)
1812                         {
1813                                 ePtr<iDVBDemux> data_demux;
1814                                 if (!h.getDataDemux(data_demux))
1815                                 {
1816                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1817                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1818                                         m_radiotext_parser->start(apid);
1819                                 }
1820                         }
1821                 }
1822                 else
1823                         m_decoder->setSyncPCR(-1);
1824
1825                 m_decoder->setTextPID(tpid);
1826
1827                 m_teletext_parser->start(program.textPid);
1828
1829                 if (!m_is_primary)
1830                         m_decoder->setTrickmode(1);
1831
1832                 m_decoder->start();
1833
1834                 if (vpid > 0 && vpid < 0x2000)
1835                         ;
1836                 else
1837                 {
1838                         std::string radio_pic;
1839                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1840                                 m_decoder->setRadioPic(radio_pic);
1841                 }
1842
1843                 m_decoder->setAudioChannel(achannel);
1844
1845 // how we can do this better?
1846 // update cache pid when the user changed the audio track or video track
1847 // TODO handling of difference audio types.. default audio types..
1848                                 
1849                 /* don't worry about non-existing services, nor pvr services */
1850                 if (m_dvb_service && !m_is_pvr)
1851                 {
1852                         if (apidtype == eDVBAudio::aMPEG)
1853                         {
1854                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1855                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1856                         }
1857                         else
1858                         {
1859                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1860                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1861                         }
1862                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1863                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1864                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1865                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1866                 }
1867         }
1868         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1869 }
1870
1871 void eDVBServicePlay::loadCuesheet()
1872 {
1873         std::string filename = m_reference.path + ".cuts";
1874         
1875         m_cue_entries.clear();
1876
1877         FILE *f = fopen(filename.c_str(), "rb");
1878
1879         if (f)
1880         {
1881                 eDebug("loading cuts..");
1882                 while (1)
1883                 {
1884                         unsigned long long where;
1885                         unsigned int what;
1886                         
1887                         if (!fread(&where, sizeof(where), 1, f))
1888                                 break;
1889                         if (!fread(&what, sizeof(what), 1, f))
1890                                 break;
1891                         
1892 #if BYTE_ORDER == LITTLE_ENDIAN
1893                         where = bswap_64(where);
1894 #endif
1895                         what = ntohl(what);
1896                         
1897                         if (what > 3)
1898                                 break;
1899                         
1900                         m_cue_entries.insert(cueEntry(where, what));
1901                 }
1902                 fclose(f);
1903                 eDebug("%d entries", m_cue_entries.size());
1904         } else
1905                 eDebug("cutfile not found!");
1906         
1907         m_cuesheet_changed = 0;
1908         cutlistToCuesheet();
1909         m_event((iPlayableService*)this, evCuesheetChanged);
1910 }
1911
1912 void eDVBServicePlay::saveCuesheet()
1913 {
1914         std::string filename = m_reference.path + ".cuts";
1915         
1916         FILE *f = fopen(filename.c_str(), "wb");
1917
1918         if (f)
1919         {
1920                 unsigned long long where;
1921                 int what;
1922
1923                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1924                 {
1925 #if BYTE_ORDER == BIG_ENDIAN
1926                         where = i->where;
1927 #else
1928                         where = bswap_64(i->where);
1929 #endif
1930                         what = htonl(i->what);
1931                         fwrite(&where, sizeof(where), 1, f);
1932                         fwrite(&what, sizeof(what), 1, f);
1933                         
1934                 }
1935                 fclose(f);
1936         }
1937         
1938         m_cuesheet_changed = 0;
1939 }
1940
1941 void eDVBServicePlay::cutlistToCuesheet()
1942 {
1943         if (!m_cue)
1944         {
1945                 eDebug("no cue sheet");
1946                 return;
1947         }       
1948         m_cue->clear();
1949         
1950         if (!m_cutlist_enabled)
1951         {
1952                 m_cue->commitSpans();
1953                 eDebug("cutlists were disabled");
1954                 return;
1955         }
1956
1957         pts_t in = 0, out = 0, length = 0;
1958         
1959         getLength(length);
1960                 
1961         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1962         
1963         while (1)
1964         {
1965                 if (i == m_cue_entries.end())
1966                         out = length;
1967                 else {
1968                         if (i->what == 0) /* in */
1969                         {
1970                                 in = i++->where;
1971                                 continue;
1972                         } else if (i->what == 1) /* out */
1973                                 out = i++->where;
1974                         else /* mark (2) or last play position (3) */
1975                         {
1976                                 i++;
1977                                 continue;
1978                         }
1979                 }
1980                 
1981                 if (in != out)
1982                         m_cue->addSourceSpan(in, out);
1983                 
1984                 in = length;
1985                 
1986                 if (i == m_cue_entries.end())
1987                         break;
1988         }
1989         m_cue->commitSpans();
1990 }
1991
1992 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *tuple)
1993 {
1994         if (m_subtitle_widget)
1995                 disableSubtitles(parent);
1996
1997         PyObject *entry = 0;
1998         int tuplesize = PyTuple_Size(tuple);
1999         int type = 0;
2000
2001         if (!PyTuple_Check(tuple))
2002                 goto error_out;
2003
2004         if (tuplesize < 1)
2005                 goto error_out;
2006
2007         entry = PyTuple_GET_ITEM(tuple, 0);
2008
2009         if (!PyInt_Check(entry))
2010                 goto error_out;
2011
2012         type = PyInt_AsLong(entry);
2013
2014         if (type == 1)  // teletext subtitles
2015         {
2016                 int page, magazine, pid;
2017                 if (tuplesize < 4)
2018                         goto error_out;
2019
2020                 if (!m_teletext_parser)
2021                 {
2022                         eDebug("enable teletext subtitles.. no parser !!!");
2023                         return -1;
2024                 }
2025
2026                 entry = PyTuple_GET_ITEM(tuple, 1);
2027                 if (!PyInt_Check(entry))
2028                         goto error_out;
2029                 pid = PyInt_AsLong(entry);
2030
2031                 entry = PyTuple_GET_ITEM(tuple, 2);
2032                 if (!PyInt_Check(entry))
2033                         goto error_out;
2034                 page = PyInt_AsLong(entry);
2035
2036                 entry = PyTuple_GET_ITEM(tuple, 3);
2037                 if (!PyInt_Check(entry))
2038                         goto error_out;
2039                 magazine = PyInt_AsLong(entry);
2040
2041                 m_subtitle_widget = new eSubtitleWidget(parent);
2042                 m_subtitle_widget->resize(parent->size()); /* full size */
2043                 m_teletext_parser->setPageAndMagazine(page, magazine);
2044                 if (m_dvb_service)
2045                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2046         }
2047         else if (type == 0)
2048         {
2049                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2050                 if (!m_subtitle_parser)
2051                 {
2052                         eDebug("enable dvb subtitles.. no parser !!!");
2053                         return -1;
2054                 }
2055                 if (tuplesize < 4)
2056                         goto error_out;
2057
2058                 entry = PyTuple_GET_ITEM(tuple, 1);
2059                 if (!PyInt_Check(entry))
2060                         goto error_out;
2061                 pid = PyInt_AsLong(entry);
2062
2063                 entry = PyTuple_GET_ITEM(tuple, 2);
2064                 if (!PyInt_Check(entry))
2065                         goto error_out;
2066                 composition_page_id = PyInt_AsLong(entry);
2067
2068                 entry = PyTuple_GET_ITEM(tuple, 3);
2069                 if (!PyInt_Check(entry))
2070                         goto error_out;
2071                 ancillary_page_id = PyInt_AsLong(entry);
2072
2073                 m_subtitle_widget = new eSubtitleWidget(parent);
2074                 m_subtitle_widget->resize(parent->size()); /* full size */
2075                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2076                 if (m_dvb_service)
2077                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2078         }
2079         else
2080                 goto error_out;
2081         return 0;
2082 error_out:
2083         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2084                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2085                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2086         return -1;
2087 }
2088
2089 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2090 {
2091         delete m_subtitle_widget;
2092         m_subtitle_widget = 0;
2093         if (m_subtitle_parser)
2094         {
2095                 m_subtitle_parser->stop();
2096                 m_dvb_subtitle_pages.clear();
2097         }
2098         if (m_teletext_parser)
2099         {
2100                 m_teletext_parser->setPageAndMagazine(-1, -1);
2101                 m_subtitle_pages.clear();
2102         }
2103         if (m_dvb_service)
2104                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2105         return 0;
2106 }
2107
2108 PyObject *eDVBServicePlay::getCachedSubtitle()
2109 {
2110         if (m_dvb_service)
2111         {
2112                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2113                 if (tmp != -1)
2114                 {
2115                         unsigned int data = (unsigned int)tmp;
2116                         int pid = (data&0xFFFF0000)>>16;
2117                         PyObject *tuple = PyTuple_New(4);
2118                         eDVBServicePMTHandler::program program;
2119                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2120                         if (!h.getProgramInfo(program))
2121                         {
2122                                 if (program.textPid==pid) // teletext
2123                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2124                                 else
2125                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2126                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2127                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2128                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2129                                 return tuple;
2130                         }
2131                 }
2132         }
2133         Py_INCREF(Py_None);
2134         return Py_None;
2135 }
2136
2137 PyObject *eDVBServicePlay::getSubtitleList()
2138 {
2139         if (!m_teletext_parser)
2140         {
2141                 Py_INCREF(Py_None);
2142                 return Py_None;
2143         }
2144         
2145         PyObject *l = PyList_New(0);
2146         std::set<int> added_ttx_pages;
2147
2148         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2149                 m_teletext_parser->m_found_subtitle_pages;
2150
2151         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2152         eDVBServicePMTHandler::program program;
2153         if (h.getProgramInfo(program))
2154                 eDebug("getting program info failed.");
2155         else
2156         {
2157                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2158                         it != program.subtitleStreams.end(); ++it)
2159                 {
2160                         switch(it->subtitling_type)
2161                         {
2162                                 case 0x01: // ebu teletext subtitles
2163                                 {
2164                                         int page_number = it->teletext_page_number & 0xFF;
2165                                         int magazine_number = it->teletext_magazine_number & 7;
2166                                         int hash = magazine_number << 8 | page_number;
2167                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2168                                         {
2169                                                 PyObject *tuple = PyTuple_New(5);
2170                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2171                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2172                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2173                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2174                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2175                                                 PyList_Append(l, tuple);
2176                                                 Py_DECREF(tuple);
2177                                                 added_ttx_pages.insert(hash);
2178                                         }
2179                                         break;
2180                                 }
2181                                 case 0x10 ... 0x13:
2182                                 case 0x20 ... 0x23: // dvb subtitles
2183                                 {
2184                                         PyObject *tuple = PyTuple_New(5);
2185                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2186                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2187                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2188                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2189                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2190                                         PyList_Insert(l, 0, tuple);
2191                                         Py_DECREF(tuple);
2192                                         break;
2193                                 }
2194                         }
2195                 }
2196         }
2197
2198         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2199                 it != subs.end(); ++it)
2200         {
2201                 int page_number = it->teletext_page_number & 0xFF;
2202                 int magazine_number = it->teletext_magazine_number & 7;
2203                 int hash = magazine_number << 8 | page_number;
2204                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2205                 {
2206                         PyObject *tuple = PyTuple_New(5);
2207                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2208                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2209                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2210                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2211                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2212                         PyList_Append(l, tuple);
2213                         Py_DECREF(tuple);
2214                 }
2215         }
2216
2217         return l;
2218 }
2219
2220 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2221 {
2222         if (m_subtitle_widget)
2223         {
2224                 m_subtitle_pages.push_back(page);
2225                 checkSubtitleTiming();
2226         }
2227 }
2228
2229 void eDVBServicePlay::checkSubtitleTiming()
2230 {
2231 //      eDebug("checkSubtitleTiming");
2232         if (!m_subtitle_widget)
2233                 return;
2234         while (1)
2235         {
2236                 enum { TELETEXT, DVB } type;
2237                 eDVBTeletextSubtitlePage page;
2238                 eDVBSubtitlePage dvb_page;
2239                 pts_t show_time;
2240                 if (!m_subtitle_pages.empty())
2241                 {
2242                         page = m_subtitle_pages.front();
2243                         type = TELETEXT;
2244                         show_time = page.m_pts;
2245                 }
2246                 else if (!m_dvb_subtitle_pages.empty())
2247                 {
2248                         dvb_page = m_dvb_subtitle_pages.front();
2249                         type = DVB;
2250                         show_time = dvb_page.m_show_time;
2251                 }
2252                 else
2253                         return;
2254         
2255                 pts_t pos = 0;
2256         
2257                 if (m_decoder)
2258                         m_decoder->getPTS(0, pos);
2259
2260 //              eDebug("%lld %lld", pos, show_time);
2261                 int diff =  show_time - pos;
2262                 if (diff < 0)
2263                 {
2264                         eDebug("[late (%d ms)]", -diff / 90);
2265                         diff = 0;
2266                 }
2267                 if (diff > 900000)
2268                 {
2269                         eDebug("[invalid]");
2270                         diff = 0;
2271                 }
2272         
2273                 if (!diff)
2274                 {
2275                         if (type == TELETEXT)
2276                         {
2277                                 eDebug("display teletext subtitle page");
2278                                 m_subtitle_widget->setPage(page);
2279                                 m_subtitle_pages.pop_front();
2280                         }
2281                         else
2282                         {
2283                                 eDebug("display dvb subtitle Page");
2284                                 m_subtitle_widget->setPage(dvb_page);
2285                                 m_dvb_subtitle_pages.pop_front();
2286                         }
2287                 } else
2288                 {
2289 //                      eDebug("start subtitle delay %d", diff / 90);
2290                         m_subtitle_sync_timer.start(diff / 90, 1);
2291                         break;
2292                 }
2293         }
2294 }
2295
2296 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2297 {
2298         if (m_subtitle_widget)
2299         {
2300                 m_dvb_subtitle_pages.push_back(p);
2301                 checkSubtitleTiming();
2302         }
2303 }
2304
2305 int eDVBServicePlay::getAC3Delay()
2306 {
2307         if (m_dvb_service)
2308                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2309         else if (m_decoder)
2310                 return m_decoder->getAC3Delay();
2311         else
2312                 return 0;
2313 }
2314
2315 int eDVBServicePlay::getPCMDelay()
2316 {
2317         if (m_dvb_service)
2318                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2319         else if (m_decoder)
2320                 return m_decoder->getPCMDelay();
2321         else
2322                 return 0;
2323 }
2324
2325 void eDVBServicePlay::setAC3Delay(int delay)
2326 {
2327         if (m_dvb_service)
2328                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2329         if (m_decoder)
2330                 m_decoder->setAC3Delay(delay);
2331 }
2332
2333 void eDVBServicePlay::setPCMDelay(int delay)
2334 {
2335         if (m_dvb_service)
2336                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2337         if (m_decoder)
2338                 m_decoder->setPCMDelay(delay);
2339 }
2340
2341 DEFINE_REF(eDVBServicePlay)
2342
2343 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");