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