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