enable http automatic redirects (requires very recent neonhttpsrc). (mpeg-1 podcasts...
[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         CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
733 }
734
735 eDVBServicePlay::~eDVBServicePlay()
736 {
737         delete m_subtitle_widget;
738 }
739
740 void eDVBServicePlay::gotNewEvent()
741 {
742 #if 0
743                 // debug only
744         ePtr<eServiceEvent> m_event_now, m_event_next;
745         getEvent(m_event_now, 0);
746         getEvent(m_event_next, 1);
747
748         if (m_event_now)
749                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
750         if (m_event_next)
751                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
752 #endif
753         m_event((iPlayableService*)this, evUpdatedEventInfo);
754 }
755
756 void eDVBServicePlay::serviceEvent(int event)
757 {
758         switch (event)
759         {
760         case eDVBServicePMTHandler::eventTuned:
761         {
762                 ePtr<iDVBDemux> m_demux;
763                 if (!m_service_handler.getDataDemux(m_demux))
764                 {
765                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
766                         int sid = ref.getParentServiceID().get();
767                         if (!sid)
768                                 sid = ref.getServiceID().get();
769                         if ( ref.getParentTransportStreamID().get() &&
770                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
771                                 m_event_handler.startOther(m_demux, sid);
772                         else
773                                 m_event_handler.start(m_demux, sid);
774                 }
775                 break;
776         }
777         case eDVBServicePMTHandler::eventTuneFailed:
778         {
779                 eDebug("DVB service failed to tune");
780                 m_event((iPlayableService*)this, evTuneFailed);
781                 break;
782         }
783         case eDVBServicePMTHandler::eventNewProgramInfo:
784         {
785                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
786                 if (m_timeshift_enabled)
787                         updateTimeshiftPids();
788                 if (!m_timeshift_active)
789                         updateDecoder();
790                 if (m_first_program_info && m_is_pvr)
791                 {
792                         m_first_program_info = 0;
793                         seekTo(0);
794                 }
795                 m_event((iPlayableService*)this, evUpdatedInfo);
796                 break;
797         }
798         case eDVBServicePMTHandler::eventEOF:
799                 m_event((iPlayableService*)this, evEOF);
800                 break;
801         case eDVBServicePMTHandler::eventSOF:
802                 m_event((iPlayableService*)this, evSOF);
803                 break;
804         }
805 }
806
807 void eDVBServicePlay::serviceEventTimeshift(int event)
808 {
809         switch (event)
810         {
811         case eDVBServicePMTHandler::eventNewProgramInfo:
812                 if (m_timeshift_active)
813                         updateDecoder();
814                 break;
815         case eDVBServicePMTHandler::eventSOF:
816                 m_event((iPlayableService*)this, evSOF);
817                 break;
818         case eDVBServicePMTHandler::eventEOF:
819                 switchToLive();
820                 break;
821         }
822 }
823
824 RESULT eDVBServicePlay::start()
825 {
826         int r;
827                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
828                    two (one for decoding, one for data source), as we must be prepared
829                    to start recording from the data demux. */
830         if (m_is_pvr)
831                 m_cue = new eCueSheet();
832
833         m_first_program_info = 1;
834         eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
835         r = m_service_handler.tune(service, m_is_pvr, m_cue);
836
837                 /* inject EIT if there is a stored one */
838         if (m_is_pvr)
839         {
840                 std::string filename = service.path;
841                 filename.erase(filename.length()-2, 2);
842                 filename+="eit";
843                 ePtr<eServiceEvent> event = new eServiceEvent;
844                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
845                 {
846                         ePtr<eServiceEvent> empty;
847                         m_event_handler.inject(event, 0);
848                         m_event_handler.inject(empty, 1);
849                 }
850         }
851
852         if (m_is_pvr)
853                 loadCuesheet();
854
855         m_event(this, evStart);
856         m_event((iPlayableService*)this, evSeekableStatusChanged);
857         return 0;
858 }
859
860 RESULT eDVBServicePlay::stop()
861 {
862                 /* add bookmark for last play position */
863         if (m_is_pvr)
864         {
865                 pts_t play_position;
866                 if (!getPlayPosition(play_position))
867                 {
868                                 /* remove last position */
869                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
870                         {
871                                 if (i->what == 3) /* current play position */
872                                 {
873                                         m_cue_entries.erase(i);
874                                         i = m_cue_entries.begin();
875                                         continue;
876                                 } else
877                                         ++i;
878                         }
879                         
880                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
881                         m_cuesheet_changed = 1;
882                 }
883         }
884
885         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
886
887         m_service_handler_timeshift.free();
888         m_service_handler.free();
889         
890         if (m_is_pvr && m_cuesheet_changed)
891         {
892                 struct stat s;
893                                 /* save cuesheet only when main file is accessible. */
894                 if (!::stat(m_reference.path.c_str(), &s))
895                         saveCuesheet();
896         }
897         
898         return 0;
899 }
900
901 RESULT eDVBServicePlay::setTarget(int target)
902 {
903         m_is_primary = !target;
904         return 0;
905 }
906
907 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
908 {
909         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
910         return 0;
911 }
912
913 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
914 {
915                 /* note: we check for timeshift to be enabled,
916                    not neccessary active. if you pause when timeshift
917                    is not active, you should activate it when unpausing */
918         if ((!m_is_pvr) && (!m_timeshift_enabled))
919         {
920                 ptr = 0;
921                 return -1;
922         }
923
924         ptr = this;
925         return 0;
926 }
927
928 RESULT eDVBServicePlay::setSlowMotion(int ratio)
929 {
930         if (m_decoder)
931                 return m_decoder->setSlowMotion(ratio);
932         else
933                 return -1;
934 }
935
936 RESULT eDVBServicePlay::setFastForward(int ratio)
937 {
938         int skipmode, ffratio;
939         
940         if (ratio > 8)
941         {
942                 skipmode = ratio;
943                 ffratio = 1;
944         } else if (ratio > 0)
945         {
946                 skipmode = 0;
947                 ffratio = ratio;
948         } else if (!ratio)
949         {
950                 skipmode = 0;
951                 ffratio = 0;
952         } else // if (ratio < 0)
953         {
954                 skipmode = ratio;
955                 ffratio = 1;
956         }
957
958         if (m_skipmode != skipmode)
959         {
960                 eDebug("setting cue skipmode to %d", skipmode);
961                 if (m_cue)
962                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
963         }
964         
965         m_skipmode = skipmode;
966         
967         if (!m_decoder)
968                 return -1;
969
970         return m_decoder->setFastForward(ffratio);
971 }
972     
973 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
974 {
975         if (m_is_pvr || m_timeshift_enabled)
976         {
977                 ptr = this;
978                 return 0;
979         }
980         
981         ptr = 0;
982         return -1;
983 }
984
985         /* TODO: when timeshift is enabled but not active, this doesn't work. */
986 RESULT eDVBServicePlay::getLength(pts_t &len)
987 {
988         ePtr<iDVBPVRChannel> pvr_channel;
989         
990         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
991                 return -1;
992         
993         return pvr_channel->getLength(len);
994 }
995
996 RESULT eDVBServicePlay::pause()
997 {
998         if (!m_is_paused && m_decoder)
999         {
1000                 m_is_paused = 1;
1001                 return m_decoder->freeze(0);
1002         } else
1003                 return -1;
1004 }
1005
1006 RESULT eDVBServicePlay::unpause()
1007 {
1008         if (m_is_paused && m_decoder)
1009         {
1010                 m_is_paused = 0;
1011                 return m_decoder->unfreeze();
1012         } else
1013                 return -1;
1014 }
1015
1016 RESULT eDVBServicePlay::seekTo(pts_t to)
1017 {
1018         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1019         
1020         if (!m_decode_demux)
1021                 return -1;
1022
1023         ePtr<iDVBPVRChannel> pvr_channel;
1024         
1025         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1026                 return -1;
1027         
1028         if (!m_cue)
1029                 return -1;
1030         
1031         m_cue->seekTo(0, to);
1032         return 0;
1033 }
1034
1035 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1036 {
1037         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1038         
1039         if (!m_decode_demux)
1040                 return -1;
1041
1042         ePtr<iDVBPVRChannel> pvr_channel;
1043         
1044         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1045                 return -1;
1046         
1047         int mode = 1;
1048         
1049                         /* HACK until we have skip-AP api */
1050         if ((to > 0) && (to < 100))
1051                 mode = 2;
1052         
1053         to *= direction;
1054         
1055         if (!m_cue)
1056                 return 0;
1057         
1058         m_cue->seekTo(mode, to);
1059         return 0;
1060 }
1061
1062 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1063 {
1064         ePtr<iDVBPVRChannel> pvr_channel;
1065         
1066         if (!m_decode_demux)
1067                 return -1;
1068         
1069         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1070                 return -1;
1071         
1072         int r = 0;
1073
1074                 /* if there is a decoder, use audio or video PTS */
1075         if (m_decoder)
1076         {
1077                 r = m_decoder->getPTS(0, pos);
1078                 if (r)
1079                         return r;
1080         }
1081         
1082                 /* fixup */
1083         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1084 }
1085
1086 RESULT eDVBServicePlay::setTrickmode(int trick)
1087 {
1088         if (m_decoder)
1089                 m_decoder->setTrickmode(trick);
1090         return 0;
1091 }
1092
1093 RESULT eDVBServicePlay::isCurrentlySeekable()
1094 {
1095         return m_is_pvr || m_timeshift_active;
1096 }
1097
1098 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1099 {
1100         ptr = this;
1101         return 0;
1102 }
1103
1104 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1105 {
1106         ptr = this;
1107         return 0;
1108 }
1109
1110 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1111 {
1112         ptr = this;
1113         return 0;
1114 }
1115
1116 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1117 {
1118         ptr = this;
1119         return 0;
1120 }
1121
1122 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1123 {
1124         ptr = this;
1125         return 0;
1126 }
1127
1128 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1129 {
1130         ptr = 0;
1131         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1132                 (m_timeshift_enabled || !m_is_pvr))
1133         {
1134                 if (!m_timeshift_enabled)
1135                 {
1136                                 /* we need enough diskspace */
1137                         struct statfs fs;
1138                         if (statfs(TSPATH "/.", &fs) < 0)
1139                         {
1140                                 eDebug("statfs failed!");
1141                                 return -2;
1142                         }
1143                 
1144                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1145                         {
1146                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1147                                 return -3;
1148                         }
1149                 }
1150                 ptr = this;
1151                 return 0;
1152         }
1153         return -1;
1154 }
1155
1156 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1157 {
1158         if (m_is_pvr)
1159         {
1160                 ptr = this;
1161                 return 0;
1162         }
1163         ptr = 0;
1164         return -1;
1165 }
1166
1167 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1168 {
1169         ptr = this;
1170         return 0;
1171 }
1172
1173 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1174 {
1175         ptr = this;
1176         return 0;
1177 }
1178
1179 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1180 {
1181         ptr = this;
1182         return 0;
1183 }
1184
1185 RESULT eDVBServicePlay::getName(std::string &name)
1186 {
1187         if (m_is_pvr)
1188         {
1189                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1190                 return i->getName(m_reference, name);
1191         }
1192         if (m_dvb_service)
1193         {
1194                 m_dvb_service->getName(m_reference, name);
1195                 if (name.empty())
1196                         name = "(...)";
1197         }
1198         else if (!m_reference.name.empty())
1199                 eStaticServiceDVBInformation().getName(m_reference, name);
1200         else
1201                 name = "DVB service";
1202         return 0;
1203 }
1204
1205 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1206 {
1207         return m_event_handler.getEvent(evt, nownext);
1208 }
1209
1210 int eDVBServicePlay::getInfo(int w)
1211 {
1212         eDVBServicePMTHandler::program program;
1213
1214         if (w == sCAIDs)
1215                 return resIsPyObject;
1216
1217         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1218         
1219         if (h.getProgramInfo(program))
1220                 return -1;
1221         
1222         switch (w)
1223         {
1224         case sAspect:
1225                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1226                 {
1227                         ePtr<eServiceEvent> evt;
1228                         if (!m_event_handler.getEvent(evt, 0))
1229                         {
1230                                 ePtr<eComponentData> data;
1231                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1232                                 {
1233                                         if ( data->getStreamContent() == 1 )
1234                                         {
1235                                                 switch(data->getComponentType())
1236                                                 {
1237                                                         // SD
1238                                                         case 1: // 4:3 SD PAL
1239                                                         case 2:
1240                                                         case 3: // 16:9 SD PAL
1241                                                         case 4: // > 16:9 PAL
1242                                                         case 5: // 4:3 SD NTSC
1243                                                         case 6: 
1244                                                         case 7: // 16:9 SD NTSC
1245                                                         case 8: // > 16:9 NTSC
1246
1247                                                         // HD
1248                                                         case 9: // 4:3 HD PAL
1249                                                         case 0xA:
1250                                                         case 0xB: // 16:9 HD PAL
1251                                                         case 0xC: // > 16:9 HD PAL
1252                                                         case 0xD: // 4:3 HD NTSC
1253                                                         case 0xE:
1254                                                         case 0xF: // 16:9 HD NTSC
1255                                                         case 0x10: // > 16:9 HD PAL
1256                                                                 return data->getComponentType();
1257                                                 }
1258                                         }
1259                                 }
1260                         }
1261                 }
1262                 return -1;
1263         case sIsCrypted: return program.isCrypted();
1264         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1265         case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1266         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1267         case sPCRPID: return program.pcrPid;
1268         case sPMTPID: return program.pmtPid;
1269         case sTXTPID: return program.textPid;
1270         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1271         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1272         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1273         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1274         case sProvider: if (!m_dvb_service) return -1; return -2;
1275         case sServiceref: return resIsString;
1276         default:
1277                 return -1;
1278         }
1279 }
1280
1281 std::string eDVBServicePlay::getInfoString(int w)
1282 {
1283         switch (w)
1284         {
1285         case sProvider:
1286                 if (!m_dvb_service) return "";
1287                 return m_dvb_service->m_provider_name;
1288         case sServiceref:
1289                 return m_reference.toString();
1290         default:
1291                 break;
1292         }
1293         return iServiceInformation::getInfoString(w);
1294 }
1295
1296 PyObject *eDVBServicePlay::getInfoObject(int w)
1297 {
1298         switch (w)
1299         {
1300         case sCAIDs:
1301                 return m_service_handler.getCaIds();
1302         default:
1303                 break;
1304         }
1305         return iServiceInformation::getInfoObject(w);
1306 }
1307
1308 int eDVBServicePlay::getNumberOfTracks()
1309 {
1310         eDVBServicePMTHandler::program program;
1311         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1312         if (h.getProgramInfo(program))
1313                 return 0;
1314         return program.audioStreams.size();
1315 }
1316
1317 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1318 {
1319         int ret = selectAudioStream(i);
1320
1321         if (m_decoder->start())
1322                 return -5;
1323
1324         return ret;
1325 }
1326
1327 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1328 {
1329         eDVBServicePMTHandler::program program;
1330         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1331
1332         if (h.getProgramInfo(program))
1333                 return -1;
1334         
1335         if (i >= program.audioStreams.size())
1336                 return -2;
1337         
1338         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1339                 info.m_description = "MPEG";
1340         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1341                 info.m_description = "AC3";
1342         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1343                 info.m_description = "AAC";
1344         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1345                 info.m_description = "DTS";
1346         else
1347                 info.m_description = "???";
1348
1349         if (program.audioStreams[i].component_tag != -1)
1350         {
1351                 ePtr<eServiceEvent> evt;
1352                 if (!m_event_handler.getEvent(evt, 0))
1353                 {
1354                         ePtr<eComponentData> data;
1355                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1356                                 info.m_language = data->getText();
1357                 }
1358         }
1359
1360         if (info.m_language.empty())
1361                 info.m_language = program.audioStreams[i].language_code;
1362         
1363         return 0;
1364 }
1365
1366 int eDVBServicePlay::selectAudioStream(int i)
1367 {
1368         eDVBServicePMTHandler::program program;
1369         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1370
1371         if (h.getProgramInfo(program))
1372                 return -1;
1373         
1374         if ((unsigned int)i >= program.audioStreams.size())
1375                 return -2;
1376         
1377         if (!m_decoder)
1378                 return -3;
1379         
1380         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1381                 return -4;
1382
1383         if (m_radiotext_parser)
1384                 m_radiotext_parser->start(program.audioStreams[i].pid);
1385
1386         if (m_dvb_service && !m_is_pvr)
1387         {
1388                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1389                 {
1390                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1391                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1392                 }
1393                 else
1394                 {
1395                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1396                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1397                 }
1398         }
1399
1400         h.resetCachedProgram();
1401
1402         return 0;
1403 }
1404
1405 int eDVBServicePlay::getCurrentChannel()
1406 {
1407         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1408 }
1409
1410 RESULT eDVBServicePlay::selectChannel(int i)
1411 {
1412         if (i < LEFT || i > RIGHT || i == STEREO)
1413                 i = -1;  // Stereo
1414         if (m_dvb_service)
1415                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1416         if (m_decoder)
1417                 m_decoder->setAudioChannel(i);
1418         return 0;
1419 }
1420
1421 std::string eDVBServicePlay::getRadioText(int x)
1422 {
1423         if (m_radiotext_parser)
1424                 switch(x)
1425                 {
1426                         case 0:
1427                                 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1428                 }
1429         return "";
1430 }
1431
1432 void eDVBServicePlay::radioTextUpdated()
1433 {
1434         m_event((iPlayableService*)this, evUpdatedRadioText);
1435 }
1436
1437 int eDVBServiceBase::getFrontendInfo(int w)
1438 {
1439         eUsePtr<iDVBChannel> channel;
1440         if(m_service_handler.getChannel(channel))
1441                 return 0;
1442         ePtr<iDVBFrontend> fe;
1443         if(channel->getFrontend(fe))
1444                 return 0;
1445         return fe->readFrontendData(w);
1446 }
1447
1448 PyObject *eDVBServiceBase::getFrontendData(bool original)
1449 {
1450         ePyObject ret;
1451
1452         eUsePtr<iDVBChannel> channel;
1453         if(!m_service_handler.getChannel(channel))
1454         {
1455                 ePtr<iDVBFrontend> fe;
1456                 if(!channel->getFrontend(fe))
1457                 {
1458                         ret = fe->readTransponderData(original);
1459                         if (ret)
1460                         {
1461                                 ePtr<iDVBFrontendParameters> feparm;
1462                                 channel->getCurrentFrontendParameters(feparm);
1463                                 if (feparm)
1464                                 {
1465                                         eDVBFrontendParametersSatellite osat;
1466                                         if (!feparm->getDVBS(osat))
1467                                         {
1468                                                 void PutToDict(ePyObject &, const char*, long);
1469                                                 void PutToDict(ePyObject &, const char*, const char*);
1470                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1471                                                 const char *tmp = "UNKNOWN";
1472                                                 switch(osat.polarisation)
1473                                                 {
1474                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1475                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1476                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1477                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1478                                                         default:break;
1479                                                 }
1480                                                 PutToDict(ret, "polarization", tmp);
1481                                         }
1482                                 }
1483                         }
1484                 }
1485         }
1486         if (!ret)
1487         {
1488                 ret = Py_None;
1489                 Py_INCREF(ret);
1490         }
1491         return ret;
1492 }
1493
1494 int eDVBServicePlay::getNumberOfSubservices()
1495 {
1496         ePtr<eServiceEvent> evt;
1497         if (!m_event_handler.getEvent(evt, 0))
1498                 return evt->getNumOfLinkageServices();
1499         return 0;
1500 }
1501
1502 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1503 {
1504         ePtr<eServiceEvent> evt;
1505         if (!m_event_handler.getEvent(evt, 0))
1506         {
1507                 if (!evt->getLinkageService(sub, m_reference, n))
1508                         return 0;
1509         }
1510         sub.type=eServiceReference::idInvalid;
1511         return -1;
1512 }
1513
1514 RESULT eDVBServicePlay::startTimeshift()
1515 {
1516         ePtr<iDVBDemux> demux;
1517         
1518         eDebug("Start timeshift!");
1519         
1520         if (m_timeshift_enabled)
1521                 return -1;
1522         
1523                 /* start recording with the data demux. */
1524         if (m_service_handler.getDataDemux(demux))
1525                 return -2;
1526
1527         demux->createTSRecorder(m_record);
1528         if (!m_record)
1529                 return -3;
1530
1531         char templ[]=TSPATH "/timeshift.XXXXXX";
1532         m_timeshift_fd = mkstemp(templ);
1533         m_timeshift_file = templ;
1534         
1535         eDebug("recording to %s", templ);
1536         
1537         if (m_timeshift_fd < 0)
1538         {
1539                 m_record = 0;
1540                 return -4;
1541         }
1542                 
1543         m_record->setTargetFD(m_timeshift_fd);
1544
1545         m_timeshift_enabled = 1;
1546         
1547         updateTimeshiftPids();
1548         m_record->start();
1549
1550         return 0;
1551 }
1552
1553 RESULT eDVBServicePlay::stopTimeshift()
1554 {
1555         if (!m_timeshift_enabled)
1556                 return -1;
1557         
1558         switchToLive();
1559         
1560         m_timeshift_enabled = 0;
1561         
1562         m_record->stop();
1563         m_record = 0;
1564         
1565         close(m_timeshift_fd);
1566         eDebug("remove timeshift file");
1567         remove(m_timeshift_file.c_str());
1568         
1569         return 0;
1570 }
1571
1572 int eDVBServicePlay::isTimeshiftActive()
1573 {
1574         return m_timeshift_enabled && m_timeshift_active;
1575 }
1576
1577 RESULT eDVBServicePlay::activateTimeshift()
1578 {
1579         if (!m_timeshift_enabled)
1580                 return -1;
1581         
1582         if (!m_timeshift_active)
1583         {
1584                 switchToTimeshift();
1585                 return 0;
1586         }
1587         
1588         return -2;
1589 }
1590
1591 PyObject *eDVBServicePlay::getCutList()
1592 {
1593         ePyObject list = PyList_New(0);
1594         
1595         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1596         {
1597                 ePyObject tuple = PyTuple_New(2);
1598                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1599                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1600                 PyList_Append(list, tuple);
1601                 Py_DECREF(tuple);
1602         }
1603         
1604         return list;
1605 }
1606
1607 void eDVBServicePlay::setCutList(ePyObject list)
1608 {
1609         if (!PyList_Check(list))
1610                 return;
1611         int size = PyList_Size(list);
1612         int i;
1613         
1614         m_cue_entries.clear();
1615         
1616         for (i=0; i<size; ++i)
1617         {
1618                 ePyObject tuple = PyList_GET_ITEM(list, i);
1619                 if (!PyTuple_Check(tuple))
1620                 {
1621                         eDebug("non-tuple in cutlist");
1622                         continue;
1623                 }
1624                 if (PyTuple_Size(tuple) != 2)
1625                 {
1626                         eDebug("cutlist entries need to be a 2-tuple");
1627                         continue;
1628                 }
1629                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1630                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1631                 {
1632                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1633                         continue;
1634                 }
1635                 pts_t pts = PyLong_AsLongLong(ppts);
1636                 int type = PyInt_AsLong(ptype);
1637                 m_cue_entries.insert(cueEntry(pts, type));
1638                 eDebug("adding %08llx, %d", pts, type);
1639         }
1640         m_cuesheet_changed = 1;
1641         
1642         cutlistToCuesheet();
1643         m_event((iPlayableService*)this, evCuesheetChanged);
1644 }
1645
1646 void eDVBServicePlay::setCutListEnable(int enable)
1647 {
1648         m_cutlist_enabled = enable;
1649         cutlistToCuesheet();
1650 }
1651
1652 void eDVBServicePlay::updateTimeshiftPids()
1653 {
1654         if (!m_record)
1655                 return;
1656         
1657         eDVBServicePMTHandler::program program;
1658         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1659
1660         if (h.getProgramInfo(program))
1661                 return;
1662         else
1663         {
1664                 std::set<int> pids_to_record;
1665                 pids_to_record.insert(0); // PAT
1666                 if (program.pmtPid != -1)
1667                         pids_to_record.insert(program.pmtPid); // PMT
1668
1669                 if (program.textPid != -1)
1670                         pids_to_record.insert(program.textPid); // Videotext
1671
1672                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1673                         i(program.videoStreams.begin()); 
1674                         i != program.videoStreams.end(); ++i)
1675                         pids_to_record.insert(i->pid);
1676
1677                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1678                         i(program.audioStreams.begin()); 
1679                         i != program.audioStreams.end(); ++i)
1680                                 pids_to_record.insert(i->pid);
1681
1682                 std::set<int> new_pids, obsolete_pids;
1683                 
1684                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1685                                 m_pids_active.begin(), m_pids_active.end(),
1686                                 std::inserter(new_pids, new_pids.begin()));
1687                 
1688                 std::set_difference(
1689                                 m_pids_active.begin(), m_pids_active.end(),
1690                                 pids_to_record.begin(), pids_to_record.end(), 
1691                                 std::inserter(new_pids, new_pids.begin())
1692                                 );
1693
1694                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1695                         m_record->addPID(*i);
1696
1697                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1698                         m_record->removePID(*i);
1699         }
1700 }
1701
1702 void eDVBServicePlay::switchToLive()
1703 {
1704         if (!m_timeshift_active)
1705                 return;
1706         
1707         m_cue = 0;
1708         m_decoder = 0;
1709         m_decode_demux = 0;
1710         m_teletext_parser = 0;
1711         m_radiotext_parser = 0;
1712         m_subtitle_parser = 0;
1713         m_new_dvb_subtitle_page_connection = 0;
1714         m_new_subtitle_page_connection = 0;
1715         m_radiotext_updated_connection = 0;
1716
1717                 /* free the timeshift service handler, we need the resources */
1718         m_service_handler_timeshift.free();
1719         m_timeshift_active = 0;
1720
1721         m_event((iPlayableService*)this, evSeekableStatusChanged);
1722
1723         updateDecoder();
1724 }
1725
1726 void eDVBServicePlay::switchToTimeshift()
1727 {
1728         if (m_timeshift_active)
1729                 return;
1730
1731         m_decode_demux = 0;
1732         m_decoder = 0;
1733         m_teletext_parser = 0;
1734         m_radiotext_parser = 0;
1735         m_subtitle_parser = 0;
1736         m_new_subtitle_page_connection = 0;
1737         m_new_dvb_subtitle_page_connection = 0;
1738         m_radiotext_updated_connection = 0;
1739
1740         m_timeshift_active = 1;
1741
1742         m_event((iPlayableService*)this, evSeekableStatusChanged);
1743
1744         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1745         r.path = m_timeshift_file;
1746
1747         m_cue = new eCueSheet();
1748         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1749         updateDecoder(); /* mainly to switch off PCR */
1750 }
1751
1752 void eDVBServicePlay::updateDecoder()
1753 {
1754         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1755
1756         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1757
1758         bool defaultac3=false;
1759         std::string default_ac3;
1760
1761         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1762                 defaultac3 = default_ac3 == "True";
1763
1764         eDVBServicePMTHandler::program program;
1765         if (h.getProgramInfo(program))
1766                 eDebug("getting program info failed.");
1767         else
1768         {
1769                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1770                 if (!program.videoStreams.empty())
1771                 {
1772                         eDebugNoNewLine(" (");
1773                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1774                                 i(program.videoStreams.begin());
1775                                 i != program.videoStreams.end(); ++i)
1776                         {
1777                                 if (vpid == -1)
1778                                 {
1779                                         vpid = i->pid;
1780                                         vpidtype = i->type;
1781                                 }
1782                                 if (i != program.videoStreams.begin())
1783                                         eDebugNoNewLine(", ");
1784                                 eDebugNoNewLine("%04x", i->pid);
1785                         }
1786                         eDebugNoNewLine(")");
1787                 }
1788                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1789                 if (!program.audioStreams.empty())
1790                 {
1791                         eDebugNoNewLine(" (");
1792                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1793                                 i(program.audioStreams.begin());
1794                                 i != program.audioStreams.end(); ++i)
1795                         {
1796                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1797                                 {
1798                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1799                                         {
1800                                                 apid = i->pid;
1801                                                 apidtype = i->type;
1802                                         }
1803                                 }
1804                                 if (i != program.audioStreams.begin())
1805                                         eDebugNoNewLine(", ");
1806                                 eDebugNoNewLine("%04x", i->pid);
1807                         }
1808                         eDebugNoNewLine(")");
1809                 }
1810                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1811                 pcrpid = program.pcrPid;
1812                 eDebug(", and the text pid is %04x", program.textPid);
1813                 tpid = program.textPid;
1814         }
1815
1816         if (!m_decoder)
1817         {
1818                 h.getDecodeDemux(m_decode_demux);
1819                 if (m_decode_demux)
1820                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1821                 if (m_cue)
1822                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1823                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1824                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1825                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1826                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1827         }
1828
1829         if (m_decoder)
1830         {
1831                 if (m_dvb_service)
1832                 {
1833                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1834                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1835                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1836                 }
1837                 else // subservice or recording
1838                 {
1839                         eServiceReferenceDVB ref;
1840                         m_service_handler.getServiceReference(ref);
1841                         eServiceReferenceDVB parent = ref.getParentServiceReference();
1842                         if (!parent)
1843                                 parent = ref;
1844                         if (parent)
1845                         {
1846                                 ePtr<eDVBResourceManager> res_mgr;
1847                                 if (!eDVBResourceManager::getInstance(res_mgr))
1848                                 {
1849                                         ePtr<iDVBChannelList> db;
1850                                         if (!res_mgr->getChannelList(db))
1851                                         {
1852                                                 ePtr<eDVBService> origService;
1853                                                 if (!db->getService(parent, origService))
1854                                                 {
1855                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1856                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1857                                                 }
1858                                         }
1859                                 }
1860                         }
1861                 }
1862                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1863                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1864
1865                 m_decoder->setVideoPID(vpid, vpidtype);
1866                 m_decoder->setAudioPID(apid, apidtype);
1867                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1868                 {
1869                         m_decoder->setSyncPCR(pcrpid);
1870                         if (apid != -1)
1871                         {
1872                                 ePtr<iDVBDemux> data_demux;
1873                                 if (!h.getDataDemux(data_demux))
1874                                 {
1875                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1876                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1877                                         m_radiotext_parser->start(apid);
1878                                 }
1879                         }
1880                 }
1881                 else
1882                         m_decoder->setSyncPCR(-1);
1883
1884                 m_decoder->setTextPID(tpid);
1885
1886                 m_teletext_parser->start(program.textPid);
1887
1888                 if (!m_is_primary)
1889                         m_decoder->setTrickmode(1);
1890
1891                 m_decoder->start();
1892
1893                 if (vpid > 0 && vpid < 0x2000)
1894                         ;
1895                 else
1896                 {
1897                         std::string radio_pic;
1898                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1899                                 m_decoder->setRadioPic(radio_pic);
1900                 }
1901
1902                 m_decoder->setAudioChannel(achannel);
1903
1904 // how we can do this better?
1905 // update cache pid when the user changed the audio track or video track
1906 // TODO handling of difference audio types.. default audio types..
1907                                 
1908                 /* don't worry about non-existing services, nor pvr services */
1909                 if (m_dvb_service && !m_is_pvr)
1910                 {
1911                         if (apidtype == eDVBAudio::aMPEG)
1912                         {
1913                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1914                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1915                         }
1916                         else
1917                         {
1918                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1919                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1920                         }
1921                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1922                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1923                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1924                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1925                 }
1926         }
1927         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1928 }
1929
1930 void eDVBServicePlay::loadCuesheet()
1931 {
1932         std::string filename = m_reference.path + ".cuts";
1933         
1934         m_cue_entries.clear();
1935
1936         FILE *f = fopen(filename.c_str(), "rb");
1937
1938         if (f)
1939         {
1940                 eDebug("loading cuts..");
1941                 while (1)
1942                 {
1943                         unsigned long long where;
1944                         unsigned int what;
1945                         
1946                         if (!fread(&where, sizeof(where), 1, f))
1947                                 break;
1948                         if (!fread(&what, sizeof(what), 1, f))
1949                                 break;
1950                         
1951 #if BYTE_ORDER == LITTLE_ENDIAN
1952                         where = bswap_64(where);
1953 #endif
1954                         what = ntohl(what);
1955                         
1956                         if (what > 3)
1957                                 break;
1958                         
1959                         m_cue_entries.insert(cueEntry(where, what));
1960                 }
1961                 fclose(f);
1962                 eDebug("%d entries", m_cue_entries.size());
1963         } else
1964                 eDebug("cutfile not found!");
1965         
1966         m_cuesheet_changed = 0;
1967         cutlistToCuesheet();
1968         m_event((iPlayableService*)this, evCuesheetChanged);
1969 }
1970
1971 void eDVBServicePlay::saveCuesheet()
1972 {
1973         std::string filename = m_reference.path + ".cuts";
1974         
1975         FILE *f = fopen(filename.c_str(), "wb");
1976
1977         if (f)
1978         {
1979                 unsigned long long where;
1980                 int what;
1981
1982                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1983                 {
1984 #if BYTE_ORDER == BIG_ENDIAN
1985                         where = i->where;
1986 #else
1987                         where = bswap_64(i->where);
1988 #endif
1989                         what = htonl(i->what);
1990                         fwrite(&where, sizeof(where), 1, f);
1991                         fwrite(&what, sizeof(what), 1, f);
1992                         
1993                 }
1994                 fclose(f);
1995         }
1996         
1997         m_cuesheet_changed = 0;
1998 }
1999
2000 void eDVBServicePlay::cutlistToCuesheet()
2001 {
2002         if (!m_cue)
2003         {
2004                 eDebug("no cue sheet");
2005                 return;
2006         }       
2007         m_cue->clear();
2008         
2009         if (!m_cutlist_enabled)
2010         {
2011                 m_cue->commitSpans();
2012                 eDebug("cutlists were disabled");
2013                 return;
2014         }
2015
2016         pts_t in = 0, out = 0, length = 0;
2017         
2018         getLength(length);
2019                 
2020         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2021         
2022         while (1)
2023         {
2024                 if (i == m_cue_entries.end())
2025                         out = length;
2026                 else {
2027                         if (i->what == 0) /* in */
2028                         {
2029                                 in = i++->where;
2030                                 continue;
2031                         } else if (i->what == 1) /* out */
2032                                 out = i++->where;
2033                         else /* mark (2) or last play position (3) */
2034                         {
2035                                 i++;
2036                                 continue;
2037                         }
2038                 }
2039                 
2040                 if (in != out)
2041                         m_cue->addSourceSpan(in, out);
2042                 
2043                 in = length;
2044                 
2045                 if (i == m_cue_entries.end())
2046                         break;
2047         }
2048         m_cue->commitSpans();
2049 }
2050
2051 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2052 {
2053         if (m_subtitle_widget)
2054                 disableSubtitles(parent);
2055
2056         ePyObject entry;
2057         int tuplesize = PyTuple_Size(tuple);
2058         int type = 0;
2059
2060         if (!PyTuple_Check(tuple))
2061                 goto error_out;
2062
2063         if (tuplesize < 1)
2064                 goto error_out;
2065
2066         entry = PyTuple_GET_ITEM(tuple, 0);
2067
2068         if (!PyInt_Check(entry))
2069                 goto error_out;
2070
2071         type = PyInt_AsLong(entry);
2072
2073         if (type == 1)  // teletext subtitles
2074         {
2075                 int page, magazine, pid;
2076                 if (tuplesize < 4)
2077                         goto error_out;
2078
2079                 if (!m_teletext_parser)
2080                 {
2081                         eDebug("enable teletext subtitles.. no parser !!!");
2082                         return -1;
2083                 }
2084
2085                 entry = PyTuple_GET_ITEM(tuple, 1);
2086                 if (!PyInt_Check(entry))
2087                         goto error_out;
2088                 pid = PyInt_AsLong(entry);
2089
2090                 entry = PyTuple_GET_ITEM(tuple, 2);
2091                 if (!PyInt_Check(entry))
2092                         goto error_out;
2093                 page = PyInt_AsLong(entry);
2094
2095                 entry = PyTuple_GET_ITEM(tuple, 3);
2096                 if (!PyInt_Check(entry))
2097                         goto error_out;
2098                 magazine = PyInt_AsLong(entry);
2099
2100                 m_subtitle_widget = new eSubtitleWidget(parent);
2101                 m_subtitle_widget->resize(parent->size()); /* full size */
2102                 m_teletext_parser->setPageAndMagazine(page, magazine);
2103                 if (m_dvb_service)
2104                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2105         }
2106         else if (type == 0)
2107         {
2108                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2109                 if (!m_subtitle_parser)
2110                 {
2111                         eDebug("enable dvb subtitles.. no parser !!!");
2112                         return -1;
2113                 }
2114                 if (tuplesize < 4)
2115                         goto error_out;
2116
2117                 entry = PyTuple_GET_ITEM(tuple, 1);
2118                 if (!PyInt_Check(entry))
2119                         goto error_out;
2120                 pid = PyInt_AsLong(entry);
2121
2122                 entry = PyTuple_GET_ITEM(tuple, 2);
2123                 if (!PyInt_Check(entry))
2124                         goto error_out;
2125                 composition_page_id = PyInt_AsLong(entry);
2126
2127                 entry = PyTuple_GET_ITEM(tuple, 3);
2128                 if (!PyInt_Check(entry))
2129                         goto error_out;
2130                 ancillary_page_id = PyInt_AsLong(entry);
2131
2132                 m_subtitle_widget = new eSubtitleWidget(parent);
2133                 m_subtitle_widget->resize(parent->size()); /* full size */
2134                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2135                 if (m_dvb_service)
2136                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2137         }
2138         else
2139                 goto error_out;
2140         return 0;
2141 error_out:
2142         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2143                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2144                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2145         return -1;
2146 }
2147
2148 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2149 {
2150         delete m_subtitle_widget;
2151         m_subtitle_widget = 0;
2152         if (m_subtitle_parser)
2153         {
2154                 m_subtitle_parser->stop();
2155                 m_dvb_subtitle_pages.clear();
2156         }
2157         if (m_teletext_parser)
2158         {
2159                 m_teletext_parser->setPageAndMagazine(-1, -1);
2160                 m_subtitle_pages.clear();
2161         }
2162         if (m_dvb_service)
2163                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2164         return 0;
2165 }
2166
2167 PyObject *eDVBServicePlay::getCachedSubtitle()
2168 {
2169         if (m_dvb_service)
2170         {
2171                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2172                 if (tmp != -1)
2173                 {
2174                         unsigned int data = (unsigned int)tmp;
2175                         int pid = (data&0xFFFF0000)>>16;
2176                         ePyObject tuple = PyTuple_New(4);
2177                         eDVBServicePMTHandler::program program;
2178                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2179                         if (!h.getProgramInfo(program))
2180                         {
2181                                 if (program.textPid==pid) // teletext
2182                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2183                                 else
2184                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2185                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2186                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2187                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2188                                 return tuple;
2189                         }
2190                 }
2191         }
2192         Py_INCREF(Py_None);
2193         return Py_None;
2194 }
2195
2196 PyObject *eDVBServicePlay::getSubtitleList()
2197 {
2198         if (!m_teletext_parser)
2199         {
2200                 Py_INCREF(Py_None);
2201                 return Py_None;
2202         }
2203         
2204         ePyObject l = PyList_New(0);
2205         std::set<int> added_ttx_pages;
2206
2207         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2208                 m_teletext_parser->m_found_subtitle_pages;
2209
2210         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2211         eDVBServicePMTHandler::program program;
2212         if (h.getProgramInfo(program))
2213                 eDebug("getting program info failed.");
2214         else
2215         {
2216                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2217                         it != program.subtitleStreams.end(); ++it)
2218                 {
2219                         switch(it->subtitling_type)
2220                         {
2221                                 case 0x01: // ebu teletext subtitles
2222                                 {
2223                                         int page_number = it->teletext_page_number & 0xFF;
2224                                         int magazine_number = it->teletext_magazine_number & 7;
2225                                         int hash = magazine_number << 8 | page_number;
2226                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2227                                         {
2228                                                 ePyObject tuple = PyTuple_New(5);
2229                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2230                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2231                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2232                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2233                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2234                                                 PyList_Append(l, tuple);
2235                                                 Py_DECREF(tuple);
2236                                                 added_ttx_pages.insert(hash);
2237                                         }
2238                                         break;
2239                                 }
2240                                 case 0x10 ... 0x13:
2241                                 case 0x20 ... 0x23: // dvb subtitles
2242                                 {
2243                                         ePyObject tuple = PyTuple_New(5);
2244                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2245                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2246                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2247                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2248                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2249                                         PyList_Insert(l, 0, tuple);
2250                                         Py_DECREF(tuple);
2251                                         break;
2252                                 }
2253                         }
2254                 }
2255         }
2256
2257         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2258                 it != subs.end(); ++it)
2259         {
2260                 int page_number = it->teletext_page_number & 0xFF;
2261                 int magazine_number = it->teletext_magazine_number & 7;
2262                 int hash = magazine_number << 8 | page_number;
2263                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2264                 {
2265                         ePyObject tuple = PyTuple_New(5);
2266                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2267                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2268                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2269                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2270                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2271                         PyList_Append(l, tuple);
2272                         Py_DECREF(tuple);
2273                 }
2274         }
2275
2276         return l;
2277 }
2278
2279 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2280 {
2281         if (m_subtitle_widget)
2282         {
2283                 m_subtitle_pages.push_back(page);
2284                 checkSubtitleTiming();
2285         }
2286 }
2287
2288 void eDVBServicePlay::checkSubtitleTiming()
2289 {
2290 //      eDebug("checkSubtitleTiming");
2291         if (!m_subtitle_widget)
2292                 return;
2293         while (1)
2294         {
2295                 enum { TELETEXT, DVB } type;
2296                 eDVBTeletextSubtitlePage page;
2297                 eDVBSubtitlePage dvb_page;
2298                 pts_t show_time;
2299                 if (!m_subtitle_pages.empty())
2300                 {
2301                         page = m_subtitle_pages.front();
2302                         type = TELETEXT;
2303                         show_time = page.m_pts;
2304                 }
2305                 else if (!m_dvb_subtitle_pages.empty())
2306                 {
2307                         dvb_page = m_dvb_subtitle_pages.front();
2308                         type = DVB;
2309                         show_time = dvb_page.m_show_time;
2310                 }
2311                 else
2312                         return;
2313         
2314                 pts_t pos = 0;
2315         
2316                 if (m_decoder)
2317                         m_decoder->getPTS(0, pos);
2318
2319 //              eDebug("%lld %lld", pos, show_time);
2320                 int diff =  show_time - pos;
2321                 if (diff < 0)
2322                 {
2323                         eDebug("[late (%d ms)]", -diff / 90);
2324                         diff = 0;
2325                 }
2326                 if (diff > 900000)
2327                 {
2328                         eDebug("[invalid]");
2329                         diff = 0;
2330                 }
2331         
2332                 if (!diff)
2333                 {
2334                         if (type == TELETEXT)
2335                         {
2336                                 eDebug("display teletext subtitle page");
2337                                 m_subtitle_widget->setPage(page);
2338                                 m_subtitle_pages.pop_front();
2339                         }
2340                         else
2341                         {
2342                                 eDebug("display dvb subtitle Page");
2343                                 m_subtitle_widget->setPage(dvb_page);
2344                                 m_dvb_subtitle_pages.pop_front();
2345                         }
2346                 } else
2347                 {
2348 //                      eDebug("start subtitle delay %d", diff / 90);
2349                         m_subtitle_sync_timer.start(diff / 90, 1);
2350                         break;
2351                 }
2352         }
2353 }
2354
2355 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2356 {
2357         if (m_subtitle_widget)
2358         {
2359                 m_dvb_subtitle_pages.push_back(p);
2360                 checkSubtitleTiming();
2361         }
2362 }
2363
2364 int eDVBServicePlay::getAC3Delay()
2365 {
2366         if (m_dvb_service)
2367                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2368         else if (m_decoder)
2369                 return m_decoder->getAC3Delay();
2370         else
2371                 return 0;
2372 }
2373
2374 int eDVBServicePlay::getPCMDelay()
2375 {
2376         if (m_dvb_service)
2377                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2378         else if (m_decoder)
2379                 return m_decoder->getPCMDelay();
2380         else
2381                 return 0;
2382 }
2383
2384 void eDVBServicePlay::setAC3Delay(int delay)
2385 {
2386         if (m_dvb_service)
2387                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2388         if (m_decoder)
2389                 m_decoder->setAC3Delay(delay);
2390 }
2391
2392 void eDVBServicePlay::setPCMDelay(int delay)
2393 {
2394         if (m_dvb_service)
2395                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2396         if (m_decoder)
2397                 m_decoder->setPCMDelay(delay);
2398 }
2399
2400 DEFINE_REF(eDVBServicePlay)
2401
2402 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");