d3c603291b31da78df10951c553ca266a29c09c6
[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         m_current_video_pid_type = 0;
960
961         CONNECT(m_subtitle_sync_timer->timeout, eDVBServicePlay::checkSubtitleTiming);
962 }
963
964 eDVBServicePlay::~eDVBServicePlay()
965 {
966         if (m_is_pvr)
967         {
968                 eDVBMetaParser meta;
969                 int ret=meta.parseFile(m_reference.path);
970                 if (!ret)
971                 {
972                         char tmp[255];
973                         meta.m_service_data="";
974                         sprintf(tmp, "f:%x", m_dvb_service->m_flags);
975                         meta.m_service_data += tmp;
976                         // cached pids
977                         for (int x=0; x < eDVBService::cacheMax; ++x)
978                         {
979                                 int entry = m_dvb_service->getCacheEntry((eDVBService::cacheID)x);
980                                 if (entry != -1)
981                                 {
982                                         sprintf(tmp, ",c:%02d%04x", x, entry);
983                                         meta.m_service_data += tmp;
984                                 }
985                         }
986                         meta.updateMeta(m_reference.path);
987                 }
988         }
989         delete m_subtitle_widget;
990 }
991
992 void eDVBServicePlay::gotNewEvent()
993 {
994 #if 0
995                 // debug only
996         ePtr<eServiceEvent> m_event_now, m_event_next;
997         getEvent(m_event_now, 0);
998         getEvent(m_event_next, 1);
999
1000         if (m_event_now)
1001                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1002         if (m_event_next)
1003                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1004 #endif
1005         m_event((iPlayableService*)this, evUpdatedEventInfo);
1006 }
1007
1008 void eDVBServicePlay::serviceEvent(int event)
1009 {
1010         m_tune_state = event;
1011
1012         switch (event)
1013         {
1014         case eDVBServicePMTHandler::eventTuned:
1015         {
1016                 ePtr<iDVBDemux> m_demux;
1017                 if (!m_service_handler.getDataDemux(m_demux))
1018                 {
1019                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1020                         int sid = ref.getParentServiceID().get();
1021                         if (!sid)
1022                                 sid = ref.getServiceID().get();
1023                         if ( ref.getParentTransportStreamID().get() &&
1024                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1025                                 m_event_handler.startOther(m_demux, sid);
1026                         else
1027                                 m_event_handler.start(m_demux, sid);
1028                 }
1029                 m_event((iPlayableService*)this, evTunedIn);
1030                 break;
1031         }
1032         case eDVBServicePMTHandler::eventNoResources:
1033         case eDVBServicePMTHandler::eventNoPAT:
1034         case eDVBServicePMTHandler::eventNoPATEntry:
1035         case eDVBServicePMTHandler::eventNoPMT:
1036         case eDVBServicePMTHandler::eventTuneFailed:
1037         case eDVBServicePMTHandler::eventMisconfiguration:
1038         {
1039                 eDebug("DVB service failed to tune - error %d", event);
1040                 m_event((iPlayableService*)this, evTuneFailed);
1041                 break;
1042         }
1043         case eDVBServicePMTHandler::eventNewProgramInfo:
1044         {
1045                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1046                 if (m_timeshift_enabled)
1047                         updateTimeshiftPids();
1048                 if (!m_timeshift_active)
1049                         updateDecoder();
1050                 if (m_first_program_info & 1 && m_is_pvr)
1051                 {
1052                         m_first_program_info &= ~1;
1053                         seekTo(0);
1054                 }
1055                 if (!m_timeshift_active)
1056                         m_event((iPlayableService*)this, evUpdatedInfo);
1057                 break;
1058         }
1059         case eDVBServicePMTHandler::eventPreStart:
1060                 loadCuesheet();
1061                 break;
1062         case eDVBServicePMTHandler::eventEOF:
1063                 m_event((iPlayableService*)this, evEOF);
1064                 break;
1065         case eDVBServicePMTHandler::eventSOF:
1066                 m_event((iPlayableService*)this, evSOF);
1067                 break;
1068         case eDVBServicePMTHandler::eventHBBTVInfo:
1069                 m_event((iPlayableService*)this, evHBBTVInfo);
1070                 break;
1071         }
1072 }
1073
1074 void eDVBServicePlay::serviceEventTimeshift(int event)
1075 {
1076         switch (event)
1077         {
1078         case eDVBServicePMTHandler::eventNewProgramInfo:
1079                 eDebug("eventNewProgramInfo TS");
1080                 if (m_timeshift_active)
1081                 {
1082                         updateDecoder();
1083                         if (m_first_program_info & 2)
1084                         {
1085                                 if (m_slowmotion)
1086                                 {
1087                                         eDebug("re-apply slowmotion after timeshift file change");
1088                                         m_decoder->setSlowMotion(m_slowmotion);
1089                                 }
1090                                 if (m_fastforward)
1091                                 {
1092                                         eDebug("re-apply skip %d, ratio %d after timeshift file change", m_skipmode, m_fastforward);
1093                                         if (m_skipmode)
1094                                                 m_cue->setSkipmode(m_skipmode * 90000); /* convert to 90000 per second */
1095                                         if (m_fastforward != 1)
1096                                                 m_decoder->setFastForward(m_fastforward);
1097                                         else
1098                                                 m_decoder->setTrickmode();
1099                                 }
1100                                 else
1101                                         seekTo(0);
1102                                 m_first_program_info &= ~2;
1103                         }
1104                         m_event((iPlayableService*)this, evUpdatedInfo);
1105                 }
1106                 break;
1107         case eDVBServicePMTHandler::eventSOF:
1108 #if 0
1109                 if (!m_timeshift_file_next.empty())
1110                 {
1111                         eDebug("timeshift SOF, switch to next file");
1112                         m_decoder->pause();
1113
1114                         m_first_program_info |= 2;
1115
1116                         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1117                         r.path = m_timeshift_file_next;
1118
1119                         /* free the timeshift service handler, we need the resources */
1120                         m_service_handler_timeshift.free();
1121                         resetTimeshift(1);
1122
1123                         if (m_skipmode < 0)
1124                                 m_cue->seekTo(0, -1000);
1125                         ePtr<iTsSource> source = createTsSource(r);
1126                         m_service_handler_timeshift.tuneExt(r, 1, source, r.path.c_str(), m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
1127
1128                         m_event((iPlayableService*)this, evUser+1);
1129                 }
1130                 else
1131 #endif
1132                         m_event((iPlayableService*)this, evSOF);
1133                 break;
1134         case eDVBServicePMTHandler::eventEOF:
1135                 if ((!m_is_paused) && (m_skipmode >= 0))
1136                 {
1137                         if (m_timeshift_file_next.empty())
1138                         {
1139                                 eDebug("timeshift EOF, so let's go live");
1140                                 switchToLive();
1141                         }
1142                         else
1143                         {
1144                                 eDebug("timeshift EOF, switch to next file");
1145
1146                                 m_first_program_info |= 2;
1147
1148                                 eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1149                                 r.path = m_timeshift_file_next;
1150
1151                                 /* free the timeshift service handler, we need the resources */
1152                                 m_service_handler_timeshift.free();
1153                                 resetTimeshift(1);
1154
1155                                 ePtr<iTsSource> source = createTsSource(r);
1156                                 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 */
1157
1158                                 m_event((iPlayableService*)this, evUser+1);
1159                         }
1160                 }
1161                 break;
1162         }
1163 }
1164
1165 RESULT eDVBServicePlay::start()
1166 {
1167         eServiceReferenceDVB service = (eServiceReferenceDVB&)m_reference;
1168
1169                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
1170                    two (one for decoding, one for data source), as we must be prepared
1171                    to start recording from the data demux. */
1172         if (m_is_pvr)
1173         {
1174                 eDVBMetaParser meta;
1175                 if (!meta.parseFile(m_reference.path))
1176                 {
1177                         service = meta.m_ref;
1178                         service.path = m_reference.path;
1179                 }
1180                 m_cue = new eCueSheet();
1181         }
1182         else
1183                 m_event(this, evStart);
1184
1185         m_first_program_info = 1;
1186         ePtr<iTsSource> source = createTsSource(service);
1187         m_service_handler.tuneExt(service, m_is_pvr, source, service.path.c_str(), m_cue, false, m_dvb_service, m_is_stream);
1188
1189         if (m_is_pvr)
1190         {
1191                 /* inject EIT if there is a stored one */
1192                 std::string filename = service.path;
1193                 filename.erase(filename.length()-2, 2);
1194                 filename+="eit";
1195                 ePtr<eServiceEvent> event = new eServiceEvent;
1196                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1197                 {
1198                         ePtr<eServiceEvent> empty;
1199                         m_event_handler.inject(event, 0);
1200                         m_event_handler.inject(empty, 1);
1201                 }
1202                 m_event(this, evStart);
1203         }
1204         return 0;
1205 }
1206
1207 RESULT eDVBServicePlay::stop()
1208 {
1209                 /* add bookmark for last play position */
1210         if (m_is_pvr)
1211         {
1212                 pts_t play_position, length;
1213                 if (!getPlayPosition(play_position))
1214                 {
1215                                 /* remove last position */
1216                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1217                         {
1218                                 if (i->what == 3) /* current play position */
1219                                 {
1220                                         m_cue_entries.erase(i);
1221                                         i = m_cue_entries.begin();
1222                                         continue;
1223                                 } else
1224                                         ++i;
1225                         }
1226                         
1227                         if (getLength(length))
1228                                 length = 0;
1229                         
1230                         if (length)
1231                         {
1232                                 m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1233                         }
1234                         m_cuesheet_changed = 1;
1235                 }
1236         }
1237
1238         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1239
1240         m_service_handler_timeshift.free();
1241         m_service_handler.free();
1242         
1243         if (m_is_pvr && m_cuesheet_changed)
1244         {
1245                 struct stat s;
1246                                 /* save cuesheet only when main file is accessible. */
1247                 if (!::stat(m_reference.path.c_str(), &s))
1248                         saveCuesheet();
1249         }
1250         m_event((iPlayableService*)this, evStopped);
1251         return 0;
1252 }
1253
1254 RESULT eDVBServicePlay::setTarget(int target)
1255 {
1256         m_is_primary = !target;
1257         return 0;
1258 }
1259
1260 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1261 {
1262         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1263         return 0;
1264 }
1265
1266 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1267 {
1268                 /* note: we check for timeshift to be enabled,
1269                    not neccessary active. if you pause when timeshift
1270                    is not active, you should activate it when unpausing */
1271         if ((!m_is_pvr) && (!m_timeshift_enabled))
1272         {
1273                 ptr = 0;
1274                 return -1;
1275         }
1276
1277         ptr = this;
1278         return 0;
1279 }
1280
1281 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1282 {
1283         ASSERT(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1284         eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1285         setFastForward_internal(0);
1286         if (m_decoder)
1287         {
1288                 m_slowmotion = ratio;
1289                 return m_decoder->setSlowMotion(ratio);
1290         }
1291         else
1292                 return -1;
1293 }
1294
1295 RESULT eDVBServicePlay::setFastForward(int ratio)
1296 {
1297         eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1298         ASSERT(ratio);
1299         return setFastForward_internal(ratio);
1300 }
1301
1302 RESULT eDVBServicePlay::setFastForward_internal(int ratio, bool final_seek)
1303 {
1304         int skipmode, ffratio, ret = 0;
1305         pts_t pos=0;
1306
1307         if (ratio > 8)
1308         {
1309                 skipmode = ratio;
1310                 ffratio = 1;
1311         } else if (ratio > 0)
1312         {
1313                 skipmode = 0;
1314                 ffratio = ratio;
1315         } else if (!ratio)
1316         {
1317                 skipmode = 0;
1318                 ffratio = 0;
1319         } else // if (ratio < 0)
1320         {
1321                 skipmode = ratio;
1322                 ffratio = 1;
1323         }
1324
1325         if (m_skipmode != skipmode)
1326         {
1327                 eDebug("setting cue skipmode to %d", skipmode);
1328                 if (m_cue)
1329                 {
1330                         long long _skipmode = skipmode;
1331                         if (m_current_video_pid_type == eDVBServicePMTHandler::videoStream::vtH265_HEVC)
1332                         {
1333                                 if (ratio < 0)
1334                                         _skipmode = skipmode * 3;
1335                                 else
1336                                         _skipmode = skipmode * 4;
1337                         }
1338
1339                         m_cue->setSkipmode(_skipmode * 90000); /* convert to 90000 per second */
1340                 }
1341         }
1342
1343         m_skipmode = skipmode;
1344
1345         if (final_seek)
1346                 eDebug("trickplay stopped .. ret %d, pos %lld", getPlayPosition(pos), pos);
1347
1348         m_fastforward = ffratio;
1349
1350         if (!m_decoder)
1351                 return -1;
1352
1353         if (ffratio == 0)
1354                 ; /* return m_decoder->play(); is done in caller*/
1355         else if (ffratio != 1)
1356                 ret = m_decoder->setFastForward(ffratio);
1357         else
1358                 ret = m_decoder->setTrickmode();
1359
1360         if (pos)
1361                 eDebug("final seek after trickplay ret %d", seekTo(pos));
1362
1363         return ret;
1364 }
1365
1366 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1367 {
1368         if (m_is_pvr || m_timeshift_enabled)
1369         {
1370                 ptr = this;
1371                 return 0;
1372         }
1373         
1374         ptr = 0;
1375         return -1;
1376 }
1377
1378         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1379 RESULT eDVBServicePlay::getLength(pts_t &len)
1380 {
1381         ePtr<iDVBPVRChannel> pvr_channel;
1382         
1383         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1384                 return -1;
1385         
1386         return pvr_channel->getLength(len);
1387 }
1388
1389 RESULT eDVBServicePlay::pause()
1390 {
1391         eDebug("eDVBServicePlay::pause");
1392         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1393         if (m_decoder)
1394         {
1395                 m_slowmotion = 0;
1396                 m_is_paused = 1;
1397                 return m_decoder->pause();
1398         } else
1399                 return -1;
1400 }
1401
1402 RESULT eDVBServicePlay::unpause()
1403 {
1404         eDebug("eDVBServicePlay::unpause");
1405         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1406         if (m_decoder)
1407         {
1408                 m_slowmotion = 0;
1409                 m_is_paused = 0;
1410                 return m_decoder->play();
1411         } else
1412                 return -1;
1413 }
1414
1415 RESULT eDVBServicePlay::seekTo(pts_t to)
1416 {
1417         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1418         
1419         if (!m_decode_demux)
1420                 return -1;
1421
1422         ePtr<iDVBPVRChannel> pvr_channel;
1423         
1424         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1425                 return -1;
1426         
1427         if (!m_cue)
1428                 return -1;
1429         
1430         m_cue->seekTo(0, to);
1431         m_dvb_subtitle_pages.clear();
1432         m_subtitle_pages.clear();
1433
1434         return 0;
1435 }
1436
1437 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1438 {
1439         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1440         
1441         if (!m_decode_demux)
1442                 return -1;
1443
1444         ePtr<iDVBPVRChannel> pvr_channel;
1445         
1446         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1447                 return -1;
1448         
1449         int mode = 1;
1450         
1451                         /* HACK until we have skip-AP api */
1452         if ((to > 0) && (to < 100))
1453                 mode = 2;
1454         
1455         to *= direction;
1456         
1457         if (!m_cue)
1458                 return 0;
1459         
1460         m_cue->seekTo(mode, to);
1461         m_dvb_subtitle_pages.clear();
1462         m_subtitle_pages.clear();
1463         return 0;
1464 }
1465
1466 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1467 {
1468         ePtr<iDVBPVRChannel> pvr_channel;
1469         
1470         if (!m_decode_demux)
1471                 return -1;
1472         
1473         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1474                 return -1;
1475         
1476         int r = 0;
1477
1478                 /* if there is a decoder, use audio or video PTS */
1479         if (m_decoder)
1480         {
1481                 r = m_decoder->getPTS(0, pos);
1482                 if (r)
1483                         return r;
1484         }
1485         
1486                 /* fixup */
1487         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1488 }
1489
1490 RESULT eDVBServicePlay::setTrickmode(int trick)
1491 {
1492                 /* currently unimplemented */
1493         return -1;
1494 }
1495
1496 RESULT eDVBServicePlay::isCurrentlySeekable()
1497 {
1498         int ret = 0;
1499         if (m_decoder)
1500         {
1501                 ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible
1502                 if (m_decoder->getVideoProgressive() == -1)
1503                         ret &= ~2;
1504         }
1505         return ret;
1506 }
1507
1508 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1509 {
1510         ptr = this;
1511         return 0;
1512 }
1513
1514 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1515 {
1516         ptr = this;
1517         return 0;
1518 }
1519
1520 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1521 {
1522         ptr = this;
1523         return 0;
1524 }
1525
1526 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1527 {
1528         ptr = this;
1529         return 0;
1530 }
1531
1532 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1533 {
1534         ptr = this;
1535         return 0;
1536 }
1537
1538 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1539 {
1540         ptr = 0;
1541         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1542                 (m_timeshift_enabled || (!m_is_pvr&&!m_is_stream)))
1543         {
1544                 if (!m_timeshift_enabled)
1545                 {
1546                         /* query config path */
1547                         std::string tspath;
1548                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1549                                 eDebug("could not query ts path from config");
1550                                 return -4;
1551                         }
1552                         tspath.append("/");
1553                         /* we need enough diskspace */
1554                         struct statfs fs;
1555                         if (statfs(tspath.c_str(), &fs) < 0)
1556                         {
1557                                 eDebug("statfs failed!");
1558                                 return -2;
1559                         }
1560                 
1561                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1562                         {
1563                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1564                                 return -3;
1565                         }
1566                 }
1567                 ptr = this;
1568                 return 0;
1569         }
1570         return -1;
1571 }
1572
1573 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1574 {
1575         if (m_is_pvr)
1576         {
1577                 ptr = this;
1578                 return 0;
1579         }
1580         ptr = 0;
1581         return -1;
1582 }
1583
1584 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1585 {
1586         ptr = this;
1587         return 0;
1588 }
1589
1590 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1591 {
1592         ptr = this;
1593         return 0;
1594 }
1595
1596 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1597 {
1598         ptr = this;
1599         return 0;
1600 }
1601
1602 RESULT eDVBServicePlay::getName(std::string &name)
1603 {
1604         if (m_is_pvr)
1605         {
1606                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1607                 return i->getName(m_reference, name);
1608         }
1609         else if (m_is_stream)
1610         {
1611                 name = m_reference.name;
1612                 if (name.empty())
1613                 {
1614                         name = m_reference.path;
1615                 }
1616                 if (name.empty())
1617                 {
1618                         name = "(...)";
1619                 }
1620         }
1621         else if (m_dvb_service)
1622         {
1623                 m_dvb_service->getName(m_reference, name);
1624                 if (name.empty())
1625                         name = "(...)";
1626         }
1627         else if (!m_reference.name.empty())
1628                 eStaticServiceDVBInformation().getName(m_reference, name);
1629         else
1630                 name = "DVB service";
1631         return 0;
1632 }
1633
1634 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1635 {
1636         return m_event_handler.getEvent(evt, nownext);
1637 }
1638
1639 int eDVBServicePlay::getInfo(int w)
1640 {
1641         eDVBServicePMTHandler::program program;
1642
1643         if (w == sCAIDs || w == sCAIDPIDs)
1644                 return resIsPyObject;
1645
1646         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1647
1648         int no_program_info = 0;
1649
1650         if (h.getProgramInfo(program))
1651                 no_program_info = 1;
1652
1653         switch (w)
1654         {
1655         case sVideoHeight:
1656                 if (m_decoder)
1657                         return m_decoder->getVideoHeight();
1658                 break;
1659         case sVideoWidth:
1660                 if (m_decoder)
1661                         return m_decoder->getVideoWidth();
1662                 break;
1663         case sFrameRate:
1664                 if (m_decoder)
1665                         return m_decoder->getVideoFrameRate();
1666                 break;
1667         case sProgressive:
1668                 if (m_decoder)
1669                         return m_decoder->getVideoProgressive();
1670                 break;
1671         case sAspect:
1672         {
1673                 int aspect = -1;
1674                 if (m_decoder)
1675                         aspect = m_decoder->getVideoAspect();
1676                 if (aspect == -1 && no_program_info)
1677                         break;
1678                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1679                 {
1680                         ePtr<eServiceEvent> evt;
1681                         if (!m_event_handler.getEvent(evt, 0))
1682                         {
1683                                 ePtr<eComponentData> data;
1684                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1685                                 {
1686                                         if ( data->getStreamContent() == 1 )
1687                                         {
1688                                                 switch(data->getComponentType())
1689                                                 {
1690                                                         // SD
1691                                                         case 1: // 4:3 SD PAL
1692                                                         case 2:
1693                                                         case 3: // 16:9 SD PAL
1694                                                         case 4: // > 16:9 PAL
1695                                                         case 5: // 4:3 SD NTSC
1696                                                         case 6: 
1697                                                         case 7: // 16:9 SD NTSC
1698                                                         case 8: // > 16:9 NTSC
1699
1700                                                         // HD
1701                                                         case 9: // 4:3 HD PAL
1702                                                         case 0xA:
1703                                                         case 0xB: // 16:9 HD PAL
1704                                                         case 0xC: // > 16:9 HD PAL
1705                                                         case 0xD: // 4:3 HD NTSC
1706                                                         case 0xE:
1707                                                         case 0xF: // 16:9 HD NTSC
1708                                                         case 0x10: // > 16:9 HD PAL
1709                                                                 return data->getComponentType();
1710                                                 }
1711                                         }
1712                                 }
1713                         }
1714                 }
1715                 else
1716                         return aspect;
1717                 break;
1718         }
1719         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1720         case sVideoPID:
1721                 if (m_dvb_service)
1722                 {
1723                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1724                         if (vpid != -1)
1725                                 return vpid;
1726                 }
1727                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1728         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1729         case sAudioPID:
1730                 if (m_dvb_service)
1731                 {
1732                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1733                         if (apid != -1)
1734                                 return apid;
1735                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1736                         if (apid != -1)
1737                                 return apid;
1738                 }
1739                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1740         case sPCRPID:
1741                 if (m_dvb_service)
1742                 {
1743                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1744                         if (pcrpid != -1)
1745                                 return pcrpid;
1746                 }
1747                 if (no_program_info) return -1; return program.pcrPid;
1748         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1749         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1750         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1751         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1752         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1753         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1754         case sProvider: if (!m_dvb_service) return -1; return -2;
1755         case sServiceref: return resIsString;
1756         case sDVBState: return m_tune_state;
1757         default:
1758                 break;
1759         }
1760         return -1;
1761 }
1762
1763 std::string eDVBServicePlay::getInfoString(int w)
1764 {
1765         switch (w)
1766         {
1767         case sProvider:
1768                 if (!m_dvb_service) return "";
1769                 return m_dvb_service->m_provider_name;
1770         case sServiceref:
1771                 return m_reference.toString();
1772         case sHBBTVUrl:
1773         {
1774                 std::string url;
1775                 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1776                 h.getHBBTVUrl(url);
1777                 return url;
1778         }
1779         case sLiveStreamDemuxId:
1780         {
1781                 int id;
1782                 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1783                 h.getDemuxID(id);
1784
1785                 std::string demux;
1786                 demux += id + '0';
1787                 return demux;
1788         }
1789         default:
1790                 break;
1791         }
1792         return iServiceInformation::getInfoString(w);
1793 }
1794
1795 PyObject *eDVBServicePlay::getInfoObject(int w)
1796 {
1797         switch (w)
1798         {
1799         case sCAIDs:
1800                 return m_service_handler.getCaIds();
1801         case sCAIDPIDs:
1802                 return m_service_handler.getCaIds(true);
1803         case sTransponderData:
1804                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1805         case sHBBTVUrl:
1806         {
1807                 eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1808                 return h.getHbbTVApplications();
1809         }
1810         default:
1811                 break;
1812         }
1813         return iServiceInformation::getInfoObject(w);
1814 }
1815
1816 int eDVBServicePlay::getNumberOfTracks()
1817 {
1818         eDVBServicePMTHandler::program program;
1819         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1820         if (h.getProgramInfo(program))
1821                 return 0;
1822         return program.audioStreams.size();
1823 }
1824
1825 int eDVBServicePlay::getCurrentTrack()
1826 {
1827         eDVBServicePMTHandler::program program;
1828         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1829         if (h.getProgramInfo(program))
1830                 return 0;
1831
1832         int max = program.audioStreams.size();
1833         int i;
1834
1835         for (i = 0; i < max; ++i)
1836                 if (program.audioStreams[i].pid == m_current_audio_pid)
1837                         return i;
1838
1839         return 0;
1840 }
1841
1842 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1843 {
1844         int ret = selectAudioStream(i);
1845
1846         if (m_decoder->set())
1847                 return -5;
1848
1849         return ret;
1850 }
1851
1852 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1853 {
1854         eDVBServicePMTHandler::program program;
1855         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1856
1857         if (h.getProgramInfo(program))
1858                 return -1;
1859         
1860         if (i >= program.audioStreams.size())
1861                 return -2;
1862         
1863         info.m_pid = program.audioStreams[i].pid;
1864
1865         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1866                 info.m_description = "MPEG";
1867         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1868                 info.m_description = "Dolby Digital";
1869         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDDP)
1870                 info.m_description = "Dolby Digital+";
1871         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1872                 info.m_description = "AAC";
1873         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1874                 info.m_description = "AAC-HE";
1875         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1876                 info.m_description = "DTS";
1877         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD)
1878                 info.m_description = "DTS-HD";
1879         else
1880                 info.m_description = "???";
1881
1882         if (program.audioStreams[i].component_tag != -1)
1883         {
1884                 ePtr<eServiceEvent> evt;
1885                 if (!m_event_handler.getEvent(evt, 0))
1886                 {
1887                         ePtr<eComponentData> data;
1888                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1889                                 info.m_language = data->getText();
1890                 }
1891         }
1892
1893         if (info.m_language.empty())
1894                 info.m_language = program.audioStreams[i].language_code;
1895         
1896         return 0;
1897 }
1898
1899 int eDVBServicePlay::selectAudioStream(int i)
1900 {
1901         eDVBServicePMTHandler::program program;
1902         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1903         pts_t position = -1;
1904
1905         if (h.getProgramInfo(program))
1906                 return -1;
1907
1908         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1909                 return -2;
1910
1911         if (!m_decoder)
1912                 return -3;
1913
1914         int stream = i;
1915         if (stream == -1)
1916                 stream = program.defaultAudioStream;
1917
1918         int apid = -1, apidtype = -1;
1919
1920         if (((unsigned int)stream) < program.audioStreams.size())
1921         {
1922                 apid = program.audioStreams[stream].pid;
1923                 apidtype = program.audioStreams[stream].type;
1924         }
1925
1926         if (i != -1 && apid != m_current_audio_pid && (m_is_pvr || m_timeshift_active))
1927                 eDebug("getPlayPosition ret %d, pos %lld in selectAudioStream", getPlayPosition(position), position);
1928
1929         m_current_audio_pid = apid;
1930
1931         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1932         {
1933                 eDebug("set audio pid failed");
1934                 return -4;
1935         }
1936
1937         if (position != -1)
1938                 eDebug("seekTo ret %d", seekTo(position));
1939
1940         int rdsPid = apid;
1941
1942                 /* 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 */
1943         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1944         {
1945                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1946                 if (different_pid)
1947                         rdsPid = program.audioStreams[stream].rdsPid;
1948                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1949                 {
1950                         m_rds_decoder = 0;
1951                         ePtr<iDVBDemux> data_demux;
1952                         if (!h.getDataDemux(data_demux))
1953                         {
1954                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1955                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1956                                 m_rds_decoder->start(rdsPid);
1957                         }
1958                 }
1959         }
1960
1961                         /* store new pid as default only when:
1962                                 a.) we have an entry in the service db for the current service,
1963                                 b.) we are not playing back something,
1964                                 c.) we are not selecting the default entry. (we wouldn't change 
1965                                     anything in the best case, or destroy the default setting in
1966                                     case the real default is not yet available.)
1967                         */
1968         if (m_dvb_service && ((i != -1)
1969                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1970         {
1971                 if (apidtype == eDVBAudio::aMPEG)
1972                 {
1973                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1974                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1975                 }
1976                 else if (apidtype == eDVBAudio::aAC3)
1977                 {
1978                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1979                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1980                 }
1981                 else
1982                 {
1983                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1984                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1985                 }
1986         }
1987
1988         h.resetCachedProgram();
1989
1990         return 0;
1991 }
1992
1993 int eDVBServicePlay::getCurrentChannel()
1994 {
1995         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1996 }
1997
1998 RESULT eDVBServicePlay::selectChannel(int i)
1999 {
2000         if (i < LEFT || i > RIGHT || i == STEREO)
2001                 i = -1;  // Stereo
2002         if (m_dvb_service)
2003                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
2004         if (m_decoder)
2005                 m_decoder->setAudioChannel(i);
2006         return 0;
2007 }
2008
2009 std::string eDVBServicePlay::getText(int x)
2010 {
2011         if (m_rds_decoder)
2012                 switch(x)
2013                 {
2014                         case RadioText:
2015                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
2016                         case RtpText:
2017                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
2018                 }
2019         return "";
2020 }
2021
2022 void eDVBServicePlay::rdsDecoderEvent(int what)
2023 {
2024         switch(what)
2025         {
2026                 case eDVBRdsDecoder::RadioTextChanged:
2027                         m_event((iPlayableService*)this, evUpdatedRadioText);
2028                         break;
2029                 case eDVBRdsDecoder::RtpTextChanged:
2030                         m_event((iPlayableService*)this, evUpdatedRtpText);
2031                         break;
2032                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
2033                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
2034                         break;
2035                 case eDVBRdsDecoder::RecvRassSlidePic:
2036                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
2037                         break;
2038         }
2039 }
2040
2041 void eDVBServicePlay::showRassSlidePicture()
2042 {
2043         if (m_rds_decoder)
2044         {
2045                 if (m_decoder)
2046                 {
2047                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
2048                         if (rass_slide_pic.length())
2049                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
2050                         else
2051                                 eDebug("empty filename for rass slide picture received!!");
2052                 }
2053                 else
2054                         eDebug("no MPEG Decoder to show iframes avail");
2055         }
2056         else
2057                 eDebug("showRassSlidePicture called.. but not decoder");
2058 }
2059
2060 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
2061 {
2062         if (m_rds_decoder)
2063         {
2064                 if (m_decoder)
2065                 {
2066                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
2067                         if (rass_interactive_pic.length())
2068                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
2069                         else
2070                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
2071                 }
2072                 else
2073                         eDebug("no MPEG Decoder to show iframes avail");
2074         }
2075         else
2076                 eDebug("showRassInteractivePic called.. but not decoder");
2077 }
2078
2079 ePyObject eDVBServicePlay::getRassInteractiveMask()
2080 {
2081         if (m_rds_decoder)
2082                 return m_rds_decoder->getRassPictureMask();
2083         Py_RETURN_NONE;
2084 }
2085
2086 int eDVBServiceBase::getFrontendInfo(int w)
2087 {
2088         eUsePtr<iDVBChannel> channel;
2089         if(m_service_handler.getChannel(channel))
2090                 return 0;
2091         ePtr<iDVBFrontend> fe;
2092         if(channel->getFrontend(fe))
2093                 return 0;
2094         return fe->readFrontendData(w);
2095 }
2096
2097 PyObject *eDVBServiceBase::getFrontendData()
2098 {
2099         ePyObject ret = PyDict_New();
2100         if (ret)
2101         {
2102                 eUsePtr<iDVBChannel> channel;
2103                 if(!m_service_handler.getChannel(channel))
2104                 {
2105                         ePtr<iDVBFrontend> fe;
2106                         if(!channel->getFrontend(fe))
2107                                 fe->getFrontendData(ret);
2108                 }
2109         }
2110         else
2111                 Py_RETURN_NONE;
2112         return ret;
2113 }
2114
2115 PyObject *eDVBServiceBase::getFrontendStatus()
2116 {
2117         ePyObject ret = PyDict_New();
2118         if (ret)
2119         {
2120                 eUsePtr<iDVBChannel> channel;
2121                 if(!m_service_handler.getChannel(channel))
2122                 {
2123                         ePtr<iDVBFrontend> fe;
2124                         if(!channel->getFrontend(fe))
2125                                 fe->getFrontendStatus(ret);
2126                 }
2127         }
2128         else
2129                 Py_RETURN_NONE;
2130         return ret;
2131 }
2132
2133 PyObject *eDVBServiceBase::getTransponderData(bool original)
2134 {
2135         ePyObject ret = PyDict_New();
2136         if (ret)
2137         {
2138                 eUsePtr<iDVBChannel> channel;
2139                 if(!m_service_handler.getChannel(channel))
2140                 {
2141                         ePtr<iDVBFrontend> fe;
2142                         if(!channel->getFrontend(fe))
2143                                 fe->getTransponderData(ret, original);
2144                 }
2145         }
2146         else
2147                 Py_RETURN_NONE;
2148         return ret;
2149 }
2150
2151 PyObject *eDVBServiceBase::getAll(bool original)
2152 {
2153         ePyObject ret = getTransponderData(original);
2154         if (ret != Py_None)
2155         {
2156                 eUsePtr<iDVBChannel> channel;
2157                 if(!m_service_handler.getChannel(channel))
2158                 {
2159                         ePtr<iDVBFrontend> fe;
2160                         if(!channel->getFrontend(fe))
2161                         {
2162                                 fe->getFrontendData(ret);
2163                                 fe->getFrontendStatus(ret);
2164                         }
2165                 }
2166         }
2167         return ret;
2168 }
2169
2170 int eDVBServicePlay::getNumberOfSubservices()
2171 {
2172         ePtr<eServiceEvent> evt;
2173         if (!m_event_handler.getEvent(evt, 0))
2174                 return evt->getNumOfLinkageServices();
2175         return 0;
2176 }
2177
2178 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2179 {
2180         ePtr<eServiceEvent> evt;
2181         if (!m_event_handler.getEvent(evt, 0))
2182         {
2183                 if (!evt->getLinkageService(sub, m_reference, n))
2184                         return 0;
2185         }
2186         sub.type=eServiceReference::idInvalid;
2187         return -1;
2188 }
2189
2190 RESULT eDVBServicePlay::startTimeshift()
2191 {
2192         ePtr<iDVBDemux> demux;
2193         
2194         eDebug("Start timeshift!");
2195         
2196         if (m_timeshift_enabled)
2197                 return -1;
2198         
2199                 /* start recording with the data demux. */
2200         if (m_service_handler.getDataDemux(demux))
2201                 return -2;
2202
2203         demux->createTSRecorder(m_record);
2204         if (!m_record)
2205                 return -3;
2206
2207         std::string tspath;
2208         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2209                 eDebug("could not query ts path");
2210                 return -5;
2211         }
2212         tspath.append("/timeshift.XXXXXX");
2213         char* templ;
2214         templ = new char[tspath.length() + 1];
2215         strcpy(templ, tspath.c_str());
2216
2217         m_timeshift_fd = mkstemp(templ);
2218         m_timeshift_file = std::string(templ);
2219
2220         eDebug("recording to %s", templ);
2221
2222         delete [] templ;
2223
2224         if (m_timeshift_fd < 0)
2225         {
2226                 m_record = 0;
2227                 return -4;
2228         }
2229                 
2230         m_record->setTargetFD(m_timeshift_fd);
2231         m_record->setTargetFilename(m_timeshift_file.c_str());
2232         m_record->enableAccessPoints(false);
2233
2234         m_timeshift_enabled = 1;
2235         
2236         updateTimeshiftPids();
2237         m_record->start();
2238
2239         return 0;
2240 }
2241
2242 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2243 {
2244         if (!m_timeshift_enabled)
2245                 return -1;
2246         
2247         if (swToLive)
2248                 switchToLive();
2249         
2250         m_timeshift_enabled = 0;
2251         
2252         m_record->stop();
2253         m_record = 0;
2254         
2255         close(m_timeshift_fd);
2256         eDebug("remove timeshift file");
2257         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2258
2259         {
2260                 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2261                 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2262         }
2263         
2264         return 0;
2265 }
2266
2267 int eDVBServicePlay::isTimeshiftActive()
2268 {
2269         return m_timeshift_enabled && m_timeshift_active;
2270 }
2271
2272 RESULT eDVBServicePlay::activateTimeshift()
2273 {
2274         if (!m_timeshift_enabled)
2275                 return -1;
2276         
2277         if (!m_timeshift_active)
2278         {
2279                 switchToTimeshift();
2280                 return 0;
2281         }
2282         
2283         return -2;
2284 }
2285
2286 PyObject *eDVBServicePlay::getCutList()
2287 {
2288         ePyObject list = PyList_New(0);
2289         
2290         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2291         {
2292                 ePyObject tuple = PyTuple_New(2);
2293                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2294                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2295                 PyList_Append(list, tuple);
2296                 Py_DECREF(tuple);
2297         }
2298         
2299         return list;
2300 }
2301
2302 void eDVBServicePlay::setCutList(ePyObject list)
2303 {
2304         if (!PyList_Check(list))
2305                 return;
2306         int size = PyList_Size(list);
2307         int i;
2308         
2309         m_cue_entries.clear();
2310         
2311         for (i=0; i<size; ++i)
2312         {
2313                 ePyObject tuple = PyList_GET_ITEM(list, i);
2314                 if (!PyTuple_Check(tuple))
2315                 {
2316                         eDebug("non-tuple in cutlist");
2317                         continue;
2318                 }
2319                 if (PyTuple_Size(tuple) != 2)
2320                 {
2321                         eDebug("cutlist entries need to be a 2-tuple");
2322                         continue;
2323                 }
2324                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2325                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2326                 {
2327                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2328                         continue;
2329                 }
2330                 pts_t pts = PyLong_AsLongLong(ppts);
2331                 int type = PyInt_AsLong(ptype);
2332                 m_cue_entries.insert(cueEntry(pts, type));
2333                 eDebug("adding %08llx, %d", pts, type);
2334         }
2335         m_cuesheet_changed = 1;
2336         
2337         cutlistToCuesheet();
2338         m_event((iPlayableService*)this, evCuesheetChanged);
2339 }
2340
2341 void eDVBServicePlay::setCutListEnable(int enable)
2342 {
2343         m_cutlist_enabled = enable;
2344         cutlistToCuesheet();
2345 }
2346
2347 void eDVBServicePlay::updateTimeshiftPids()
2348 {
2349         if (!m_record)
2350                 return;
2351         
2352         eDVBServicePMTHandler::program program;
2353         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2354
2355         if (h.getProgramInfo(program))
2356                 return;
2357         else
2358         {
2359                 int timing_pid = -1;
2360                 int timing_pid_type = -1;
2361                 std::set<int> pids_to_record;
2362                 pids_to_record.insert(0); // PAT
2363                 if (program.pmtPid != -1)
2364                         pids_to_record.insert(program.pmtPid); // PMT
2365
2366                 if (program.textPid != -1)
2367                         pids_to_record.insert(program.textPid); // Videotext
2368
2369                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2370                         i(program.videoStreams.begin()); 
2371                         i != program.videoStreams.end(); ++i)
2372                 {
2373                         pids_to_record.insert(i->pid);
2374
2375                         if (timing_pid == -1)
2376                         {
2377                                 timing_pid = i->pid;
2378                                 timing_pid_type = i->type;
2379                         }
2380                 }
2381
2382                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2383                         i(program.audioStreams.begin()); 
2384                         i != program.audioStreams.end(); ++i)
2385                 {
2386                         pids_to_record.insert(i->pid);
2387
2388                         if (timing_pid == -1)
2389                         {
2390                                 timing_pid = i->pid;
2391                                 timing_pid_type = -1;
2392                         }
2393                 }
2394
2395                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2396                         i(program.subtitleStreams.begin());
2397                         i != program.subtitleStreams.end(); ++i)
2398                                 pids_to_record.insert(i->pid);
2399
2400                 std::set<int> new_pids, obsolete_pids;
2401                 
2402                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2403                                 m_pids_active.begin(), m_pids_active.end(),
2404                                 std::inserter(new_pids, new_pids.begin()));
2405                 
2406                 std::set_difference(
2407                                 m_pids_active.begin(), m_pids_active.end(),
2408                                 pids_to_record.begin(), pids_to_record.end(), 
2409                                 std::inserter(new_pids, new_pids.begin())
2410                                 );
2411
2412                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2413                         m_record->addPID(*i);
2414
2415                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2416                         m_record->removePID(*i);
2417
2418                 if (timing_pid != -1)
2419                         m_record->setTimingPID(timing_pid, timing_pid_type);
2420         }
2421 }
2422
2423 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2424 {
2425         m_timeshift_file_next = f;
2426         return 0;
2427 }
2428
2429 void eDVBServicePlay::switchToLive()
2430 {
2431         if (!m_timeshift_active)
2432                 return;
2433
2434         eDebug("SwitchToLive");
2435
2436         resetTimeshift(0);
2437
2438         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2439
2440         /* free the timeshift service handler, we need the resources */
2441         m_service_handler_timeshift.free();
2442
2443         updateDecoder(true);
2444 }
2445
2446 void eDVBServicePlay::resetTimeshift(int start)
2447 {
2448         m_cue = 0;
2449         m_decode_demux = 0;
2450         m_decoder = 0;
2451         m_teletext_parser = 0;
2452         m_rds_decoder = 0;
2453         m_subtitle_parser = 0;
2454         m_new_subtitle_page_connection = 0;
2455         m_new_dvb_subtitle_page_connection = 0;
2456         m_rds_decoder_event_connection = 0;
2457         m_video_event_connection = 0;
2458         m_timeshift_changed = 1;
2459         m_timeshift_file_next.clear();
2460
2461         if (start)
2462         {
2463                 m_cue = new eCueSheet();
2464                 m_timeshift_active = 1;
2465         }
2466         else
2467                 m_timeshift_active = 0;
2468 }
2469
2470 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2471 {
2472         if (m_is_stream)
2473         {
2474                 eHttpStream *f = new eHttpStream();
2475                 f->open(ref.path.c_str());
2476                 return ePtr<iTsSource>(f);
2477         }
2478         else
2479         {
2480                 eRawFile *f = new eRawFile();
2481                 f->open(ref.path.c_str());
2482                 return ePtr<iTsSource>(f);
2483         }
2484 }
2485
2486 void eDVBServicePlay::switchToTimeshift()
2487 {
2488         if (m_timeshift_active)
2489                 return;
2490
2491         resetTimeshift(1);
2492
2493         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2494         r.path = m_timeshift_file;
2495
2496         m_cue->seekTo(0, -1000);
2497
2498         ePtr<iTsSource> source = createTsSource(r);
2499         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 */
2500
2501         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2502         pause();
2503         updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2504 }
2505
2506 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2507 {
2508         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2509         bool mustPlay = false;
2510
2511         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2512
2513         eDVBServicePMTHandler::program program;
2514         if (h.getProgramInfo(program))
2515                 eDebug("getting program info failed.");
2516         else
2517         {
2518                 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2519                 if (!program.videoStreams.empty())
2520                 {
2521                         eDebugNoNewLine(" (");
2522                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2523                                 i(program.videoStreams.begin());
2524                                 i != program.videoStreams.end(); ++i)
2525                         {
2526                                 if (vpid == -1)
2527                                 {
2528                                         vpid = i->pid;
2529                                         vpidtype = i->type;
2530                                 }
2531                                 if (i != program.videoStreams.begin())
2532                                         eDebugNoNewLine(", ");
2533                                 eDebugNoNewLine("%04x", i->pid);
2534                         }
2535                         eDebugNoNewLine(")");
2536                 }
2537                 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2538                 if (!program.audioStreams.empty())
2539                 {
2540                         eDebugNoNewLine(" (");
2541                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2542                                 i(program.audioStreams.begin());
2543                                 i != program.audioStreams.end(); ++i)
2544                         {
2545                                 if (i != program.audioStreams.begin())
2546                                         eDebugNoNewLine(", ");
2547                                 eDebugNoNewLine("%04x", i->pid);
2548                         }
2549                         eDebugNoNewLine(")");
2550                 }
2551                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2552                 pcrpid = program.pcrPid;
2553                 eDebug(", and the text pid is %04x", program.textPid);
2554                 tpid = program.textPid;
2555         }
2556
2557         if (!m_decoder)
2558         {
2559                 h.getDecodeDemux(m_decode_demux);
2560                 if (m_decode_demux)
2561                 {
2562                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2563                         if (m_decoder)
2564                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2565                         if (m_is_primary)
2566                         {
2567                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2568                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2569                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2570                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2571                                 if (m_timeshift_changed)
2572                                 {
2573                                         ePyObject subs = getCachedSubtitle();
2574                                         if (subs != Py_None)
2575                                         {
2576                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2577                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2578                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2579                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2580                                                 if (type == 0) // dvb
2581                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2582                                                 else if (type == 1) // ttx
2583                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2584                                         }
2585                                         Py_DECREF(subs);
2586                                 }
2587                         }
2588                 }
2589                 if (m_cue)
2590                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2591                 mustPlay = true;
2592         }
2593
2594         m_timeshift_changed = 0;
2595
2596         if (m_decoder)
2597         {
2598                 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2599                 if (m_dvb_service)
2600                 {
2601                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2602                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2603                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2604                 }
2605                 else // subservice
2606                 {
2607                         eServiceReferenceDVB ref;
2608                         m_service_handler.getServiceReference(ref);
2609                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2610                         if (!parent)
2611                                 parent = ref;
2612                         if (parent)
2613                         {
2614                                 ePtr<eDVBResourceManager> res_mgr;
2615                                 if (!eDVBResourceManager::getInstance(res_mgr))
2616                                 {
2617                                         ePtr<iDVBChannelList> db;
2618                                         if (!res_mgr->getChannelList(db))
2619                                         {
2620                                                 ePtr<eDVBService> origService;
2621                                                 if (!db->getService(parent, origService))
2622                                                 {
2623                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2624                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2625                                                 }
2626                                         }
2627                                 }
2628                         }
2629                 }
2630
2631                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2632                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2633
2634                 m_decoder->setVideoPID(vpid, vpidtype);
2635                 m_current_video_pid_type = vpidtype;
2636                 selectAudioStream();
2637
2638                 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2639                 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2640                         m_decoder->setSyncPCR(pcrpid);
2641                 else
2642                         m_decoder->setSyncPCR(-1);
2643
2644                 if (m_is_primary)
2645                 {
2646                         m_decoder->setTextPID(tpid);
2647                         m_teletext_parser->start(program.textPid);
2648                 }
2649
2650                 if (vpid > 0 && vpid < 0x2000)
2651                         ;
2652                 else
2653                 {
2654                         std::string radio_pic;
2655                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2656                                 m_decoder->setRadioPic(radio_pic);
2657                 }
2658
2659                 if (mustPlay)
2660                         m_decoder->play();
2661                 else
2662                         m_decoder->set();
2663
2664                 m_decoder->setAudioChannel(achannel);
2665
2666                 /* don't worry about non-existing services, nor pvr services */
2667                 if (m_dvb_service)
2668                 {
2669                                 /* (audio pid will be set in selectAudioTrack */
2670                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2671                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2672                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2673                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2674                 }
2675                 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2676                         sendSeekableStateChanged = true;
2677         }
2678         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2679
2680         if (sendSeekableStateChanged)
2681                 m_event((iPlayableService*)this, evSeekableStatusChanged);
2682 }
2683
2684 void eDVBServicePlay::loadCuesheet()
2685 {
2686         std::string filename = m_reference.path + ".cuts";
2687         
2688         m_cue_entries.clear();
2689
2690         FILE *f = fopen(filename.c_str(), "rb");
2691
2692         if (f)
2693         {
2694                 eDebug("loading cuts..");
2695                 while (1)
2696                 {
2697                         unsigned long long where;
2698                         unsigned int what;
2699                         
2700                         if (!fread(&where, sizeof(where), 1, f))
2701                                 break;
2702                         if (!fread(&what, sizeof(what), 1, f))
2703                                 break;
2704                         
2705 #if BYTE_ORDER == LITTLE_ENDIAN
2706                         where = bswap_64(where);
2707 #endif
2708                         what = ntohl(what);
2709                         
2710                         if (what > 3)
2711                                 break;
2712                         
2713                         m_cue_entries.insert(cueEntry(where, what));
2714                 }
2715                 fclose(f);
2716                 eDebug("%zd entries", m_cue_entries.size());
2717         } else
2718                 eDebug("cutfile not found!");
2719         
2720         m_cuesheet_changed = 0;
2721         cutlistToCuesheet();
2722         m_event((iPlayableService*)this, evCuesheetChanged);
2723 }
2724
2725 void eDVBServicePlay::saveCuesheet()
2726 {
2727         std::string filename = m_reference.path + ".cuts";
2728         
2729         FILE *f = fopen(filename.c_str(), "wb");
2730
2731         if (f)
2732         {
2733                 unsigned long long where;
2734                 int what;
2735
2736                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2737                 {
2738 #if BYTE_ORDER == BIG_ENDIAN
2739                         where = i->where;
2740 #else
2741                         where = bswap_64(i->where);
2742 #endif
2743                         what = htonl(i->what);
2744                         fwrite(&where, sizeof(where), 1, f);
2745                         fwrite(&what, sizeof(what), 1, f);
2746                         
2747                 }
2748                 fclose(f);
2749         }
2750         
2751         m_cuesheet_changed = 0;
2752 }
2753
2754 void eDVBServicePlay::cutlistToCuesheet()
2755 {
2756         if (!m_cue)
2757         {
2758                 eDebug("no cue sheet");
2759                 return;
2760         }       
2761         m_cue->clear();
2762         
2763         if (!m_cutlist_enabled)
2764         {
2765                 m_cue->commitSpans();
2766                 eDebug("cutlists were disabled");
2767                 return;
2768         }
2769
2770         pts_t in = 0, out = 0, length = 0;
2771         
2772         getLength(length);
2773                 
2774         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2775         
2776         int have_any_span = 0;
2777         
2778         while (1)
2779         {
2780                 if (i == m_cue_entries.end())
2781                 {
2782                         if (!have_any_span && !in)
2783                                 break;
2784                         out = length;
2785                 } else {
2786                         if (i->what == 0) /* in */
2787                         {
2788                                 in = i++->where;
2789                                 continue;
2790                         } else if (i->what == 1) /* out */
2791                                 out = i++->where;
2792                         else /* mark (2) or last play position (3) */
2793                         {
2794                                 i++;
2795                                 continue;
2796                         }
2797                 }
2798                 
2799                 if (in < 0)
2800                         in = 0;
2801                 if (out < 0)
2802                         out = 0;
2803                 if (in > length)
2804                         in = length;
2805                 if (out > length)
2806                         out = length;
2807                 
2808                 if (in < out)
2809                 {
2810                         have_any_span = 1;
2811                         m_cue->addSourceSpan(in, out);
2812                         in = out = 0;
2813                 }
2814                 
2815                 in = length;
2816                 
2817                 if (i == m_cue_entries.end())
2818                         break;
2819         }
2820         m_cue->commitSpans();
2821 }
2822
2823 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2824 {
2825         if (m_subtitle_widget)
2826                 disableSubtitles(parent);
2827
2828         ePyObject entry;
2829         int tuplesize = PyTuple_Size(tuple);
2830         int type = 0;
2831
2832         if (!PyTuple_Check(tuple))
2833                 goto error_out;
2834
2835         if (tuplesize < 1)
2836                 goto error_out;
2837
2838         entry = PyTuple_GET_ITEM(tuple, 0);
2839
2840         if (!PyInt_Check(entry))
2841                 goto error_out;
2842
2843         type = PyInt_AsLong(entry);
2844
2845         if (type == 1)  // teletext subtitles
2846         {
2847                 int page, magazine, pid;
2848                 if (tuplesize < 4)
2849                         goto error_out;
2850
2851                 if (!m_teletext_parser)
2852                 {
2853                         eDebug("enable teletext subtitles.. no parser !!!");
2854                         return -1;
2855                 }
2856
2857                 entry = PyTuple_GET_ITEM(tuple, 1);
2858                 if (!PyInt_Check(entry))
2859                         goto error_out;
2860                 pid = PyInt_AsLong(entry);
2861
2862                 entry = PyTuple_GET_ITEM(tuple, 2);
2863                 if (!PyInt_Check(entry))
2864                         goto error_out;
2865                 page = PyInt_AsLong(entry);
2866
2867                 entry = PyTuple_GET_ITEM(tuple, 3);
2868                 if (!PyInt_Check(entry))
2869                         goto error_out;
2870                 magazine = PyInt_AsLong(entry);
2871
2872                 m_subtitle_widget = new eSubtitleWidget(parent);
2873                 m_subtitle_widget->resize(parent->size()); /* full size */
2874                 m_teletext_parser->setPageAndMagazine(page, magazine);
2875                 if (m_dvb_service)
2876                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2877         }
2878         else if (type == 0)
2879         {
2880                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2881                 if (!m_subtitle_parser)
2882                 {
2883                         eDebug("enable dvb subtitles.. no parser !!!");
2884                         return -1;
2885                 }
2886                 if (tuplesize < 4)
2887                         goto error_out;
2888
2889                 entry = PyTuple_GET_ITEM(tuple, 1);
2890                 if (!PyInt_Check(entry))
2891                         goto error_out;
2892                 pid = PyInt_AsLong(entry);
2893
2894                 entry = PyTuple_GET_ITEM(tuple, 2);
2895                 if (!PyInt_Check(entry))
2896                         goto error_out;
2897                 composition_page_id = PyInt_AsLong(entry);
2898
2899                 entry = PyTuple_GET_ITEM(tuple, 3);
2900                 if (!PyInt_Check(entry))
2901                         goto error_out;
2902                 ancillary_page_id = PyInt_AsLong(entry);
2903
2904                 m_subtitle_widget = new eSubtitleWidget(parent);
2905                 m_subtitle_widget->resize(parent->size()); /* full size */
2906                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2907                 if (m_dvb_service)
2908                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2909         }
2910         else
2911                 goto error_out;
2912         return 0;
2913 error_out:
2914         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2915                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2916                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2917         return -1;
2918 }
2919
2920 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2921 {
2922         delete m_subtitle_widget;
2923         m_subtitle_widget = 0;
2924         if (m_subtitle_parser)
2925         {
2926                 m_subtitle_parser->stop();
2927                 m_dvb_subtitle_pages.clear();
2928         }
2929         if (m_teletext_parser)
2930         {
2931                 m_teletext_parser->setPageAndMagazine(-1, -1);
2932                 m_subtitle_pages.clear();
2933         }
2934         if (m_dvb_service)
2935                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2936         return 0;
2937 }
2938
2939 PyObject *eDVBServicePlay::getCachedSubtitle()
2940 {
2941         if (m_dvb_service)
2942         {
2943                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2944                 if (tmp != -1)
2945                 {
2946                         unsigned int data = (unsigned int)tmp;
2947                         int pid = (data&0xFFFF0000)>>16;
2948                         ePyObject tuple = PyTuple_New(4);
2949                         eDVBServicePMTHandler::program program;
2950                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2951                         if (!h.getProgramInfo(program))
2952                         {
2953                                 if (program.textPid==pid) // teletext
2954                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2955                                 else
2956                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2957                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2958                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2959                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2960                                 return tuple;
2961                         }
2962                 }
2963         }
2964         Py_RETURN_NONE;
2965 }
2966
2967 PyObject *eDVBServicePlay::getSubtitleList()
2968 {
2969         if (!m_teletext_parser)
2970                 Py_RETURN_NONE;
2971         
2972         ePyObject l = PyList_New(0);
2973         std::set<int> added_ttx_pages;
2974
2975         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2976                 m_teletext_parser->m_found_subtitle_pages;
2977
2978         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2979         eDVBServicePMTHandler::program program;
2980         if (h.getProgramInfo(program))
2981                 eDebug("getting program info failed.");
2982         else
2983         {
2984                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2985                         it != program.subtitleStreams.end(); ++it)
2986                 {
2987                         switch(it->subtitling_type)
2988                         {
2989                                 case 0x01: // ebu teletext subtitles
2990                                 {
2991                                         int page_number = it->teletext_page_number & 0xFF;
2992                                         int magazine_number = it->teletext_magazine_number & 7;
2993                                         int hash = magazine_number << 8 | page_number;
2994                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2995                                         {
2996                                                 ePyObject tuple = PyTuple_New(5);
2997                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2998                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2999                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3000                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3001                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3002                                                 PyList_Append(l, tuple);
3003                                                 Py_DECREF(tuple);
3004                                                 added_ttx_pages.insert(hash);
3005                                         }
3006                                         break;
3007                                 }
3008                                 case 0x10 ... 0x13:
3009                                 case 0x20 ... 0x23: // dvb subtitles
3010                                 {
3011                                         ePyObject tuple = PyTuple_New(5);
3012                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3013                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3014                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3015                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3016                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3017                                         PyList_Insert(l, 0, tuple);
3018                                         Py_DECREF(tuple);
3019                                         break;
3020                                 }
3021                         }
3022                 }
3023         }
3024
3025         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3026                 it != subs.end(); ++it)
3027         {
3028                 int page_number = it->teletext_page_number & 0xFF;
3029                 int magazine_number = it->teletext_magazine_number & 7;
3030                 int hash = magazine_number << 8 | page_number;
3031                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3032                 {
3033                         ePyObject tuple = PyTuple_New(5);
3034                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3035                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3036                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3037                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3038                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
3039                         PyList_Append(l, tuple);
3040                         Py_DECREF(tuple);
3041                 }
3042         }
3043
3044         return l;
3045 }
3046
3047 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3048 {
3049         if (m_subtitle_widget)
3050         {
3051                 pts_t pos = 0;
3052                 if (m_decoder)
3053                         m_decoder->getPTS(0, pos);
3054                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3055                 m_subtitle_pages.push_back(page);
3056                 checkSubtitleTiming();
3057         }
3058 }
3059
3060 void eDVBServicePlay::checkSubtitleTiming()
3061 {
3062         eDebug("checkSubtitleTiming");
3063         if (!m_subtitle_widget)
3064                 return;
3065         while (1)
3066         {
3067                 enum { TELETEXT, DVB } type;
3068                 eDVBTeletextSubtitlePage page;
3069                 eDVBSubtitlePage dvb_page;
3070                 pts_t show_time;
3071                 if (!m_subtitle_pages.empty())
3072                 {
3073                         page = m_subtitle_pages.front();
3074                         type = TELETEXT;
3075                         show_time = page.m_pts;
3076                 }
3077                 else if (!m_dvb_subtitle_pages.empty())
3078                 {
3079                         dvb_page = m_dvb_subtitle_pages.front();
3080                         type = DVB;
3081                         show_time = dvb_page.m_show_time;
3082                 }
3083                 else
3084                         return;
3085         
3086                 pts_t pos = 0;
3087         
3088                 if (m_decoder)
3089                         m_decoder->getPTS(0, pos);
3090
3091                 eDebug("%lld %lld", pos, show_time);
3092                 int diff = show_time - pos;
3093                 if (type == TELETEXT && !page.m_have_pts)
3094                 {
3095                         eDebug("ttx subtitle page without pts... immediate show");
3096                         diff = 0;
3097                 }
3098                 if (diff < 0)
3099                 {
3100                         eDebug("[late (%d ms)]", -diff / 90);
3101                         diff = 0;
3102                 }
3103                 if (abs(diff) > 1800000)
3104                 {
3105                         eDebug("[invalid]... immediate show!");
3106                         diff = 0;
3107                 }
3108                 if ((diff/90)<20)
3109                 {
3110                         if (type == TELETEXT)
3111                         {
3112                                 eDebug("display teletext subtitle page %lld", show_time);
3113                                 m_subtitle_widget->setPage(page);
3114                                 m_subtitle_pages.pop_front();
3115                         }
3116                         else
3117                         {
3118                                 eDebug("display dvb subtitle Page %lld", show_time);
3119                                 m_subtitle_widget->setPage(dvb_page);
3120                                 m_dvb_subtitle_pages.pop_front();
3121                         }
3122                 } else
3123                 {
3124                         eDebug("start subtitle delay %d", diff / 90);
3125                         m_subtitle_sync_timer->start(diff / 90, 1);
3126                         break;
3127                 }
3128         }
3129 }
3130
3131 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3132 {
3133         if (m_subtitle_widget)
3134         {
3135                 pts_t pos = 0;
3136                 if (m_decoder)
3137                         m_decoder->getPTS(0, pos);
3138                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3139                 m_dvb_subtitle_pages.push_back(p);
3140                 checkSubtitleTiming();
3141         }
3142 }
3143
3144 int eDVBServicePlay::getAC3Delay()
3145 {
3146         if (m_dvb_service)
3147                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3148         else if (m_decoder)
3149                 return m_decoder->getAC3Delay();
3150         else
3151                 return 0;
3152 }
3153
3154 int eDVBServicePlay::getPCMDelay()
3155 {
3156         if (m_dvb_service)
3157                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3158         else if (m_decoder)
3159                 return m_decoder->getPCMDelay();
3160         else
3161                 return 0;
3162 }
3163
3164 void eDVBServicePlay::setAC3Delay(int delay)
3165 {
3166         if (m_dvb_service)
3167                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3168         if (m_decoder) {
3169                 std::string config_delay;
3170                 int config_delay_int = 0;
3171                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3172                         config_delay_int = atoi(config_delay.c_str());
3173                 m_decoder->setAC3Delay(delay + config_delay_int);
3174         }
3175 }
3176
3177 void eDVBServicePlay::setPCMDelay(int delay)
3178 {
3179         if (m_dvb_service)
3180                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3181         if (m_decoder) {
3182                 std::string config_delay;
3183                 int config_delay_int = 0;
3184                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3185                         config_delay_int = atoi(config_delay.c_str());
3186                 else
3187                         config_delay_int = 0;
3188                 m_decoder->setPCMDelay(delay + config_delay_int);
3189         }
3190 }
3191
3192 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3193 {
3194         switch(event.type) {
3195                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3196                         m_event((iPlayableService*)this, evVideoSizeChanged);
3197                         break;
3198                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3199                         m_event((iPlayableService*)this, evVideoFramerateChanged);
3200                         break;
3201                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3202                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
3203                         break;
3204                 default:
3205                         break;
3206         }
3207 }
3208
3209 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3210 {
3211         ptr = this;
3212         return 0;
3213 }
3214
3215 PyObject *eDVBServicePlay::getStreamingData()
3216 {
3217         eDVBServicePMTHandler::program program;
3218         if (m_service_handler.getProgramInfo(program))
3219         {
3220                 Py_RETURN_NONE;
3221         }
3222
3223         ePyObject r = program.createPythonObject();
3224         ePtr<iDVBDemux> demux;
3225         if (!m_service_handler.getDataDemux(demux))
3226         {
3227                 uint8_t demux_id;
3228                 if (!demux->getCADemuxID(demux_id))
3229                         PutToDict(r, "demux", demux_id);
3230         }
3231
3232         return r;
3233 }
3234
3235
3236 DEFINE_REF(eDVBServicePlay)
3237
3238 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3239 {
3240         switch (w)
3241         {
3242         case iServiceInformation::sTransponderData:
3243                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3244         default:
3245                 break;
3246         }
3247         return iStaticServiceInformation::getInfoObject(ref, w);
3248 }
3249
3250 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");