add new skin stuff
[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)
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         int curChannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1283         return curChannel == -1 ? STEREO : curChannel;
1284 }
1285
1286 RESULT eDVBServicePlay::selectChannel(int i)
1287 {
1288         if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT)
1289                 i = -1;  // Stereo
1290         if (m_dvb_service->getCacheEntry(eDVBService::cACHANNEL) != i)
1291         {
1292                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1293                 if (m_decoder)
1294                         m_decoder->setAudioChannel(i);
1295         }
1296         return 0;
1297 }
1298
1299 int eDVBServiceBase::getFrontendInfo(int w)
1300 {
1301         eUsePtr<iDVBChannel> channel;
1302         if(m_service_handler.getChannel(channel))
1303                 return 0;
1304         ePtr<iDVBFrontend> fe;
1305         if(channel->getFrontend(fe))
1306                 return 0;
1307         return fe->readFrontendData(w);
1308 }
1309
1310 PyObject *eDVBServiceBase::getFrontendData(bool original)
1311 {
1312         PyObject *ret=0;
1313
1314         eUsePtr<iDVBChannel> channel;
1315         if(!m_service_handler.getChannel(channel))
1316         {
1317                 ePtr<iDVBFrontend> fe;
1318                 if(!channel->getFrontend(fe))
1319                 {
1320                         ret = fe->readTransponderData(original);
1321                         if (ret)
1322                         {
1323                                 ePtr<iDVBFrontendParameters> feparm;
1324                                 channel->getCurrentFrontendParameters(feparm);
1325                                 if (feparm)
1326                                 {
1327                                         eDVBFrontendParametersSatellite osat;
1328                                         if (!feparm->getDVBS(osat))
1329                                         {
1330                                                 void PutToDict(PyObject *, const char*, long);
1331                                                 void PutToDict(PyObject *, const char*, const char*);
1332                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1333                                                 const char *tmp = "UNKNOWN";
1334                                                 switch(osat.polarisation)
1335                                                 {
1336                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1337                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1338                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1339                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1340                                                         default:break;
1341                                                 }
1342                                                 PutToDict(ret, "polarization", tmp);
1343                                         }
1344                                 }
1345                         }
1346                 }
1347         }
1348         if (!ret)
1349         {
1350                 ret = Py_None;
1351                 Py_INCREF(ret);
1352         }
1353         return ret;
1354 }
1355
1356 int eDVBServicePlay::getNumberOfSubservices()
1357 {
1358         ePtr<eServiceEvent> evt;
1359         if (!m_event_handler.getEvent(evt, 0))
1360                 return evt->getNumOfLinkageServices();
1361         return 0;
1362 }
1363
1364 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1365 {
1366         ePtr<eServiceEvent> evt;
1367         if (!m_event_handler.getEvent(evt, 0))
1368         {
1369                 if (!evt->getLinkageService(sub, m_reference, n))
1370                         return 0;
1371         }
1372         sub.type=eServiceReference::idInvalid;
1373         return -1;
1374 }
1375
1376 RESULT eDVBServicePlay::startTimeshift()
1377 {
1378         ePtr<iDVBDemux> demux;
1379         
1380         eDebug("Start timeshift!");
1381         
1382         if (m_timeshift_enabled)
1383                 return -1;
1384         
1385                 /* start recording with the data demux. */
1386         if (m_service_handler.getDataDemux(demux))
1387                 return -2;
1388
1389         demux->createTSRecorder(m_record);
1390         if (!m_record)
1391                 return -3;
1392
1393         char templ[]=TSPATH "/timeshift.XXXXXX";
1394         m_timeshift_fd = mkstemp(templ);
1395         m_timeshift_file = templ;
1396         
1397         eDebug("recording to %s", templ);
1398         
1399         if (m_timeshift_fd < 0)
1400         {
1401                 m_record = 0;
1402                 return -4;
1403         }
1404                 
1405         m_record->setTargetFD(m_timeshift_fd);
1406
1407         m_timeshift_enabled = 1;
1408         
1409         updateTimeshiftPids();
1410         m_record->start();
1411
1412         return 0;
1413 }
1414
1415 RESULT eDVBServicePlay::stopTimeshift()
1416 {
1417         if (!m_timeshift_enabled)
1418                 return -1;
1419         
1420         switchToLive();
1421         
1422         m_timeshift_enabled = 0;
1423         
1424         m_record->stop();
1425         m_record = 0;
1426         
1427         close(m_timeshift_fd);
1428         eDebug("remove timeshift file");
1429         remove(m_timeshift_file.c_str());
1430         
1431         return 0;
1432 }
1433
1434 int eDVBServicePlay::isTimeshiftActive()
1435 {
1436         return m_timeshift_enabled && m_timeshift_active;
1437 }
1438
1439 RESULT eDVBServicePlay::activateTimeshift()
1440 {
1441         if (!m_timeshift_enabled)
1442                 return -1;
1443         
1444         if (!m_timeshift_active)
1445         {
1446                 switchToTimeshift();
1447                 return 0;
1448         }
1449         
1450         return -2;
1451 }
1452
1453 PyObject *eDVBServicePlay::getCutList()
1454 {
1455         PyObject *list = PyList_New(0);
1456         
1457         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1458         {
1459                 PyObject *tuple = PyTuple_New(2);
1460                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1461                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1462                 PyList_Append(list, tuple);
1463                 Py_DECREF(tuple);
1464         }
1465         
1466         return list;
1467 }
1468
1469 void eDVBServicePlay::setCutList(PyObject *list)
1470 {
1471         if (!PyList_Check(list))
1472                 return;
1473         int size = PyList_Size(list);
1474         int i;
1475         
1476         m_cue_entries.clear();
1477         
1478         for (i=0; i<size; ++i)
1479         {
1480                 PyObject *tuple = PyList_GetItem(list, i);
1481                 if (!PyTuple_Check(tuple))
1482                 {
1483                         eDebug("non-tuple in cutlist");
1484                         continue;
1485                 }
1486                 if (PyTuple_Size(tuple) != 2)
1487                 {
1488                         eDebug("cutlist entries need to be a 2-tuple");
1489                         continue;
1490                 }
1491                 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1492                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1493                 {
1494                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1495                         continue;
1496                 }
1497                 pts_t pts = PyLong_AsLongLong(ppts);
1498                 int type = PyInt_AsLong(ptype);
1499                 m_cue_entries.insert(cueEntry(pts, type));
1500                 eDebug("adding %08llx, %d", pts, type);
1501         }
1502         m_cuesheet_changed = 1;
1503         
1504         cutlistToCuesheet();
1505         m_event((iPlayableService*)this, evCuesheetChanged);
1506 }
1507
1508 void eDVBServicePlay::setCutListEnable(int enable)
1509 {
1510         m_cutlist_enabled = enable;
1511         cutlistToCuesheet();
1512 }
1513
1514 void eDVBServicePlay::updateTimeshiftPids()
1515 {
1516         if (!m_record)
1517                 return;
1518         
1519         eDVBServicePMTHandler::program program;
1520         if (m_service_handler.getProgramInfo(program))
1521                 return;
1522         else
1523         {
1524                 std::set<int> pids_to_record;
1525                 pids_to_record.insert(0); // PAT
1526                 if (program.pmtPid != -1)
1527                         pids_to_record.insert(program.pmtPid); // PMT
1528
1529                 if (program.textPid != -1)
1530                         pids_to_record.insert(program.textPid); // Videotext
1531
1532                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1533                         i(program.videoStreams.begin()); 
1534                         i != program.videoStreams.end(); ++i)
1535                         pids_to_record.insert(i->pid);
1536
1537                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1538                         i(program.audioStreams.begin()); 
1539                         i != program.audioStreams.end(); ++i)
1540                                 pids_to_record.insert(i->pid);
1541
1542                 std::set<int> new_pids, obsolete_pids;
1543                 
1544                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1545                                 m_pids_active.begin(), m_pids_active.end(),
1546                                 std::inserter(new_pids, new_pids.begin()));
1547                 
1548                 std::set_difference(
1549                                 m_pids_active.begin(), m_pids_active.end(),
1550                                 pids_to_record.begin(), pids_to_record.end(), 
1551                                 std::inserter(new_pids, new_pids.begin())
1552                                 );
1553
1554                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1555                         m_record->addPID(*i);
1556
1557                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1558                         m_record->removePID(*i);
1559         }
1560 }
1561
1562 void eDVBServicePlay::switchToLive()
1563 {
1564         if (!m_timeshift_active)
1565                 return;
1566         
1567         m_cue = 0;
1568         m_decoder = 0;
1569         m_decode_demux = 0;
1570         m_teletext_parser = 0;
1571         
1572                 /* free the timeshift service handler, we need the resources */
1573         m_service_handler_timeshift.free();
1574         m_timeshift_active = 0;
1575         
1576         m_event((iPlayableService*)this, evSeekableStatusChanged);
1577         
1578         updateDecoder();
1579 }
1580
1581 void eDVBServicePlay::switchToTimeshift()
1582 {
1583         if (m_timeshift_active)
1584                 return;
1585         
1586         m_decode_demux = 0;
1587         m_decoder = 0;
1588         m_teletext_parser = 0;
1589         
1590         m_timeshift_active = 1;
1591
1592         m_event((iPlayableService*)this, evSeekableStatusChanged);
1593         
1594         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1595         r.path = m_timeshift_file;
1596         
1597         m_cue = new eCueSheet();
1598         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1599         updateDecoder(); /* mainly to switch off PCR */
1600 }
1601
1602 void eDVBServicePlay::updateDecoder()
1603 {
1604         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1;
1605         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1606
1607         bool defaultac3=false;
1608         std::string default_ac3;
1609
1610         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1611                 defaultac3 = default_ac3 == "enable";
1612
1613         eDVBServicePMTHandler::program program;
1614         if (h.getProgramInfo(program))
1615                 eDebug("getting program info failed.");
1616         else
1617         {
1618                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1619                 if (!program.videoStreams.empty())
1620                 {
1621                         eDebugNoNewLine(" (");
1622                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1623                                 i(program.videoStreams.begin()); 
1624                                 i != program.videoStreams.end(); ++i)
1625                         {
1626                                 if (vpid == -1)
1627                                 {
1628                                         vpid = i->pid;
1629                                         vpidtype = i->type;
1630                                 }
1631                                 if (i != program.videoStreams.begin())
1632                                         eDebugNoNewLine(", ");
1633                                 eDebugNoNewLine("%04x", i->pid);
1634                         }
1635                         eDebugNoNewLine(")");
1636                 }
1637                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1638                 if (!program.audioStreams.empty())
1639                 {
1640                         eDebugNoNewLine(" (");
1641                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1642                                 i(program.audioStreams.begin()); 
1643                                 i != program.audioStreams.end(); ++i)
1644                         {
1645                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1646                                 {
1647                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1648                                         {
1649                                                 apid = i->pid;
1650                                                 apidtype = i->type;
1651                                         }
1652                                 }
1653                                 if (i != program.audioStreams.begin())
1654                                         eDebugNoNewLine(", ");
1655                                 eDebugNoNewLine("%04x", i->pid);
1656                         }
1657                         eDebugNoNewLine(")");
1658                 }
1659                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1660                 pcrpid = program.pcrPid;
1661                 eDebug(", and the text pid is %04x", program.textPid);
1662                 tpid = program.textPid;
1663                 achannel = program.audioChannel;
1664         }
1665
1666         if (!m_decoder)
1667         {
1668                 h.getDecodeDemux(m_decode_demux);
1669                 if (m_decode_demux)
1670                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1671                 if (m_cue)
1672                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1673 #ifdef INTERNAL_TELETEXT
1674                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1675                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1676 #endif
1677         }
1678
1679         if (m_decoder)
1680         {
1681                 m_decoder->setVideoPID(vpid, vpidtype);
1682                 m_current_audio_stream = 0;
1683                 m_decoder->setAudioPID(apid, apidtype);
1684                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1685                         m_decoder->setSyncPCR(pcrpid);
1686                 else
1687                         m_decoder->setSyncPCR(-1);
1688 #ifndef INTERNAL_TELETEXT
1689                 m_decoder->setTextPID(tpid);
1690 #else
1691                 if (m_teletext_parser)
1692                         m_teletext_parser->start(tpid);
1693 #endif
1694
1695                 if (!m_is_primary)
1696                         m_decoder->setTrickmode(1);
1697
1698                 m_decoder->start();
1699
1700                 m_decoder->setAudioChannel(achannel);
1701
1702 // how we can do this better?
1703 // update cache pid when the user changed the audio track or video track
1704 // TODO handling of difference audio types.. default audio types..
1705                                 
1706                 /* don't worry about non-existing services, nor pvr services */
1707                 if (m_dvb_service && !m_is_pvr)
1708                 {
1709                         if (apidtype == eDVBAudio::aMPEG)
1710                         {
1711                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1712                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1713                         }
1714                         else
1715                         {
1716                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1717                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1718                         }
1719                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1720                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1721                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1722                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1723                 }
1724         }
1725 }
1726
1727 void eDVBServicePlay::loadCuesheet()
1728 {
1729         std::string filename = m_reference.path + ".cuts";
1730         
1731         m_cue_entries.clear();
1732
1733         FILE *f = fopen(filename.c_str(), "rb");
1734
1735         if (f)
1736         {
1737                 eDebug("loading cuts..");
1738                 while (1)
1739                 {
1740                         unsigned long long where;
1741                         unsigned int what;
1742                         
1743                         if (!fread(&where, sizeof(where), 1, f))
1744                                 break;
1745                         if (!fread(&what, sizeof(what), 1, f))
1746                                 break;
1747                         
1748 #if BYTE_ORDER == LITTLE_ENDIAN
1749                         where = bswap_64(where);
1750 #endif
1751                         what = ntohl(what);
1752                         
1753                         if (what > 2)
1754                                 break;
1755                         
1756                         m_cue_entries.insert(cueEntry(where, what));
1757                 }
1758                 fclose(f);
1759                 eDebug("%d entries", m_cue_entries.size());
1760         } else
1761                 eDebug("cutfile not found!");
1762         
1763         m_cuesheet_changed = 0;
1764         cutlistToCuesheet();
1765         m_event((iPlayableService*)this, evCuesheetChanged);
1766 }
1767
1768 void eDVBServicePlay::saveCuesheet()
1769 {
1770         std::string filename = m_reference.path + ".cuts";
1771         
1772         FILE *f = fopen(filename.c_str(), "wb");
1773
1774         if (f)
1775         {
1776                 unsigned long long where;
1777                 int what;
1778
1779                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1780                 {
1781 #if BYTE_ORDER == BIG_ENDIAN
1782                         where = i->where;
1783 #else
1784                         where = bswap_64(i->where);
1785 #endif
1786                         what = htonl(i->what);
1787                         fwrite(&where, sizeof(where), 1, f);
1788                         fwrite(&what, sizeof(what), 1, f);
1789                         
1790                 }
1791                 fclose(f);
1792         }
1793         
1794         m_cuesheet_changed = 0;
1795 }
1796
1797 void eDVBServicePlay::cutlistToCuesheet()
1798 {
1799         if (!m_cue)
1800         {
1801                 eDebug("no cue sheet");
1802                 return;
1803         }       
1804         m_cue->clear();
1805         
1806         if (!m_cutlist_enabled)
1807         {
1808                 m_cue->commitSpans();
1809                 eDebug("cutlists where disabled");
1810                 return;
1811         }
1812
1813         pts_t in = 0, out = 0, length = 0;
1814         
1815         getLength(length);
1816                 
1817         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1818         
1819         while (1)
1820         {
1821                 if (i == m_cue_entries.end())
1822                         out = length;
1823                 else {
1824                         if (i->what == 0) /* in */
1825                         {
1826                                 in = i++->where;
1827                                 continue;
1828                         } else if (i->what == 1) /* out */
1829                                 out = i++->where;
1830                         else /* mark */
1831                         {
1832                                 i++;
1833                                 continue;
1834                         }
1835                 }
1836                 
1837                 if (in != out)
1838                         m_cue->addSourceSpan(in, out);
1839                 
1840                 in = length;
1841                 
1842                 if (i == m_cue_entries.end())
1843                         break;
1844         }
1845         m_cue->commitSpans();
1846 }
1847
1848 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1849 {
1850         if (m_subtitle_widget)
1851                 disableSubtitles(parent);
1852         
1853         if (!m_teletext_parser)
1854                 return -1;
1855         
1856         if (!PyInt_Check(entry))
1857                 return -1;
1858         
1859         m_subtitle_widget = new eSubtitleWidget(parent);
1860         m_subtitle_widget->resize(parent->size()); /* full size */
1861         
1862         int page = PyInt_AsLong(entry);
1863         
1864         m_teletext_parser->setPage(page);
1865
1866         return 0;
1867 }
1868
1869 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1870 {
1871         delete m_subtitle_widget;
1872         m_subtitle_widget = 0;
1873         return 0;
1874 }
1875
1876 PyObject *eDVBServicePlay::getSubtitleList()
1877 {
1878         if (!m_teletext_parser)
1879         {
1880                 Py_INCREF(Py_None);
1881                 return Py_None;
1882         }
1883         
1884         PyObject *l = PyList_New(0);
1885         
1886         for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
1887         {
1888                 PyObject *tuple = PyTuple_New(2);
1889                 char desc[20];
1890                 sprintf(desc, "Page %x", *i);
1891                 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
1892                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
1893                 PyList_Append(l, tuple);
1894         }
1895         
1896         return l;
1897 }
1898
1899 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
1900 {
1901         if (m_subtitle_widget)
1902         {
1903                 m_subtitle_pages.push_back(page);
1904                 
1905                 checkSubtitleTiming();
1906         }
1907 }
1908
1909 void eDVBServicePlay::checkSubtitleTiming()
1910 {
1911         while (1)
1912         {
1913                 if (m_subtitle_pages.empty())
1914                         return;
1915         
1916                 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
1917         
1918                 pts_t pos = 0;
1919         
1920                 if (m_decoder)
1921                         m_decoder->getPTS(0, pos);
1922         
1923                 int diff = p.m_pts - pos;
1924                 if (diff < 0)
1925                 {
1926                         eDebug("[late (%d ms)]", -diff / 90);
1927                         diff = 0;
1928                 }
1929                 if (diff > 900000)
1930                 {
1931                         eDebug("[invalid]");
1932                         diff = 0;
1933                 }
1934         
1935                 if (!diff)
1936                 {
1937                         m_subtitle_widget->setPage(p);
1938                         m_subtitle_pages.pop_front();
1939                 } else
1940                 {
1941                         m_subtitle_sync_timer.start(diff / 90, 1);
1942                         break;
1943                 }
1944         }
1945 }
1946
1947 DEFINE_REF(eDVBServicePlay)
1948
1949 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");