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