Limit filesize for Timeshift on eMMC (<2GBytes)
[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
2251         m_timeshift_enabled = 1;
2252         
2253         updateTimeshiftPids();
2254         m_record->start();
2255
2256         return 0;
2257 }
2258
2259 RESULT eDVBServicePlay::stopTimeshift(bool swToLive)
2260 {
2261         if (!m_timeshift_enabled)
2262                 return -1;
2263         
2264         if (swToLive)
2265                 switchToLive();
2266         
2267         m_timeshift_enabled = 0;
2268         
2269         m_record->stop();
2270         m_record = 0;
2271         
2272         close(m_timeshift_fd);
2273         eDebug("remove timeshift file");
2274         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2275
2276         {
2277                 std::string timeshift_file_sc = m_timeshift_file + ".sc";
2278                 eBackgroundFileEraser::getInstance()->erase(timeshift_file_sc.c_str());
2279         }
2280         
2281         return 0;
2282 }
2283
2284 int eDVBServicePlay::isTimeshiftActive()
2285 {
2286         return m_timeshift_enabled && m_timeshift_active;
2287 }
2288
2289 RESULT eDVBServicePlay::activateTimeshift()
2290 {
2291         if (!m_timeshift_enabled)
2292                 return -1;
2293         
2294         if (!m_timeshift_active)
2295         {
2296                 switchToTimeshift();
2297                 return 0;
2298         }
2299         
2300         return -2;
2301 }
2302
2303 PyObject *eDVBServicePlay::getCutList()
2304 {
2305         ePyObject list = PyList_New(0);
2306         
2307         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2308         {
2309                 ePyObject tuple = PyTuple_New(2);
2310                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2311                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2312                 PyList_Append(list, tuple);
2313                 Py_DECREF(tuple);
2314         }
2315         
2316         return list;
2317 }
2318
2319 void eDVBServicePlay::setCutList(ePyObject list)
2320 {
2321         if (!PyList_Check(list))
2322                 return;
2323         int size = PyList_Size(list);
2324         int i;
2325         
2326         m_cue_entries.clear();
2327         
2328         for (i=0; i<size; ++i)
2329         {
2330                 ePyObject tuple = PyList_GET_ITEM(list, i);
2331                 if (!PyTuple_Check(tuple))
2332                 {
2333                         eDebug("non-tuple in cutlist");
2334                         continue;
2335                 }
2336                 if (PyTuple_Size(tuple) != 2)
2337                 {
2338                         eDebug("cutlist entries need to be a 2-tuple");
2339                         continue;
2340                 }
2341                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2342                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2343                 {
2344                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2345                         continue;
2346                 }
2347                 pts_t pts = PyLong_AsLongLong(ppts);
2348                 int type = PyInt_AsLong(ptype);
2349                 m_cue_entries.insert(cueEntry(pts, type));
2350                 eDebug("adding %08llx, %d", pts, type);
2351         }
2352         m_cuesheet_changed = 1;
2353         
2354         cutlistToCuesheet();
2355         m_event((iPlayableService*)this, evCuesheetChanged);
2356 }
2357
2358 void eDVBServicePlay::setCutListEnable(int enable)
2359 {
2360         m_cutlist_enabled = enable;
2361         cutlistToCuesheet();
2362 }
2363
2364 void eDVBServicePlay::updateTimeshiftPids()
2365 {
2366         if (!m_record)
2367                 return;
2368         
2369         eDVBServicePMTHandler::program program;
2370         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2371
2372         if (h.getProgramInfo(program))
2373                 return;
2374         else
2375         {
2376                 int timing_pid = -1;
2377                 int timing_pid_type = -1;
2378                 std::set<int> pids_to_record;
2379                 pids_to_record.insert(0); // PAT
2380                 if (program.pmtPid != -1)
2381                         pids_to_record.insert(program.pmtPid); // PMT
2382
2383                 if (program.textPid != -1)
2384                         pids_to_record.insert(program.textPid); // Videotext
2385
2386                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2387                         i(program.videoStreams.begin()); 
2388                         i != program.videoStreams.end(); ++i)
2389                 {
2390                         pids_to_record.insert(i->pid);
2391
2392                         if (timing_pid == -1)
2393                         {
2394                                 timing_pid = i->pid;
2395                                 timing_pid_type = i->type;
2396                         }
2397                 }
2398
2399                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2400                         i(program.audioStreams.begin()); 
2401                         i != program.audioStreams.end(); ++i)
2402                 {
2403                         pids_to_record.insert(i->pid);
2404
2405                         if (timing_pid == -1)
2406                         {
2407                                 timing_pid = i->pid;
2408                                 timing_pid_type = -1;
2409                         }
2410                 }
2411
2412                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2413                         i(program.subtitleStreams.begin());
2414                         i != program.subtitleStreams.end(); ++i)
2415                                 pids_to_record.insert(i->pid);
2416
2417                 std::set<int> new_pids, obsolete_pids;
2418                 
2419                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2420                                 m_pids_active.begin(), m_pids_active.end(),
2421                                 std::inserter(new_pids, new_pids.begin()));
2422                 
2423                 std::set_difference(
2424                                 m_pids_active.begin(), m_pids_active.end(),
2425                                 pids_to_record.begin(), pids_to_record.end(), 
2426                                 std::inserter(new_pids, new_pids.begin())
2427                                 );
2428
2429                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2430                         m_record->addPID(*i);
2431
2432                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2433                         m_record->removePID(*i);
2434
2435                 if (timing_pid != -1)
2436                         m_record->setTimingPID(timing_pid, timing_pid_type);
2437         }
2438 }
2439
2440 RESULT eDVBServicePlay::setNextPlaybackFile(const char *f)
2441 {
2442         m_timeshift_file_next = f;
2443         return 0;
2444 }
2445
2446 void eDVBServicePlay::switchToLive()
2447 {
2448         if (!m_timeshift_active)
2449                 return;
2450
2451         eDebug("SwitchToLive");
2452
2453         resetTimeshift(0);
2454
2455         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2456
2457         /* free the timeshift service handler, we need the resources */
2458         m_service_handler_timeshift.free();
2459
2460         updateDecoder(true);
2461 }
2462
2463 void eDVBServicePlay::resetTimeshift(int start)
2464 {
2465         m_cue = 0;
2466         m_decode_demux = 0;
2467         m_decoder = 0;
2468         m_teletext_parser = 0;
2469         m_rds_decoder = 0;
2470         m_subtitle_parser = 0;
2471         m_new_subtitle_page_connection = 0;
2472         m_new_dvb_subtitle_page_connection = 0;
2473         m_rds_decoder_event_connection = 0;
2474         m_video_event_connection = 0;
2475         m_timeshift_changed = 1;
2476         m_timeshift_file_next.clear();
2477
2478         if (start)
2479         {
2480                 m_cue = new eCueSheet();
2481                 m_timeshift_active = 1;
2482         }
2483         else
2484                 m_timeshift_active = 0;
2485 }
2486
2487 ePtr<iTsSource> eDVBServicePlay::createTsSource(eServiceReferenceDVB &ref)
2488 {
2489         if (m_is_stream)
2490         {
2491                 eHttpStream *f = new eHttpStream();
2492                 f->open(ref.path.c_str());
2493                 return ePtr<iTsSource>(f);
2494         }
2495         else
2496         {
2497                 eRawFile *f = new eRawFile();
2498                 f->open(ref.path.c_str());
2499                 return ePtr<iTsSource>(f);
2500         }
2501 }
2502
2503 void eDVBServicePlay::switchToTimeshift()
2504 {
2505         if (m_timeshift_active)
2506                 return;
2507
2508         resetTimeshift(1);
2509
2510         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2511         r.path = m_timeshift_file;
2512
2513         m_cue->seekTo(0, -1000);
2514
2515         ePtr<iTsSource> source = createTsSource(r);
2516         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 */
2517
2518         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2519         pause();
2520         updateDecoder(true); /* mainly to switch off PCR, and to set pause */
2521 }
2522
2523 void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged)
2524 {
2525         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2526         bool mustPlay = false;
2527
2528         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2529
2530         eDVBServicePMTHandler::program program;
2531         if (h.getProgramInfo(program))
2532                 eDebug("getting program info failed.");
2533         else
2534         {
2535                 eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size());
2536                 if (!program.videoStreams.empty())
2537                 {
2538                         eDebugNoNewLine(" (");
2539                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2540                                 i(program.videoStreams.begin());
2541                                 i != program.videoStreams.end(); ++i)
2542                         {
2543                                 if (vpid == -1)
2544                                 {
2545                                         vpid = i->pid;
2546                                         vpidtype = i->type;
2547                                 }
2548                                 if (i != program.videoStreams.begin())
2549                                         eDebugNoNewLine(", ");
2550                                 eDebugNoNewLine("%04x", i->pid);
2551                         }
2552                         eDebugNoNewLine(")");
2553                 }
2554                 eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size());
2555                 if (!program.audioStreams.empty())
2556                 {
2557                         eDebugNoNewLine(" (");
2558                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2559                                 i(program.audioStreams.begin());
2560                                 i != program.audioStreams.end(); ++i)
2561                         {
2562                                 if (i != program.audioStreams.begin())
2563                                         eDebugNoNewLine(", ");
2564                                 eDebugNoNewLine("%04x", i->pid);
2565                         }
2566                         eDebugNoNewLine(")");
2567                 }
2568                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2569                 pcrpid = program.pcrPid;
2570                 eDebug(", and the text pid is %04x", program.textPid);
2571                 tpid = program.textPid;
2572         }
2573
2574         if (!m_decoder)
2575         {
2576                 h.getDecodeDemux(m_decode_demux);
2577                 if (m_decode_demux)
2578                 {
2579                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2580                         if (m_decoder)
2581                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2582                         if (m_is_primary)
2583                         {
2584                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2585                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2586                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2587                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2588                                 if (m_timeshift_changed)
2589                                 {
2590                                         ePyObject subs = getCachedSubtitle();
2591                                         if (subs != Py_None)
2592                                         {
2593                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2594                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2595                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2596                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2597                                                 if (type == 0) // dvb
2598                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2599                                                 else if (type == 1) // ttx
2600                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2601                                         }
2602                                         Py_DECREF(subs);
2603                                 }
2604                         }
2605                 }
2606                 if (m_cue)
2607                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2608                 mustPlay = true;
2609         }
2610
2611         m_timeshift_changed = 0;
2612
2613         if (m_decoder)
2614         {
2615                 bool wasSeekable = m_decoder->getVideoProgressive() != -1;
2616                 if (m_dvb_service)
2617                 {
2618                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2619                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2620                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2621                 }
2622                 else // subservice
2623                 {
2624                         eServiceReferenceDVB ref;
2625                         m_service_handler.getServiceReference(ref);
2626                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2627                         if (!parent)
2628                                 parent = ref;
2629                         if (parent)
2630                         {
2631                                 ePtr<eDVBResourceManager> res_mgr;
2632                                 if (!eDVBResourceManager::getInstance(res_mgr))
2633                                 {
2634                                         ePtr<iDVBChannelList> db;
2635                                         if (!res_mgr->getChannelList(db))
2636                                         {
2637                                                 ePtr<eDVBService> origService;
2638                                                 if (!db->getService(parent, origService))
2639                                                 {
2640                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2641                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2642                                                 }
2643                                         }
2644                                 }
2645                         }
2646                 }
2647
2648                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2649                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2650
2651                 m_decoder->setVideoPID(vpid, vpidtype);
2652                 m_current_video_pid_type = vpidtype;
2653                 selectAudioStream();
2654
2655                 //if (!(m_is_pvr || m_is_stream || m_timeshift_active || !m_is_primary))
2656                 if (!(m_is_pvr || m_is_stream || m_timeshift_active))
2657                         m_decoder->setSyncPCR(pcrpid);
2658                 else
2659                         m_decoder->setSyncPCR(-1);
2660
2661                 if (m_is_primary)
2662                 {
2663                         m_decoder->setTextPID(tpid);
2664                         m_teletext_parser->start(program.textPid);
2665                 }
2666
2667                 if (vpid > 0 && vpid < 0x2000)
2668                         ;
2669                 else
2670                 {
2671                         std::string radio_pic;
2672                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2673                                 m_decoder->setRadioPic(radio_pic);
2674                 }
2675
2676                 if (mustPlay)
2677                         m_decoder->play();
2678                 else
2679                         m_decoder->set();
2680
2681                 m_decoder->setAudioChannel(achannel);
2682
2683                 /* don't worry about non-existing services, nor pvr services */
2684                 if (m_dvb_service)
2685                 {
2686                                 /* (audio pid will be set in selectAudioTrack */
2687                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2688                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2689                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2690                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2691                 }
2692                 if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable)
2693                         sendSeekableStateChanged = true;
2694         }
2695         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2696
2697         if (sendSeekableStateChanged)
2698                 m_event((iPlayableService*)this, evSeekableStatusChanged);
2699 }
2700
2701 void eDVBServicePlay::loadCuesheet()
2702 {
2703         std::string filename = m_reference.path + ".cuts";
2704         
2705         m_cue_entries.clear();
2706
2707         FILE *f = fopen(filename.c_str(), "rb");
2708
2709         if (f)
2710         {
2711                 eDebug("loading cuts..");
2712                 while (1)
2713                 {
2714                         unsigned long long where;
2715                         unsigned int what;
2716                         
2717                         if (!fread(&where, sizeof(where), 1, f))
2718                                 break;
2719                         if (!fread(&what, sizeof(what), 1, f))
2720                                 break;
2721                         
2722 #if BYTE_ORDER == LITTLE_ENDIAN
2723                         where = bswap_64(where);
2724 #endif
2725                         what = ntohl(what);
2726                         
2727                         if (what > 3)
2728                                 break;
2729                         
2730                         m_cue_entries.insert(cueEntry(where, what));
2731                 }
2732                 fclose(f);
2733                 eDebug("%zd entries", m_cue_entries.size());
2734         } else
2735                 eDebug("cutfile not found!");
2736         
2737         m_cuesheet_changed = 0;
2738         cutlistToCuesheet();
2739         m_event((iPlayableService*)this, evCuesheetChanged);
2740 }
2741
2742 void eDVBServicePlay::saveCuesheet()
2743 {
2744         std::string filename = m_reference.path + ".cuts";
2745         
2746         FILE *f = fopen(filename.c_str(), "wb");
2747
2748         if (f)
2749         {
2750                 unsigned long long where;
2751                 int what;
2752
2753                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2754                 {
2755 #if BYTE_ORDER == BIG_ENDIAN
2756                         where = i->where;
2757 #else
2758                         where = bswap_64(i->where);
2759 #endif
2760                         what = htonl(i->what);
2761                         fwrite(&where, sizeof(where), 1, f);
2762                         fwrite(&what, sizeof(what), 1, f);
2763                         
2764                 }
2765                 fclose(f);
2766         }
2767         
2768         m_cuesheet_changed = 0;
2769 }
2770
2771 void eDVBServicePlay::cutlistToCuesheet()
2772 {
2773         if (!m_cue)
2774         {
2775                 eDebug("no cue sheet");
2776                 return;
2777         }       
2778         m_cue->clear();
2779         
2780         if (!m_cutlist_enabled)
2781         {
2782                 m_cue->commitSpans();
2783                 eDebug("cutlists were disabled");
2784                 return;
2785         }
2786
2787         pts_t in = 0, out = 0, length = 0;
2788         
2789         getLength(length);
2790                 
2791         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2792         
2793         int have_any_span = 0;
2794         
2795         while (1)
2796         {
2797                 if (i == m_cue_entries.end())
2798                 {
2799                         if (!have_any_span && !in)
2800                                 break;
2801                         out = length;
2802                 } else {
2803                         if (i->what == 0) /* in */
2804                         {
2805                                 in = i++->where;
2806                                 continue;
2807                         } else if (i->what == 1) /* out */
2808                                 out = i++->where;
2809                         else /* mark (2) or last play position (3) */
2810                         {
2811                                 i++;
2812                                 continue;
2813                         }
2814                 }
2815                 
2816                 if (in < 0)
2817                         in = 0;
2818                 if (out < 0)
2819                         out = 0;
2820                 if (in > length)
2821                         in = length;
2822                 if (out > length)
2823                         out = length;
2824                 
2825                 if (in < out)
2826                 {
2827                         have_any_span = 1;
2828                         m_cue->addSourceSpan(in, out);
2829                         in = out = 0;
2830                 }
2831                 
2832                 in = length;
2833                 
2834                 if (i == m_cue_entries.end())
2835                         break;
2836         }
2837         m_cue->commitSpans();
2838 }
2839
2840 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2841 {
2842         if (m_subtitle_widget)
2843                 disableSubtitles(parent);
2844
2845         ePyObject entry;
2846         int tuplesize = PyTuple_Size(tuple);
2847         int type = 0;
2848
2849         if (!PyTuple_Check(tuple))
2850                 goto error_out;
2851
2852         if (tuplesize < 1)
2853                 goto error_out;
2854
2855         entry = PyTuple_GET_ITEM(tuple, 0);
2856
2857         if (!PyInt_Check(entry))
2858                 goto error_out;
2859
2860         type = PyInt_AsLong(entry);
2861
2862         if (type == 1)  // teletext subtitles
2863         {
2864                 int page, magazine, pid;
2865                 if (tuplesize < 4)
2866                         goto error_out;
2867
2868                 if (!m_teletext_parser)
2869                 {
2870                         eDebug("enable teletext subtitles.. no parser !!!");
2871                         return -1;
2872                 }
2873
2874                 entry = PyTuple_GET_ITEM(tuple, 1);
2875                 if (!PyInt_Check(entry))
2876                         goto error_out;
2877                 pid = PyInt_AsLong(entry);
2878
2879                 entry = PyTuple_GET_ITEM(tuple, 2);
2880                 if (!PyInt_Check(entry))
2881                         goto error_out;
2882                 page = PyInt_AsLong(entry);
2883
2884                 entry = PyTuple_GET_ITEM(tuple, 3);
2885                 if (!PyInt_Check(entry))
2886                         goto error_out;
2887                 magazine = PyInt_AsLong(entry);
2888
2889                 m_subtitle_widget = new eSubtitleWidget(parent);
2890                 m_subtitle_widget->resize(parent->size()); /* full size */
2891                 m_teletext_parser->setPageAndMagazine(page, magazine);
2892                 if (m_dvb_service)
2893                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2894         }
2895         else if (type == 0)
2896         {
2897                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2898                 if (!m_subtitle_parser)
2899                 {
2900                         eDebug("enable dvb subtitles.. no parser !!!");
2901                         return -1;
2902                 }
2903                 if (tuplesize < 4)
2904                         goto error_out;
2905
2906                 entry = PyTuple_GET_ITEM(tuple, 1);
2907                 if (!PyInt_Check(entry))
2908                         goto error_out;
2909                 pid = PyInt_AsLong(entry);
2910
2911                 entry = PyTuple_GET_ITEM(tuple, 2);
2912                 if (!PyInt_Check(entry))
2913                         goto error_out;
2914                 composition_page_id = PyInt_AsLong(entry);
2915
2916                 entry = PyTuple_GET_ITEM(tuple, 3);
2917                 if (!PyInt_Check(entry))
2918                         goto error_out;
2919                 ancillary_page_id = PyInt_AsLong(entry);
2920
2921                 m_subtitle_widget = new eSubtitleWidget(parent);
2922                 m_subtitle_widget->resize(parent->size()); /* full size */
2923                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2924                 if (m_dvb_service)
2925                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2926         }
2927         else
2928                 goto error_out;
2929         return 0;
2930 error_out:
2931         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2932                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2933                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2934         return -1;
2935 }
2936
2937 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2938 {
2939         delete m_subtitle_widget;
2940         m_subtitle_widget = 0;
2941         if (m_subtitle_parser)
2942         {
2943                 m_subtitle_parser->stop();
2944                 m_dvb_subtitle_pages.clear();
2945         }
2946         if (m_teletext_parser)
2947         {
2948                 m_teletext_parser->setPageAndMagazine(-1, -1);
2949                 m_subtitle_pages.clear();
2950         }
2951         if (m_dvb_service)
2952                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2953         return 0;
2954 }
2955
2956 PyObject *eDVBServicePlay::getCachedSubtitle()
2957 {
2958         if (m_dvb_service)
2959         {
2960                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2961                 if (tmp != -1)
2962                 {
2963                         unsigned int data = (unsigned int)tmp;
2964                         int pid = (data&0xFFFF0000)>>16;
2965                         ePyObject tuple = PyTuple_New(4);
2966                         eDVBServicePMTHandler::program program;
2967                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2968                         if (!h.getProgramInfo(program))
2969                         {
2970                                 if (program.textPid==pid) // teletext
2971                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2972                                 else
2973                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2974                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2975                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2976                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2977                                 return tuple;
2978                         }
2979                 }
2980         }
2981         Py_RETURN_NONE;
2982 }
2983
2984 PyObject *eDVBServicePlay::getSubtitleList()
2985 {
2986         if (!m_teletext_parser)
2987                 Py_RETURN_NONE;
2988         
2989         ePyObject l = PyList_New(0);
2990         std::set<int> added_ttx_pages;
2991
2992         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2993                 m_teletext_parser->m_found_subtitle_pages;
2994
2995         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2996         eDVBServicePMTHandler::program program;
2997         if (h.getProgramInfo(program))
2998                 eDebug("getting program info failed.");
2999         else
3000         {
3001                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
3002                         it != program.subtitleStreams.end(); ++it)
3003                 {
3004                         switch(it->subtitling_type)
3005                         {
3006                                 case 0x01: // ebu teletext subtitles
3007                                 {
3008                                         int page_number = it->teletext_page_number & 0xFF;
3009                                         int magazine_number = it->teletext_magazine_number & 7;
3010                                         int hash = magazine_number << 8 | page_number;
3011                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3012                                         {
3013                                                 ePyObject tuple = PyTuple_New(5);
3014                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3015                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3016                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3017                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3018                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3019                                                 PyList_Append(l, tuple);
3020                                                 Py_DECREF(tuple);
3021                                                 added_ttx_pages.insert(hash);
3022                                         }
3023                                         break;
3024                                 }
3025                                 case 0x10 ... 0x13:
3026                                 case 0x20 ... 0x23: // dvb subtitles
3027                                 {
3028                                         ePyObject tuple = PyTuple_New(5);
3029                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
3030                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3031                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
3032                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
3033                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
3034                                         PyList_Insert(l, 0, tuple);
3035                                         Py_DECREF(tuple);
3036                                         break;
3037                                 }
3038                         }
3039                 }
3040         }
3041
3042         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
3043                 it != subs.end(); ++it)
3044         {
3045                 int page_number = it->teletext_page_number & 0xFF;
3046                 int magazine_number = it->teletext_magazine_number & 7;
3047                 int hash = magazine_number << 8 | page_number;
3048                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
3049                 {
3050                         ePyObject tuple = PyTuple_New(5);
3051                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
3052                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
3053                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
3054                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
3055                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
3056                         PyList_Append(l, tuple);
3057                         Py_DECREF(tuple);
3058                 }
3059         }
3060
3061         return l;
3062 }
3063
3064 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
3065 {
3066         if (m_subtitle_widget)
3067         {
3068                 int subtitledelay = 0;
3069                 pts_t pos = 0;
3070                 if (m_decoder)
3071                         m_decoder->getPTS(0, pos);
3072                 if (m_is_pvr || m_timeshift_enabled)
3073                 {
3074                         eDebug("Subtitle in recording/timeshift");
3075                         subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3076                 }
3077                 else
3078                 {
3079                         /* check the setting for subtitle delay in live playback, either with pos, or without pos */
3080                         subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3081                 }
3082
3083                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
3084                 eDVBTeletextSubtitlePage tmppage = page;
3085                 tmppage.m_have_pts = true;
3086
3087                 if (abs(tmppage.m_pts - pos) > 20*90000)
3088                         tmppage.m_pts = pos; // fix abnormal pos diffs
3089
3090                 tmppage.m_pts += subtitledelay;
3091                 m_subtitle_pages.push_back(tmppage);
3092                 checkSubtitleTiming();
3093         }
3094 }
3095
3096 void eDVBServicePlay::checkSubtitleTiming()
3097 {
3098         eDebug("checkSubtitleTiming");
3099         if (!m_subtitle_widget)
3100                 return;
3101         while (1)
3102         {
3103                 enum { TELETEXT, DVB } type;
3104                 eDVBTeletextSubtitlePage page;
3105                 eDVBSubtitlePage dvb_page;
3106                 pts_t show_time;
3107                 if (!m_subtitle_pages.empty())
3108                 {
3109                         page = m_subtitle_pages.front();
3110                         type = TELETEXT;
3111                         show_time = page.m_pts;
3112                 }
3113                 else if (!m_dvb_subtitle_pages.empty())
3114                 {
3115                         dvb_page = m_dvb_subtitle_pages.front();
3116                         type = DVB;
3117                         show_time = dvb_page.m_show_time;
3118                 }
3119                 else
3120                         return;
3121         
3122                 pts_t pos = 0;
3123         
3124                 if (m_decoder)
3125                         m_decoder->getPTS(0, pos);
3126
3127                 eDebug("%lld %lld", pos, show_time);
3128                 int diff = show_time - pos;
3129                 if (type == TELETEXT && !page.m_have_pts)
3130                 {
3131                         eDebug("ttx subtitle page without pts... immediate show");
3132                         diff = 0;
3133                 }
3134                 if (diff < 0)
3135                 {
3136                         eDebug("[late (%d ms)]", -diff / 90);
3137                         diff = 0;
3138                 }
3139                 if (abs(diff) > 1800000)
3140                 {
3141                         eDebug("[invalid]... immediate show!");
3142                         diff = 0;
3143                 }
3144                 if ((diff/90)<20)
3145                 {
3146                         if (type == TELETEXT)
3147                         {
3148                                 eDebug("display teletext subtitle page %lld", show_time);
3149                                 m_subtitle_widget->setPage(page);
3150                                 m_subtitle_pages.pop_front();
3151                         }
3152                         else
3153                         {
3154                                 eDebug("display dvb subtitle Page %lld", show_time);
3155                                 m_subtitle_widget->setPage(dvb_page);
3156                                 m_dvb_subtitle_pages.pop_front();
3157                         }
3158                 } else
3159                 {
3160                         eDebug("start subtitle delay %d", diff / 90);
3161                         m_subtitle_sync_timer->start(diff / 90, 1);
3162                         break;
3163                 }
3164         }
3165 }
3166
3167 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
3168 {
3169         if (m_subtitle_widget)
3170         {
3171                 pts_t pos = 0;
3172                 if (m_decoder)
3173                         m_decoder->getPTS(0, pos);
3174                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
3175                 if ( abs(pos-p.m_show_time)>1800000 && (m_is_pvr || m_timeshift_enabled))
3176                 {
3177                         eDebug("[eDVBServicePlay] Subtitle without PTS and recording");
3178                         int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_noPTSrecordingdelay", 315000);
3179
3180                         eDVBSubtitlePage tmppage;
3181                         tmppage = p;
3182                         tmppage.m_show_time = pos + subtitledelay;
3183                         m_dvb_subtitle_pages.push_back(tmppage);
3184                 }
3185                 else
3186                 {
3187                         int subtitledelay = ePythonConfigQuery::getConfigIntValue("config.subtitles.subtitle_bad_timing_delay", 0);
3188                         if (subtitledelay != 0)
3189                         {
3190                                 eDVBSubtitlePage tmppage;
3191                                 tmppage = p;
3192                                 tmppage.m_show_time += subtitledelay;
3193                                 m_dvb_subtitle_pages.push_back(tmppage);
3194                         }
3195                         else
3196                                 m_dvb_subtitle_pages.push_back(p);
3197                 }
3198                 checkSubtitleTiming();
3199         }
3200 }
3201
3202 int eDVBServicePlay::getAC3Delay()
3203 {
3204         if (m_dvb_service)
3205                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
3206         else if (m_decoder)
3207                 return m_decoder->getAC3Delay();
3208         else
3209                 return 0;
3210 }
3211
3212 int eDVBServicePlay::getPCMDelay()
3213 {
3214         if (m_dvb_service)
3215                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
3216         else if (m_decoder)
3217                 return m_decoder->getPCMDelay();
3218         else
3219                 return 0;
3220 }
3221
3222 void eDVBServicePlay::setAC3Delay(int delay)
3223 {
3224         if (m_dvb_service)
3225                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3226         if (m_decoder) {
3227                 std::string config_delay;
3228                 int config_delay_int = 0;
3229                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
3230                         config_delay_int = atoi(config_delay.c_str());
3231                 m_decoder->setAC3Delay(delay + config_delay_int);
3232         }
3233 }
3234
3235 void eDVBServicePlay::setPCMDelay(int delay)
3236 {
3237         if (m_dvb_service)
3238                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3239         if (m_decoder) {
3240                 std::string config_delay;
3241                 int config_delay_int = 0;
3242                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
3243                         config_delay_int = atoi(config_delay.c_str());
3244                 else
3245                         config_delay_int = 0;
3246                 m_decoder->setPCMDelay(delay + config_delay_int);
3247         }
3248 }
3249
3250 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3251 {
3252         switch(event.type) {
3253                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3254                         m_event((iPlayableService*)this, evVideoSizeChanged);
3255                         break;
3256                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3257                         m_event((iPlayableService*)this, evVideoFramerateChanged);
3258                         break;
3259                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3260                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
3261                         break;
3262                 default:
3263                         break;
3264         }
3265 }
3266
3267 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3268 {
3269         ptr = this;
3270         return 0;
3271 }
3272
3273 PyObject *eDVBServicePlay::getStreamingData()
3274 {
3275         eDVBServicePMTHandler::program program;
3276         if (m_service_handler.getProgramInfo(program))
3277         {
3278                 Py_RETURN_NONE;
3279         }
3280
3281         ePyObject r = program.createPythonObject();
3282         ePtr<iDVBDemux> demux;
3283         if (!m_service_handler.getDataDemux(demux))
3284         {
3285                 uint8_t demux_id;
3286                 if (!demux->getCADemuxID(demux_id))
3287                         PutToDict(r, "demux", demux_id);
3288         }
3289
3290         return r;
3291 }
3292
3293
3294 DEFINE_REF(eDVBServicePlay)
3295
3296 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3297 {
3298         switch (w)
3299         {
3300         case iServiceInformation::sTransponderData:
3301                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3302         default:
3303                 break;
3304         }
3305         return iStaticServiceInformation::getInfoObject(ref, w);
3306 }
3307
3308 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");