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