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