more work on dvb subtitles (not finished/working yet)
[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_subtitle_parser = 0;
1644         m_new_dvb_subtitle_region_connection = 0;
1645         m_new_subtitle_page_connection = 0;
1646         m_radiotext_updated_connection = 0;
1647
1648                 /* free the timeshift service handler, we need the resources */
1649         m_service_handler_timeshift.free();
1650         m_timeshift_active = 0;
1651         
1652         m_event((iPlayableService*)this, evSeekableStatusChanged);
1653         
1654         updateDecoder();
1655 }
1656
1657 void eDVBServicePlay::switchToTimeshift()
1658 {
1659         if (m_timeshift_active)
1660                 return;
1661         
1662         m_decode_demux = 0;
1663         m_decoder = 0;
1664         m_teletext_parser = 0;
1665         m_radiotext_parser = 0;
1666         m_subtitle_parser = 0;
1667         m_new_subtitle_page_connection = 0;
1668         m_new_dvb_subtitle_region_connection = 0;
1669         m_radiotext_updated_connection = 0;
1670
1671         m_timeshift_active = 1;
1672
1673         m_event((iPlayableService*)this, evSeekableStatusChanged);
1674         
1675         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1676         r.path = m_timeshift_file;
1677         
1678         m_cue = new eCueSheet();
1679         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1680         updateDecoder(); /* mainly to switch off PCR */
1681 }
1682
1683 void eDVBServicePlay::updateDecoder()
1684 {
1685         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1686
1687         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1688
1689         bool defaultac3=false;
1690         std::string default_ac3;
1691
1692         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1693                 defaultac3 = default_ac3 == "True";
1694
1695         eDVBServicePMTHandler::program program;
1696         if (h.getProgramInfo(program))
1697                 eDebug("getting program info failed.");
1698         else
1699         {
1700                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1701                 if (!program.videoStreams.empty())
1702                 {
1703                         eDebugNoNewLine(" (");
1704                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1705                                 i(program.videoStreams.begin()); 
1706                                 i != program.videoStreams.end(); ++i)
1707                         {
1708                                 if (vpid == -1)
1709                                 {
1710                                         vpid = i->pid;
1711                                         vpidtype = i->type;
1712                                 }
1713                                 if (i != program.videoStreams.begin())
1714                                         eDebugNoNewLine(", ");
1715                                 eDebugNoNewLine("%04x", i->pid);
1716                         }
1717                         eDebugNoNewLine(")");
1718                 }
1719                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1720                 if (!program.audioStreams.empty())
1721                 {
1722                         eDebugNoNewLine(" (");
1723                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1724                                 i(program.audioStreams.begin()); 
1725                                 i != program.audioStreams.end(); ++i)
1726                         {
1727                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1728                                 {
1729                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1730                                         {
1731                                                 apid = i->pid;
1732                                                 apidtype = i->type;
1733                                         }
1734                                 }
1735                                 if (i != program.audioStreams.begin())
1736                                         eDebugNoNewLine(", ");
1737                                 eDebugNoNewLine("%04x", i->pid);
1738                         }
1739                         eDebugNoNewLine(")");
1740                 }
1741                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1742                 pcrpid = program.pcrPid;
1743                 eDebug(", and the text pid is %04x", program.textPid);
1744                 tpid = program.textPid;
1745         }
1746
1747         if (!m_decoder)
1748         {
1749                 h.getDecodeDemux(m_decode_demux);
1750                 if (m_decode_demux)
1751                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1752                 if (m_cue)
1753                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1754 #ifdef INTERNAL_TELETEXT
1755                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1756                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1757 #endif
1758                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1759                 m_subtitle_parser->connectNewRegion(slot(*this, &eDVBServicePlay::newDVBSubtitleRegion), m_new_dvb_subtitle_region_connection);
1760         }
1761
1762         if (m_decoder)
1763         {
1764                 if (m_dvb_service)
1765                 {
1766                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1767                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1768                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1769                 }
1770                 else // subservice or recording
1771                 {
1772                         eServiceReferenceDVB ref;
1773                         m_service_handler.getServiceReference(ref);
1774                         eServiceReferenceDVB parent = ref.getParentServiceReference();
1775                         if (!parent)
1776                                 parent = ref;
1777                         if (parent)
1778                         {
1779                                 ePtr<eDVBResourceManager> res_mgr;
1780                                 if (!eDVBResourceManager::getInstance(res_mgr))
1781                                 {
1782                                         ePtr<iDVBChannelList> db;
1783                                         if (!res_mgr->getChannelList(db))
1784                                         {
1785                                                 ePtr<eDVBService> origService;
1786                                                 if (!db->getService(parent, origService))
1787                                                 {
1788                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1789                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1790                                                 }
1791                                         }
1792                                 }
1793                         }
1794                 }
1795                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1796                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1797
1798                 m_decoder->setVideoPID(vpid, vpidtype);
1799                 m_decoder->setAudioPID(apid, apidtype);
1800                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1801                 {
1802                         m_decoder->setSyncPCR(pcrpid);
1803                         if (apid != -1)
1804                         {
1805                                 ePtr<iDVBDemux> data_demux;
1806                                 if (!h.getDataDemux(data_demux))
1807                                 {
1808                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1809                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1810                                         m_radiotext_parser->start(apid);
1811                                 }
1812                         }
1813                 }
1814                 else
1815                         m_decoder->setSyncPCR(-1);
1816
1817                 m_decoder->setTextPID(tpid);
1818
1819                 if (m_teletext_parser)
1820                         m_teletext_parser->start(tpid);
1821
1822                 if (m_subtitle_parser && program.subtitleStreams.size() > 0)
1823                         m_subtitle_parser->start(program.subtitleStreams[0].pid);
1824
1825                 if (!m_is_primary)
1826                         m_decoder->setTrickmode(1);
1827
1828                 m_decoder->start();
1829
1830                 if (vpid > 0 && vpid < 0x2000)
1831                         ;
1832                 else
1833                 {
1834                         std::string radio_pic;
1835                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1836                                 m_decoder->setRadioPic(radio_pic);
1837                 }
1838
1839                 m_decoder->setAudioChannel(achannel);
1840
1841 // how we can do this better?
1842 // update cache pid when the user changed the audio track or video track
1843 // TODO handling of difference audio types.. default audio types..
1844                                 
1845                 /* don't worry about non-existing services, nor pvr services */
1846                 if (m_dvb_service && !m_is_pvr)
1847                 {
1848                         if (apidtype == eDVBAudio::aMPEG)
1849                         {
1850                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1851                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1852                         }
1853                         else
1854                         {
1855                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1856                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1857                         }
1858                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1859                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1860                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1861                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1862                 }
1863         }
1864         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1865 }
1866
1867 void eDVBServicePlay::loadCuesheet()
1868 {
1869         std::string filename = m_reference.path + ".cuts";
1870         
1871         m_cue_entries.clear();
1872
1873         FILE *f = fopen(filename.c_str(), "rb");
1874
1875         if (f)
1876         {
1877                 eDebug("loading cuts..");
1878                 while (1)
1879                 {
1880                         unsigned long long where;
1881                         unsigned int what;
1882                         
1883                         if (!fread(&where, sizeof(where), 1, f))
1884                                 break;
1885                         if (!fread(&what, sizeof(what), 1, f))
1886                                 break;
1887                         
1888 #if BYTE_ORDER == LITTLE_ENDIAN
1889                         where = bswap_64(where);
1890 #endif
1891                         what = ntohl(what);
1892                         
1893                         if (what > 3)
1894                                 break;
1895                         
1896                         m_cue_entries.insert(cueEntry(where, what));
1897                 }
1898                 fclose(f);
1899                 eDebug("%d entries", m_cue_entries.size());
1900         } else
1901                 eDebug("cutfile not found!");
1902         
1903         m_cuesheet_changed = 0;
1904         cutlistToCuesheet();
1905         m_event((iPlayableService*)this, evCuesheetChanged);
1906 }
1907
1908 void eDVBServicePlay::saveCuesheet()
1909 {
1910         std::string filename = m_reference.path + ".cuts";
1911         
1912         FILE *f = fopen(filename.c_str(), "wb");
1913
1914         if (f)
1915         {
1916                 unsigned long long where;
1917                 int what;
1918
1919                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1920                 {
1921 #if BYTE_ORDER == BIG_ENDIAN
1922                         where = i->where;
1923 #else
1924                         where = bswap_64(i->where);
1925 #endif
1926                         what = htonl(i->what);
1927                         fwrite(&where, sizeof(where), 1, f);
1928                         fwrite(&what, sizeof(what), 1, f);
1929                         
1930                 }
1931                 fclose(f);
1932         }
1933         
1934         m_cuesheet_changed = 0;
1935 }
1936
1937 void eDVBServicePlay::cutlistToCuesheet()
1938 {
1939         if (!m_cue)
1940         {
1941                 eDebug("no cue sheet");
1942                 return;
1943         }       
1944         m_cue->clear();
1945         
1946         if (!m_cutlist_enabled)
1947         {
1948                 m_cue->commitSpans();
1949                 eDebug("cutlists were disabled");
1950                 return;
1951         }
1952
1953         pts_t in = 0, out = 0, length = 0;
1954         
1955         getLength(length);
1956                 
1957         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1958         
1959         while (1)
1960         {
1961                 if (i == m_cue_entries.end())
1962                         out = length;
1963                 else {
1964                         if (i->what == 0) /* in */
1965                         {
1966                                 in = i++->where;
1967                                 continue;
1968                         } else if (i->what == 1) /* out */
1969                                 out = i++->where;
1970                         else /* mark (2) or last play position (3) */
1971                         {
1972                                 i++;
1973                                 continue;
1974                         }
1975                 }
1976                 
1977                 if (in != out)
1978                         m_cue->addSourceSpan(in, out);
1979                 
1980                 in = length;
1981                 
1982                 if (i == m_cue_entries.end())
1983                         break;
1984         }
1985         m_cue->commitSpans();
1986 }
1987
1988 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry)
1989 {
1990         if (m_subtitle_widget)
1991                 disableSubtitles(parent);
1992         
1993         if (!m_teletext_parser)
1994                 return -1;
1995         
1996         if (!PyInt_Check(entry))
1997                 return -1;
1998         
1999         m_subtitle_widget = new eSubtitleWidget(parent);
2000         m_subtitle_widget->resize(parent->size()); /* full size */
2001         
2002         int page = PyInt_AsLong(entry);
2003         
2004         m_teletext_parser->setPage(page);
2005
2006         return 0;
2007 }
2008
2009 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2010 {
2011         delete m_subtitle_widget;
2012         m_subtitle_widget = 0;
2013         return 0;
2014 }
2015
2016 PyObject *eDVBServicePlay::getSubtitleList()
2017 {
2018         if (!m_teletext_parser)
2019         {
2020                 Py_INCREF(Py_None);
2021                 return Py_None;
2022         }
2023         
2024         PyObject *l = PyList_New(0);
2025         
2026         for (std::set<int>::iterator i(m_teletext_parser->m_found_subtitle_pages.begin()); i != m_teletext_parser->m_found_subtitle_pages.end(); ++i)
2027         {
2028                 PyObject *tuple = PyTuple_New(2);
2029                 char desc[20];
2030                 sprintf(desc, "Page %x", *i);
2031                 PyTuple_SetItem(tuple, 0, PyString_FromString(desc));
2032                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i));
2033                 PyList_Append(l, tuple);
2034         }
2035         
2036         return l;
2037 }
2038
2039 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2040 {
2041         if (m_subtitle_widget)
2042         {
2043                 m_subtitle_pages.push_back(page);
2044                 
2045                 checkSubtitleTiming();
2046         }
2047 }
2048
2049 void eDVBServicePlay::checkSubtitleTiming()
2050 {
2051         while (1)
2052         {
2053                 if (m_subtitle_pages.empty())
2054                         return;
2055         
2056                 eDVBTeletextSubtitlePage p = m_subtitle_pages.front();
2057         
2058                 pts_t pos = 0;
2059         
2060                 if (m_decoder)
2061                         m_decoder->getPTS(0, pos);
2062         
2063                 int diff = p.m_pts - pos;
2064                 if (diff < 0)
2065                 {
2066                         eDebug("[late (%d ms)]", -diff / 90);
2067                         diff = 0;
2068                 }
2069                 if (diff > 900000)
2070                 {
2071                         eDebug("[invalid]");
2072                         diff = 0;
2073                 }
2074         
2075                 if (!diff)
2076                 {
2077                         m_subtitle_widget->setPage(p);
2078                         m_subtitle_pages.pop_front();
2079                 } else
2080                 {
2081                         m_subtitle_sync_timer.start(diff / 90, 1);
2082                         break;
2083                 }
2084         }
2085 }
2086
2087 void eDVBServicePlay::newDVBSubtitleRegion(const eDVBSubtitleRegion &p)
2088 {
2089         eDebug("new dvb subtitle region");
2090 }
2091
2092 void eDVBServicePlay::checkDvbSubtitleTiming()
2093 {
2094         eDebug("check dvb subtitle timing");
2095 }
2096
2097 int eDVBServicePlay::getAC3Delay()
2098 {
2099         if (m_dvb_service)
2100                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2101         else if (m_decoder)
2102                 return m_decoder->getAC3Delay();
2103         else
2104                 return 0;
2105 }
2106
2107 int eDVBServicePlay::getPCMDelay()
2108 {
2109         if (m_dvb_service)
2110                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2111         else if (m_decoder)
2112                 return m_decoder->getPCMDelay();
2113         else
2114                 return 0;
2115 }
2116
2117 void eDVBServicePlay::setAC3Delay(int delay)
2118 {
2119         if (m_dvb_service)
2120                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2121         if (m_decoder)
2122                 m_decoder->setAC3Delay(delay);
2123 }
2124
2125 void eDVBServicePlay::setPCMDelay(int delay)
2126 {
2127         if (m_dvb_service)
2128                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2129         if (m_decoder)
2130                 m_decoder->setPCMDelay(delay);
2131 }
2132
2133 DEFINE_REF(eDVBServicePlay)
2134
2135 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");