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