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