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