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