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