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