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