use aspect ratio information from mpeg sequence header instead of eit (needs
[vuplus_dvbapp] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/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         memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
718         m_is_primary = 1;
719         m_is_pvr = !m_reference.path.empty();
720         
721         m_timeshift_enabled = m_timeshift_active = 0;
722         m_skipmode = 0;
723         
724         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
725         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
726         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
727
728         m_cuesheet_changed = 0;
729         m_cutlist_enabled = 1;
730         
731         m_subtitle_widget = 0;
732         
733         m_tune_state = -1;
734         
735         CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
736 }
737
738 eDVBServicePlay::~eDVBServicePlay()
739 {
740         delete m_subtitle_widget;
741 }
742
743 void eDVBServicePlay::gotNewEvent()
744 {
745 #if 0
746                 // debug only
747         ePtr<eServiceEvent> m_event_now, m_event_next;
748         getEvent(m_event_now, 0);
749         getEvent(m_event_next, 1);
750
751         if (m_event_now)
752                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
753         if (m_event_next)
754                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
755 #endif
756         m_event((iPlayableService*)this, evUpdatedEventInfo);
757 }
758
759 void eDVBServicePlay::serviceEvent(int event)
760 {
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         if (w == sCAIDs)
1223                 return resIsPyObject;
1224
1225         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1226         
1227         int no_program_info = 0;
1228         
1229         if (h.getProgramInfo(program))
1230                 no_program_info = 1;
1231         
1232         switch (w)
1233         {
1234 #if HAVE_DVB_API_VERSION >= 3
1235         case sVideoHeight:
1236                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1237                         return m_videoEventData.height;
1238                 return -1;
1239         case sVideoWidth:
1240                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1241                         return m_videoEventData.width;
1242                 return -1;
1243 #else
1244 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1245 #endif
1246         case sAspect:
1247 #if HAVE_DVB_API_VERSION >= 3
1248                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1249                         return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1250                 else
1251 #else
1252 #warning "FIXMEE implement sAspect for old DVB API"
1253 #endif
1254                 if (no_program_info)
1255                         return -1; 
1256                 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1257                 {
1258                         ePtr<eServiceEvent> evt;
1259                         if (!m_event_handler.getEvent(evt, 0))
1260                         {
1261                                 ePtr<eComponentData> data;
1262                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1263                                 {
1264                                         if ( data->getStreamContent() == 1 )
1265                                         {
1266                                                 switch(data->getComponentType())
1267                                                 {
1268                                                         // SD
1269                                                         case 1: // 4:3 SD PAL
1270                                                         case 2:
1271                                                         case 3: // 16:9 SD PAL
1272                                                         case 4: // > 16:9 PAL
1273                                                         case 5: // 4:3 SD NTSC
1274                                                         case 6: 
1275                                                         case 7: // 16:9 SD NTSC
1276                                                         case 8: // > 16:9 NTSC
1277
1278                                                         // HD
1279                                                         case 9: // 4:3 HD PAL
1280                                                         case 0xA:
1281                                                         case 0xB: // 16:9 HD PAL
1282                                                         case 0xC: // > 16:9 HD PAL
1283                                                         case 0xD: // 4:3 HD NTSC
1284                                                         case 0xE:
1285                                                         case 0xF: // 16:9 HD NTSC
1286                                                         case 0x10: // > 16:9 HD PAL
1287                                                                 return data->getComponentType();
1288                                                 }
1289                                         }
1290                                 }
1291                         }
1292                 }
1293                 return -1;
1294         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1295         case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1296         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1297         case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1298         case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1299         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1300         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1301         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1302         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1303         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1304         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1305         case sProvider: if (!m_dvb_service) return -1; return -2;
1306         case sServiceref: return resIsString;
1307         case sDVBState: return m_tune_state;
1308         default:
1309                 return -1;
1310         }
1311 }
1312
1313 std::string eDVBServicePlay::getInfoString(int w)
1314 {
1315         switch (w)
1316         {
1317         case sProvider:
1318                 if (!m_dvb_service) return "";
1319                 return m_dvb_service->m_provider_name;
1320         case sServiceref:
1321                 return m_reference.toString();
1322         default:
1323                 break;
1324         }
1325         return iServiceInformation::getInfoString(w);
1326 }
1327
1328 PyObject *eDVBServicePlay::getInfoObject(int w)
1329 {
1330         switch (w)
1331         {
1332         case sCAIDs:
1333                 return m_service_handler.getCaIds();
1334         default:
1335                 break;
1336         }
1337         return iServiceInformation::getInfoObject(w);
1338 }
1339
1340 int eDVBServicePlay::getNumberOfTracks()
1341 {
1342         eDVBServicePMTHandler::program program;
1343         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1344         if (h.getProgramInfo(program))
1345                 return 0;
1346         return program.audioStreams.size();
1347 }
1348
1349 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1350 {
1351         int ret = selectAudioStream(i);
1352
1353         if (m_decoder->start())
1354                 return -5;
1355
1356         return ret;
1357 }
1358
1359 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1360 {
1361         eDVBServicePMTHandler::program program;
1362         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1363
1364         if (h.getProgramInfo(program))
1365                 return -1;
1366         
1367         if (i >= program.audioStreams.size())
1368                 return -2;
1369         
1370         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1371                 info.m_description = "MPEG";
1372         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1373                 info.m_description = "AC3";
1374         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1375                 info.m_description = "AAC";
1376         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1377                 info.m_description = "DTS";
1378         else
1379                 info.m_description = "???";
1380
1381         if (program.audioStreams[i].component_tag != -1)
1382         {
1383                 ePtr<eServiceEvent> evt;
1384                 if (!m_event_handler.getEvent(evt, 0))
1385                 {
1386                         ePtr<eComponentData> data;
1387                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1388                                 info.m_language = data->getText();
1389                 }
1390         }
1391
1392         if (info.m_language.empty())
1393                 info.m_language = program.audioStreams[i].language_code;
1394         
1395         return 0;
1396 }
1397
1398 int eDVBServicePlay::selectAudioStream(int i)
1399 {
1400         eDVBServicePMTHandler::program program;
1401         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1402
1403         if (h.getProgramInfo(program))
1404                 return -1;
1405         
1406         if ((unsigned int)i >= program.audioStreams.size())
1407                 return -2;
1408         
1409         if (!m_decoder)
1410                 return -3;
1411         
1412         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1413                 return -4;
1414
1415         if (m_radiotext_parser)
1416                 m_radiotext_parser->start(program.audioStreams[i].pid);
1417
1418         if (m_dvb_service && !m_is_pvr)
1419         {
1420                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1421                 {
1422                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1423                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1424                 }
1425                 else
1426                 {
1427                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1428                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1429                 }
1430         }
1431
1432         h.resetCachedProgram();
1433
1434         return 0;
1435 }
1436
1437 int eDVBServicePlay::getCurrentChannel()
1438 {
1439         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1440 }
1441
1442 RESULT eDVBServicePlay::selectChannel(int i)
1443 {
1444         if (i < LEFT || i > RIGHT || i == STEREO)
1445                 i = -1;  // Stereo
1446         if (m_dvb_service)
1447                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1448         if (m_decoder)
1449                 m_decoder->setAudioChannel(i);
1450         return 0;
1451 }
1452
1453 std::string eDVBServicePlay::getRadioText(int x)
1454 {
1455         if (m_radiotext_parser)
1456                 switch(x)
1457                 {
1458                         case 0:
1459                                 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1460                 }
1461         return "";
1462 }
1463
1464 void eDVBServicePlay::radioTextUpdated()
1465 {
1466         m_event((iPlayableService*)this, evUpdatedRadioText);
1467 }
1468
1469 int eDVBServiceBase::getFrontendInfo(int w)
1470 {
1471         eUsePtr<iDVBChannel> channel;
1472         if(m_service_handler.getChannel(channel))
1473                 return 0;
1474         ePtr<iDVBFrontend> fe;
1475         if(channel->getFrontend(fe))
1476                 return 0;
1477         return fe->readFrontendData(w);
1478 }
1479
1480 PyObject *eDVBServiceBase::getFrontendData(bool original)
1481 {
1482         ePyObject ret;
1483
1484         eUsePtr<iDVBChannel> channel;
1485         if(!m_service_handler.getChannel(channel))
1486         {
1487                 ePtr<iDVBFrontend> fe;
1488                 if(!channel->getFrontend(fe))
1489                 {
1490                         ret = fe->readTransponderData(original);
1491                         if (ret)
1492                         {
1493                                 ePtr<iDVBFrontendParameters> feparm;
1494                                 channel->getCurrentFrontendParameters(feparm);
1495                                 if (feparm)
1496                                 {
1497                                         eDVBFrontendParametersSatellite osat;
1498                                         if (!feparm->getDVBS(osat))
1499                                         {
1500                                                 void PutToDict(ePyObject &, const char*, long);
1501                                                 void PutToDict(ePyObject &, const char*, const char*);
1502                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1503                                                 const char *tmp = "UNKNOWN";
1504                                                 switch(osat.polarisation)
1505                                                 {
1506                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1507                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1508                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1509                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1510                                                         default:break;
1511                                                 }
1512                                                 PutToDict(ret, "polarization", tmp);
1513                                         }
1514                                 }
1515                         }
1516                 }
1517         }
1518         if (!ret)
1519         {
1520                 ret = Py_None;
1521                 Py_INCREF(ret);
1522         }
1523         return ret;
1524 }
1525
1526 int eDVBServicePlay::getNumberOfSubservices()
1527 {
1528         ePtr<eServiceEvent> evt;
1529         if (!m_event_handler.getEvent(evt, 0))
1530                 return evt->getNumOfLinkageServices();
1531         return 0;
1532 }
1533
1534 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1535 {
1536         ePtr<eServiceEvent> evt;
1537         if (!m_event_handler.getEvent(evt, 0))
1538         {
1539                 if (!evt->getLinkageService(sub, m_reference, n))
1540                         return 0;
1541         }
1542         sub.type=eServiceReference::idInvalid;
1543         return -1;
1544 }
1545
1546 RESULT eDVBServicePlay::startTimeshift()
1547 {
1548         ePtr<iDVBDemux> demux;
1549         
1550         eDebug("Start timeshift!");
1551         
1552         if (m_timeshift_enabled)
1553                 return -1;
1554         
1555                 /* start recording with the data demux. */
1556         if (m_service_handler.getDataDemux(demux))
1557                 return -2;
1558
1559         demux->createTSRecorder(m_record);
1560         if (!m_record)
1561                 return -3;
1562
1563         char templ[]=TSPATH "/timeshift.XXXXXX";
1564         m_timeshift_fd = mkstemp(templ);
1565         m_timeshift_file = templ;
1566         
1567         eDebug("recording to %s", templ);
1568         
1569         if (m_timeshift_fd < 0)
1570         {
1571                 m_record = 0;
1572                 return -4;
1573         }
1574                 
1575         m_record->setTargetFD(m_timeshift_fd);
1576
1577         m_timeshift_enabled = 1;
1578         
1579         updateTimeshiftPids();
1580         m_record->start();
1581
1582         return 0;
1583 }
1584
1585 RESULT eDVBServicePlay::stopTimeshift()
1586 {
1587         if (!m_timeshift_enabled)
1588                 return -1;
1589         
1590         switchToLive();
1591         
1592         m_timeshift_enabled = 0;
1593         
1594         m_record->stop();
1595         m_record = 0;
1596         
1597         close(m_timeshift_fd);
1598         eDebug("remove timeshift file");
1599         remove(m_timeshift_file.c_str());
1600         
1601         return 0;
1602 }
1603
1604 int eDVBServicePlay::isTimeshiftActive()
1605 {
1606         return m_timeshift_enabled && m_timeshift_active;
1607 }
1608
1609 RESULT eDVBServicePlay::activateTimeshift()
1610 {
1611         if (!m_timeshift_enabled)
1612                 return -1;
1613         
1614         if (!m_timeshift_active)
1615         {
1616                 switchToTimeshift();
1617                 return 0;
1618         }
1619         
1620         return -2;
1621 }
1622
1623 PyObject *eDVBServicePlay::getCutList()
1624 {
1625         ePyObject list = PyList_New(0);
1626         
1627         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1628         {
1629                 ePyObject tuple = PyTuple_New(2);
1630                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1631                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1632                 PyList_Append(list, tuple);
1633                 Py_DECREF(tuple);
1634         }
1635         
1636         return list;
1637 }
1638
1639 void eDVBServicePlay::setCutList(ePyObject list)
1640 {
1641         if (!PyList_Check(list))
1642                 return;
1643         int size = PyList_Size(list);
1644         int i;
1645         
1646         m_cue_entries.clear();
1647         
1648         for (i=0; i<size; ++i)
1649         {
1650                 ePyObject tuple = PyList_GET_ITEM(list, i);
1651                 if (!PyTuple_Check(tuple))
1652                 {
1653                         eDebug("non-tuple in cutlist");
1654                         continue;
1655                 }
1656                 if (PyTuple_Size(tuple) != 2)
1657                 {
1658                         eDebug("cutlist entries need to be a 2-tuple");
1659                         continue;
1660                 }
1661                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1662                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1663                 {
1664                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1665                         continue;
1666                 }
1667                 pts_t pts = PyLong_AsLongLong(ppts);
1668                 int type = PyInt_AsLong(ptype);
1669                 m_cue_entries.insert(cueEntry(pts, type));
1670                 eDebug("adding %08llx, %d", pts, type);
1671         }
1672         m_cuesheet_changed = 1;
1673         
1674         cutlistToCuesheet();
1675         m_event((iPlayableService*)this, evCuesheetChanged);
1676 }
1677
1678 void eDVBServicePlay::setCutListEnable(int enable)
1679 {
1680         m_cutlist_enabled = enable;
1681         cutlistToCuesheet();
1682 }
1683
1684 void eDVBServicePlay::updateTimeshiftPids()
1685 {
1686         if (!m_record)
1687                 return;
1688         
1689         eDVBServicePMTHandler::program program;
1690         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1691
1692         if (h.getProgramInfo(program))
1693                 return;
1694         else
1695         {
1696                 std::set<int> pids_to_record;
1697                 pids_to_record.insert(0); // PAT
1698                 if (program.pmtPid != -1)
1699                         pids_to_record.insert(program.pmtPid); // PMT
1700
1701                 if (program.textPid != -1)
1702                         pids_to_record.insert(program.textPid); // Videotext
1703
1704                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1705                         i(program.videoStreams.begin()); 
1706                         i != program.videoStreams.end(); ++i)
1707                         pids_to_record.insert(i->pid);
1708
1709                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1710                         i(program.audioStreams.begin()); 
1711                         i != program.audioStreams.end(); ++i)
1712                                 pids_to_record.insert(i->pid);
1713
1714                 std::set<int> new_pids, obsolete_pids;
1715                 
1716                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1717                                 m_pids_active.begin(), m_pids_active.end(),
1718                                 std::inserter(new_pids, new_pids.begin()));
1719                 
1720                 std::set_difference(
1721                                 m_pids_active.begin(), m_pids_active.end(),
1722                                 pids_to_record.begin(), pids_to_record.end(), 
1723                                 std::inserter(new_pids, new_pids.begin())
1724                                 );
1725
1726                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1727                         m_record->addPID(*i);
1728
1729                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1730                         m_record->removePID(*i);
1731         }
1732 }
1733
1734 void eDVBServicePlay::switchToLive()
1735 {
1736         if (!m_timeshift_active)
1737                 return;
1738         
1739         m_cue = 0;
1740         m_decoder = 0;
1741         m_decode_demux = 0;
1742         m_teletext_parser = 0;
1743         m_radiotext_parser = 0;
1744         m_subtitle_parser = 0;
1745         m_new_dvb_subtitle_page_connection = 0;
1746         m_new_subtitle_page_connection = 0;
1747         m_radiotext_updated_connection = 0;
1748
1749                 /* free the timeshift service handler, we need the resources */
1750         m_service_handler_timeshift.free();
1751         m_timeshift_active = 0;
1752
1753         m_event((iPlayableService*)this, evSeekableStatusChanged);
1754
1755         updateDecoder();
1756 }
1757
1758 void eDVBServicePlay::switchToTimeshift()
1759 {
1760         if (m_timeshift_active)
1761                 return;
1762
1763         m_decode_demux = 0;
1764         m_decoder = 0;
1765         m_teletext_parser = 0;
1766         m_radiotext_parser = 0;
1767         m_subtitle_parser = 0;
1768         m_new_subtitle_page_connection = 0;
1769         m_new_dvb_subtitle_page_connection = 0;
1770         m_radiotext_updated_connection = 0;
1771
1772         m_timeshift_active = 1;
1773
1774         m_event((iPlayableService*)this, evSeekableStatusChanged);
1775
1776         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1777         r.path = m_timeshift_file;
1778
1779         m_cue = new eCueSheet();
1780         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1781         updateDecoder(); /* mainly to switch off PCR */
1782 }
1783
1784 void eDVBServicePlay::updateDecoder()
1785 {
1786         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
1787
1788         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1789
1790         bool defaultac3=false;
1791         std::string default_ac3;
1792
1793         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1794                 defaultac3 = default_ac3 == "True";
1795
1796         eDVBServicePMTHandler::program program;
1797         if (h.getProgramInfo(program))
1798                 eDebug("getting program info failed.");
1799         else
1800         {
1801                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1802                 if (!program.videoStreams.empty())
1803                 {
1804                         eDebugNoNewLine(" (");
1805                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1806                                 i(program.videoStreams.begin());
1807                                 i != program.videoStreams.end(); ++i)
1808                         {
1809                                 if (vpid == -1)
1810                                 {
1811                                         vpid = i->pid;
1812                                         vpidtype = i->type;
1813                                 }
1814                                 if (i != program.videoStreams.begin())
1815                                         eDebugNoNewLine(", ");
1816                                 eDebugNoNewLine("%04x", i->pid);
1817                         }
1818                         eDebugNoNewLine(")");
1819                 }
1820                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1821                 if (!program.audioStreams.empty())
1822                 {
1823                         eDebugNoNewLine(" (");
1824                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1825                                 i(program.audioStreams.begin());
1826                                 i != program.audioStreams.end(); ++i)
1827                         {
1828                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1829                                 {
1830                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1831                                         {
1832                                                 apid = i->pid;
1833                                                 apidtype = i->type;
1834                                         }
1835                                 }
1836                                 if (i != program.audioStreams.begin())
1837                                         eDebugNoNewLine(", ");
1838                                 eDebugNoNewLine("%04x", i->pid);
1839                         }
1840                         eDebugNoNewLine(")");
1841                 }
1842                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1843                 pcrpid = program.pcrPid;
1844                 eDebug(", and the text pid is %04x", program.textPid);
1845                 tpid = program.textPid;
1846         }
1847
1848         if (!m_decoder)
1849         {
1850                 h.getDecodeDemux(m_decode_demux);
1851                 if (m_decode_demux)
1852                 {
1853                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1854                         if (m_decoder)
1855                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
1856                 }
1857                 if (m_cue)
1858                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1859                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1860                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
1861                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
1862                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
1863         }
1864
1865         if (m_decoder)
1866         {
1867                 if (m_dvb_service)
1868                 {
1869                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
1870                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
1871                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
1872                 }
1873                 else // subservice or recording
1874                 {
1875                         eServiceReferenceDVB ref;
1876                         m_service_handler.getServiceReference(ref);
1877                         eServiceReferenceDVB parent = ref.getParentServiceReference();
1878                         if (!parent)
1879                                 parent = ref;
1880                         if (parent)
1881                         {
1882                                 ePtr<eDVBResourceManager> res_mgr;
1883                                 if (!eDVBResourceManager::getInstance(res_mgr))
1884                                 {
1885                                         ePtr<iDVBChannelList> db;
1886                                         if (!res_mgr->getChannelList(db))
1887                                         {
1888                                                 ePtr<eDVBService> origService;
1889                                                 if (!db->getService(parent, origService))
1890                                                 {
1891                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
1892                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
1893                                                 }
1894                                         }
1895                                 }
1896                         }
1897                 }
1898                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
1899                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
1900
1901                 m_decoder->setVideoPID(vpid, vpidtype);
1902                 m_decoder->setAudioPID(apid, apidtype);
1903                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1904                 {
1905                         m_decoder->setSyncPCR(pcrpid);
1906                         if (apid != -1)
1907                         {
1908                                 ePtr<iDVBDemux> data_demux;
1909                                 if (!h.getDataDemux(data_demux))
1910                                 {
1911                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
1912                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
1913                                         m_radiotext_parser->start(apid);
1914                                 }
1915                         }
1916                 }
1917                 else
1918                         m_decoder->setSyncPCR(-1);
1919
1920                 m_decoder->setTextPID(tpid);
1921
1922                 m_teletext_parser->start(program.textPid);
1923
1924                 if (!m_is_primary)
1925                         m_decoder->setTrickmode(1);
1926
1927                 m_decoder->start();
1928
1929                 if (vpid > 0 && vpid < 0x2000)
1930                         ;
1931                 else
1932                 {
1933                         std::string radio_pic;
1934                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
1935                                 m_decoder->setRadioPic(radio_pic);
1936                 }
1937
1938                 m_decoder->setAudioChannel(achannel);
1939
1940 // how we can do this better?
1941 // update cache pid when the user changed the audio track or video track
1942 // TODO handling of difference audio types.. default audio types..
1943                                 
1944                 /* don't worry about non-existing services, nor pvr services */
1945                 if (m_dvb_service && !m_is_pvr)
1946                 {
1947                         if (apidtype == eDVBAudio::aMPEG)
1948                         {
1949                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1950                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1951                         }
1952                         else
1953                         {
1954                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1955                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1956                         }
1957                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
1958                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
1959                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
1960                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
1961                 }
1962         }
1963         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
1964 }
1965
1966 void eDVBServicePlay::loadCuesheet()
1967 {
1968         std::string filename = m_reference.path + ".cuts";
1969         
1970         m_cue_entries.clear();
1971
1972         FILE *f = fopen(filename.c_str(), "rb");
1973
1974         if (f)
1975         {
1976                 eDebug("loading cuts..");
1977                 while (1)
1978                 {
1979                         unsigned long long where;
1980                         unsigned int what;
1981                         
1982                         if (!fread(&where, sizeof(where), 1, f))
1983                                 break;
1984                         if (!fread(&what, sizeof(what), 1, f))
1985                                 break;
1986                         
1987 #if BYTE_ORDER == LITTLE_ENDIAN
1988                         where = bswap_64(where);
1989 #endif
1990                         what = ntohl(what);
1991                         
1992                         if (what > 3)
1993                                 break;
1994                         
1995                         m_cue_entries.insert(cueEntry(where, what));
1996                 }
1997                 fclose(f);
1998                 eDebug("%d entries", m_cue_entries.size());
1999         } else
2000                 eDebug("cutfile not found!");
2001         
2002         m_cuesheet_changed = 0;
2003         cutlistToCuesheet();
2004         m_event((iPlayableService*)this, evCuesheetChanged);
2005 }
2006
2007 void eDVBServicePlay::saveCuesheet()
2008 {
2009         std::string filename = m_reference.path + ".cuts";
2010         
2011         FILE *f = fopen(filename.c_str(), "wb");
2012
2013         if (f)
2014         {
2015                 unsigned long long where;
2016                 int what;
2017
2018                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2019                 {
2020 #if BYTE_ORDER == BIG_ENDIAN
2021                         where = i->where;
2022 #else
2023                         where = bswap_64(i->where);
2024 #endif
2025                         what = htonl(i->what);
2026                         fwrite(&where, sizeof(where), 1, f);
2027                         fwrite(&what, sizeof(what), 1, f);
2028                         
2029                 }
2030                 fclose(f);
2031         }
2032         
2033         m_cuesheet_changed = 0;
2034 }
2035
2036 void eDVBServicePlay::cutlistToCuesheet()
2037 {
2038         if (!m_cue)
2039         {
2040                 eDebug("no cue sheet");
2041                 return;
2042         }       
2043         m_cue->clear();
2044         
2045         if (!m_cutlist_enabled)
2046         {
2047                 m_cue->commitSpans();
2048                 eDebug("cutlists were disabled");
2049                 return;
2050         }
2051
2052         pts_t in = 0, out = 0, length = 0;
2053         
2054         getLength(length);
2055                 
2056         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2057         
2058         while (1)
2059         {
2060                 if (i == m_cue_entries.end())
2061                         out = length;
2062                 else {
2063                         if (i->what == 0) /* in */
2064                         {
2065                                 in = i++->where;
2066                                 continue;
2067                         } else if (i->what == 1) /* out */
2068                                 out = i++->where;
2069                         else /* mark (2) or last play position (3) */
2070                         {
2071                                 i++;
2072                                 continue;
2073                         }
2074                 }
2075                 
2076                 if (in != out)
2077                         m_cue->addSourceSpan(in, out);
2078                 
2079                 in = length;
2080                 
2081                 if (i == m_cue_entries.end())
2082                         break;
2083         }
2084         m_cue->commitSpans();
2085 }
2086
2087 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2088 {
2089         if (m_subtitle_widget)
2090                 disableSubtitles(parent);
2091
2092         ePyObject entry;
2093         int tuplesize = PyTuple_Size(tuple);
2094         int type = 0;
2095
2096         if (!PyTuple_Check(tuple))
2097                 goto error_out;
2098
2099         if (tuplesize < 1)
2100                 goto error_out;
2101
2102         entry = PyTuple_GET_ITEM(tuple, 0);
2103
2104         if (!PyInt_Check(entry))
2105                 goto error_out;
2106
2107         type = PyInt_AsLong(entry);
2108
2109         if (type == 1)  // teletext subtitles
2110         {
2111                 int page, magazine, pid;
2112                 if (tuplesize < 4)
2113                         goto error_out;
2114
2115                 if (!m_teletext_parser)
2116                 {
2117                         eDebug("enable teletext subtitles.. no parser !!!");
2118                         return -1;
2119                 }
2120
2121                 entry = PyTuple_GET_ITEM(tuple, 1);
2122                 if (!PyInt_Check(entry))
2123                         goto error_out;
2124                 pid = PyInt_AsLong(entry);
2125
2126                 entry = PyTuple_GET_ITEM(tuple, 2);
2127                 if (!PyInt_Check(entry))
2128                         goto error_out;
2129                 page = PyInt_AsLong(entry);
2130
2131                 entry = PyTuple_GET_ITEM(tuple, 3);
2132                 if (!PyInt_Check(entry))
2133                         goto error_out;
2134                 magazine = PyInt_AsLong(entry);
2135
2136                 m_subtitle_widget = new eSubtitleWidget(parent);
2137                 m_subtitle_widget->resize(parent->size()); /* full size */
2138                 m_teletext_parser->setPageAndMagazine(page, magazine);
2139                 if (m_dvb_service)
2140                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2141         }
2142         else if (type == 0)
2143         {
2144                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2145                 if (!m_subtitle_parser)
2146                 {
2147                         eDebug("enable dvb subtitles.. no parser !!!");
2148                         return -1;
2149                 }
2150                 if (tuplesize < 4)
2151                         goto error_out;
2152
2153                 entry = PyTuple_GET_ITEM(tuple, 1);
2154                 if (!PyInt_Check(entry))
2155                         goto error_out;
2156                 pid = PyInt_AsLong(entry);
2157
2158                 entry = PyTuple_GET_ITEM(tuple, 2);
2159                 if (!PyInt_Check(entry))
2160                         goto error_out;
2161                 composition_page_id = PyInt_AsLong(entry);
2162
2163                 entry = PyTuple_GET_ITEM(tuple, 3);
2164                 if (!PyInt_Check(entry))
2165                         goto error_out;
2166                 ancillary_page_id = PyInt_AsLong(entry);
2167
2168                 m_subtitle_widget = new eSubtitleWidget(parent);
2169                 m_subtitle_widget->resize(parent->size()); /* full size */
2170                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2171                 if (m_dvb_service)
2172                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2173         }
2174         else
2175                 goto error_out;
2176         return 0;
2177 error_out:
2178         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2179                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2180                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2181         return -1;
2182 }
2183
2184 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2185 {
2186         delete m_subtitle_widget;
2187         m_subtitle_widget = 0;
2188         if (m_subtitle_parser)
2189         {
2190                 m_subtitle_parser->stop();
2191                 m_dvb_subtitle_pages.clear();
2192         }
2193         if (m_teletext_parser)
2194         {
2195                 m_teletext_parser->setPageAndMagazine(-1, -1);
2196                 m_subtitle_pages.clear();
2197         }
2198         if (m_dvb_service)
2199                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2200         return 0;
2201 }
2202
2203 PyObject *eDVBServicePlay::getCachedSubtitle()
2204 {
2205         if (m_dvb_service)
2206         {
2207                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2208                 if (tmp != -1)
2209                 {
2210                         unsigned int data = (unsigned int)tmp;
2211                         int pid = (data&0xFFFF0000)>>16;
2212                         ePyObject tuple = PyTuple_New(4);
2213                         eDVBServicePMTHandler::program program;
2214                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2215                         if (!h.getProgramInfo(program))
2216                         {
2217                                 if (program.textPid==pid) // teletext
2218                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2219                                 else
2220                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2221                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2222                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2223                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2224                                 return tuple;
2225                         }
2226                 }
2227         }
2228         Py_INCREF(Py_None);
2229         return Py_None;
2230 }
2231
2232 PyObject *eDVBServicePlay::getSubtitleList()
2233 {
2234         if (!m_teletext_parser)
2235         {
2236                 Py_INCREF(Py_None);
2237                 return Py_None;
2238         }
2239         
2240         ePyObject l = PyList_New(0);
2241         std::set<int> added_ttx_pages;
2242
2243         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2244                 m_teletext_parser->m_found_subtitle_pages;
2245
2246         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2247         eDVBServicePMTHandler::program program;
2248         if (h.getProgramInfo(program))
2249                 eDebug("getting program info failed.");
2250         else
2251         {
2252                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2253                         it != program.subtitleStreams.end(); ++it)
2254                 {
2255                         switch(it->subtitling_type)
2256                         {
2257                                 case 0x01: // ebu teletext subtitles
2258                                 {
2259                                         int page_number = it->teletext_page_number & 0xFF;
2260                                         int magazine_number = it->teletext_magazine_number & 7;
2261                                         int hash = magazine_number << 8 | page_number;
2262                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2263                                         {
2264                                                 ePyObject tuple = PyTuple_New(5);
2265                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2266                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2267                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2268                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2269                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2270                                                 PyList_Append(l, tuple);
2271                                                 Py_DECREF(tuple);
2272                                                 added_ttx_pages.insert(hash);
2273                                         }
2274                                         break;
2275                                 }
2276                                 case 0x10 ... 0x13:
2277                                 case 0x20 ... 0x23: // dvb subtitles
2278                                 {
2279                                         ePyObject tuple = PyTuple_New(5);
2280                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2281                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2282                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2283                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2284                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2285                                         PyList_Insert(l, 0, tuple);
2286                                         Py_DECREF(tuple);
2287                                         break;
2288                                 }
2289                         }
2290                 }
2291         }
2292
2293         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2294                 it != subs.end(); ++it)
2295         {
2296                 int page_number = it->teletext_page_number & 0xFF;
2297                 int magazine_number = it->teletext_magazine_number & 7;
2298                 int hash = magazine_number << 8 | page_number;
2299                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2300                 {
2301                         ePyObject tuple = PyTuple_New(5);
2302                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2303                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2304                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2305                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2306                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2307                         PyList_Append(l, tuple);
2308                         Py_DECREF(tuple);
2309                 }
2310         }
2311
2312         return l;
2313 }
2314
2315 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2316 {
2317         if (m_subtitle_widget)
2318         {
2319                 m_subtitle_pages.push_back(page);
2320                 checkSubtitleTiming();
2321         }
2322 }
2323
2324 void eDVBServicePlay::checkSubtitleTiming()
2325 {
2326 //      eDebug("checkSubtitleTiming");
2327         if (!m_subtitle_widget)
2328                 return;
2329         while (1)
2330         {
2331                 enum { TELETEXT, DVB } type;
2332                 eDVBTeletextSubtitlePage page;
2333                 eDVBSubtitlePage dvb_page;
2334                 pts_t show_time;
2335                 if (!m_subtitle_pages.empty())
2336                 {
2337                         page = m_subtitle_pages.front();
2338                         type = TELETEXT;
2339                         show_time = page.m_pts;
2340                 }
2341                 else if (!m_dvb_subtitle_pages.empty())
2342                 {
2343                         dvb_page = m_dvb_subtitle_pages.front();
2344                         type = DVB;
2345                         show_time = dvb_page.m_show_time;
2346                 }
2347                 else
2348                         return;
2349         
2350                 pts_t pos = 0;
2351         
2352                 if (m_decoder)
2353                         m_decoder->getPTS(0, pos);
2354
2355 //              eDebug("%lld %lld", pos, show_time);
2356                 int diff =  show_time - pos;
2357                 if (diff < 0)
2358                 {
2359                         eDebug("[late (%d ms)]", -diff / 90);
2360                         diff = 0;
2361                 }
2362                 if (diff > 900000)
2363                 {
2364                         eDebug("[invalid]");
2365                         diff = 0;
2366                 }
2367         
2368                 if (!diff)
2369                 {
2370                         if (type == TELETEXT)
2371                         {
2372                                 eDebug("display teletext subtitle page");
2373                                 m_subtitle_widget->setPage(page);
2374                                 m_subtitle_pages.pop_front();
2375                         }
2376                         else
2377                         {
2378                                 eDebug("display dvb subtitle Page");
2379                                 m_subtitle_widget->setPage(dvb_page);
2380                                 m_dvb_subtitle_pages.pop_front();
2381                         }
2382                 } else
2383                 {
2384 //                      eDebug("start subtitle delay %d", diff / 90);
2385                         m_subtitle_sync_timer.start(diff / 90, 1);
2386                         break;
2387                 }
2388         }
2389 }
2390
2391 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2392 {
2393         if (m_subtitle_widget)
2394         {
2395                 m_dvb_subtitle_pages.push_back(p);
2396                 checkSubtitleTiming();
2397         }
2398 }
2399
2400 int eDVBServicePlay::getAC3Delay()
2401 {
2402         if (m_dvb_service)
2403                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2404         else if (m_decoder)
2405                 return m_decoder->getAC3Delay();
2406         else
2407                 return 0;
2408 }
2409
2410 int eDVBServicePlay::getPCMDelay()
2411 {
2412         if (m_dvb_service)
2413                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2414         else if (m_decoder)
2415                 return m_decoder->getPCMDelay();
2416         else
2417                 return 0;
2418 }
2419
2420 void eDVBServicePlay::setAC3Delay(int delay)
2421 {
2422         if (m_dvb_service)
2423                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2424         if (m_decoder)
2425                 m_decoder->setAC3Delay(delay);
2426 }
2427
2428 void eDVBServicePlay::setPCMDelay(int delay)
2429 {
2430         if (m_dvb_service)
2431                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2432         if (m_decoder)
2433                 m_decoder->setPCMDelay(delay);
2434 }
2435
2436 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2437 {
2438         eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2439         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2440         m_event((iPlayableService*)this, evVideoSizeChanged);
2441 }
2442
2443 DEFINE_REF(eDVBServicePlay)
2444
2445 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");