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