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