add support for radiotext (python gui component missing yet)
[vuplus_dvbapp] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/init_num.h>
7 #include <lib/base/init.h>
8 #include <lib/base/nconfig.h> // access to python config
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19
20                 /* for subtitles */
21 #include <lib/gui/esubtitle.h>
22
23 #include <sys/vfs.h>
24
25 #include <byteswap.h>
26 #include <netinet/in.h>
27
28 #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                 if (apid != 1)
1744                 {
1745                         ePtr<iDVBDemux> data_demux;
1746                         if ( (m_timeshift_active && !m_service_handler_timeshift.getDataDemux(data_demux))
1747                                 || (!m_timeshift_active && !m_service_handler.getDataDemux(data_demux)))
1748                         {
1749                                 m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1750                                 m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1751                         }
1752                 }
1753         }
1754
1755         if (m_decoder)
1756         {
1757                 if (m_dvb_service)
1758                 {
1759                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1760                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1761                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1762                 }
1763                 else // subservice or recording
1764                 {
1765                         eServiceReferenceDVB ref;
1766                         m_service_handler.getServiceReference(ref);
1767                         eServiceReferenceDVB parent = ref.getParentServiceReference();
1768                         if (!parent)
1769                                 parent = ref;
1770                         if (parent)
1771                         {
1772                                 ePtr<eDVBResourceManager> res_mgr;
1773                                 if (!eDVBResourceManager::getInstance(res_mgr))
1774                                 {
1775                                         ePtr<iDVBChannelList> db;
1776                                         if (!res_mgr->getChannelList(db))
1777                                         {
1778                                                 ePtr<eDVBService> origService;
1779                                                 if (!db->getService(parent, origService))
1780                                                 {
1781                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1782                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1783                                                 }
1784                                         }
1785                                 }
1786                         }
1787                 }
1788                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1789                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1790
1791                 m_decoder->setVideoPID(vpid, vpidtype);
1792                 m_current_audio_stream = 0;
1793                 m_decoder->setAudioPID(apid, apidtype);
1794                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1795                         m_decoder->setSyncPCR(pcrpid);
1796                 else
1797                         m_decoder->setSyncPCR(-1);
1798
1799                 m_decoder->setTextPID(tpid);
1800
1801                 if (m_teletext_parser)
1802                         m_teletext_parser->start(tpid);
1803
1804                 if (m_radiotext_parser)
1805                         m_radiotext_parser->start(apid);
1806
1807                 if (!m_is_primary)
1808                         m_decoder->setTrickmode(1);
1809
1810                 m_decoder->start();
1811
1812                 if (vpid > 0 && vpid < 0x2000)
1813                         ;
1814                 else
1815                 {
1816                         std::string radio_pic;
1817                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1818                                 m_decoder->setRadioPic(radio_pic);
1819                 }
1820
1821                 m_decoder->setAudioChannel(achannel);
1822
1823 // how we can do this better?
1824 // update cache pid when the user changed the audio track or video track
1825 // TODO handling of difference audio types.. default audio types..
1826                                 
1827                 /* don't worry about non-existing services, nor pvr services */
1828                 if (m_dvb_service && !m_is_pvr)
1829                 {
1830                         if (apidtype == eDVBAudio::aMPEG)
1831                         {
1832                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1833                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1834                         }
1835                         else
1836                         {
1837                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1838                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1839                         }
1840                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1841                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1842                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1843                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1844                 }
1845         }
1846         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1847 }
1848
1849 void eDVBServicePlay::loadCuesheet()
1850 {
1851         std::string filename = m_reference.path + ".cuts";
1852         
1853         m_cue_entries.clear();
1854
1855         FILE *f = fopen(filename.c_str(), "rb");
1856
1857         if (f)
1858         {
1859                 eDebug("loading cuts..");
1860                 while (1)
1861                 {
1862                         unsigned long long where;
1863                         unsigned int what;
1864                         
1865                         if (!fread(&where, sizeof(where), 1, f))
1866                                 break;
1867                         if (!fread(&what, sizeof(what), 1, f))
1868                                 break;
1869                         
1870 #if BYTE_ORDER == LITTLE_ENDIAN
1871                         where = bswap_64(where);
1872 #endif
1873                         what = ntohl(what);
1874                         
1875                         if (what > 3)
1876                                 break;
1877                         
1878                         m_cue_entries.insert(cueEntry(where, what));
1879                 }
1880                 fclose(f);
1881                 eDebug("%d entries", m_cue_entries.size());
1882         } else
1883                 eDebug("cutfile not found!");
1884         
1885         m_cuesheet_changed = 0;
1886         cutlistToCuesheet();
1887         m_event((iPlayableService*)this, evCuesheetChanged);
1888 }
1889
1890 void eDVBServicePlay::saveCuesheet()
1891 {
1892         std::string filename = m_reference.path + ".cuts";
1893         
1894         FILE *f = fopen(filename.c_str(), "wb");
1895
1896         if (f)
1897         {
1898                 unsigned long long where;
1899                 int what;
1900
1901                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1902                 {
1903 #if BYTE_ORDER == BIG_ENDIAN
1904                         where = i->where;
1905 #else
1906                         where = bswap_64(i->where);
1907 #endif
1908                         what = htonl(i->what);
1909                         fwrite(&where, sizeof(where), 1, f);
1910                         fwrite(&what, sizeof(what), 1, f);
1911                         
1912                 }
1913                 fclose(f);
1914         }
1915         
1916         m_cuesheet_changed = 0;
1917 }
1918
1919 void eDVBServicePlay::cutlistToCuesheet()
1920 {
1921         if (!m_cue)
1922         {
1923                 eDebug("no cue sheet");
1924                 return;
1925         }       
1926         m_cue->clear();
1927         
1928         if (!m_cutlist_enabled)
1929         {
1930                 m_cue->commitSpans();
1931                 eDebug("cutlists were disabled");
1932                 return;
1933         }
1934
1935         pts_t in = 0, out = 0, length = 0;
1936         
1937         getLength(length);
1938                 
1939         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1940         
1941         while (1)
1942         {
1943                 if (i == m_cue_entries.end())
1944                         out = length;
1945                 else {
1946                         if (i->what == 0) /* in */
1947                         {
1948                                 in = i++->where;
1949                                 continue;
1950                         } else if (i->what == 1) /* out */
1951                                 out = i++->where;
1952                         else /* mark (2) or last play position (3) */
1953                         {
1954                                 i++;
1955                                 continue;
1956                         }
1957                 }
1958                 
1959                 if (in != out)
1960                         m_cue->addSourceSpan(in, out);
1961                 
1962                 in = length;
1963                 
1964                 if (i == m_cue_entries.end())
1965                         break;
1966         }
1967         m_cue->commitSpans();
1968 }
1969
1970 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1971 {
1972         if (m_subtitle_widget)
1973                 disableSubtitles(parent);
1974         
1975         if (!m_teletext_parser)
1976                 return -1;
1977         
1978         if (!PyInt_Check(entry))
1979                 return -1;
1980         
1981         m_subtitle_widget = new eSubtitleWidget(parent);
1982         m_subtitle_widget->resize(parent->size()); /* full size */
1983         
1984         int page = PyInt_AsLong(entry);
1985         
1986         m_teletext_parser->setPage(page);
1987
1988         return 0;
1989 }
1990
1991 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
1992 {
1993         delete m_subtitle_widget;
1994         m_subtitle_widget = 0;
1995         return 0;
1996 }
1997
1998 PyObject *eDVBServicePlay::getSubtitleList()
1999 {
2000         if (!m_teletext_parser)
2001         {
2002                 Py_INCREF(Py_None);
2003                 return Py_None;
2004         }
2005         
2006         PyObject *l = PyList_New(0);
2007         
2008         for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2009         {
2010                 PyObject *tuple = PyTuple_New(2);
2011                 char desc[20];
2012                 sprintf(desc, "Page %x", *i);
2013                 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2014                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2015                 PyList_Append(l, tuple);
2016         }
2017         
2018         return l;
2019 }
2020
2021 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2022 {
2023         if (m_subtitle_widget)
2024         {
2025                 m_subtitle_pages.push_back(page);
2026                 
2027                 checkSubtitleTiming();
2028         }
2029 }
2030
2031 void eDVBServicePlay::checkSubtitleTiming()
2032 {
2033         while (1)
2034         {
2035                 if (m_subtitle_pages.empty())
2036                         return;
2037         
2038                 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
2039         
2040                 pts_t pos = 0;
2041         
2042                 if (m_decoder)
2043                         m_decoder->getPTS(0, pos);
2044         
2045                 int diff = p.m_pts - pos;
2046                 if (diff < 0)
2047                 {
2048                         eDebug("[late (%d ms)]", -diff / 90);
2049                         diff = 0;
2050                 }
2051                 if (diff > 900000)
2052                 {
2053                         eDebug("[invalid]");
2054                         diff = 0;
2055                 }
2056         
2057                 if (!diff)
2058                 {
2059                         m_subtitle_widget->setPage(p);
2060                         m_subtitle_pages.pop_front();
2061                 } else
2062                 {
2063                         m_subtitle_sync_timer.start(diff / 90, 1);
2064                         break;
2065                 }
2066         }
2067 }
2068
2069 int eDVBServicePlay::getAC3Delay()
2070 {
2071         if (m_dvb_service)
2072                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2073         else if (m_decoder)
2074                 return m_decoder->getAC3Delay();
2075         else
2076                 return 0;
2077 }
2078
2079 int eDVBServicePlay::getPCMDelay()
2080 {
2081         if (m_dvb_service)
2082                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2083         else if (m_decoder)
2084                 return m_decoder->getPCMDelay();
2085         else
2086                 return 0;
2087 }
2088
2089 void eDVBServicePlay::setAC3Delay(int delay)
2090 {
2091         if (m_dvb_service)
2092                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2093         if (m_decoder)
2094                 m_decoder->setAC3Delay(delay);
2095 }
2096
2097 void eDVBServicePlay::setPCMDelay(int delay)
2098 {
2099         if (m_dvb_service)
2100                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2101         if (m_decoder)
2102                 m_decoder->setPCMDelay(delay);
2103 }
2104
2105 DEFINE_REF(eDVBServicePlay)
2106
2107 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");