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