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