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