bae45aaea2fb12404b8848443ad6755c9719c0b3
[openblackhole/openblackhole-enigma2.git] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/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_have_video_pid(0), 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_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1032                 (m_timeshift_enabled || !m_is_pvr))
1033         {
1034                 if (!m_timeshift_enabled)
1035                 {
1036                                 /* we need enough diskspace */
1037                         struct statfs fs;
1038                         if (statfs(TSPATH "/.", &fs) < 0)
1039                         {
1040                                 eDebug("statfs failed!");
1041                                 return -2;
1042                         }
1043                 
1044                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1045                         {
1046                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1047                                 return -3;
1048                         }
1049                 }
1050                 ptr = this;
1051                 return 0;
1052         }
1053         return -1;
1054 }
1055
1056 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1057 {
1058         if (m_is_pvr)
1059         {
1060                 ptr = this;
1061                 return 0;
1062         }
1063         ptr = 0;
1064         return -1;
1065 }
1066
1067 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1068 {
1069         ptr = this;
1070         return 0;
1071 }
1072
1073 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1074 {
1075         ptr = this;
1076         return 0;
1077 }
1078
1079 RESULT eDVBServicePlay::getName(std::string &name)
1080 {
1081         if (m_is_pvr)
1082         {
1083                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1084                 return i->getName(m_reference, name);
1085         }
1086         if (m_dvb_service)
1087         {
1088                 m_dvb_service->getName(m_reference, name);
1089                 if (name.empty())
1090                         name = "(...)";
1091         }
1092         else if (!m_reference.name.empty())
1093                 eStaticServiceDVBInformation().getName(m_reference, name);
1094         else
1095                 name = "DVB service";
1096         return 0;
1097 }
1098
1099 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1100 {
1101         return m_event_handler.getEvent(evt, nownext);
1102 }
1103
1104 int eDVBServicePlay::getInfo(int w)
1105 {
1106         eDVBServicePMTHandler::program program;
1107
1108         if (w == sCAIDs)
1109                 return resIsPyObject;
1110
1111         if (m_service_handler.getProgramInfo(program))
1112                 return -1;
1113         
1114         switch (w)
1115         {
1116         case sAspect:
1117                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1118                 {
1119                         ePtr<eServiceEvent> evt;
1120                         if (!m_event_handler.getEvent(evt, 0))
1121                         {
1122                                 ePtr<eComponentData> data;
1123                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1124                                 {
1125                                         if ( data->getStreamContent() == 1 )
1126                                         {
1127                                                 switch(data->getComponentType())
1128                                                 {
1129                                                         // SD
1130                                                         case 1: // 4:3 SD PAL
1131                                                         case 2:
1132                                                         case 3: // 16:9 SD PAL
1133                                                         case 4: // > 16:9 PAL
1134                                                         case 5: // 4:3 SD NTSC
1135                                                         case 6: 
1136                                                         case 7: // 16:9 SD NTSC
1137                                                         case 8: // > 16:9 NTSC
1138
1139                                                         // HD
1140                                                         case 9: // 4:3 HD PAL
1141                                                         case 0xA:
1142                                                         case 0xB: // 16:9 HD PAL
1143                                                         case 0xC: // > 16:9 HD PAL
1144                                                         case 0xD: // 4:3 HD NTSC
1145                                                         case 0xE:
1146                                                         case 0xF: // 16:9 HD NTSC
1147                                                         case 0x10: // > 16:9 HD PAL
1148                                                                 return data->getComponentType();
1149                                                 }
1150                                         }
1151                                 }
1152                         }
1153                 }
1154                 return -1;
1155         case sIsCrypted: return program.isCrypted();
1156         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1157         case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1158         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1159         case sPCRPID: return program.pcrPid;
1160         case sPMTPID: return program.pmtPid;
1161         case sTXTPID: return program.textPid;
1162         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1163         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1164         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1165         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1166         case sProvider: if (!m_dvb_service) return -1; return -2;
1167         default:
1168                 return -1;
1169         }
1170 }
1171
1172 std::string eDVBServicePlay::getInfoString(int w)
1173 {
1174         switch (w)
1175         {
1176         case sProvider:
1177                 if (!m_dvb_service) return "";
1178                 return m_dvb_service->m_provider_name;
1179         default:
1180                 break;
1181         }
1182         return iServiceInformation::getInfoString(w);
1183 }
1184
1185 PyObject *eDVBServicePlay::getInfoObject(int w)
1186 {
1187         switch (w)
1188         {
1189         case sCAIDs:
1190                 return m_service_handler.getCaIds();
1191         default:
1192                 break;
1193         }
1194         return iServiceInformation::getInfoObject(w);
1195 }
1196
1197 int eDVBServicePlay::getNumberOfTracks()
1198 {
1199         eDVBServicePMTHandler::program program;
1200         if (m_service_handler.getProgramInfo(program))
1201                 return 0;
1202         return program.audioStreams.size();
1203 }
1204
1205 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1206 {
1207         int ret = selectAudioStream(i);
1208
1209         if (m_decoder->start())
1210                 return -5;
1211
1212         return ret;
1213 }
1214
1215 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1216 {
1217         eDVBServicePMTHandler::program program;
1218
1219         if (m_service_handler.getProgramInfo(program))
1220                 return -1;
1221         
1222         if (i >= program.audioStreams.size())
1223                 return -2;
1224         
1225         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1226                 info.m_description = "MPEG";
1227         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1228                 info.m_description = "AC3";
1229         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1230                 info.m_description = "AAC";
1231         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1232                 info.m_description = "DTS";
1233         else
1234                 info.m_description = "???";
1235
1236         if (program.audioStreams[i].component_tag != -1)
1237         {
1238                 ePtr<eServiceEvent> evt;
1239                 if (!m_event_handler.getEvent(evt, 0))
1240                 {
1241                         ePtr<eComponentData> data;
1242                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1243                                 info.m_language = data->getText();
1244                 }
1245         }
1246
1247         if (info.m_language.empty())
1248                 info.m_language = program.audioStreams[i].language_code;
1249         
1250         return 0;
1251 }
1252
1253 int eDVBServicePlay::selectAudioStream(int i)
1254 {
1255         eDVBServicePMTHandler::program program;
1256
1257         if (m_service_handler.getProgramInfo(program))
1258                 return -1;
1259         
1260         if ((unsigned int)i >= program.audioStreams.size())
1261                 return -2;
1262         
1263         if (!m_decoder)
1264                 return -3;
1265         
1266         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1267                 return -4;
1268
1269         if (m_dvb_service && !m_is_pvr)
1270         {
1271                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1272                 {
1273                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1274                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1275                 }       else
1276                 {
1277                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1278                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1279                 }
1280         }
1281
1282         m_current_audio_stream = i;
1283
1284         return 0;
1285 }
1286
1287 int eDVBServicePlay::getCurrentChannel()
1288 {
1289         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1290 }
1291
1292 RESULT eDVBServicePlay::selectChannel(int i)
1293 {
1294         if (i < LEFT || i > RIGHT || i == STEREO)
1295                 i = -1;  // Stereo
1296         if (m_dvb_service)
1297                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1298         if (m_decoder)
1299                 m_decoder->setAudioChannel(i);
1300         return 0;
1301 }
1302
1303 int eDVBServiceBase::getFrontendInfo(int w)
1304 {
1305         eUsePtr<iDVBChannel> channel;
1306         if(m_service_handler.getChannel(channel))
1307                 return 0;
1308         ePtr<iDVBFrontend> fe;
1309         if(channel->getFrontend(fe))
1310                 return 0;
1311         return fe->readFrontendData(w);
1312 }
1313
1314 PyObject *eDVBServiceBase::getFrontendData(bool original)
1315 {
1316         PyObject *ret=0;
1317
1318         eUsePtr<iDVBChannel> channel;
1319         if(!m_service_handler.getChannel(channel))
1320         {
1321                 ePtr<iDVBFrontend> fe;
1322                 if(!channel->getFrontend(fe))
1323                 {
1324                         ret = fe->readTransponderData(original);
1325                         if (ret)
1326                         {
1327                                 ePtr<iDVBFrontendParameters> feparm;
1328                                 channel->getCurrentFrontendParameters(feparm);
1329                                 if (feparm)
1330                                 {
1331                                         eDVBFrontendParametersSatellite osat;
1332                                         if (!feparm->getDVBS(osat))
1333                                         {
1334                                                 void PutToDict(PyObject *, const char*, long);
1335                                                 void PutToDict(PyObject *, const char*, const char*);
1336                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1337                                                 const char *tmp = "UNKNOWN";
1338                                                 switch(osat.polarisation)
1339                                                 {
1340                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1341                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1342                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1343                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1344                                                         default:break;
1345                                                 }
1346                                                 PutToDict(ret, "polarization", tmp);
1347                                         }
1348                                 }
1349                         }
1350                 }
1351         }
1352         if (!ret)
1353         {
1354                 ret = Py_None;
1355                 Py_INCREF(ret);
1356         }
1357         return ret;
1358 }
1359
1360 int eDVBServicePlay::getNumberOfSubservices()
1361 {
1362         ePtr<eServiceEvent> evt;
1363         if (!m_event_handler.getEvent(evt, 0))
1364                 return evt->getNumOfLinkageServices();
1365         return 0;
1366 }
1367
1368 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1369 {
1370         ePtr<eServiceEvent> evt;
1371         if (!m_event_handler.getEvent(evt, 0))
1372         {
1373                 if (!evt->getLinkageService(sub, m_reference, n))
1374                         return 0;
1375         }
1376         sub.type=eServiceReference::idInvalid;
1377         return -1;
1378 }
1379
1380 RESULT eDVBServicePlay::startTimeshift()
1381 {
1382         ePtr<iDVBDemux> demux;
1383         
1384         eDebug("Start timeshift!");
1385         
1386         if (m_timeshift_enabled)
1387                 return -1;
1388         
1389                 /* start recording with the data demux. */
1390         if (m_service_handler.getDataDemux(demux))
1391                 return -2;
1392
1393         demux->createTSRecorder(m_record);
1394         if (!m_record)
1395                 return -3;
1396
1397         char templ[]=TSPATH "/timeshift.XXXXXX";
1398         m_timeshift_fd = mkstemp(templ);
1399         m_timeshift_file = templ;
1400         
1401         eDebug("recording to %s", templ);
1402         
1403         if (m_timeshift_fd < 0)
1404         {
1405                 m_record = 0;
1406                 return -4;
1407         }
1408                 
1409         m_record->setTargetFD(m_timeshift_fd);
1410
1411         m_timeshift_enabled = 1;
1412         
1413         updateTimeshiftPids();
1414         m_record->start();
1415
1416         return 0;
1417 }
1418
1419 RESULT eDVBServicePlay::stopTimeshift()
1420 {
1421         if (!m_timeshift_enabled)
1422                 return -1;
1423         
1424         switchToLive();
1425         
1426         m_timeshift_enabled = 0;
1427         
1428         m_record->stop();
1429         m_record = 0;
1430         
1431         close(m_timeshift_fd);
1432         eDebug("remove timeshift file");
1433         remove(m_timeshift_file.c_str());
1434         
1435         return 0;
1436 }
1437
1438 int eDVBServicePlay::isTimeshiftActive()
1439 {
1440         return m_timeshift_enabled && m_timeshift_active;
1441 }
1442
1443 RESULT eDVBServicePlay::activateTimeshift()
1444 {
1445         if (!m_timeshift_enabled)
1446                 return -1;
1447         
1448         if (!m_timeshift_active)
1449         {
1450                 switchToTimeshift();
1451                 return 0;
1452         }
1453         
1454         return -2;
1455 }
1456
1457 PyObject *eDVBServicePlay::getCutList()
1458 {
1459         PyObject *list = PyList_New(0);
1460         
1461         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1462         {
1463                 PyObject *tuple = PyTuple_New(2);
1464                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1465                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1466                 PyList_Append(list, tuple);
1467                 Py_DECREF(tuple);
1468         }
1469         
1470         return list;
1471 }
1472
1473 void eDVBServicePlay::setCutList(PyObject *list)
1474 {
1475         if (!PyList_Check(list))
1476                 return;
1477         int size = PyList_Size(list);
1478         int i;
1479         
1480         m_cue_entries.clear();
1481         
1482         for (i=0; i<size; ++i)
1483         {
1484                 PyObject *tuple = PyList_GetItem(list, i);
1485                 if (!PyTuple_Check(tuple))
1486                 {
1487                         eDebug("non-tuple in cutlist");
1488                         continue;
1489                 }
1490                 if (PyTuple_Size(tuple) != 2)
1491                 {
1492                         eDebug("cutlist entries need to be a 2-tuple");
1493                         continue;
1494                 }
1495                 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1496                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1497                 {
1498                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1499                         continue;
1500                 }
1501                 pts_t pts = PyLong_AsLongLong(ppts);
1502                 int type = PyInt_AsLong(ptype);
1503                 m_cue_entries.insert(cueEntry(pts, type));
1504                 eDebug("adding %08llx, %d", pts, type);
1505         }
1506         m_cuesheet_changed = 1;
1507         
1508         cutlistToCuesheet();
1509         m_event((iPlayableService*)this, evCuesheetChanged);
1510 }
1511
1512 void eDVBServicePlay::setCutListEnable(int enable)
1513 {
1514         m_cutlist_enabled = enable;
1515         cutlistToCuesheet();
1516 }
1517
1518 void eDVBServicePlay::updateTimeshiftPids()
1519 {
1520         if (!m_record)
1521                 return;
1522         
1523         eDVBServicePMTHandler::program program;
1524         if (m_service_handler.getProgramInfo(program))
1525                 return;
1526         else
1527         {
1528                 std::set<int> pids_to_record;
1529                 pids_to_record.insert(0); // PAT
1530                 if (program.pmtPid != -1)
1531                         pids_to_record.insert(program.pmtPid); // PMT
1532
1533                 if (program.textPid != -1)
1534                         pids_to_record.insert(program.textPid); // Videotext
1535
1536                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1537                         i(program.videoStreams.begin()); 
1538                         i != program.videoStreams.end(); ++i)
1539                         pids_to_record.insert(i->pid);
1540
1541                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1542                         i(program.audioStreams.begin()); 
1543                         i != program.audioStreams.end(); ++i)
1544                                 pids_to_record.insert(i->pid);
1545
1546                 std::set<int> new_pids, obsolete_pids;
1547                 
1548                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1549                                 m_pids_active.begin(), m_pids_active.end(),
1550                                 std::inserter(new_pids, new_pids.begin()));
1551                 
1552                 std::set_difference(
1553                                 m_pids_active.begin(), m_pids_active.end(),
1554                                 pids_to_record.begin(), pids_to_record.end(), 
1555                                 std::inserter(new_pids, new_pids.begin())
1556                                 );
1557
1558                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1559                         m_record->addPID(*i);
1560
1561                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1562                         m_record->removePID(*i);
1563         }
1564 }
1565
1566 void eDVBServicePlay::switchToLive()
1567 {
1568         if (!m_timeshift_active)
1569                 return;
1570         
1571         m_cue = 0;
1572         m_decoder = 0;
1573         m_decode_demux = 0;
1574         m_teletext_parser = 0;
1575         m_new_subtitle_page_connection = 0;
1576         
1577                 /* free the timeshift service handler, we need the resources */
1578         m_service_handler_timeshift.free();
1579         m_timeshift_active = 0;
1580         
1581         m_event((iPlayableService*)this, evSeekableStatusChanged);
1582         
1583         updateDecoder();
1584 }
1585
1586 void eDVBServicePlay::switchToTimeshift()
1587 {
1588         if (m_timeshift_active)
1589                 return;
1590         
1591         m_decode_demux = 0;
1592         m_decoder = 0;
1593         m_teletext_parser = 0;
1594         m_new_subtitle_page_connection = 0;
1595         
1596         m_timeshift_active = 1;
1597
1598         m_event((iPlayableService*)this, evSeekableStatusChanged);
1599         
1600         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1601         r.path = m_timeshift_file;
1602         
1603         m_cue = new eCueSheet();
1604         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1605         updateDecoder(); /* mainly to switch off PCR */
1606 }
1607
1608 void eDVBServicePlay::updateDecoder()
1609 {
1610         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1611
1612         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1613
1614         bool defaultac3=false;
1615         std::string default_ac3;
1616
1617         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1618                 defaultac3 = default_ac3 == "enable";
1619
1620         eDVBServicePMTHandler::program program;
1621         if (h.getProgramInfo(program))
1622                 eDebug("getting program info failed.");
1623         else
1624         {
1625                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1626                 if (!program.videoStreams.empty())
1627                 {
1628                         eDebugNoNewLine(" (");
1629                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1630                                 i(program.videoStreams.begin()); 
1631                                 i != program.videoStreams.end(); ++i)
1632                         {
1633                                 if (vpid == -1)
1634                                 {
1635                                         vpid = i->pid;
1636                                         vpidtype = i->type;
1637                                 }
1638                                 if (i != program.videoStreams.begin())
1639                                         eDebugNoNewLine(", ");
1640                                 eDebugNoNewLine("%04x", i->pid);
1641                         }
1642                         eDebugNoNewLine(")");
1643                 }
1644                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1645                 if (!program.audioStreams.empty())
1646                 {
1647                         eDebugNoNewLine(" (");
1648                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1649                                 i(program.audioStreams.begin()); 
1650                                 i != program.audioStreams.end(); ++i)
1651                         {
1652                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1653                                 {
1654                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1655                                         {
1656                                                 apid = i->pid;
1657                                                 apidtype = i->type;
1658                                         }
1659                                 }
1660                                 if (i != program.audioStreams.begin())
1661                                         eDebugNoNewLine(", ");
1662                                 eDebugNoNewLine("%04x", i->pid);
1663                         }
1664                         eDebugNoNewLine(")");
1665                 }
1666                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1667                 pcrpid = program.pcrPid;
1668                 eDebug(", and the text pid is %04x", program.textPid);
1669                 tpid = program.textPid;
1670         }
1671
1672         if (!m_decoder)
1673         {
1674                 h.getDecodeDemux(m_decode_demux);
1675                 if (m_decode_demux)
1676                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1677                 if (m_cue)
1678                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1679 #ifdef INTERNAL_TELETEXT
1680                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1681                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1682 #endif
1683         }
1684
1685         if (m_decoder)
1686         {
1687                 if (m_dvb_service)
1688                 {
1689                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1690                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1691                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1692                 }
1693                 else // subservice or recording
1694                 {
1695                         eServiceReferenceDVB ref;
1696                         m_service_handler.getServiceReference(ref);
1697                         eServiceReferenceDVB parent = ref.getParentServiceReference();
1698                         if (!parent)
1699                                 parent = ref;
1700                         if (parent)
1701                         {
1702                                 ePtr<eDVBResourceManager> res_mgr;
1703                                 if (!eDVBResourceManager::getInstance(res_mgr))
1704                                 {
1705                                         ePtr<iDVBChannelList> db;
1706                                         if (!res_mgr->getChannelList(db))
1707                                         {
1708                                                 ePtr<eDVBService> origService;
1709                                                 if (!db->getService(parent, origService))
1710                                                 {
1711                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1712                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1713                                                 }
1714                                         }
1715                                 }
1716                         }
1717                 }
1718                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1719                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1720
1721                 m_decoder->setVideoPID(vpid, vpidtype);
1722                 m_current_audio_stream = 0;
1723                 m_decoder->setAudioPID(apid, apidtype);
1724                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1725                         m_decoder->setSyncPCR(pcrpid);
1726                 else
1727                         m_decoder->setSyncPCR(-1);
1728
1729                 m_decoder->setTextPID(tpid);
1730
1731                 if (m_teletext_parser)
1732                         m_teletext_parser->start(tpid);
1733
1734                 if (!m_is_primary)
1735                         m_decoder->setTrickmode(1);
1736
1737                 m_decoder->start();
1738
1739                 if (vpid > 0 && vpid < 0x2000)
1740                         ;
1741                 else
1742                 {
1743                         std::string radio_pic;
1744                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1745                                 m_decoder->setRadioPic(radio_pic);
1746                 }
1747
1748                 m_decoder->setAudioChannel(achannel);
1749
1750 // how we can do this better?
1751 // update cache pid when the user changed the audio track or video track
1752 // TODO handling of difference audio types.. default audio types..
1753                                 
1754                 /* don't worry about non-existing services, nor pvr services */
1755                 if (m_dvb_service && !m_is_pvr)
1756                 {
1757                         if (apidtype == eDVBAudio::aMPEG)
1758                         {
1759                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1760                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1761                         }
1762                         else
1763                         {
1764                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1765                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1766                         }
1767                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1768                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1769                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1770                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1771                 }
1772         }
1773         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1774 }
1775
1776 void eDVBServicePlay::loadCuesheet()
1777 {
1778         std::string filename = m_reference.path + ".cuts";
1779         
1780         m_cue_entries.clear();
1781
1782         FILE *f = fopen(filename.c_str(), "rb");
1783
1784         if (f)
1785         {
1786                 eDebug("loading cuts..");
1787                 while (1)
1788                 {
1789                         unsigned long long where;
1790                         unsigned int what;
1791                         
1792                         if (!fread(&where, sizeof(where), 1, f))
1793                                 break;
1794                         if (!fread(&what, sizeof(what), 1, f))
1795                                 break;
1796                         
1797 #if BYTE_ORDER == LITTLE_ENDIAN
1798                         where = bswap_64(where);
1799 #endif
1800                         what = ntohl(what);
1801                         
1802                         if (what > 2)
1803                                 break;
1804                         
1805                         m_cue_entries.insert(cueEntry(where, what));
1806                 }
1807                 fclose(f);
1808                 eDebug("%d entries", m_cue_entries.size());
1809         } else
1810                 eDebug("cutfile not found!");
1811         
1812         m_cuesheet_changed = 0;
1813         cutlistToCuesheet();
1814         m_event((iPlayableService*)this, evCuesheetChanged);
1815 }
1816
1817 void eDVBServicePlay::saveCuesheet()
1818 {
1819         std::string filename = m_reference.path + ".cuts";
1820         
1821         FILE *f = fopen(filename.c_str(), "wb");
1822
1823         if (f)
1824         {
1825                 unsigned long long where;
1826                 int what;
1827
1828                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1829                 {
1830 #if BYTE_ORDER == BIG_ENDIAN
1831                         where = i->where;
1832 #else
1833                         where = bswap_64(i->where);
1834 #endif
1835                         what = htonl(i->what);
1836                         fwrite(&where, sizeof(where), 1, f);
1837                         fwrite(&what, sizeof(what), 1, f);
1838                         
1839                 }
1840                 fclose(f);
1841         }
1842         
1843         m_cuesheet_changed = 0;
1844 }
1845
1846 void eDVBServicePlay::cutlistToCuesheet()
1847 {
1848         if (!m_cue)
1849         {
1850                 eDebug("no cue sheet");
1851                 return;
1852         }       
1853         m_cue->clear();
1854         
1855         if (!m_cutlist_enabled)
1856         {
1857                 m_cue->commitSpans();
1858                 eDebug("cutlists where disabled");
1859                 return;
1860         }
1861
1862         pts_t in = 0, out = 0, length = 0;
1863         
1864         getLength(length);
1865                 
1866         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1867         
1868         while (1)
1869         {
1870                 if (i == m_cue_entries.end())
1871                         out = length;
1872                 else {
1873                         if (i->what == 0) /* in */
1874                         {
1875                                 in = i++->where;
1876                                 continue;
1877                         } else if (i->what == 1) /* out */
1878                                 out = i++->where;
1879                         else /* mark */
1880                         {
1881                                 i++;
1882                                 continue;
1883                         }
1884                 }
1885                 
1886                 if (in != out)
1887                         m_cue->addSourceSpan(in, out);
1888                 
1889                 in = length;
1890                 
1891                 if (i == m_cue_entries.end())
1892                         break;
1893         }
1894         m_cue->commitSpans();
1895 }
1896
1897 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1898 {
1899         if (m_subtitle_widget)
1900                 disableSubtitles(parent);
1901         
1902         if (!m_teletext_parser)
1903                 return -1;
1904         
1905         if (!PyInt_Check(entry))
1906                 return -1;
1907         
1908         m_subtitle_widget = new eSubtitleWidget(parent);
1909         m_subtitle_widget->resize(parent->size()); /* full size */
1910         
1911         int page = PyInt_AsLong(entry);
1912         
1913         m_teletext_parser->setPage(page);
1914
1915         return 0;
1916 }
1917
1918 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1919 {
1920         delete m_subtitle_widget;
1921         m_subtitle_widget = 0;
1922         return 0;
1923 }
1924
1925 PyObject *eDVBServicePlay::getSubtitleList()
1926 {
1927         if (!m_teletext_parser)
1928         {
1929                 Py_INCREF(Py_None);
1930                 return Py_None;
1931         }
1932         
1933         PyObject *l = PyList_New(0);
1934         
1935         for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1936         {
1937                 PyObject *tuple = PyTuple_New(2);
1938                 char desc[20];
1939                 sprintf(desc, "Page %x", *i);
1940                 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1941                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1942                 PyList_Append(l, tuple);
1943         }
1944         
1945         return l;
1946 }
1947
1948 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1949 {
1950         if (m_subtitle_widget)
1951         {
1952                 m_subtitle_pages.push_back(page);
1953                 
1954                 checkSubtitleTiming();
1955         }
1956 }
1957
1958 void eDVBServicePlay::checkSubtitleTiming()
1959 {
1960         while (1)
1961         {
1962                 if (m_subtitle_pages.empty())
1963                         return;
1964         
1965                 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1966         
1967                 pts_t pos = 0;
1968         
1969                 if (m_decoder)
1970                         m_decoder->getPTS(0, pos);
1971         
1972                 int diff = p.m_pts - pos;
1973                 if (diff < 0)
1974                 {
1975                         eDebug("[late (%d ms)]", -diff / 90);
1976                         diff = 0;
1977                 }
1978                 if (diff > 900000)
1979                 {
1980                         eDebug("[invalid]");
1981                         diff = 0;
1982                 }
1983         
1984                 if (!diff)
1985                 {
1986                         m_subtitle_widget->setPage(p);
1987                         m_subtitle_pages.pop_front();
1988                 } else
1989                 {
1990                         m_subtitle_sync_timer.start(diff / 90, 1);
1991                         break;
1992                 }
1993         }
1994 }
1995
1996 int eDVBServicePlay::getAC3Delay()
1997 {
1998         if (m_dvb_service)
1999                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2000         else if (m_decoder)
2001                 return m_decoder->getAC3Delay();
2002         else
2003                 return 0;
2004 }
2005
2006 int eDVBServicePlay::getPCMDelay()
2007 {
2008         if (m_dvb_service)
2009                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2010         else if (m_decoder)
2011                 return m_decoder->getPCMDelay();
2012         else
2013                 return 0;
2014 }
2015
2016 void eDVBServicePlay::setAC3Delay(int delay)
2017 {
2018         if (m_dvb_service)
2019                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2020         if (m_decoder)
2021                 m_decoder->setAC3Delay(delay);
2022 }
2023
2024 void eDVBServicePlay::setPCMDelay(int delay)
2025 {
2026         if (m_dvb_service)
2027                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2028         if (m_decoder)
2029                 m_decoder->setPCMDelay(delay);
2030 }
2031
2032 DEFINE_REF(eDVBServicePlay)
2033
2034 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");