Set sync PCR at PIP mode.
[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/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
20 #include <lib/base/httpstream.h>
21
22                 /* for subtitles */
23 #include <lib/gui/esubtitle.h>
24
25 #include <sys/vfs.h>
26 #include <sys/stat.h>
27
28 #include <byteswap.h>
29 #include <netinet/in.h>
30
31 #ifndef BYTE_ORDER
32 #error no byte order defined!
33 #endif
34
35 class eStaticServiceDVBInformation: public iStaticServiceInformation
36 {
37         DECLARE_REF(eStaticServiceDVBInformation);
38 public:
39         RESULT getName(const eServiceReference &ref, std::string &name);
40         int getLength(const eServiceReference &ref);
41         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
42         PyObject *getInfoObject(const eServiceReference &ref, int);
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                                                 name=buildShortName(name) + " - ";
68                                 }
69                         }
70                 }
71                 else
72                         name="";
73                 name += ref.name;
74                 return 0;
75         }
76         else
77                 return -1;
78 }
79
80 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
81 {
82         return -1;
83 }
84
85 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
86 {
87         ePtr<eDVBResourceManager> res_mgr;
88         if ( eDVBResourceManager::getInstance( res_mgr ) )
89                 eDebug("isPlayable... no res manager!!");
90         else
91         {
92                 eDVBChannelID chid, chid_ignore;
93                 int system;
94                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
95                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
96                 return res_mgr->canAllocateChannel(chid, chid_ignore, system);
97         }
98         return false;
99 }
100
101 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
102 extern void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm); // defined in dvb/frontend.cpp
103 extern void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm); // defined in dvb/frontend.cpp
104 extern void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm); // defined in dvb/frontend.cpp
105
106 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
107 {
108         if (r.type == eServiceReference::idDVB)
109         {
110                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
111                 switch(what)
112                 {
113                         case iServiceInformation::sTransponderData:
114                         {
115                                 ePtr<eDVBResourceManager> res;
116                                 if (!eDVBResourceManager::getInstance(res))
117                                 {
118                                         ePtr<iDVBChannelList> db;
119                                         if (!res->getChannelList(db))
120                                         {
121                                                 eDVBChannelID chid;
122                                                 ref.getChannelID(chid);
123                                                 ePtr<iDVBFrontendParameters> feparm;
124                                                 if (!db->getChannelFrontendData(chid, feparm))
125                                                 {
126                                                         int system;
127                                                         if (!feparm->getSystem(system))
128                                                         {
129                                                                 ePyObject dict = PyDict_New();
130                                                                 switch(system)
131                                                                 {
132                                                                         case iDVBFrontend::feSatellite:
133                                                                         {
134                                                                                 eDVBFrontendParametersSatellite s;
135                                                                                 feparm->getDVBS(s);
136                                                                                 PutSatelliteDataToDict(dict, s);
137                                                                                 break;
138                                                                         }
139                                                                         case iDVBFrontend::feTerrestrial:
140                                                                         {
141                                                                                 eDVBFrontendParametersTerrestrial t;
142                                                                                 feparm->getDVBT(t);
143                                                                                 PutTerrestrialDataToDict(dict, t);
144                                                                                 break;
145                                                                         }
146                                                                         case iDVBFrontend::feCable:
147                                                                         {
148                                                                                 eDVBFrontendParametersCable c;
149                                                                                 feparm->getDVBC(c);
150                                                                                 PutCableDataToDict(dict, c);
151                                                                                 break;
152                                                                         }
153                                                                         default:
154                                                                                 eDebug("unknown frontend type %d", system);
155                                                                                 Py_DECREF(dict);
156                                                                                 break;
157                                                                 }
158                                                                 return dict;
159                                                         }
160                                                 }
161                                         }
162                                 }
163                         }
164                 }
165         }
166         Py_RETURN_NONE;
167 }
168
169 DEFINE_REF(eStaticServiceDVBBouquetInformation);
170
171 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
172 {
173         ePtr<iDVBChannelList> db;
174         ePtr<eDVBResourceManager> res;
175
176         int err;
177         if ((err = eDVBResourceManager::getInstance(res)) != 0)
178         {
179                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
180                 return err;
181         }
182         if ((err = res->getChannelList(db)) != 0)
183         {
184                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
185                 return err;
186         }
187
188         eBouquet *bouquet=0;
189         if ((err = db->getBouquet(ref, bouquet)) != 0)
190         {
191                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
192                 return -1;
193         }
194
195         if ( bouquet && bouquet->m_bouquet_name.length() )
196         {
197                 name = bouquet->m_bouquet_name;
198                 return 0;
199         }
200         else
201                 return -1;
202 }
203
204 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate)
205 {
206         if (ref.flags & eServiceReference::isGroup)
207         {
208                 ePtr<iDVBChannelList> db;
209                 ePtr<eDVBResourceManager> res;
210
211                 if (eDVBResourceManager::getInstance(res))
212                 {
213                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
214                         return 0;
215                 }
216
217                 if (res->getChannelList(db))
218                 {
219                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
220                         return 0;
221                 }
222
223                 eBouquet *bouquet=0;
224                 if (db->getBouquet(ref, bouquet))
225                 {
226                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
227                         return 0;
228                 }
229
230                 int prio_order = eDVBFrontend::getTypePriorityOrder();
231                 int cur=0;
232                 eDVBChannelID chid, chid_ignore;
233                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
234                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
235                 {
236                         static unsigned char prio_map[6][3] = {
237                                 { 3, 2, 1 }, // -S -C -T
238                                 { 3, 1, 2 }, // -S -T -C
239                                 { 2, 3, 1 }, // -C -S -T
240                                 { 1, 3, 2 }, // -C -T -S
241                                 { 1, 2, 3 }, // -T -C -S
242                                 { 2, 1, 3 }  // -T -S -C
243                         };
244                         int system;
245                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
246                         int tmp = res->canAllocateChannel(chid, chid_ignore, system, simulate);
247                         if (tmp > 0)
248                         {
249                                 switch (system)
250                                 {
251                                         case iDVBFrontend::feTerrestrial:
252                                                 tmp = prio_map[prio_order][2];
253                                                 break;
254                                         case iDVBFrontend::feCable:
255                                                 tmp = prio_map[prio_order][1];
256                                                 break;
257                                         default:
258                                         case iDVBFrontend::feSatellite:
259                                                 tmp = prio_map[prio_order][0];
260                                                 break;
261                                 }
262                         }
263                         if (tmp > cur)
264                         {
265                                 m_playable_service = *it;
266                                 cur = tmp;
267                         }
268                 }
269                 if (cur)
270                         return cur;
271         }
272         m_playable_service = eServiceReference();
273         return 0;
274 }
275
276 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
277 {
278         return -1;
279 }
280
281 #include <lib/dvb/epgcache.h>
282
283 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
284 {
285         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
286 }
287
288 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
289 {
290         DECLARE_REF(eStaticServiceDVBPVRInformation);
291         eServiceReference m_ref;
292         eDVBMetaParser m_parser;
293 public:
294         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
295         RESULT getName(const eServiceReference &ref, std::string &name);
296         int getLength(const eServiceReference &ref);
297         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
298         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore, bool simulate) { return 1; }
299         int getInfo(const eServiceReference &ref, int w);
300         std::string getInfoString(const eServiceReference &ref,int w);
301         PyObject *getInfoObject(const eServiceReference &r, int what);
302 };
303
304 DEFINE_REF(eStaticServiceDVBPVRInformation);
305
306 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
307 {
308         m_ref = ref;
309         m_parser.parseFile(ref.path);
310 }
311
312 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
313 {
314         ASSERT(ref == m_ref);
315         if (!ref.name.empty())
316                 name = ref.name;
317         else if (!m_parser.m_name.empty())
318                 name = m_parser.m_name;
319         else
320         {
321                 name = ref.path;
322                 size_t n = name.rfind('/');
323                 if (n != std::string::npos)
324                         name = name.substr(n + 1);
325         }
326         return 0;
327 }
328
329 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
330 {
331         ASSERT(ref == m_ref);
332         
333         eDVBTSTools tstools;
334         
335         struct stat s;
336         stat(ref.path.c_str(), &s);
337
338         if (tstools.openFile(ref.path.c_str(), 1))
339                 return 0;
340
341                         /* check if cached data is still valid */
342         if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
343                 return m_parser.m_length / 90000;
344
345                         /* open again, this time with stream info */
346         if (tstools.openFile(ref.path.c_str()))
347                 return 0;
348
349                         /* otherwise, re-calc length and update meta file */
350         pts_t len;
351         if (tstools.calcLen(len))
352                 return 0;
353
354         m_parser.m_length = len;
355         m_parser.m_filesize = s.st_size;
356         m_parser.updateMeta(ref.path);
357         return m_parser.m_length / 90000;
358 }
359
360 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
361 {
362         switch (w)
363         {
364         case iServiceInformation::sDescription:
365                 return iServiceInformation::resIsString;
366         case iServiceInformation::sServiceref:
367                 return iServiceInformation::resIsString;
368         case iServiceInformation::sFileSize:
369                 return m_parser.m_filesize;
370         case iServiceInformation::sTimeCreate:
371                 if (m_parser.m_time_create)
372                         return m_parser.m_time_create;
373                 else
374                         return iServiceInformation::resNA;
375         default:
376                 return iServiceInformation::resNA;
377         }
378 }
379
380 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
381 {
382         switch (w)
383         {
384         case iServiceInformation::sDescription:
385                 return m_parser.m_description;
386         case iServiceInformation::sServiceref:
387                 return m_parser.m_ref.toString();
388         case iServiceInformation::sTags:
389                 return m_parser.m_tags;
390         default:
391                 return "";
392         }
393 }
394
395 PyObject *eStaticServiceDVBPVRInformation::getInfoObject(const eServiceReference &r, int what)
396 {
397         switch (what)
398         {
399         case iServiceInformation::sFileSize:
400                 return PyLong_FromLongLong(m_parser.m_filesize);
401         default:
402                 Py_RETURN_NONE;
403         }
404 }
405
406 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
407 {
408         if (!ref.path.empty())
409         {
410                 if (ref.path.substr(0, 7) == "http://")
411                 {
412                         eServiceReference equivalentref(ref);
413                         /* this might be a scrambled stream (id + 0x100), force equivalent dvb type */
414                         equivalentref.type = eServiceFactoryDVB::id;
415                         equivalentref.path.clear();
416                         return eEPGCache::getInstance()->lookupEventTime(equivalentref, start_time, evt);
417                 }
418                 else
419                 {
420                         ePtr<eServiceEvent> event = new eServiceEvent;
421                         std::string filename = ref.path;
422                         filename.erase(filename.length()-2, 2);
423                         filename+="eit";
424                         if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
425                         {
426                                 evt = event;
427                                 return 0;
428                         }
429                 }
430         }
431         evt = 0;
432         return -1;
433 }
434
435 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
436 {
437         DECLARE_REF(eDVBPVRServiceOfflineOperations);
438         eServiceReferenceDVB m_ref;
439 public:
440         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
441         
442         RESULT deleteFromDisk(int simulate);
443         RESULT getListOfFilenames(std::list<std::string> &);
444         RESULT reindex();
445 };
446
447 DEFINE_REF(eDVBPVRServiceOfflineOperations);
448
449 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
450 {
451 }
452
453 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
454 {
455         if (simulate)
456                 return 0;
457         else
458         {
459                 std::list<std::string> res;
460                 if (getListOfFilenames(res))
461                         return -1;
462                 
463                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
464                 if (!eraser)
465                         eDebug("FATAL !! can't get background file eraser");
466                 
467                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
468                 {
469                         eDebug("Removing %s...", i->c_str());
470                         if (eraser)
471                                 eraser->erase(i->c_str());
472                         else
473                                 ::unlink(i->c_str());
474                 }
475                 
476                 return 0;
477         }
478 }
479
480 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
481 {
482         res.clear();
483         res.push_back(m_ref.path);
484
485 // handling for old splitted recordings (enigma 1)
486         char buf[255];
487         int slice=1;
488         while(true)
489         {
490                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
491                 struct stat s;
492                 if (stat(buf, &s) < 0)
493                         break;
494                 res.push_back(buf);
495         }       
496
497         res.push_back(m_ref.path + ".meta");
498         res.push_back(m_ref.path + ".ap");
499         res.push_back(m_ref.path + ".sc");
500         res.push_back(m_ref.path + ".cuts");
501         std::string tmp = m_ref.path;
502         tmp.erase(m_ref.path.length()-3);
503         res.push_back(tmp + ".eit");
504         return 0;
505 }
506
507 RESULT eDVBPVRServiceOfflineOperations::reindex()
508 {
509         const char *filename = m_ref.path.c_str();
510         eDebug("reindexing %s...", filename);
511
512         eMPEGStreamInformation info;
513         eMPEGStreamParserTS parser(info);
514         
515         info.startSave(filename);
516         
517         eRawFile f;
518         
519         int err = f.open(m_ref.path.c_str(), 0);
520         if (err < 0)
521                 return -1;
522
523         off_t offset = 0;
524         off_t length = f.length();
525         unsigned char buffer[188*256*4];
526         while (1)
527         {
528                 eDebug("at %08llx / %08llx (%d %%)", offset, length, (int)(offset * 100 / length));
529                 int r = f.read(offset, buffer, sizeof(buffer));
530                 if (!r)
531                         break;
532                 if (r < 0)
533                         return r;
534                 offset += r;
535                 parser.parseData(offset, buffer, r);
536         }
537         
538         info.stopSave();
539         f.close();
540         
541         return 0;
542 }
543
544 DEFINE_REF(eServiceFactoryDVB)
545
546 eServiceFactoryDVB::eServiceFactoryDVB()
547 {
548         ePtr<eServiceCenter> sc;
549         
550         eServiceCenter::getPrivInstance(sc);
551         if (sc)
552         {
553                 std::list<std::string> extensions;
554                 extensions.push_back("ts");
555                 extensions.push_back("trp");
556                 sc->addServiceFactory(eServiceFactoryDVB::id, this, extensions);
557         }
558
559         m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
560         m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
561 }
562
563 eServiceFactoryDVB::~eServiceFactoryDVB()
564 {
565         ePtr<eServiceCenter> sc;
566         
567         eServiceCenter::getPrivInstance(sc);
568         if (sc)
569                 sc->removeServiceFactory(eServiceFactoryDVB::id);
570 }
571
572 DEFINE_REF(eDVBServiceList);
573
574 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
575 {
576 }
577
578 eDVBServiceList::~eDVBServiceList()
579 {
580 }
581
582 RESULT eDVBServiceList::startQuery()
583 {
584         ePtr<iDVBChannelList> db;
585         ePtr<eDVBResourceManager> res;
586         
587         int err;
588         if ((err = eDVBResourceManager::getInstance(res)) != 0)
589         {
590                 eDebug("no resource manager");
591                 return err;
592         }
593         if ((err = res->getChannelList(db)) != 0)
594         {
595                 eDebug("no channel list");
596                 return err;
597         }
598         
599         ePtr<eDVBChannelQuery> q;
600         
601         if (!m_parent.path.empty())
602         {
603                 eDVBChannelQuery::compile(q, m_parent.path);
604                 if (!q)
605                 {
606                         eDebug("compile query failed");
607                         return err;
608                 }
609         }
610         
611         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
612         {
613                 eDebug("startQuery failed");
614                 return err;
615         }
616
617         return 0;
618 }
619
620 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
621 {
622         eServiceReferenceDVB ref;
623         
624         if (!m_query)
625                 return -1;
626
627         while (!m_query->getNextResult(ref))
628                 list.push_back(ref);
629
630         if (sorted)
631                 list.sort(iListableServiceCompare(this));
632
633         return 0;
634 }
635
636 //   The first argument of this function is a format string to specify the order and
637 //   the content of the returned list
638 //   useable format options are
639 //   R = Service Reference (as swig object .. this is very slow)
640 //   S = Service Reference (as python string object .. same as ref.toString())
641 //   C = Service Reference (as python string object .. same as ref.toCompareString())
642 //   N = Service Name (as python string object)
643 //   n = Short Service Name (short name brakets used) (as python string object)
644 //   when exactly one return value per service is selected in the format string,
645 //   then each value is directly a list entry
646 //   when more than one value is returned per service, then the list is a list of
647 //   python tuples
648 //   unknown format string chars are returned as python None values !
649 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
650 {
651         ePyObject ret;
652         std::list<eServiceReference> tmplist;
653         int retcount=1;
654
655         if (!format || !(retcount=strlen(format)))
656                 format = "R"; // just return service reference swig object ...
657
658         if (!getContent(tmplist, sorted))
659         {
660                 int services=tmplist.size();
661                 ePtr<iStaticServiceInformation> sptr;
662                 eServiceCenterPtr service_center;
663
664                 if (strchr(format, 'N') || strchr(format, 'n'))
665                         eServiceCenter::getPrivInstance(service_center);
666
667                 ret = PyList_New(services);
668                 std::list<eServiceReference>::iterator it(tmplist.begin());
669
670                 for (int cnt=0; cnt < services; ++cnt)
671                 {
672                         eServiceReference &ref=*it++;
673                         ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
674                         for (int i=0; i < retcount; ++i)
675                         {
676                                 ePyObject tmp;
677                                 switch(format[i])
678                                 {
679                                 case 'R':  // service reference (swig)object
680                                         tmp = NEW_eServiceReference(ref);
681                                         break;
682                                 case 'C':  // service reference compare string
683                                         tmp = PyString_FromString(ref.toCompareString().c_str());
684                                         break;
685                                 case 'S':  // service reference string
686                                         tmp = PyString_FromString(ref.toString().c_str());
687                                         break;
688                                 case 'N':  // service name
689                                         if (service_center)
690                                         {
691                                                 service_center->info(ref, sptr);
692                                                 if (sptr)
693                                                 {
694                                                         std::string name;
695                                                         sptr->getName(ref, name);
696
697                                                         // filter short name brakets
698                                                         size_t pos;
699                                                         while((pos = name.find("\xc2\x86")) != std::string::npos)
700                                                                 name.erase(pos,2);
701                                                         while((pos = name.find("\xc2\x87")) != std::string::npos)
702                                                                 name.erase(pos,2);
703
704                                                         if (name.length())
705                                                                 tmp = PyString_FromString(name.c_str());
706                                                 }
707                                         }
708                                         if (!tmp)
709                                                 tmp = PyString_FromString("<n/a>");
710                                         break;
711                                 case 'n':  // short service name
712                                         if (service_center)
713                                         {
714                                                 service_center->info(ref, sptr);
715                                                 if (sptr)
716                                                 {
717                                                         std::string name;
718                                                         sptr->getName(ref, name);
719                                                         name = buildShortName(name);
720                                                         if (name.length())
721                                                                 tmp = PyString_FromString(name.c_str());
722                                                 }
723                                         }
724                                         if (!tmp)
725                                                 tmp = PyString_FromString("<n/a>");
726                                         break;
727                                 default:
728                                         if (tuple)
729                                         {
730                                                 tmp = Py_None;
731                                                 Py_INCREF(Py_None);
732                                         }
733                                         break;
734                                 }
735                                 if (tmp)
736                                 {
737                                         if (tuple)
738                                                 PyTuple_SET_ITEM(tuple, i, tmp);
739                                         else
740                                                 PyList_SET_ITEM(ret, cnt, tmp);
741                                 }
742                         }
743                         if (tuple)
744                                 PyList_SET_ITEM(ret, cnt, tuple);
745                 }
746         }
747         return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
748 }
749
750 RESULT eDVBServiceList::getNext(eServiceReference &ref)
751 {
752         if (!m_query)
753                 return -1;
754         
755         return m_query->getNextResult((eServiceReferenceDVB&)ref);
756 }
757
758 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
759 {
760         if (m_parent.flags & eServiceReference::canDescent) // bouquet
761         {
762                 ePtr<iDVBChannelList> db;
763                 ePtr<eDVBResourceManager> resm;
764
765                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
766                         return -1;
767
768                 if (db->getBouquet(m_parent, m_bouquet) != 0)
769                         return -1;
770
771                 res = this;
772                 
773                 return 0;
774         }
775         res = 0;
776         return -1;
777 }
778
779 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
780 {
781         if (!m_bouquet)
782                 return -1;
783         return m_bouquet->addService(ref, before);
784 }
785
786 RESULT eDVBServiceList::removeService(eServiceReference &ref)
787 {
788         if (!m_bouquet)
789                 return -1;
790         return m_bouquet->removeService(ref);
791 }
792
793 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
794 {
795         if (!m_bouquet)
796                 return -1;
797         return m_bouquet->moveService(ref, pos);
798 }
799
800 RESULT eDVBServiceList::flushChanges()
801 {
802         if (!m_bouquet)
803                 return -1;
804         return m_bouquet->flushChanges();
805 }
806
807 RESULT eDVBServiceList::setListName(const std::string &name)
808 {
809         if (!m_bouquet)
810                 return -1;
811         return m_bouquet->setListName(name);
812 }
813
814 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
815 {
816         ePtr<eDVBService> service;
817         int r = lookupService(service, ref);
818         if (r)
819                 service = 0;
820                 // check resources...
821         ptr = new eDVBServicePlay(ref, service);
822         return 0;
823 }
824
825 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
826 {
827         if (ref.path.empty())
828         {
829                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
830                 return 0;
831         } else
832         {
833                 bool isstream = ref.path.substr(0, 7) == "http://";
834                 if(isstream)
835                 {
836                         ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref, isstream);
837                         return 0;
838                 }
839                 ptr = 0;
840                 return -1;
841         }
842 }
843
844 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
845 {
846         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
847         if (list->startQuery())
848         {
849                 ptr = 0;
850                 return -1;
851         }
852         
853         ptr = list;
854         return 0;
855 }
856
857 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
858 {
859         /* is a listable service? */
860         if (ref.flags & eServiceReference::canDescent) // bouquet
861         {
862                 if ( !ref.name.empty() )  // satellites or providers list
863                         ptr = m_StaticServiceDVBInfo;
864                 else // a dvb bouquet
865                         ptr = m_StaticServiceDVBBouquetInfo;
866         }
867         else if (!ref.path.empty()) /* do we have a PVR service? */
868                 ptr = new eStaticServiceDVBPVRInformation(ref);
869         else // normal dvb service
870         {
871                 ePtr<eDVBService> service;
872                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
873                         ptr = m_StaticServiceDVBInfo;
874                 else
875                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
876                         ptr = service;
877         }
878         return 0;
879 }
880
881 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
882 {
883         if (ref.path.empty())
884         {
885                 ptr = 0;
886                 return -1;
887         } else
888         {
889                 ptr = new eDVBPVRServiceOfflineOperations(ref);
890                 return 0;
891         }
892 }
893
894 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
895 {
896         if (!ref.path.empty()) // playback
897         {
898                 eDVBMetaParser parser;
899                 int ret=parser.parseFile(ref.path);
900                 service = new eDVBService;
901                 if (!ret)
902                         eDVBDB::getInstance()->parseServiceData(service, parser.m_service_data);
903         }
904         else
905         {
906                         // TODO: handle the listing itself
907                 // if (ref.... == -1) .. return "... bouquets ...";
908                 // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
909                         // TODO: cache
910                 ePtr<iDVBChannelList> db;
911                 ePtr<eDVBResourceManager> res;
912         
913                 int err;
914                 if ((err = eDVBResourceManager::getInstance(res)) != 0)
915                 {
916                         eDebug("no resource manager");
917                         return err;
918                 }
919                 if ((err = res->getChannelList(db)) != 0)
920                 {
921                         eDebug("no channel list");
922                         return err;
923                 }
924         
925                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
926                 if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
927                 {
928 //                      eDebug("getService failed!");
929                         return err;
930                 }
931         }
932
933         return 0;
934 }
935
936 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service):
937         m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
938 {
939         m_is_primary = 1;
940         m_is_stream = m_reference.path.substr(0, 7) == "http://";
941         m_is_pvr = (!m_reference.path.empty() && !m_is_stream);
942         
943         m_timeshift_enabled = m_timeshift_active = 0, m_timeshift_changed = 0;
944         m_skipmode = m_fastforward = m_slowmotion = 0;
945         
946         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
947         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
948         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
949
950         m_cuesheet_changed = 0;
951         m_cutlist_enabled = 1;
952         
953         m_subtitle_widget = 0;
954         
955         m_tune_state = -1;
956
957         m_subtitle_sync_timer = eTimer::create(eApp);
958
959         CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
960 }
961
962 eDVBServicePlay::~eDVBServicePlay()
963 {
964         if (m_is_pvr)
965         {
966                 eDVBMetaParser meta;
967                 int ret=meta.parseFile(m_reference.path);
968                 if (!ret)
969                 {
970                         char tmp[255];
971                         meta.m_service_data="";
972                         sprintf(tmp, "f:%x", m_dvb_service->m_flags);
973                         meta.m_service_data += tmp;
974                         // cached pids
975                         for (int x=0; x < eDVBService::cacheMax; ++x)
976                         {
977                                 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
978                                 if (entry != -1)
979                                 {
980                                         sprintf(tmp, ",c:%02d%04x", x, entry);
981                                         meta.m_service_data += tmp;
982                                 }
983                         }
984                         meta.updateMeta(m_reference.path);
985                 }
986         }
987         delete m_subtitle_widget;
988 }
989
990 void eDVBServicePlay::gotNewEvent()
991 {
992 #if 0
993                 // debug only
994         ePtr<eServiceEvent> m_event_now, m_event_next;
995         getEvent(m_event_now, 0);
996         getEvent(m_event_next, 1);
997
998         if (m_event_now)
999                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1000         if (m_event_next)
1001                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1002 #endif
1003         m_event((iPlayableService*)this, evUpdatedEventInfo);
1004 }
1005
1006 void eDVBServicePlay::serviceEvent(int event)
1007 {
1008         m_tune_state = event;
1009
1010         switch (event)
1011         {
1012         case eDVBServicePMTHandler::eventTuned:
1013         {
1014                 ePtr<iDVBDemux> m_demux;
1015                 if (!m_service_handler.getDataDemux(m_demux))
1016                 {
1017                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1018                         int sid = ref.getParentServiceID().get();
1019                         if (!sid)
1020                                 sid = ref.getServiceID().get();
1021                         if ( ref.getParentTransportStreamID().get() &&
1022                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1023                                 m_event_handler.startOther(m_demux, sid);
1024                         else
1025                                 m_event_handler.start(m_demux, sid);
1026                 }
1027                 m_event((iPlayableService*)this, evTunedIn);
1028                 break;
1029         }
1030         case eDVBServicePMTHandler::eventNoResources:
1031         case eDVBServicePMTHandler::eventNoPAT:
1032         case eDVBServicePMTHandler::eventNoPATEntry:
1033         case eDVBServicePMTHandler::eventNoPMT:
1034         case eDVBServicePMTHandler::eventTuneFailed:
1035         case eDVBServicePMTHandler::eventMisconfiguration:
1036         {
1037                 eDebug("DVB service failed to tune - error %d", event);
1038                 m_event((iPlayableService*)this, evTuneFailed);
1039                 break;
1040         }
1041         case eDVBServicePMTHandler::eventNewProgramInfo:
1042         {
1043                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1044                 if (m_timeshift_enabled)
1045                         updateTimeshiftPids();
1046                 if (!m_timeshift_active)
1047                         updateDecoder();
1048                 if (m_first_program_info & 1 && m_is_pvr)
1049                 {
1050                         m_first_program_info &= ~1;
1051                         seekTo(0);
1052                 }
1053                 if (!m_timeshift_active)
1054                         m_event((iPlayableService*)this, evUpdatedInfo);
1055                 break;
1056         }
1057         case eDVBServicePMTHandler::eventPreStart:
1058                 loadCuesheet();
1059                 break;
1060         case eDVBServicePMTHandler::eventEOF:
1061                 m_event((iPlayableService*)this, evEOF);
1062                 break;
1063         case eDVBServicePMTHandler::eventSOF:
1064                 m_event((iPlayableService*)this, evSOF);
1065                 break;
1066         case eDVBServicePMTHandler::eventHBBTVInfo:
1067                 m_event((iPlayableService*)this, evHBBTVInfo);
1068                 break;
1069         }
1070 }
1071
1072 void eDVBServicePlay::serviceEventTimeshift(int event)
1073 {
1074         switch (event)
1075         {
1076         case eDVBServicePMTHandler::eventNewProgramInfo:
1077                 eDebug("eventNewProgramInfo TS");
1078                 if (m_timeshift_active)
1079                 {
1080                         updateDecoder();
1081                         if (m_first_program_info & 2)
1082                         {
1083                                 if (m_slowmotion)
1084                                 {
1085                                         eDebug("re-apply slowmotion after timeshift file change");
1086                                         m_decoder->setSlowMotion(m_slowmotion);
1087                                 }
1088                                 if (m_fastforward)
1089                                 {
1090                                         eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1091                                         if (m_skipmode)
1092                                                 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1093                                         if (m_fastforward != 1)
1094                                                 m_decoder->setFastForward(m_fastforward);
1095                                         else
1096                                                 m_decoder->setTrickmode();
1097                                 }
1098                                 else
1099                                         seekTo(0);
1100                                 m_first_program_info &= ~2;
1101                         }
1102                         m_event((iPlayableService*)this, evUpdatedInfo);
1103                 }
1104                 break;
1105         case eDVBServicePMTHandler::eventSOF:
1106 #if 0
1107                 if (!m_timeshift_file_next.empty())
1108                 {
1109                         eDebug("timeshift SOF, switch to next file");
1110                         m_decoder->pause();
1111
1112                         m_first_program_info |= 2;
1113
1114                         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1115                         r.path = m_timeshift_file_next;
1116
1117                         /* free the timeshift service handler, we need the resources */
1118                         m_service_handler_timeshift.free();
1119                         resetTimeshift(1);
1120
1121                         if (m_skipmode < 0)
1122                                 m_cue->seekTo(0, -1000);
1123                         ePtr<iTsSource> source = createTsSource(r);
1124                         m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1125
1126                         m_event((iPlayableService*)this, evUser+1);
1127                 }
1128                 else
1129 #endif
1130                         m_event((iPlayableService*)this, evSOF);
1131                 break;
1132         case eDVBServicePMTHandler::eventEOF:
1133                 if ((!m_is_paused) && (m_skipmode >= 0))
1134                 {
1135                         if (m_timeshift_file_next.empty())
1136                         {
1137                                 eDebug("timeshift EOF, so let's go live");
1138                                 switchToLive();
1139                         }
1140                         else
1141                         {
1142                                 eDebug("timeshift EOF, switch to next file");
1143
1144                                 m_first_program_info |= 2;
1145
1146                                 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1147                                 r.path = m_timeshift_file_next;
1148
1149                                 /* free the timeshift service handler, we need the resources */
1150                                 m_service_handler_timeshift.free();
1151                                 resetTimeshift(1);
1152
1153                                 ePtr<iTsSource> source = createTsSource(r);
1154                                 m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file_next.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1155
1156                                 m_event((iPlayableService*)this, evUser+1);
1157                         }
1158                 }
1159                 break;
1160         }
1161 }
1162
1163 RESULT eDVBServicePlay::start()
1164 {
1165         eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1166
1167                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
1168                    two (one for decoding, one for data source), as we must be prepared
1169                    to start recording from the data demux. */
1170         if (m_is_pvr)
1171         {
1172                 eDVBMetaParser meta;
1173                 if (!meta.parseFile(m_reference.path))
1174                 {
1175                         service = meta.m_ref;
1176                         service.path = m_reference.path;
1177                 }
1178                 m_cue = new eCueSheet();
1179         }
1180         else
1181                 m_event(this, evStart);
1182
1183         m_first_program_info = 1;
1184         ePtr<iTsSource> source = createTsSource(service);
1185         m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1186
1187         if (m_is_pvr)
1188         {
1189                 /* inject EIT if there is a stored one */
1190                 std::string filename = service.path;
1191                 filename.erase(filename.length()-2, 2);
1192                 filename+="eit";
1193                 ePtr<eServiceEvent> event = new eServiceEvent;
1194                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1195                 {
1196                         ePtr<eServiceEvent> empty;
1197                         m_event_handler.inject(event, 0);
1198                         m_event_handler.inject(empty, 1);
1199                 }
1200                 m_event(this, evStart);
1201         }
1202         return 0;
1203 }
1204
1205 RESULT eDVBServicePlay::stop()
1206 {
1207                 /* add bookmark for last play position */
1208         if (m_is_pvr)
1209         {
1210                 pts_t play_position, length;
1211                 if (!getPlayPosition(play_position))
1212                 {
1213                                 /* remove last position */
1214                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1215                         {
1216                                 if (i->what == 3) /* current play position */
1217                                 {
1218                                         m_cue_entries.erase(i);
1219                                         i = m_cue_entries.begin();
1220                                         continue;
1221                                 } else
1222                                         ++i;
1223                         }
1224                         
1225                         if (getLength(length))
1226                                 length = 0;
1227                         
1228                         if (length)
1229                         {
1230                                 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1231                         }
1232                         m_cuesheet_changed = 1;
1233                 }
1234         }
1235
1236         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1237
1238         m_service_handler_timeshift.free();
1239         m_service_handler.free();
1240         
1241         if (m_is_pvr && m_cuesheet_changed)
1242         {
1243                 struct stat s;
1244                                 /* save cuesheet only when main file is accessible. */
1245                 if (!::stat(m_reference.path.c_str(), &s))
1246                         saveCuesheet();
1247         }
1248         m_event((iPlayableService*)this, evStopped);
1249         return 0;
1250 }
1251
1252 RESULT eDVBServicePlay::setTarget(int target)
1253 {
1254         m_is_primary = !target;
1255         return 0;
1256 }
1257
1258 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1259 {
1260         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1261         return 0;
1262 }
1263
1264 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1265 {
1266                 /* note: we check for timeshift to be enabled,
1267                    not neccessary active. if you pause when timeshift
1268                    is not active, you should activate it when unpausing */
1269         if ((!m_is_pvr) && (!m_timeshift_enabled))
1270         {
1271                 ptr = 0;
1272                 return -1;
1273         }
1274
1275         ptr = this;
1276         return 0;
1277 }
1278
1279 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1280 {
1281         ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1282         eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1283         setFastForward_internal(0);
1284         if (m_decoder)
1285         {
1286                 m_slowmotion = ratio;
1287                 return m_decoder->setSlowMotion(ratio);
1288         }
1289         else
1290                 return -1;
1291 }
1292
1293 RESULT eDVBServicePlay::setFastForward(int ratio)
1294 {
1295         eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1296         ASSERT(ratio);
1297         return setFastForward_internal(ratio);
1298 }
1299
1300 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1301 {
1302         int skipmode, ffratio, ret = 0;
1303         pts_t pos=0;
1304
1305         if (ratio > 8)
1306         {
1307                 skipmode = ratio;
1308                 ffratio = 1;
1309         } else if (ratio > 0)
1310         {
1311                 skipmode = 0;
1312                 ffratio = ratio;
1313         } else if (!ratio)
1314         {
1315                 skipmode = 0;
1316                 ffratio = 0;
1317         } else // if (ratio < 0)
1318         {
1319                 skipmode = ratio;
1320                 ffratio = 1;
1321         }
1322
1323         if (m_skipmode != skipmode)
1324         {
1325                 eDebug("setting cue skipmode to %d", skipmode);
1326                 if (m_cue)
1327                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1328         }
1329
1330         m_skipmode = skipmode;
1331
1332         if (final_seek)
1333                 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1334
1335         m_fastforward = ffratio;
1336
1337         if (!m_decoder)
1338                 return -1;
1339
1340         if (ffratio == 0)
1341                 ; /* return m_decoder->play(); is done in caller*/
1342         else if (ffratio != 1)
1343                 ret = m_decoder->setFastForward(ffratio);
1344         else
1345                 ret = m_decoder->setTrickmode();
1346
1347         if (pos)
1348                 eDebug("final seek after trickplay ret %d", seekTo(pos));
1349
1350         return ret;
1351 }
1352
1353 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1354 {
1355         if (m_is_pvr || m_timeshift_enabled)
1356         {
1357                 ptr = this;
1358                 return 0;
1359         }
1360         
1361         ptr = 0;
1362         return -1;
1363 }
1364
1365         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1366 RESULT eDVBServicePlay::getLength(pts_t &len)
1367 {
1368         ePtr<iDVBPVRChannel> pvr_channel;
1369         
1370         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1371                 return -1;
1372         
1373         return pvr_channel->getLength(len);
1374 }
1375
1376 RESULT eDVBServicePlay::pause()
1377 {
1378         eDebug("eDVBServicePlay::pause");
1379         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1380         if (m_decoder)
1381         {
1382                 m_slowmotion = 0;
1383                 m_is_paused = 1;
1384                 return m_decoder->pause();
1385         } else
1386                 return -1;
1387 }
1388
1389 RESULT eDVBServicePlay::unpause()
1390 {
1391         eDebug("eDVBServicePlay::unpause");
1392         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1393         if (m_decoder)
1394         {
1395                 m_slowmotion = 0;
1396                 m_is_paused = 0;
1397                 return m_decoder->play();
1398         } else
1399                 return -1;
1400 }
1401
1402 RESULT eDVBServicePlay::seekTo(pts_t to)
1403 {
1404         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1405         
1406         if (!m_decode_demux)
1407                 return -1;
1408
1409         ePtr<iDVBPVRChannel> pvr_channel;
1410         
1411         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1412                 return -1;
1413         
1414         if (!m_cue)
1415                 return -1;
1416         
1417         m_cue->seekTo(0, to);
1418         m_dvb_subtitle_pages.clear();
1419         m_subtitle_pages.clear();
1420
1421         return 0;
1422 }
1423
1424 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1425 {
1426         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1427         
1428         if (!m_decode_demux)
1429                 return -1;
1430
1431         ePtr<iDVBPVRChannel> pvr_channel;
1432         
1433         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1434                 return -1;
1435         
1436         int mode = 1;
1437         
1438                         /* HACK until we have skip-AP api */
1439         if ((to > 0) && (to < 100))
1440                 mode = 2;
1441         
1442         to *= direction;
1443         
1444         if (!m_cue)
1445                 return 0;
1446         
1447         m_cue->seekTo(mode, to);
1448         m_dvb_subtitle_pages.clear();
1449         m_subtitle_pages.clear();
1450         return 0;
1451 }
1452
1453 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1454 {
1455         ePtr<iDVBPVRChannel> pvr_channel;
1456         
1457         if (!m_decode_demux)
1458                 return -1;
1459         
1460         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1461                 return -1;
1462         
1463         int r = 0;
1464
1465                 /* if there is a decoder, use audio or video PTS */
1466         if (m_decoder)
1467         {
1468                 r = m_decoder->getPTS(0, pos);
1469                 if (r)
1470                         return r;
1471         }
1472         
1473                 /* fixup */
1474         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1475 }
1476
1477 RESULT eDVBServicePlay::setTrickmode(int trick)
1478 {
1479                 /* currently unimplemented */
1480         return -1;
1481 }
1482
1483 RESULT eDVBServicePlay::isCurrentlySeekable()
1484 {
1485         int ret = 0;
1486         if (m_decoder)
1487         {
1488                 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1489                 if (m_decoder->getVideoProgressive() == -1)
1490                         ret &= ~2;
1491         }
1492         return ret;
1493 }
1494
1495 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1496 {
1497         ptr = this;
1498         return 0;
1499 }
1500
1501 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1502 {
1503         ptr = this;
1504         return 0;
1505 }
1506
1507 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1508 {
1509         ptr = this;
1510         return 0;
1511 }
1512
1513 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1514 {
1515         ptr = this;
1516         return 0;
1517 }
1518
1519 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1520 {
1521         ptr = this;
1522         return 0;
1523 }
1524
1525 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1526 {
1527         ptr = 0;
1528         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1529                 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1530         {
1531                 if (!m_timeshift_enabled)
1532                 {
1533                         /* query config path */
1534                         std::string tspath;
1535                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1536                                 eDebug("could not query ts path from config");
1537                                 return -4;
1538                         }
1539                         tspath.append("/");
1540                         /* we need enough diskspace */
1541                         struct statfs fs;
1542                         if (statfs(tspath.c_str(), &fs) < 0)
1543                         {
1544                                 eDebug("statfs failed!");
1545                                 return -2;
1546                         }
1547                 
1548                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1549                         {
1550                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1551                                 return -3;
1552                         }
1553                 }
1554                 ptr = this;
1555                 return 0;
1556         }
1557         return -1;
1558 }
1559
1560 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1561 {
1562         if (m_is_pvr)
1563         {
1564                 ptr = this;
1565                 return 0;
1566         }
1567         ptr = 0;
1568         return -1;
1569 }
1570
1571 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1572 {
1573         ptr = this;
1574         return 0;
1575 }
1576
1577 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1578 {
1579         ptr = this;
1580         return 0;
1581 }
1582
1583 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1584 {
1585         ptr = this;
1586         return 0;
1587 }
1588
1589 RESULT eDVBServicePlay::getName(std::string &name)
1590 {
1591         if (m_is_pvr)
1592         {
1593                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1594                 return i->getName(m_reference, name);
1595         }
1596         else if (m_is_stream)
1597         {
1598                 name = m_reference.name;
1599                 if (name.empty())
1600                 {
1601                         name = m_reference.path;
1602                 }
1603                 if (name.empty())
1604                 {
1605                         name = "(...)";
1606                 }
1607         }
1608         else if (m_dvb_service)
1609         {
1610                 m_dvb_service->getName(m_reference, name);
1611                 if (name.empty())
1612                         name = "(...)";
1613         }
1614         else if (!m_reference.name.empty())
1615                 eStaticServiceDVBInformation().getName(m_reference, name);
1616         else
1617                 name = "DVB service";
1618         return 0;
1619 }
1620
1621 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1622 {
1623         return m_event_handler.getEvent(evt, nownext);
1624 }
1625
1626 int eDVBServicePlay::getInfo(int w)
1627 {
1628         eDVBServicePMTHandler::program program;
1629
1630         if (w == sCAIDs || w == sCAIDPIDs)
1631                 return resIsPyObject;
1632
1633         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1634
1635         int no_program_info = 0;
1636
1637         if (h.getProgramInfo(program))
1638                 no_program_info = 1;
1639
1640         switch (w)
1641         {
1642         case sVideoHeight:
1643                 if (m_decoder)
1644                         return m_decoder->getVideoHeight();
1645                 break;
1646         case sVideoWidth:
1647                 if (m_decoder)
1648                         return m_decoder->getVideoWidth();
1649                 break;
1650         case sFrameRate:
1651                 if (m_decoder)
1652                         return m_decoder->getVideoFrameRate();
1653                 break;
1654         case sProgressive:
1655                 if (m_decoder)
1656                         return m_decoder->getVideoProgressive();
1657                 break;
1658         case sAspect:
1659         {
1660                 int aspect = -1;
1661                 if (m_decoder)
1662                         aspect = m_decoder->getVideoAspect();
1663                 if (aspect == -1 && no_program_info)
1664                         break;
1665                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1666                 {
1667                         ePtr<eServiceEvent> evt;
1668                         if (!m_event_handler.getEvent(evt, 0))
1669                         {
1670                                 ePtr<eComponentData> data;
1671                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1672                                 {
1673                                         if ( data->getStreamContent() == 1 )
1674                                         {
1675                                                 switch(data->getComponentType())
1676                                                 {
1677                                                         // SD
1678                                                         case 1: // 4:3 SD PAL
1679                                                         case 2:
1680                                                         case 3: // 16:9 SD PAL
1681                                                         case 4: // > 16:9 PAL
1682                                                         case 5: // 4:3 SD NTSC
1683                                                         case 6: 
1684                                                         case 7: // 16:9 SD NTSC
1685                                                         case 8: // > 16:9 NTSC
1686
1687                                                         // HD
1688                                                         case 9: // 4:3 HD PAL
1689                                                         case 0xA:
1690                                                         case 0xB: // 16:9 HD PAL
1691                                                         case 0xC: // > 16:9 HD PAL
1692                                                         case 0xD: // 4:3 HD NTSC
1693                                                         case 0xE:
1694                                                         case 0xF: // 16:9 HD NTSC
1695                                                         case 0x10: // > 16:9 HD PAL
1696                                                                 return data->getComponentType();
1697                                                 }
1698                                         }
1699                                 }
1700                         }
1701                 }
1702                 else
1703                         return aspect;
1704                 break;
1705         }
1706         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1707         case sVideoPID:
1708                 if (m_dvb_service)
1709                 {
1710                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1711                         if (vpid != -1)
1712                                 return vpid;
1713                 }
1714                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1715         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1716         case sAudioPID:
1717                 if (m_dvb_service)
1718                 {
1719                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1720                         if (apid != -1)
1721                                 return apid;
1722                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1723                         if (apid != -1)
1724                                 return apid;
1725                 }
1726                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1727         case sPCRPID:
1728                 if (m_dvb_service)
1729                 {
1730                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1731                         if (pcrpid != -1)
1732                                 return pcrpid;
1733                 }
1734                 if (no_program_info) return -1; return program.pcrPid;
1735         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1736         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1737         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1738         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1739         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1740         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1741         case sProvider: if (!m_dvb_service) return -1; return -2;
1742         case sServiceref: return resIsString;
1743         case sDVBState: return m_tune_state;
1744         default:
1745                 break;
1746         }
1747         return -1;
1748 }
1749
1750 std::string eDVBServicePlay::getInfoString(int w)
1751 {
1752         switch (w)
1753         {
1754         case sProvider:
1755                 if (!m_dvb_service) return "";
1756                 return m_dvb_service->m_provider_name;
1757         case sServiceref:
1758                 return m_reference.toString();
1759         case sHBBTVUrl:
1760         {
1761                 std::string url;
1762                 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1763                 h.getHBBTVUrl(url);
1764                 return url;
1765         }
1766         case sLiveStreamDemuxId:
1767         {
1768                 int id;
1769                 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1770                 h.getDemuxID(id);
1771
1772                 std::string demux;
1773                 demux += id + '0';
1774                 return demux;
1775         }
1776         default:
1777                 break;
1778         }
1779         return iServiceInformation::getInfoString(w);
1780 }
1781
1782 PyObject *eDVBServicePlay::getInfoObject(int w)
1783 {
1784         switch (w)
1785         {
1786         case sCAIDs:
1787                 return m_service_handler.getCaIds();
1788         case sCAIDPIDs:
1789                 return m_service_handler.getCaIds(true);
1790         case sTransponderData:
1791                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1792         case sHBBTVUrl:
1793         {
1794                 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1795                 return h.getHbbTVApplications();
1796         }
1797         default:
1798                 break;
1799         }
1800         return iServiceInformation::getInfoObject(w);
1801 }
1802
1803 int eDVBServicePlay::getNumberOfTracks()
1804 {
1805         eDVBServicePMTHandler::program program;
1806         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1807         if (h.getProgramInfo(program))
1808                 return 0;
1809         return program.audioStreams.size();
1810 }
1811
1812 int eDVBServicePlay::getCurrentTrack()
1813 {
1814         eDVBServicePMTHandler::program program;
1815         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1816         if (h.getProgramInfo(program))
1817                 return 0;
1818
1819         int max = program.audioStreams.size();
1820         int i;
1821
1822         for (i = 0; i < max; ++i)
1823                 if (program.audioStreams[i].pid == m_current_audio_pid)
1824                         return i;
1825
1826         return 0;
1827 }
1828
1829 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1830 {
1831         int ret = selectAudioStream(i);
1832
1833         if (m_decoder->set())
1834                 return -5;
1835
1836         return ret;
1837 }
1838
1839 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1840 {
1841         eDVBServicePMTHandler::program program;
1842         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1843
1844         if (h.getProgramInfo(program))
1845                 return -1;
1846         
1847         if (i >= program.audioStreams.size())
1848                 return -2;
1849         
1850         info.m_pid = program.audioStreams[i].pid;
1851
1852         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1853                 info.m_description = "MPEG";
1854         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1855                 info.m_description = "Dolby Digital";
1856         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1857                 info.m_description = "Dolby Digital+";
1858         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1859                 info.m_description = "AAC";
1860         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1861                 info.m_description = "AAC-HE";
1862         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1863                 info.m_description = "DTS";
1864         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1865                 info.m_description = "DTS-HD";
1866         else
1867                 info.m_description = "???";
1868
1869         if (program.audioStreams[i].component_tag != -1)
1870         {
1871                 ePtr<eServiceEvent> evt;
1872                 if (!m_event_handler.getEvent(evt, 0))
1873                 {
1874                         ePtr<eComponentData> data;
1875                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1876                                 info.m_language = data->getText();
1877                 }
1878         }
1879
1880         if (info.m_language.empty())
1881                 info.m_language = program.audioStreams[i].language_code;
1882         
1883         return 0;
1884 }
1885
1886 int eDVBServicePlay::selectAudioStream(int i)
1887 {
1888         eDVBServicePMTHandler::program program;
1889         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1890         pts_t position = -1;
1891
1892         if (h.getProgramInfo(program))
1893                 return -1;
1894
1895         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1896                 return -2;
1897
1898         if (!m_decoder)
1899                 return -3;
1900
1901         int stream = i;
1902         if (stream == -1)
1903                 stream = program.defaultAudioStream;
1904
1905         int apid = -1, apidtype = -1;
1906
1907         if (((unsigned int)stream) < program.audioStreams.size())
1908         {
1909                 apid = program.audioStreams[stream].pid;
1910                 apidtype = program.audioStreams[stream].type;
1911         }
1912
1913         if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1914                 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1915
1916         m_current_audio_pid = apid;
1917
1918         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1919         {
1920                 eDebug("set audio pid failed");
1921                 return -4;
1922         }
1923
1924         if (position != -1)
1925                 eDebug("seekTo ret %d", seekTo(position));
1926
1927         int rdsPid = apid;
1928
1929                 /* if we are not in PVR mode, timeshift is not active and we are not in pip mode, check if we need to enable the rds reader */
1930         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1931         {
1932                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1933                 if (different_pid)
1934                         rdsPid = program.audioStreams[stream].rdsPid;
1935                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1936                 {
1937                         m_rds_decoder = 0;
1938                         ePtr<iDVBDemux> data_demux;
1939                         if (!h.getDataDemux(data_demux))
1940                         {
1941                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1942                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1943                                 m_rds_decoder->start(rdsPid);
1944                         }
1945                 }
1946         }
1947
1948                         /* store new pid as default only when:
1949                                 a.) we have an entry in the service db for the current service,
1950                                 b.) we are not playing back something,
1951                                 c.) we are not selecting the default entry. (we wouldn't change 
1952                                     anything in the best case, or destroy the default setting in
1953                                     case the real default is not yet available.)
1954                         */
1955         if (m_dvb_service && ((i != -1)
1956                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1957         {
1958                 if (apidtype == eDVBAudio::aMPEG)
1959                 {
1960                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1961                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1962                 }
1963                 else if (apidtype == eDVBAudio::aAC3)
1964                 {
1965                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1966                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1967                 }
1968                 else
1969                 {
1970                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1971                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1972                 }
1973         }
1974
1975         h.resetCachedProgram();
1976
1977         return 0;
1978 }
1979
1980 int eDVBServicePlay::getCurrentChannel()
1981 {
1982         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1983 }
1984
1985 RESULT eDVBServicePlay::selectChannel(int i)
1986 {
1987         if (i < LEFT || i > RIGHT || i == STEREO)
1988                 i = -1;  // Stereo
1989         if (m_dvb_service)
1990                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1991         if (m_decoder)
1992                 m_decoder->setAudioChannel(i);
1993         return 0;
1994 }
1995
1996 std::string eDVBServicePlay::getText(int x)
1997 {
1998         if (m_rds_decoder)
1999                 switch(x)
2000                 {
2001                         case RadioText:
2002                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2003                         case RtpText:
2004                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2005                 }
2006         return "";
2007 }
2008
2009 void eDVBServicePlay::rdsDecoderEvent(int what)
2010 {
2011         switch(what)
2012         {
2013                 case eDVBRdsDecoder::RadioTextChanged:
2014                         m_event((iPlayableService*)this, evUpdatedRadioText);
2015                         break;
2016                 case eDVBRdsDecoder::RtpTextChanged:
2017                         m_event((iPlayableService*)this, evUpdatedRtpText);
2018                         break;
2019                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2020                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2021                         break;
2022                 case eDVBRdsDecoder::RecvRassSlidePic:
2023                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2024                         break;
2025         }
2026 }
2027
2028 void eDVBServicePlay::showRassSlidePicture()
2029 {
2030         if (m_rds_decoder)
2031         {
2032                 if (m_decoder)
2033                 {
2034                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2035                         if (rass_slide_pic.length())
2036                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
2037                         else
2038                                 eDebug("empty filename for rass slide picture received!!");
2039                 }
2040                 else
2041                         eDebug("no MPEG Decoder to show iframes avail");
2042         }
2043         else
2044                 eDebug("showRassSlidePicture called.. but not decoder");
2045 }
2046
2047 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2048 {
2049         if (m_rds_decoder)
2050         {
2051                 if (m_decoder)
2052                 {
2053                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2054                         if (rass_interactive_pic.length())
2055                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2056                         else
2057                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2058                 }
2059                 else
2060                         eDebug("no MPEG Decoder to show iframes avail");
2061         }
2062         else
2063                 eDebug("showRassInteractivePic called.. but not decoder");
2064 }
2065
2066 ePyObject eDVBServicePlay::getRassInteractiveMask()
2067 {
2068         if (m_rds_decoder)
2069                 return m_rds_decoder->getRassPictureMask();
2070         Py_RETURN_NONE;
2071 }
2072
2073 int eDVBServiceBase::getFrontendInfo(int w)
2074 {
2075         eUsePtr<iDVBChannel> channel;
2076         if(m_service_handler.getChannel(channel))
2077                 return 0;
2078         ePtr<iDVBFrontend> fe;
2079         if(channel->getFrontend(fe))
2080                 return 0;
2081         return fe->readFrontendData(w);
2082 }
2083
2084 PyObject *eDVBServiceBase::getFrontendData()
2085 {
2086         ePyObject ret = PyDict_New();
2087         if (ret)
2088         {
2089                 eUsePtr<iDVBChannel> channel;
2090                 if(!m_service_handler.getChannel(channel))
2091                 {
2092                         ePtr<iDVBFrontend> fe;
2093                         if(!channel->getFrontend(fe))
2094                                 fe->getFrontendData(ret);
2095                 }
2096         }
2097         else
2098                 Py_RETURN_NONE;
2099         return ret;
2100 }
2101
2102 PyObject *eDVBServiceBase::getFrontendStatus()
2103 {
2104         ePyObject ret = PyDict_New();
2105         if (ret)
2106         {
2107                 eUsePtr<iDVBChannel> channel;
2108                 if(!m_service_handler.getChannel(channel))
2109                 {
2110                         ePtr<iDVBFrontend> fe;
2111                         if(!channel->getFrontend(fe))
2112                                 fe->getFrontendStatus(ret);
2113                 }
2114         }
2115         else
2116                 Py_RETURN_NONE;
2117         return ret;
2118 }
2119
2120 PyObject *eDVBServiceBase::getTransponderData(bool original)
2121 {
2122         ePyObject ret = PyDict_New();
2123         if (ret)
2124         {
2125                 eUsePtr<iDVBChannel> channel;
2126                 if(!m_service_handler.getChannel(channel))
2127                 {
2128                         ePtr<iDVBFrontend> fe;
2129                         if(!channel->getFrontend(fe))
2130                                 fe->getTransponderData(ret, original);
2131                 }
2132         }
2133         else
2134                 Py_RETURN_NONE;
2135         return ret;
2136 }
2137
2138 PyObject *eDVBServiceBase::getAll(bool original)
2139 {
2140         ePyObject ret = getTransponderData(original);
2141         if (ret != Py_None)
2142         {
2143                 eUsePtr<iDVBChannel> channel;
2144                 if(!m_service_handler.getChannel(channel))
2145                 {
2146                         ePtr<iDVBFrontend> fe;
2147                         if(!channel->getFrontend(fe))
2148                         {
2149                                 fe->getFrontendData(ret);
2150                                 fe->getFrontendStatus(ret);
2151                         }
2152                 }
2153         }
2154         return ret;
2155 }
2156
2157 int eDVBServicePlay::getNumberOfSubservices()
2158 {
2159         ePtr<eServiceEvent> evt;
2160         if (!m_event_handler.getEvent(evt, 0))
2161                 return evt->getNumOfLinkageServices();
2162         return 0;
2163 }
2164
2165 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2166 {
2167         ePtr<eServiceEvent> evt;
2168         if (!m_event_handler.getEvent(evt, 0))
2169         {
2170                 if (!evt->getLinkageService(sub, m_reference, n))
2171                         return 0;
2172         }
2173         sub.type=eServiceReference::idInvalid;
2174         return -1;
2175 }
2176
2177 RESULT eDVBServicePlay::startTimeshift()
2178 {
2179         ePtr<iDVBDemux> demux;
2180         
2181         eDebug("Start timeshift!");
2182         
2183         if (m_timeshift_enabled)
2184                 return -1;
2185         
2186                 /* start recording with the data demux. */
2187         if (m_service_handler.getDataDemux(demux))
2188                 return -2;
2189
2190         demux->createTSRecorder(m_record);
2191         if (!m_record)
2192                 return -3;
2193
2194         std::string tspath;
2195         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2196                 eDebug("could not query ts path");
2197                 return -5;
2198         }
2199         tspath.append("/timeshift.XXXXXX");
2200         char* templ;
2201         templ = new char[tspath.length() + 1];
2202         strcpy(templ, tspath.c_str());
2203
2204         m_timeshift_fd = mkstemp(templ);
2205         m_timeshift_file = std::string(templ);
2206
2207         eDebug("recording to %s", templ);
2208
2209         delete [] templ;
2210
2211         if (m_timeshift_fd < 0)
2212         {
2213                 m_record = 0;
2214                 return -4;
2215         }
2216                 
2217         m_record->setTargetFD(m_timeshift_fd);
2218
2219         m_timeshift_enabled = 1;
2220         
2221         updateTimeshiftPids();
2222         m_record->start();
2223
2224         return 0;
2225 }
2226
2227 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2228 {
2229         if (!m_timeshift_enabled)
2230                 return -1;
2231         
2232         if (swToLive)
2233                 switchToLive();
2234         
2235         m_timeshift_enabled = 0;
2236         
2237         m_record->stop();
2238         m_record = 0;
2239         
2240         close(m_timeshift_fd);
2241         eDebug("remove timeshift file");
2242         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2243         
2244         return 0;
2245 }
2246
2247 int eDVBServicePlay::isTimeshiftActive()
2248 {
2249         return m_timeshift_enabled && m_timeshift_active;
2250 }
2251
2252 RESULT eDVBServicePlay::activateTimeshift()
2253 {
2254         if (!m_timeshift_enabled)
2255                 return -1;
2256         
2257         if (!m_timeshift_active)
2258         {
2259                 switchToTimeshift();
2260                 return 0;
2261         }
2262         
2263         return -2;
2264 }
2265
2266 PyObject *eDVBServicePlay::getCutList()
2267 {
2268         ePyObject list = PyList_New(0);
2269         
2270         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2271         {
2272                 ePyObject tuple = PyTuple_New(2);
2273                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2274                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2275                 PyList_Append(list, tuple);
2276                 Py_DECREF(tuple);
2277         }
2278         
2279         return list;
2280 }
2281
2282 void eDVBServicePlay::setCutList(ePyObject list)
2283 {
2284         if (!PyList_Check(list))
2285                 return;
2286         int size = PyList_Size(list);
2287         int i;
2288         
2289         m_cue_entries.clear();
2290         
2291         for (i=0; i<size; ++i)
2292         {
2293                 ePyObject tuple = PyList_GET_ITEM(list, i);
2294                 if (!PyTuple_Check(tuple))
2295                 {
2296                         eDebug("non-tuple in cutlist");
2297                         continue;
2298                 }
2299                 if (PyTuple_Size(tuple) != 2)
2300                 {
2301                         eDebug("cutlist entries need to be a 2-tuple");
2302                         continue;
2303                 }
2304                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2305                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2306                 {
2307                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2308                         continue;
2309                 }
2310                 pts_t pts = PyLong_AsLongLong(ppts);
2311                 int type = PyInt_AsLong(ptype);
2312                 m_cue_entries.insert(cueEntry(pts, type));
2313                 eDebug("adding %08llx, %d", pts, type);
2314         }
2315         m_cuesheet_changed = 1;
2316         
2317         cutlistToCuesheet();
2318         m_event((iPlayableService*)this, evCuesheetChanged);
2319 }
2320
2321 void eDVBServicePlay::setCutListEnable(int enable)
2322 {
2323         m_cutlist_enabled = enable;
2324         cutlistToCuesheet();
2325 }
2326
2327 void eDVBServicePlay::updateTimeshiftPids()
2328 {
2329         if (!m_record)
2330                 return;
2331         
2332         eDVBServicePMTHandler::program program;
2333         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2334
2335         if (h.getProgramInfo(program))
2336                 return;
2337         else
2338         {
2339                 std::set<int> pids_to_record;
2340                 pids_to_record.insert(0); // PAT
2341                 if (program.pmtPid != -1)
2342                         pids_to_record.insert(program.pmtPid); // PMT
2343
2344                 if (program.textPid != -1)
2345                         pids_to_record.insert(program.textPid); // Videotext
2346
2347                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2348                         i(program.videoStreams.begin()); 
2349                         i != program.videoStreams.end(); ++i)
2350                         pids_to_record.insert(i->pid);
2351
2352                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2353                         i(program.audioStreams.begin()); 
2354                         i != program.audioStreams.end(); ++i)
2355                                 pids_to_record.insert(i->pid);
2356
2357                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2358                         i(program.subtitleStreams.begin());
2359                         i != program.subtitleStreams.end(); ++i)
2360                                 pids_to_record.insert(i->pid);
2361
2362                 std::set<int> new_pids, obsolete_pids;
2363                 
2364                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2365                                 m_pids_active.begin(), m_pids_active.end(),
2366                                 std::inserter(new_pids, new_pids.begin()));
2367                 
2368                 std::set_difference(
2369                                 m_pids_active.begin(), m_pids_active.end(),
2370                                 pids_to_record.begin(), pids_to_record.end(), 
2371                                 std::inserter(new_pids, new_pids.begin())
2372                                 );
2373
2374                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2375                         m_record->addPID(*i);
2376
2377                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2378                         m_record->removePID(*i);
2379         }
2380 }
2381
2382 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2383 {
2384         m_timeshift_file_next = f;
2385         return 0;
2386 }
2387
2388 void eDVBServicePlay::switchToLive()
2389 {
2390         if (!m_timeshift_active)
2391                 return;
2392
2393         eDebug("SwitchToLive");
2394
2395         resetTimeshift(0);
2396
2397         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2398
2399         /* free the timeshift service handler, we need the resources */
2400         m_service_handler_timeshift.free();
2401
2402         updateDecoder(true);
2403 }
2404
2405 void eDVBServicePlay::resetTimeshift(int start)
2406 {
2407         m_cue = 0;
2408         m_decode_demux = 0;
2409         m_decoder = 0;
2410         m_teletext_parser = 0;
2411         m_rds_decoder = 0;
2412         m_subtitle_parser = 0;
2413         m_new_subtitle_page_connection = 0;
2414         m_new_dvb_subtitle_page_connection = 0;
2415         m_rds_decoder_event_connection = 0;
2416         m_video_event_connection = 0;
2417         m_timeshift_changed = 1;
2418         m_timeshift_file_next.clear();
2419
2420         if (start)
2421         {
2422                 m_cue = new eCueSheet();
2423                 m_timeshift_active = 1;
2424         }
2425         else
2426                 m_timeshift_active = 0;
2427 }
2428
2429 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2430 {
2431         if (m_is_stream)
2432         {
2433                 eHttpStream *f = new eHttpStream();
2434                 f->open(ref.path.c_str());
2435                 return ePtr<iTsSource>(f);
2436         }
2437         else
2438         {
2439                 eRawFile *f = new eRawFile();
2440                 f->open(ref.path.c_str());
2441                 return ePtr<iTsSource>(f);
2442         }
2443 }
2444
2445 void eDVBServicePlay::switchToTimeshift()
2446 {
2447         if (m_timeshift_active)
2448                 return;
2449
2450         resetTimeshift(1);
2451
2452         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2453         r.path = m_timeshift_file;
2454
2455         m_cue->seekTo(0, -1000);
2456
2457         ePtr<iTsSource> source = createTsSource(r);
2458         m_service_handler_timeshift.tuneExt(r, 1, source, m_timeshift_file.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2459
2460         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2461         pause();
2462         updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2463 }
2464
2465 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2466 {
2467         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2468         bool mustPlay = false;
2469
2470         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2471
2472         eDVBServicePMTHandler::program program;
2473         if (h.getProgramInfo(program))
2474                 eDebug("getting program info failed.");
2475         else
2476         {
2477                 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2478                 if (!program.videoStreams.empty())
2479                 {
2480                         eDebugNoNewLine(" (");
2481                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2482                                 i(program.videoStreams.begin());
2483                                 i != program.videoStreams.end(); ++i)
2484                         {
2485                                 if (vpid == -1)
2486                                 {
2487                                         vpid = i->pid;
2488                                         vpidtype = i->type;
2489                                 }
2490                                 if (i != program.videoStreams.begin())
2491                                         eDebugNoNewLine(", ");
2492                                 eDebugNoNewLine("%04x", i->pid);
2493                         }
2494                         eDebugNoNewLine(")");
2495                 }
2496                 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2497                 if (!program.audioStreams.empty())
2498                 {
2499                         eDebugNoNewLine(" (");
2500                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2501                                 i(program.audioStreams.begin());
2502                                 i != program.audioStreams.end(); ++i)
2503                         {
2504                                 if (i != program.audioStreams.begin())
2505                                         eDebugNoNewLine(", ");
2506                                 eDebugNoNewLine("%04x", i->pid);
2507                         }
2508                         eDebugNoNewLine(")");
2509                 }
2510                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2511                 pcrpid = program.pcrPid;
2512                 eDebug(", and the text pid is %04x", program.textPid);
2513                 tpid = program.textPid;
2514         }
2515
2516         if (!m_decoder)
2517         {
2518                 h.getDecodeDemux(m_decode_demux);
2519                 if (m_decode_demux)
2520                 {
2521                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2522                         if (m_decoder)
2523                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2524                         if (m_is_primary)
2525                         {
2526                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2527                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2528                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2529                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2530                                 if (m_timeshift_changed)
2531                                 {
2532                                         ePyObject subs = getCachedSubtitle();
2533                                         if (subs != Py_None)
2534                                         {
2535                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2536                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2537                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2538                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2539                                                 if (type == 0) // dvb
2540                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2541                                                 else if (type == 1) // ttx
2542                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2543                                         }
2544                                         Py_DECREF(subs);
2545                                 }
2546                         }
2547                 }
2548                 if (m_cue)
2549                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2550                 mustPlay = true;
2551         }
2552
2553         m_timeshift_changed = 0;
2554
2555         if (m_decoder)
2556         {
2557                 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2558                 if (m_dvb_service)
2559                 {
2560                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2561                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2562                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2563                 }
2564                 else // subservice
2565                 {
2566                         eServiceReferenceDVB ref;
2567                         m_service_handler.getServiceReference(ref);
2568                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2569                         if (!parent)
2570                                 parent = ref;
2571                         if (parent)
2572                         {
2573                                 ePtr<eDVBResourceManager> res_mgr;
2574                                 if (!eDVBResourceManager::getInstance(res_mgr))
2575                                 {
2576                                         ePtr<iDVBChannelList> db;
2577                                         if (!res_mgr->getChannelList(db))
2578                                         {
2579                                                 ePtr<eDVBService> origService;
2580                                                 if (!db->getService(parent, origService))
2581                                                 {
2582                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2583                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2584                                                 }
2585                                         }
2586                                 }
2587                         }
2588                 }
2589
2590                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2591                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2592
2593                 m_decoder->setVideoPID(vpid, vpidtype);
2594                 selectAudioStream();
2595
2596                 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2597                 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2598                         m_decoder->setSyncPCR(pcrpid);
2599                 else
2600                         m_decoder->setSyncPCR(-1);
2601
2602                 if (m_is_primary)
2603                 {
2604                         m_decoder->setTextPID(tpid);
2605                         m_teletext_parser->start(program.textPid);
2606                 }
2607
2608                 if (vpid > 0 && vpid < 0x2000)
2609                         ;
2610                 else
2611                 {
2612                         std::string radio_pic;
2613                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2614                                 m_decoder->setRadioPic(radio_pic);
2615                 }
2616
2617                 if (mustPlay)
2618                         m_decoder->play();
2619                 else
2620                         m_decoder->set();
2621
2622                 m_decoder->setAudioChannel(achannel);
2623
2624                 /* don't worry about non-existing services, nor pvr services */
2625                 if (m_dvb_service)
2626                 {
2627                                 /* (audio pid will be set in selectAudioTrack */
2628                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2629                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2630                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2631                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2632                 }
2633                 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2634                         sendSeekableStateChanged = true;
2635         }
2636         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2637
2638         if (sendSeekableStateChanged)
2639                 m_event((iPlayableService*)this, evSeekableStatusChanged);
2640 }
2641
2642 void eDVBServicePlay::loadCuesheet()
2643 {
2644         std::string filename = m_reference.path + ".cuts";
2645         
2646         m_cue_entries.clear();
2647
2648         FILE *f = fopen(filename.c_str(), "rb");
2649
2650         if (f)
2651         {
2652                 eDebug("loading cuts..");
2653                 while (1)
2654                 {
2655                         unsigned long long where;
2656                         unsigned int what;
2657                         
2658                         if (!fread(&where, sizeof(where), 1, f))
2659                                 break;
2660                         if (!fread(&what, sizeof(what), 1, f))
2661                                 break;
2662                         
2663 #if BYTE_ORDER == LITTLE_ENDIAN
2664                         where = bswap_64(where);
2665 #endif
2666                         what = ntohl(what);
2667                         
2668                         if (what > 3)
2669                                 break;
2670                         
2671                         m_cue_entries.insert(cueEntry(where, what));
2672                 }
2673                 fclose(f);
2674                 eDebug("%zd entries", m_cue_entries.size());
2675         } else
2676                 eDebug("cutfile not found!");
2677         
2678         m_cuesheet_changed = 0;
2679         cutlistToCuesheet();
2680         m_event((iPlayableService*)this, evCuesheetChanged);
2681 }
2682
2683 void eDVBServicePlay::saveCuesheet()
2684 {
2685         std::string filename = m_reference.path + ".cuts";
2686         
2687         FILE *f = fopen(filename.c_str(), "wb");
2688
2689         if (f)
2690         {
2691                 unsigned long long where;
2692                 int what;
2693
2694                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2695                 {
2696 #if BYTE_ORDER == BIG_ENDIAN
2697                         where = i->where;
2698 #else
2699                         where = bswap_64(i->where);
2700 #endif
2701                         what = htonl(i->what);
2702                         fwrite(&where, sizeof(where), 1, f);
2703                         fwrite(&what, sizeof(what), 1, f);
2704                         
2705                 }
2706                 fclose(f);
2707         }
2708         
2709         m_cuesheet_changed = 0;
2710 }
2711
2712 void eDVBServicePlay::cutlistToCuesheet()
2713 {
2714         if (!m_cue)
2715         {
2716                 eDebug("no cue sheet");
2717                 return;
2718         }       
2719         m_cue->clear();
2720         
2721         if (!m_cutlist_enabled)
2722         {
2723                 m_cue->commitSpans();
2724                 eDebug("cutlists were disabled");
2725                 return;
2726         }
2727
2728         pts_t in = 0, out = 0, length = 0;
2729         
2730         getLength(length);
2731                 
2732         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2733         
2734         int have_any_span = 0;
2735         
2736         while (1)
2737         {
2738                 if (i == m_cue_entries.end())
2739                 {
2740                         if (!have_any_span && !in)
2741                                 break;
2742                         out = length;
2743                 } else {
2744                         if (i->what == 0) /* in */
2745                         {
2746                                 in = i++->where;
2747                                 continue;
2748                         } else if (i->what == 1) /* out */
2749                                 out = i++->where;
2750                         else /* mark (2) or last play position (3) */
2751                         {
2752                                 i++;
2753                                 continue;
2754                         }
2755                 }
2756                 
2757                 if (in < 0)
2758                         in = 0;
2759                 if (out < 0)
2760                         out = 0;
2761                 if (in > length)
2762                         in = length;
2763                 if (out > length)
2764                         out = length;
2765                 
2766                 if (in < out)
2767                 {
2768                         have_any_span = 1;
2769                         m_cue->addSourceSpan(in, out);
2770                         in = out = 0;
2771                 }
2772                 
2773                 in = length;
2774                 
2775                 if (i == m_cue_entries.end())
2776                         break;
2777         }
2778         m_cue->commitSpans();
2779 }
2780
2781 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2782 {
2783         if (m_subtitle_widget)
2784                 disableSubtitles(parent);
2785
2786         ePyObject entry;
2787         int tuplesize = PyTuple_Size(tuple);
2788         int type = 0;
2789
2790         if (!PyTuple_Check(tuple))
2791                 goto error_out;
2792
2793         if (tuplesize < 1)
2794                 goto error_out;
2795
2796         entry = PyTuple_GET_ITEM(tuple, 0);
2797
2798         if (!PyInt_Check(entry))
2799                 goto error_out;
2800
2801         type = PyInt_AsLong(entry);
2802
2803         if (type == 1)  // teletext subtitles
2804         {
2805                 int page, magazine, pid;
2806                 if (tuplesize < 4)
2807                         goto error_out;
2808
2809                 if (!m_teletext_parser)
2810                 {
2811                         eDebug("enable teletext subtitles.. no parser !!!");
2812                         return -1;
2813                 }
2814
2815                 entry = PyTuple_GET_ITEM(tuple, 1);
2816                 if (!PyInt_Check(entry))
2817                         goto error_out;
2818                 pid = PyInt_AsLong(entry);
2819
2820                 entry = PyTuple_GET_ITEM(tuple, 2);
2821                 if (!PyInt_Check(entry))
2822                         goto error_out;
2823                 page = PyInt_AsLong(entry);
2824
2825                 entry = PyTuple_GET_ITEM(tuple, 3);
2826                 if (!PyInt_Check(entry))
2827                         goto error_out;
2828                 magazine = PyInt_AsLong(entry);
2829
2830                 m_subtitle_widget = new eSubtitleWidget(parent);
2831                 m_subtitle_widget->resize(parent->size()); /* full size */
2832                 m_teletext_parser->setPageAndMagazine(page, magazine);
2833                 if (m_dvb_service)
2834                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2835         }
2836         else if (type == 0)
2837         {
2838                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2839                 if (!m_subtitle_parser)
2840                 {
2841                         eDebug("enable dvb subtitles.. no parser !!!");
2842                         return -1;
2843                 }
2844                 if (tuplesize < 4)
2845                         goto error_out;
2846
2847                 entry = PyTuple_GET_ITEM(tuple, 1);
2848                 if (!PyInt_Check(entry))
2849                         goto error_out;
2850                 pid = PyInt_AsLong(entry);
2851
2852                 entry = PyTuple_GET_ITEM(tuple, 2);
2853                 if (!PyInt_Check(entry))
2854                         goto error_out;
2855                 composition_page_id = PyInt_AsLong(entry);
2856
2857                 entry = PyTuple_GET_ITEM(tuple, 3);
2858                 if (!PyInt_Check(entry))
2859                         goto error_out;
2860                 ancillary_page_id = PyInt_AsLong(entry);
2861
2862                 m_subtitle_widget = new eSubtitleWidget(parent);
2863                 m_subtitle_widget->resize(parent->size()); /* full size */
2864                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2865                 if (m_dvb_service)
2866                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2867         }
2868         else
2869                 goto error_out;
2870         return 0;
2871 error_out:
2872         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2873                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2874                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2875         return -1;
2876 }
2877
2878 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2879 {
2880         delete m_subtitle_widget;
2881         m_subtitle_widget = 0;
2882         if (m_subtitle_parser)
2883         {
2884                 m_subtitle_parser->stop();
2885                 m_dvb_subtitle_pages.clear();
2886         }
2887         if (m_teletext_parser)
2888         {
2889                 m_teletext_parser->setPageAndMagazine(-1, -1);
2890                 m_subtitle_pages.clear();
2891         }
2892         if (m_dvb_service)
2893                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2894         return 0;
2895 }
2896
2897 PyObject *eDVBServicePlay::getCachedSubtitle()
2898 {
2899         if (m_dvb_service)
2900         {
2901                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2902                 if (tmp != -1)
2903                 {
2904                         unsigned int data = (unsigned int)tmp;
2905                         int pid = (data&0xFFFF0000)>>16;
2906                         ePyObject tuple = PyTuple_New(4);
2907                         eDVBServicePMTHandler::program program;
2908                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2909                         if (!h.getProgramInfo(program))
2910                         {
2911                                 if (program.textPid==pid) // teletext
2912                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2913                                 else
2914                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2915                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2916                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2917                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2918                                 return tuple;
2919                         }
2920                 }
2921         }
2922         Py_RETURN_NONE;
2923 }
2924
2925 PyObject *eDVBServicePlay::getSubtitleList()
2926 {
2927         if (!m_teletext_parser)
2928                 Py_RETURN_NONE;
2929         
2930         ePyObject l = PyList_New(0);
2931         std::set<int> added_ttx_pages;
2932
2933         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2934                 m_teletext_parser->m_found_subtitle_pages;
2935
2936         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2937         eDVBServicePMTHandler::program program;
2938         if (h.getProgramInfo(program))
2939                 eDebug("getting program info failed.");
2940         else
2941         {
2942                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2943                         it != program.subtitleStreams.end(); ++it)
2944                 {
2945                         switch(it->subtitling_type)
2946                         {
2947                                 case 0x01: // ebu teletext subtitles
2948                                 {
2949                                         int page_number = it->teletext_page_number & 0xFF;
2950                                         int magazine_number = it->teletext_magazine_number & 7;
2951                                         int hash = magazine_number << 8 | page_number;
2952                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2953                                         {
2954                                                 ePyObject tuple = PyTuple_New(5);
2955                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2956                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2957                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2958                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2959                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2960                                                 PyList_Append(l, tuple);
2961                                                 Py_DECREF(tuple);
2962                                                 added_ttx_pages.insert(hash);
2963                                         }
2964                                         break;
2965                                 }
2966                                 case 0x10 ... 0x13:
2967                                 case 0x20 ... 0x23: // dvb subtitles
2968                                 {
2969                                         ePyObject tuple = PyTuple_New(5);
2970                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2971                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2972                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2973                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2974                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2975                                         PyList_Insert(l, 0, tuple);
2976                                         Py_DECREF(tuple);
2977                                         break;
2978                                 }
2979                         }
2980                 }
2981         }
2982
2983         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2984                 it != subs.end(); ++it)
2985         {
2986                 int page_number = it->teletext_page_number & 0xFF;
2987                 int magazine_number = it->teletext_magazine_number & 7;
2988                 int hash = magazine_number << 8 | page_number;
2989                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2990                 {
2991                         ePyObject tuple = PyTuple_New(5);
2992                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2993                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2994                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2995                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2996                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2997                         PyList_Append(l, tuple);
2998                         Py_DECREF(tuple);
2999                 }
3000         }
3001
3002         return l;
3003 }
3004
3005 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3006 {
3007         if (m_subtitle_widget)
3008         {
3009                 pts_t pos = 0;
3010                 if (m_decoder)
3011                         m_decoder->getPTS(0, pos);
3012                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3013                 m_subtitle_pages.push_back(page);
3014                 checkSubtitleTiming();
3015         }
3016 }
3017
3018 void eDVBServicePlay::checkSubtitleTiming()
3019 {
3020         eDebug("checkSubtitleTiming");
3021         if (!m_subtitle_widget)
3022                 return;
3023         while (1)
3024         {
3025                 enum { TELETEXT, DVB } type;
3026                 eDVBTeletextSubtitlePage page;
3027                 eDVBSubtitlePage dvb_page;
3028                 pts_t show_time;
3029                 if (!m_subtitle_pages.empty())
3030                 {
3031                         page = m_subtitle_pages.front();
3032                         type = TELETEXT;
3033                         show_time = page.m_pts;
3034                 }
3035                 else if (!m_dvb_subtitle_pages.empty())
3036                 {
3037                         dvb_page = m_dvb_subtitle_pages.front();
3038                         type = DVB;
3039                         show_time = dvb_page.m_show_time;
3040                 }
3041                 else
3042                         return;
3043         
3044                 pts_t pos = 0;
3045         
3046                 if (m_decoder)
3047                         m_decoder->getPTS(0, pos);
3048
3049                 eDebug("%lld %lld", pos, show_time);
3050                 int diff = show_time - pos;
3051                 if (type == TELETEXT && !page.m_have_pts)
3052                 {
3053                         eDebug("ttx subtitle page without pts... immediate show");
3054                         diff = 0;
3055                 }
3056                 if (diff < 0)
3057                 {
3058                         eDebug("[late (%d ms)]", -diff / 90);
3059                         diff = 0;
3060                 }
3061                 if (abs(diff) > 1800000)
3062                 {
3063                         eDebug("[invalid]... immediate show!");
3064                         diff = 0;
3065                 }
3066                 if ((diff/90)<20)
3067                 {
3068                         if (type == TELETEXT)
3069                         {
3070                                 eDebug("display teletext subtitle page %lld", show_time);
3071                                 m_subtitle_widget->setPage(page);
3072                                 m_subtitle_pages.pop_front();
3073                         }
3074                         else
3075                         {
3076                                 eDebug("display dvb subtitle Page %lld", show_time);
3077                                 m_subtitle_widget->setPage(dvb_page);
3078                                 m_dvb_subtitle_pages.pop_front();
3079                         }
3080                 } else
3081                 {
3082                         eDebug("start subtitle delay %d", diff / 90);
3083                         m_subtitle_sync_timer->start(diff / 90, 1);
3084                         break;
3085                 }
3086         }
3087 }
3088
3089 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3090 {
3091         if (m_subtitle_widget)
3092         {
3093                 pts_t pos = 0;
3094                 if (m_decoder)
3095                         m_decoder->getPTS(0, pos);
3096                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3097                 m_dvb_subtitle_pages.push_back(p);
3098                 checkSubtitleTiming();
3099         }
3100 }
3101
3102 int eDVBServicePlay::getAC3Delay()
3103 {
3104         if (m_dvb_service)
3105                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3106         else if (m_decoder)
3107                 return m_decoder->getAC3Delay();
3108         else
3109                 return 0;
3110 }
3111
3112 int eDVBServicePlay::getPCMDelay()
3113 {
3114         if (m_dvb_service)
3115                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3116         else if (m_decoder)
3117                 return m_decoder->getPCMDelay();
3118         else
3119                 return 0;
3120 }
3121
3122 void eDVBServicePlay::setAC3Delay(int delay)
3123 {
3124         if (m_dvb_service)
3125                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3126         if (m_decoder) {
3127                 std::string config_delay;
3128                 int config_delay_int = 0;
3129                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3130                         config_delay_int = atoi(config_delay.c_str());
3131                 m_decoder->setAC3Delay(delay + config_delay_int);
3132         }
3133 }
3134
3135 void eDVBServicePlay::setPCMDelay(int delay)
3136 {
3137         if (m_dvb_service)
3138                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3139         if (m_decoder) {
3140                 std::string config_delay;
3141                 int config_delay_int = 0;
3142                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3143                         config_delay_int = atoi(config_delay.c_str());
3144                 else
3145                         config_delay_int = 0;
3146                 m_decoder->setPCMDelay(delay + config_delay_int);
3147         }
3148 }
3149
3150 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3151 {
3152         switch(event.type) {
3153                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3154                         m_event((iPlayableService*)this, evVideoSizeChanged);
3155                         break;
3156                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3157                         m_event((iPlayableService*)this, evVideoFramerateChanged);
3158                         break;
3159                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3160                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
3161                         break;
3162                 default:
3163                         break;
3164         }
3165 }
3166
3167 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3168 {
3169         ptr = this;
3170         return 0;
3171 }
3172
3173 PyObject *eDVBServicePlay::getStreamingData()
3174 {
3175         eDVBServicePMTHandler::program program;
3176         if (m_service_handler.getProgramInfo(program))
3177         {
3178                 Py_RETURN_NONE;
3179         }
3180
3181         ePyObject r = program.createPythonObject();
3182         ePtr<iDVBDemux> demux;
3183         if (!m_service_handler.getDataDemux(demux))
3184         {
3185                 uint8_t demux_id;
3186                 if (!demux->getCADemuxID(demux_id))
3187                         PutToDict(r, "demux", demux_id);
3188         }
3189
3190         return r;
3191 }
3192
3193
3194 DEFINE_REF(eDVBServicePlay)
3195
3196 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3197 {
3198         switch (w)
3199         {
3200         case iServiceInformation::sTransponderData:
3201                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3202         default:
3203                 break;
3204         }
3205         return iStaticServiceInformation::getInfoObject(ref, w);
3206 }
3207
3208 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");