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