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