add possibility to set per service ac3/pcm delay (not yet via gui)
[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                 /* inject EIT if there is a stored one */
756         if (m_is_pvr)
757         {
758                 std::string filename = service.path;
759                 filename.erase(filename.length()-2, 2);
760                 filename+="eit";
761                 int fd = ::open( filename.c_str(), O_RDONLY );
762                 if ( fd > -1 )
763                 {
764                         __u8 buf[4096];
765                         int rd = ::read(fd, buf, 4096);
766                         ::close(fd);
767                         if ( rd > 12 /*EIT_LOOP_SIZE*/ )
768                         {
769                                 Event ev(buf);
770                                 ePtr<eServiceEvent> event = new eServiceEvent;
771                                 ePtr<eServiceEvent> empty;
772                                 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
773                                 m_event_handler.inject(event, 0);
774                                 m_event_handler.inject(empty, 1);
775                                 eDebug("injected");
776                         }
777                 }
778         }
779         
780         if (m_is_pvr)
781                 loadCuesheet();
782
783         m_event(this, evStart);
784         m_event((iPlayableService*)this, evSeekableStatusChanged);
785         return 0;
786 }
787
788 RESULT eDVBServicePlay::stop()
789 {
790         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
791
792         m_service_handler_timeshift.free();
793         m_service_handler.free();
794         
795         if (m_is_pvr && m_cuesheet_changed)
796                 saveCuesheet();
797         
798         return 0;
799 }
800
801 RESULT eDVBServicePlay::setTarget(int target)
802 {
803         m_is_primary = !target;
804         return 0;
805 }
806
807 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
808 {
809         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
810         return 0;
811 }
812
813 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
814 {
815                 /* note: we check for timeshift to be enabled,
816                    not neccessary active. if you pause when timeshift
817                    is not active, you should activate it when unpausing */
818         if ((!m_is_pvr) && (!m_timeshift_enabled))
819         {
820                 ptr = 0;
821                 return -1;
822         }
823
824         ptr = this;
825         return 0;
826 }
827
828 RESULT eDVBServicePlay::setSlowMotion(int ratio)
829 {
830         if (m_decoder)
831                 return m_decoder->setSlowMotion(ratio);
832         else
833                 return -1;
834 }
835
836 RESULT eDVBServicePlay::setFastForward(int ratio)
837 {
838         int skipmode, ffratio;
839         
840         if (ratio > 8)
841         {
842                 skipmode = ratio;
843                 ffratio = 1;
844         } else if (ratio > 0)
845         {
846                 skipmode = 0;
847                 ffratio = ratio;
848         } else if (!ratio)
849         {
850                 skipmode = 0;
851                 ffratio = 0;
852         } else // if (ratio < 0)
853         {
854                 skipmode = ratio;
855                 ffratio = 1;
856         }
857
858         if (m_skipmode != skipmode)
859         {
860                 eDebug("setting cue skipmode to %d", skipmode);
861                 if (m_cue)
862                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
863         }
864         
865         m_skipmode = skipmode;
866         
867         if (!m_decoder)
868                 return -1;
869
870         return m_decoder->setFastForward(ffratio);
871 }
872     
873 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
874 {
875         if (m_is_pvr || m_timeshift_enabled)
876         {
877                 ptr = this;
878                 return 0;
879         }
880         
881         ptr = 0;
882         return -1;
883 }
884
885         /* TODO: when timeshift is enabled but not active, this doesn't work. */
886 RESULT eDVBServicePlay::getLength(pts_t &len)
887 {
888         ePtr<iDVBPVRChannel> pvr_channel;
889         
890         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
891                 return -1;
892         
893         return pvr_channel->getLength(len);
894 }
895
896 RESULT eDVBServicePlay::pause()
897 {
898         if (!m_is_paused && m_decoder)
899         {
900                 m_is_paused = 1;
901                 return m_decoder->freeze(0);
902         } else
903                 return -1;
904 }
905
906 RESULT eDVBServicePlay::unpause()
907 {
908         if (m_is_paused && m_decoder)
909         {
910                 m_is_paused = 0;
911                 return m_decoder->unfreeze();
912         } else
913                 return -1;
914 }
915
916 RESULT eDVBServicePlay::seekTo(pts_t to)
917 {
918         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
919         
920         if (!m_decode_demux)
921                 return -1;
922
923         ePtr<iDVBPVRChannel> pvr_channel;
924         
925         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
926                 return -1;
927         
928         if (!m_cue)
929                 return -1;
930         
931         m_cue->seekTo(0, to);
932         return 0;
933 }
934
935 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
936 {
937         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
938         
939         if (!m_decode_demux)
940                 return -1;
941
942         ePtr<iDVBPVRChannel> pvr_channel;
943         
944         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
945                 return -1;
946         
947         int mode = 1;
948         
949                         /* HACK until we have skip-AP api */
950         if ((to > 0) && (to < 100))
951                 mode = 2;
952         
953         to *= direction;
954         
955         if (!m_cue)
956                 return 0;
957         
958         m_cue->seekTo(mode, to);
959         return 0;
960 }
961
962 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
963 {
964         ePtr<iDVBPVRChannel> pvr_channel;
965         
966         if (!m_decode_demux)
967                 return -1;
968         
969         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
970                 return -1;
971         
972         int r = 0;
973
974                 /* if there is a decoder, use audio or video PTS */
975         if (m_decoder)
976         {
977                 r = m_decoder->getPTS(0, pos);
978                 if (r)
979                         return r;
980         }
981         
982                 /* fixup */
983         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
984 }
985
986 RESULT eDVBServicePlay::setTrickmode(int trick)
987 {
988         if (m_decoder)
989                 m_decoder->setTrickmode(trick);
990         return 0;
991 }
992
993 RESULT eDVBServicePlay::isCurrentlySeekable()
994 {
995         return m_is_pvr || m_timeshift_active;
996 }
997
998 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
999 {
1000         ptr = this;
1001         return 0;
1002 }
1003
1004 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1005 {
1006         ptr = this;
1007         return 0;
1008 }
1009
1010 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1011 {
1012         ptr = this;
1013         return 0;
1014 }
1015
1016 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1017 {
1018         ptr = this;
1019         return 0;
1020 }
1021
1022 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1023 {
1024         ptr = this;
1025         return 0;
1026 }
1027
1028 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1029 {
1030         ptr = 0;
1031         if (m_timeshift_enabled || !m_is_pvr)
1032         {
1033                 if (!m_timeshift_enabled)
1034                 {
1035                                 /* we need enough diskspace */
1036                         struct statfs fs;
1037                         if (statfs(TSPATH "/.", &fs) < 0)
1038                         {
1039                                 eDebug("statfs failed!");
1040                                 return -2;
1041                         }
1042                 
1043                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1044                         {
1045                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1046                                 return -3;
1047                         }
1048                 }
1049                 ptr = this;
1050                 return 0;
1051         }
1052         return -1;
1053 }
1054
1055 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1056 {
1057         if (m_is_pvr)
1058         {
1059                 ptr = this;
1060                 return 0;
1061         }
1062         ptr = 0;
1063         return -1;
1064 }
1065
1066 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1067 {
1068         ptr = this;
1069         return 0;
1070 }
1071
1072 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1073 {
1074         ptr = this;
1075         return 0;
1076 }
1077
1078 RESULT eDVBServicePlay::getName(std::string &name)
1079 {
1080         if (m_is_pvr)
1081         {
1082                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1083                 return i->getName(m_reference, name);
1084         }
1085         if (m_dvb_service)
1086         {
1087                 m_dvb_service->getName(m_reference, name);
1088                 if (name.empty())
1089                         name = "(...)";
1090         }
1091         else if (!m_reference.name.empty())
1092                 eStaticServiceDVBInformation().getName(m_reference, name);
1093         else
1094                 name = "DVB service";
1095         return 0;
1096 }
1097
1098 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1099 {
1100         return m_event_handler.getEvent(evt, nownext);
1101 }
1102
1103 int eDVBServicePlay::getInfo(int w)
1104 {
1105         eDVBServicePMTHandler::program program;
1106
1107         if (w == sCAIDs)
1108                 return resIsPyObject;
1109
1110         if (m_service_handler.getProgramInfo(program))
1111                 return -1;
1112         
1113         switch (w)
1114         {
1115         case sAspect:
1116                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1117                 {
1118                         ePtr<eServiceEvent> evt;
1119                         if (!m_event_handler.getEvent(evt, 0))
1120                         {
1121                                 ePtr<eComponentData> data;
1122                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1123                                 {
1124                                         if ( data->getStreamContent() == 1 )
1125                                         {
1126                                                 switch(data->getComponentType())
1127                                                 {
1128                                                         // SD
1129                                                         case 1: // 4:3 SD PAL
1130                                                         case 2:
1131                                                         case 3: // 16:9 SD PAL
1132                                                         case 4: // > 16:9 PAL
1133                                                         case 5: // 4:3 SD NTSC
1134                                                         case 6: 
1135                                                         case 7: // 16:9 SD NTSC
1136                                                         case 8: // > 16:9 NTSC
1137
1138                                                         // HD
1139                                                         case 9: // 4:3 HD PAL
1140                                                         case 0xA:
1141                                                         case 0xB: // 16:9 HD PAL
1142                                                         case 0xC: // > 16:9 HD PAL
1143                                                         case 0xD: // 4:3 HD NTSC
1144                                                         case 0xE:
1145                                                         case 0xF: // 16:9 HD NTSC
1146                                                         case 0x10: // > 16:9 HD PAL
1147                                                                 return data->getComponentType();
1148                                                 }
1149                                         }
1150                                 }
1151                         }
1152                 }
1153                 return -1;
1154         case sIsCrypted: return program.isCrypted();
1155         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1156         case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1157         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1158         case sPCRPID: return program.pcrPid;
1159         case sPMTPID: return program.pmtPid;
1160         case sTXTPID: return program.textPid;
1161         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1162         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1163         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1164         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1165         case sProvider: if (!m_dvb_service) return -1; return -2;
1166         default:
1167                 return -1;
1168         }
1169 }
1170
1171 std::string eDVBServicePlay::getInfoString(int w)
1172 {
1173         switch (w)
1174         {
1175         case sProvider:
1176                 if (!m_dvb_service) return "";
1177                 return m_dvb_service->m_provider_name;
1178         default:
1179                 break;
1180         }
1181         return iServiceInformation::getInfoString(w);
1182 }
1183
1184 PyObject *eDVBServicePlay::getInfoObject(int w)
1185 {
1186         switch (w)
1187         {
1188         case sCAIDs:
1189                 return m_service_handler.getCaIds();
1190         default:
1191                 break;
1192         }
1193         return iServiceInformation::getInfoObject(w);
1194 }
1195
1196 int eDVBServicePlay::getNumberOfTracks()
1197 {
1198         eDVBServicePMTHandler::program program;
1199         if (m_service_handler.getProgramInfo(program))
1200                 return 0;
1201         return program.audioStreams.size();
1202 }
1203
1204 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1205 {
1206         int ret = selectAudioStream(i);
1207
1208         if (m_decoder->start())
1209                 return -5;
1210
1211         return ret;
1212 }
1213
1214 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1215 {
1216         eDVBServicePMTHandler::program program;
1217
1218         if (m_service_handler.getProgramInfo(program))
1219                 return -1;
1220         
1221         if (i >= program.audioStreams.size())
1222                 return -2;
1223         
1224         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1225                 info.m_description = "MPEG";
1226         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1227                 info.m_description = "AC3";
1228         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1229                 info.m_description = "AAC";
1230         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1231                 info.m_description = "DTS";
1232         else
1233                 info.m_description = "???";
1234
1235         if (program.audioStreams[i].component_tag != -1)
1236         {
1237                 ePtr<eServiceEvent> evt;
1238                 if (!m_event_handler.getEvent(evt, 0))
1239                 {
1240                         ePtr<eComponentData> data;
1241                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1242                                 info.m_language = data->getText();
1243                 }
1244         }
1245
1246         if (info.m_language.empty())
1247                 info.m_language = program.audioStreams[i].language_code;
1248         
1249         return 0;
1250 }
1251
1252 int eDVBServicePlay::selectAudioStream(int i)
1253 {
1254         eDVBServicePMTHandler::program program;
1255
1256         if (m_service_handler.getProgramInfo(program))
1257                 return -1;
1258         
1259         if ((unsigned int)i >= program.audioStreams.size())
1260                 return -2;
1261         
1262         if (!m_decoder)
1263                 return -3;
1264         
1265         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1266                 return -4;
1267
1268         if (m_dvb_service && !m_is_pvr)
1269         {
1270                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1271                 {
1272                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1273                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1274                 }       else
1275                 {
1276                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1277                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1278                 }
1279         }
1280
1281         m_current_audio_stream = i;
1282
1283         return 0;
1284 }
1285
1286 int eDVBServicePlay::getCurrentChannel()
1287 {
1288         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1289 }
1290
1291 RESULT eDVBServicePlay::selectChannel(int i)
1292 {
1293         if (i < LEFT || i > RIGHT)
1294                 i = -1;  // Stereo
1295         if (m_dvb_service)
1296                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1297         if (m_decoder)
1298                 m_decoder->setAudioChannel(i);
1299         return 0;
1300 }
1301
1302 int eDVBServiceBase::getFrontendInfo(int w)
1303 {
1304         eUsePtr<iDVBChannel> channel;
1305         if(m_service_handler.getChannel(channel))
1306                 return 0;
1307         ePtr<iDVBFrontend> fe;
1308         if(channel->getFrontend(fe))
1309                 return 0;
1310         return fe->readFrontendData(w);
1311 }
1312
1313 PyObject *eDVBServiceBase::getFrontendData(bool original)
1314 {
1315         PyObject *ret=0;
1316
1317         eUsePtr<iDVBChannel> channel;
1318         if(!m_service_handler.getChannel(channel))
1319         {
1320                 ePtr<iDVBFrontend> fe;
1321                 if(!channel->getFrontend(fe))
1322                 {
1323                         ret = fe->readTransponderData(original);
1324                         if (ret)
1325                         {
1326                                 ePtr<iDVBFrontendParameters> feparm;
1327                                 channel->getCurrentFrontendParameters(feparm);
1328                                 if (feparm)
1329                                 {
1330                                         eDVBFrontendParametersSatellite osat;
1331                                         if (!feparm->getDVBS(osat))
1332                                         {
1333                                                 void PutToDict(PyObject *, const char*, long);
1334                                                 void PutToDict(PyObject *, const char*, const char*);
1335                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1336                                                 const char *tmp = "UNKNOWN";
1337                                                 switch(osat.polarisation)
1338                                                 {
1339                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1340                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1341                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1342                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1343                                                         default:break;
1344                                                 }
1345                                                 PutToDict(ret, "polarization", tmp);
1346                                         }
1347                                 }
1348                         }
1349                 }
1350         }
1351         if (!ret)
1352         {
1353                 ret = Py_None;
1354                 Py_INCREF(ret);
1355         }
1356         return ret;
1357 }
1358
1359 int eDVBServicePlay::getNumberOfSubservices()
1360 {
1361         ePtr<eServiceEvent> evt;
1362         if (!m_event_handler.getEvent(evt, 0))
1363                 return evt->getNumOfLinkageServices();
1364         return 0;
1365 }
1366
1367 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1368 {
1369         ePtr<eServiceEvent> evt;
1370         if (!m_event_handler.getEvent(evt, 0))
1371         {
1372                 if (!evt->getLinkageService(sub, m_reference, n))
1373                         return 0;
1374         }
1375         sub.type=eServiceReference::idInvalid;
1376         return -1;
1377 }
1378
1379 RESULT eDVBServicePlay::startTimeshift()
1380 {
1381         ePtr<iDVBDemux> demux;
1382         
1383         eDebug("Start timeshift!");
1384         
1385         if (m_timeshift_enabled)
1386                 return -1;
1387         
1388                 /* start recording with the data demux. */
1389         if (m_service_handler.getDataDemux(demux))
1390                 return -2;
1391
1392         demux->createTSRecorder(m_record);
1393         if (!m_record)
1394                 return -3;
1395
1396         char templ[]=TSPATH "/timeshift.XXXXXX";
1397         m_timeshift_fd = mkstemp(templ);
1398         m_timeshift_file = templ;
1399         
1400         eDebug("recording to %s", templ);
1401         
1402         if (m_timeshift_fd < 0)
1403         {
1404                 m_record = 0;
1405                 return -4;
1406         }
1407                 
1408         m_record->setTargetFD(m_timeshift_fd);
1409
1410         m_timeshift_enabled = 1;
1411         
1412         updateTimeshiftPids();
1413         m_record->start();
1414
1415         return 0;
1416 }
1417
1418 RESULT eDVBServicePlay::stopTimeshift()
1419 {
1420         if (!m_timeshift_enabled)
1421                 return -1;
1422         
1423         switchToLive();
1424         
1425         m_timeshift_enabled = 0;
1426         
1427         m_record->stop();
1428         m_record = 0;
1429         
1430         close(m_timeshift_fd);
1431         eDebug("remove timeshift file");
1432         remove(m_timeshift_file.c_str());
1433         
1434         return 0;
1435 }
1436
1437 int eDVBServicePlay::isTimeshiftActive()
1438 {
1439         return m_timeshift_enabled && m_timeshift_active;
1440 }
1441
1442 RESULT eDVBServicePlay::activateTimeshift()
1443 {
1444         if (!m_timeshift_enabled)
1445                 return -1;
1446         
1447         if (!m_timeshift_active)
1448         {
1449                 switchToTimeshift();
1450                 return 0;
1451         }
1452         
1453         return -2;
1454 }
1455
1456 PyObject *eDVBServicePlay::getCutList()
1457 {
1458         PyObject *list = PyList_New(0);
1459         
1460         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1461         {
1462                 PyObject *tuple = PyTuple_New(2);
1463                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1464                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1465                 PyList_Append(list, tuple);
1466                 Py_DECREF(tuple);
1467         }
1468         
1469         return list;
1470 }
1471
1472 void eDVBServicePlay::setCutList(PyObject *list)
1473 {
1474         if (!PyList_Check(list))
1475                 return;
1476         int size = PyList_Size(list);
1477         int i;
1478         
1479         m_cue_entries.clear();
1480         
1481         for (i=0; i<size; ++i)
1482         {
1483                 PyObject *tuple = PyList_GetItem(list, i);
1484                 if (!PyTuple_Check(tuple))
1485                 {
1486                         eDebug("non-tuple in cutlist");
1487                         continue;
1488                 }
1489                 if (PyTuple_Size(tuple) != 2)
1490                 {
1491                         eDebug("cutlist entries need to be a 2-tuple");
1492                         continue;
1493                 }
1494                 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1495                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1496                 {
1497                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1498                         continue;
1499                 }
1500                 pts_t pts = PyLong_AsLongLong(ppts);
1501                 int type = PyInt_AsLong(ptype);
1502                 m_cue_entries.insert(cueEntry(pts, type));
1503                 eDebug("adding %08llx, %d", pts, type);
1504         }
1505         m_cuesheet_changed = 1;
1506         
1507         cutlistToCuesheet();
1508         m_event((iPlayableService*)this, evCuesheetChanged);
1509 }
1510
1511 void eDVBServicePlay::setCutListEnable(int enable)
1512 {
1513         m_cutlist_enabled = enable;
1514         cutlistToCuesheet();
1515 }
1516
1517 void eDVBServicePlay::updateTimeshiftPids()
1518 {
1519         if (!m_record)
1520                 return;
1521         
1522         eDVBServicePMTHandler::program program;
1523         if (m_service_handler.getProgramInfo(program))
1524                 return;
1525         else
1526         {
1527                 std::set<int> pids_to_record;
1528                 pids_to_record.insert(0); // PAT
1529                 if (program.pmtPid != -1)
1530                         pids_to_record.insert(program.pmtPid); // PMT
1531
1532                 if (program.textPid != -1)
1533                         pids_to_record.insert(program.textPid); // Videotext
1534
1535                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1536                         i(program.videoStreams.begin()); 
1537                         i != program.videoStreams.end(); ++i)
1538                         pids_to_record.insert(i->pid);
1539
1540                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1541                         i(program.audioStreams.begin()); 
1542                         i != program.audioStreams.end(); ++i)
1543                                 pids_to_record.insert(i->pid);
1544
1545                 std::set<int> new_pids, obsolete_pids;
1546                 
1547                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1548                                 m_pids_active.begin(), m_pids_active.end(),
1549                                 std::inserter(new_pids, new_pids.begin()));
1550                 
1551                 std::set_difference(
1552                                 m_pids_active.begin(), m_pids_active.end(),
1553                                 pids_to_record.begin(), pids_to_record.end(), 
1554                                 std::inserter(new_pids, new_pids.begin())
1555                                 );
1556
1557                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1558                         m_record->addPID(*i);
1559
1560                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1561                         m_record->removePID(*i);
1562         }
1563 }
1564
1565 void eDVBServicePlay::switchToLive()
1566 {
1567         if (!m_timeshift_active)
1568                 return;
1569         
1570         m_cue = 0;
1571         m_decoder = 0;
1572         m_decode_demux = 0;
1573         m_teletext_parser = 0;
1574         m_new_subtitle_page_connection = 0;
1575         
1576                 /* free the timeshift service handler, we need the resources */
1577         m_service_handler_timeshift.free();
1578         m_timeshift_active = 0;
1579         
1580         m_event((iPlayableService*)this, evSeekableStatusChanged);
1581         
1582         updateDecoder();
1583 }
1584
1585 void eDVBServicePlay::switchToTimeshift()
1586 {
1587         if (m_timeshift_active)
1588                 return;
1589         
1590         m_decode_demux = 0;
1591         m_decoder = 0;
1592         m_teletext_parser = 0;
1593         m_new_subtitle_page_connection = 0;
1594         
1595         m_timeshift_active = 1;
1596
1597         m_event((iPlayableService*)this, evSeekableStatusChanged);
1598         
1599         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1600         r.path = m_timeshift_file;
1601         
1602         m_cue = new eCueSheet();
1603         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1604         updateDecoder(); /* mainly to switch off PCR */
1605 }
1606
1607 void eDVBServicePlay::updateDecoder()
1608 {
1609         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1610
1611         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1612
1613         bool defaultac3=false;
1614         std::string default_ac3;
1615
1616         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1617                 defaultac3 = default_ac3 == "enable";
1618
1619         eDVBServicePMTHandler::program program;
1620         if (h.getProgramInfo(program))
1621                 eDebug("getting program info failed.");
1622         else
1623         {
1624                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1625                 if (!program.videoStreams.empty())
1626                 {
1627                         eDebugNoNewLine(" (");
1628                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1629                                 i(program.videoStreams.begin()); 
1630                                 i != program.videoStreams.end(); ++i)
1631                         {
1632                                 if (vpid == -1)
1633                                 {
1634                                         vpid = i->pid;
1635                                         vpidtype = i->type;
1636                                 }
1637                                 if (i != program.videoStreams.begin())
1638                                         eDebugNoNewLine(", ");
1639                                 eDebugNoNewLine("%04x", i->pid);
1640                         }
1641                         eDebugNoNewLine(")");
1642                 }
1643                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1644                 if (!program.audioStreams.empty())
1645                 {
1646                         eDebugNoNewLine(" (");
1647                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1648                                 i(program.audioStreams.begin()); 
1649                                 i != program.audioStreams.end(); ++i)
1650                         {
1651                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1652                                 {
1653                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1654                                         {
1655                                                 apid = i->pid;
1656                                                 apidtype = i->type;
1657                                         }
1658                                 }
1659                                 if (i != program.audioStreams.begin())
1660                                         eDebugNoNewLine(", ");
1661                                 eDebugNoNewLine("%04x", i->pid);
1662                         }
1663                         eDebugNoNewLine(")");
1664                 }
1665                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1666                 pcrpid = program.pcrPid;
1667                 eDebug(", and the text pid is %04x", program.textPid);
1668                 tpid = program.textPid;
1669         }
1670
1671         if (!m_decoder)
1672         {
1673                 h.getDecodeDemux(m_decode_demux);
1674                 if (m_decode_demux)
1675                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1676                 if (m_cue)
1677                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1678 #ifdef INTERNAL_TELETEXT
1679                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1680                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1681 #endif
1682         }
1683
1684         if (m_decoder)
1685         {
1686                 if (m_dvb_service)
1687                 {
1688                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1689                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1690                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1691                 }
1692 /*
1693                 else if (m_reference.path.length()) // workaround for recordings
1694                 {
1695                         eDebug("playback %s", m_reference.toString().c_str());
1696                         
1697                         ePtr<eDVBResourceManager> res_mgr;
1698                         if (!eDVBResourceManager::getInstance(res_mgr))
1699                         {
1700                                 ePtr<iDVBChannelList> db;
1701                                 if (!res_mgr->getChannelList(db))
1702                                 {
1703                                         ePtr<eDVBService> origService;
1704                                         eServiceReference tmp = m_reference;
1705                                         tmp.path="";
1706                                         if (!db->getService((eServiceReferenceDVB&)tmp, origService))
1707                                         {
1708                                                 ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1709                                                 pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1710                                         }
1711                                 }
1712                         }
1713                 }
1714 */
1715
1716                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1717                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1718
1719                 m_decoder->setVideoPID(vpid, vpidtype);
1720                 m_current_audio_stream = 0;
1721                 m_decoder->setAudioPID(apid, apidtype);
1722                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1723                         m_decoder->setSyncPCR(pcrpid);
1724                 else
1725                         m_decoder->setSyncPCR(-1);
1726
1727                 m_decoder->setTextPID(tpid);
1728
1729                 if (m_teletext_parser)
1730                         m_teletext_parser->start(tpid);
1731
1732                 if (!m_is_primary)
1733                         m_decoder->setTrickmode(1);
1734
1735                 m_decoder->start();
1736
1737                 m_decoder->setAudioChannel(achannel);
1738
1739 // how we can do this better?
1740 // update cache pid when the user changed the audio track or video track
1741 // TODO handling of difference audio types.. default audio types..
1742                                 
1743                 /* don't worry about non-existing services, nor pvr services */
1744                 if (m_dvb_service && !m_is_pvr)
1745                 {
1746                         if (apidtype == eDVBAudio::aMPEG)
1747                         {
1748                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1749                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1750                         }
1751                         else
1752                         {
1753                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1754                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1755                         }
1756                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1757                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1758                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1759                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1760                 }
1761         }
1762 }
1763
1764 void eDVBServicePlay::loadCuesheet()
1765 {
1766         std::string filename = m_reference.path + ".cuts";
1767         
1768         m_cue_entries.clear();
1769
1770         FILE *f = fopen(filename.c_str(), "rb");
1771
1772         if (f)
1773         {
1774                 eDebug("loading cuts..");
1775                 while (1)
1776                 {
1777                         unsigned long long where;
1778                         unsigned int what;
1779                         
1780                         if (!fread(&where, sizeof(where), 1, f))
1781                                 break;
1782                         if (!fread(&what, sizeof(what), 1, f))
1783                                 break;
1784                         
1785 #if BYTE_ORDER == LITTLE_ENDIAN
1786                         where = bswap_64(where);
1787 #endif
1788                         what = ntohl(what);
1789                         
1790                         if (what > 2)
1791                                 break;
1792                         
1793                         m_cue_entries.insert(cueEntry(where, what));
1794                 }
1795                 fclose(f);
1796                 eDebug("%d entries", m_cue_entries.size());
1797         } else
1798                 eDebug("cutfile not found!");
1799         
1800         m_cuesheet_changed = 0;
1801         cutlistToCuesheet();
1802         m_event((iPlayableService*)this, evCuesheetChanged);
1803 }
1804
1805 void eDVBServicePlay::saveCuesheet()
1806 {
1807         std::string filename = m_reference.path + ".cuts";
1808         
1809         FILE *f = fopen(filename.c_str(), "wb");
1810
1811         if (f)
1812         {
1813                 unsigned long long where;
1814                 int what;
1815
1816                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1817                 {
1818 #if BYTE_ORDER == BIG_ENDIAN
1819                         where = i->where;
1820 #else
1821                         where = bswap_64(i->where);
1822 #endif
1823                         what = htonl(i->what);
1824                         fwrite(&where, sizeof(where), 1, f);
1825                         fwrite(&what, sizeof(what), 1, f);
1826                         
1827                 }
1828                 fclose(f);
1829         }
1830         
1831         m_cuesheet_changed = 0;
1832 }
1833
1834 void eDVBServicePlay::cutlistToCuesheet()
1835 {
1836         if (!m_cue)
1837         {
1838                 eDebug("no cue sheet");
1839                 return;
1840         }       
1841         m_cue->clear();
1842         
1843         if (!m_cutlist_enabled)
1844         {
1845                 m_cue->commitSpans();
1846                 eDebug("cutlists where disabled");
1847                 return;
1848         }
1849
1850         pts_t in = 0, out = 0, length = 0;
1851         
1852         getLength(length);
1853                 
1854         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1855         
1856         while (1)
1857         {
1858                 if (i == m_cue_entries.end())
1859                         out = length;
1860                 else {
1861                         if (i->what == 0) /* in */
1862                         {
1863                                 in = i++->where;
1864                                 continue;
1865                         } else if (i->what == 1) /* out */
1866                                 out = i++->where;
1867                         else /* mark */
1868                         {
1869                                 i++;
1870                                 continue;
1871                         }
1872                 }
1873                 
1874                 if (in != out)
1875                         m_cue->addSourceSpan(in, out);
1876                 
1877                 in = length;
1878                 
1879                 if (i == m_cue_entries.end())
1880                         break;
1881         }
1882         m_cue->commitSpans();
1883 }
1884
1885 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1886 {
1887         if (m_subtitle_widget)
1888                 disableSubtitles(parent);
1889         
1890         if (!m_teletext_parser)
1891                 return -1;
1892         
1893         if (!PyInt_Check(entry))
1894                 return -1;
1895         
1896         m_subtitle_widget = new eSubtitleWidget(parent);
1897         m_subtitle_widget->resize(parent->size()); /* full size */
1898         
1899         int page = PyInt_AsLong(entry);
1900         
1901         m_teletext_parser->setPage(page);
1902
1903         return 0;
1904 }
1905
1906 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1907 {
1908         delete m_subtitle_widget;
1909         m_subtitle_widget = 0;
1910         return 0;
1911 }
1912
1913 PyObject *eDVBServicePlay::getSubtitleList()
1914 {
1915         if (!m_teletext_parser)
1916         {
1917                 Py_INCREF(Py_None);
1918                 return Py_None;
1919         }
1920         
1921         PyObject *l = PyList_New(0);
1922         
1923         for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1924         {
1925                 PyObject *tuple = PyTuple_New(2);
1926                 char desc[20];
1927                 sprintf(desc, "Page %x", *i);
1928                 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1929                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1930                 PyList_Append(l, tuple);
1931         }
1932         
1933         return l;
1934 }
1935
1936 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1937 {
1938         if (m_subtitle_widget)
1939         {
1940                 m_subtitle_pages.push_back(page);
1941                 
1942                 checkSubtitleTiming();
1943         }
1944 }
1945
1946 void eDVBServicePlay::checkSubtitleTiming()
1947 {
1948         while (1)
1949         {
1950                 if (m_subtitle_pages.empty())
1951                         return;
1952         
1953                 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1954         
1955                 pts_t pos = 0;
1956         
1957                 if (m_decoder)
1958                         m_decoder->getPTS(0, pos);
1959         
1960                 int diff = p.m_pts - pos;
1961                 if (diff < 0)
1962                 {
1963                         eDebug("[late (%d ms)]", -diff / 90);
1964                         diff = 0;
1965                 }
1966                 if (diff > 900000)
1967                 {
1968                         eDebug("[invalid]");
1969                         diff = 0;
1970                 }
1971         
1972                 if (!diff)
1973                 {
1974                         m_subtitle_widget->setPage(p);
1975                         m_subtitle_pages.pop_front();
1976                 } else
1977                 {
1978                         m_subtitle_sync_timer.start(diff / 90, 1);
1979                         break;
1980                 }
1981         }
1982 }
1983
1984 int eDVBServicePlay::getAC3Delay()
1985 {
1986         if (m_dvb_service)
1987                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1988         else if (m_decoder)
1989                 return m_decoder->getAC3Delay();
1990         else
1991                 return 0;
1992 }
1993
1994 int eDVBServicePlay::getPCMDelay()
1995 {
1996         if (m_dvb_service)
1997                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1998         else if (m_decoder)
1999                 return m_decoder->getPCMDelay();
2000         else
2001                 return 0;
2002 }
2003
2004 void eDVBServicePlay::setAC3Delay(int delay)
2005 {
2006         if (m_dvb_service)
2007                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay);
2008         if (m_decoder)
2009                 m_decoder->setAC3Delay(delay);
2010 }
2011
2012 void eDVBServicePlay::setPCMDelay(int delay)
2013 {
2014         if (m_dvb_service)
2015                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay);
2016         if (m_decoder)
2017                 m_decoder->setPCMDelay(delay);
2018 }
2019
2020 DEFINE_REF(eDVBServicePlay)
2021
2022 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");