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