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