add possibility to get a dict with transponderdata for servicerefs
[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/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
13
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
20
21                 /* for subtitles */
22 #include <lib/gui/esubtitle.h>
23
24 #include <sys/vfs.h>
25 #include <sys/stat.h>
26
27 #include <byteswap.h>
28 #include <netinet/in.h>
29
30 #ifndef BYTE_ORDER
31 #error no byte order defined!
32 #endif
33
34 #define TSPATH "/media/hdd"
35
36 class eStaticServiceDVBInformation: public iStaticServiceInformation
37 {
38         DECLARE_REF(eStaticServiceDVBInformation);
39 public:
40         RESULT getName(const eServiceReference &ref, std::string &name);
41         int getLength(const eServiceReference &ref);
42         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
43         PyObject *getInfoObject(const eServiceReference &ref, int);
44 };
45
46 DEFINE_REF(eStaticServiceDVBInformation);
47
48 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
49 {
50         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
51         if ( !ref.name.empty() )
52         {
53                 if (service.getParentTransportStreamID().get()) // linkage subservice
54                 {
55                         ePtr<iServiceHandler> service_center;
56                         if (!eServiceCenter::getInstance(service_center))
57                         {
58                                 eServiceReferenceDVB parent = service;
59                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
60                                 parent.setServiceID( service.getParentServiceID() );
61                                 parent.setParentTransportStreamID(eTransportStreamID(0));
62                                 parent.setParentServiceID(eServiceID(0));
63                                 parent.name="";
64                                 ePtr<iStaticServiceInformation> service_info;
65                                 if (!service_center->info(parent, service_info))
66                                 {
67                                         if (!service_info->getName(parent, name))
68                                         {
69                                                 // just show short name
70                                                 unsigned int pos = name.find("\xc2\x86");
71                                                 if ( pos != std::string::npos )
72                                                         name.erase(0, pos+2);
73                                                 pos = name.find("\xc2\x87");
74                                                 if ( pos != std::string::npos )
75                                                         name.erase(pos);
76                                                 name+=" - ";
77                                         }
78                                 }
79                         }
80                 }
81                 else
82                         name="";
83                 name += ref.name;
84                 return 0;
85         }
86         else
87                 return -1;
88 }
89
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
91 {
92         return -1;
93 }
94
95 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
96 {
97         ePtr<eDVBResourceManager> res_mgr;
98         if ( eDVBResourceManager::getInstance( res_mgr ) )
99                 eDebug("isPlayble... no res manager!!");
100         else
101         {
102                 eDVBChannelID chid, chid_ignore;
103                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
104                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
105                 return res_mgr->canAllocateChannel(chid, chid_ignore);
106         }
107         return false;
108 }
109
110 static void PutToDict(ePyObject &dict, const char*key, long value)
111 {
112         ePyObject item = PyString_FromFormat("%d", value);
113         if (item)
114         {
115                 if (PyDict_SetItemString(dict, key, item))
116                         eDebug("put %s to dict failed", key);
117                 Py_DECREF(item);
118         }
119         else
120                 eDebug("could not create PyObject for %s", key);
121 }
122
123 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
124
125 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
126 {
127         const char *tmp=0;
128         PutToDict(dict, "type", "satellite");
129         PutToDict(dict, "frequency", feparm.frequency);
130         PutToDict(dict, "symbolrate", feparm.symbol_rate);
131         PutToDict(dict, "orbital position", feparm.orbital_position);
132         switch (feparm.inversion)
133         {
134                 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
135                 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
136                 default:
137                 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
138         }
139         PutToDict(dict, "inversion", tmp);
140         switch (feparm.fec)
141         {
142                 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
143                 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
144                 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
145                 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
146                 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
147                 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
148                 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
149                 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
150                 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
151                 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
152                 default:
153                 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
154         }
155         PutToDict(dict, "fec inner", tmp);
156         switch (feparm.modulation)
157         {
158                 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
159                 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
160                 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
161                 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
162         }
163         PutToDict(dict, "modulation", tmp);
164         switch(feparm.polarisation)
165         {
166                 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
167                 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
168                 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
169                 default:
170                 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
171         }
172         PutToDict(dict, "polarization", tmp);
173         switch(feparm.system)
174         {
175                 default:
176                 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
177                 case eDVBFrontendParametersSatellite::System::DVB_S2:
178                         switch(feparm.roll_off)
179                         {
180                                 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
181                                 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
182                                 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
183                                 default:
184                                 case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
185                         }
186                         PutToDict(dict, "roll off", tmp);
187                         tmp="DVB-S2";
188                         break;
189         }
190         PutToDict(dict, "system", tmp);
191 }
192
193 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
194 {
195         PutToDict(dict, "type", "terrestrial");
196         PutToDict(dict, "frequency", feparm.frequency);
197         const char *tmp=0;
198         switch (feparm.bandwidth)
199         {
200         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 Mhz"; break;
201         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 Mhz"; break;
202         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 Mhz"; break;
203         default:
204         case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
205         }
206         PutToDict(dict, "bandwidth", tmp);
207         switch (feparm.code_rate_LP)
208         {
209         case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
210         case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
211         case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
212         case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
213         case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
214         default:
215         case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
216         }
217         PutToDict(dict, "code rate lp", tmp);
218         switch (feparm.code_rate_HP)
219         {
220         case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
221         case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
222         case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
223         case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
224         case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
225         default:
226         case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
227         }
228         PutToDict(dict, "code rate hp", tmp);
229         switch (feparm.modulation)
230         {
231         case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
232         case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
233         case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
234         default:
235         case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
236         }
237         PutToDict(dict, "constellation", tmp);
238         switch (feparm.transmission_mode)
239         {
240         case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
241         case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
242         default:
243         case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
244         }
245         PutToDict(dict, "transmission mode", tmp);
246         switch (feparm.guard_interval)
247         {
248                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
249                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
250                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
251                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
252                 default:
253                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
254         }
255         PutToDict(dict, "guard interval", tmp);
256         switch (feparm.hierarchy)
257         {
258                 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
259                 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
260                 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
261                 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
262                 default:
263                 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
264         }
265         PutToDict(dict, "hierarchy", tmp);
266         switch (feparm.inversion)
267         {
268                 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
269                 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
270                 default:
271                 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
272         }
273         PutToDict(dict, "inversion", tmp);
274 }
275
276 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
277 {
278         const char *tmp=0;
279         PutToDict(dict, "type", "cable");
280         PutToDict(dict, "frequency", feparm.frequency);
281         PutToDict(dict, "symbolrate", feparm.symbol_rate);
282         switch (feparm.modulation)
283         {
284         case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
285         case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
286         case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
287         case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
288         case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
289         default:
290         case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
291         }
292         PutToDict(dict, "modulation", tmp);
293         switch (feparm.inversion)
294         {
295         case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
296         case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
297         default:
298         case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
299         }
300         PutToDict(dict, "inversion", tmp);
301         switch (feparm.fec_inner)
302         {
303         case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
304         case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
305         case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
306         case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
307         case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
308         case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
309         case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
310         default:
311         case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
312         }
313         PutToDict(dict, "fec inner", tmp);
314 }
315
316 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
317 {
318         if (r.type == eServiceReference::idDVB)
319         {
320                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
321                 switch(what)
322                 {
323                         case iServiceInformation::sTransponderData:
324                         {
325                                 ePtr<eDVBResourceManager> res;
326                                 if (!eDVBResourceManager::getInstance(res))
327                                 {
328                                         ePtr<iDVBChannelList> db;
329                                         if (!res->getChannelList(db))
330                                         {
331                                                 eDVBChannelID chid;
332                                                 ref.getChannelID(chid);
333                                                 ePtr<iDVBFrontendParameters> feparm;
334                                                 if (!db->getChannelFrontendData(chid, feparm))
335                                                 {
336                                                         int system;
337                                                         if (!feparm->getSystem(system))
338                                                         {
339                                                                 ePyObject dict = PyDict_New();
340                                                                 switch(system)
341                                                                 {
342                                                                         case iDVBFrontend::feSatellite:
343                                                                         {
344                                                                                 eDVBFrontendParametersSatellite s;
345                                                                                 feparm->getDVBS(s);
346                                                                                 PutSatelliteDataToDict(dict, s);
347                                                                                 break;
348                                                                         }
349                                                                         case iDVBFrontend::feTerrestrial:
350                                                                         {
351                                                                                 eDVBFrontendParametersTerrestrial t;
352                                                                                 feparm->getDVBT(t);
353                                                                                 PutTerrestrialDataToDict(dict, t);
354                                                                                 break;
355                                                                         }
356                                                                         case iDVBFrontend::feCable:
357                                                                         {
358                                                                                 eDVBFrontendParametersCable c;
359                                                                                 feparm->getDVBC(c);
360                                                                                 PutCableDataToDict(dict, c);
361                                                                                 break;
362                                                                         }
363                                                                 }
364                                                         }
365                                                 }
366                                         }
367                                 }
368                         }
369                 }
370         }
371         Py_RETURN_NONE;
372 }
373
374 DEFINE_REF(eStaticServiceDVBBouquetInformation);
375
376 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
377 {
378         ePtr<iDVBChannelList> db;
379         ePtr<eDVBResourceManager> res;
380
381         int err;
382         if ((err = eDVBResourceManager::getInstance(res)) != 0)
383         {
384                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
385                 return err;
386         }
387         if ((err = res->getChannelList(db)) != 0)
388         {
389                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
390                 return err;
391         }
392
393         eBouquet *bouquet=0;
394         if ((err = db->getBouquet(ref, bouquet)) != 0)
395         {
396                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
397                 return -1;
398         }
399
400         if ( bouquet && bouquet->m_bouquet_name.length() )
401         {
402                 name = bouquet->m_bouquet_name;
403                 return 0;
404         }
405         else
406                 return -1;
407 }
408
409 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
410 {
411         if (ref.flags & eServiceReference::isGroup)
412         {
413                 ePtr<iDVBChannelList> db;
414                 ePtr<eDVBResourceManager> res;
415
416                 if (eDVBResourceManager::getInstance(res))
417                 {
418                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
419                         return 0;
420                 }
421
422                 if (res->getChannelList(db))
423                 {
424                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
425                         return 0;
426                 }
427
428                 eBouquet *bouquet=0;
429                 if (db->getBouquet(ref, bouquet))
430                 {
431                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
432                         return 0;
433                 }
434
435                 int cur=0;
436                 eDVBChannelID chid, chid_ignore;
437                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
438                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
439                 {
440                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
441                         int tmp=res->canAllocateChannel(chid, chid_ignore);
442                         if (tmp > cur)
443                         {
444                                 m_playable_service = *it;
445                                 cur = tmp;
446                         }
447                 }
448                 if (cur)
449                         return cur;
450         }
451         m_playable_service = eServiceReference();
452         return 0;
453 }
454
455 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
456 {
457         return -1;
458 }
459
460 #include <lib/dvb/epgcache.h>
461
462 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
463 {
464         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
465 }
466
467 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
468 {
469         DECLARE_REF(eStaticServiceDVBPVRInformation);
470         eServiceReference m_ref;
471         eDVBMetaParser m_parser;
472 public:
473         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
474         RESULT getName(const eServiceReference &ref, std::string &name);
475         int getLength(const eServiceReference &ref);
476         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
477         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
478         int getInfo(const eServiceReference &ref, int w);
479         std::string getInfoString(const eServiceReference &ref,int w);
480 };
481
482 DEFINE_REF(eStaticServiceDVBPVRInformation);
483
484 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
485 {
486         m_ref = ref;
487         m_parser.parseFile(ref.path);
488 }
489
490 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
491 {
492         ASSERT(ref == m_ref);
493         name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
494         return 0;
495 }
496
497 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
498 {
499         ASSERT(ref == m_ref);
500         
501         eDVBTSTools tstools;
502         
503         if (tstools.openFile(ref.path.c_str()))
504                 return 0;
505
506         pts_t len;
507         if (tstools.calcLen(len))
508                 return 0;
509
510         return len / 90000;
511 }
512
513 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
514 {
515         switch (w)
516         {
517         case iServiceInformation::sDescription:
518                 return iServiceInformation::resIsString;
519         case iServiceInformation::sServiceref:
520                 return iServiceInformation::resIsString;
521         case iServiceInformation::sTimeCreate:
522                 if (m_parser.m_time_create)
523                         return m_parser.m_time_create;
524                 else
525                         return iServiceInformation::resNA;
526         default:
527                 return iServiceInformation::resNA;
528         }
529 }
530
531 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
532 {
533         switch (w)
534         {
535         case iServiceInformation::sDescription:
536                 return m_parser.m_description;
537         case iServiceInformation::sServiceref:
538                 return m_parser.m_ref.toString();
539         case iServiceInformation::sTags:
540                 return m_parser.m_tags;
541         default:
542                 return "";
543         }
544 }
545
546 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
547 {
548         if (!ref.path.empty())
549         {
550                 ePtr<eServiceEvent> event = new eServiceEvent;
551                 std::string filename = ref.path;
552                 filename.erase(filename.length()-2, 2);
553                 filename+="eit";
554                 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
555                 {
556                         evt = event;
557                         return 0;
558                 }
559         }
560         evt = 0;
561         return -1;
562 }
563
564 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
565 {
566         DECLARE_REF(eDVBPVRServiceOfflineOperations);
567         eServiceReferenceDVB m_ref;
568 public:
569         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
570         
571         RESULT deleteFromDisk(int simulate);
572         RESULT getListOfFilenames(std::list<std::string> &);
573 };
574
575 DEFINE_REF(eDVBPVRServiceOfflineOperations);
576
577 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
578 {
579 }
580
581 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
582 {
583         if (simulate)
584                 return 0;
585         else
586         {
587                 std::list<std::string> res;
588                 if (getListOfFilenames(res))
589                         return -1;
590                 
591                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
592                 if (!eraser)
593                         eDebug("FATAL !! can't get background file eraser");
594                 
595                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
596                 {
597                         eDebug("Removing %s...", i->c_str());
598                         if (eraser)
599                                 eraser->erase(i->c_str());
600                         else
601                                 ::unlink(i->c_str());
602                 }
603                 
604                 return 0;
605         }
606 }
607
608 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
609 {
610         res.clear();
611         res.push_back(m_ref.path);
612
613 // handling for old splitted recordings (enigma 1)
614         char buf[255];
615         int slice=1;
616         while(true)
617         {
618                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
619                 struct stat s;
620                 if (stat(buf, &s) < 0)
621                         break;
622                 res.push_back(buf);
623         }       
624
625         res.push_back(m_ref.path + ".meta");
626         res.push_back(m_ref.path + ".ap");
627         res.push_back(m_ref.path + ".cuts");
628         std::string tmp = m_ref.path;
629         tmp.erase(m_ref.path.length()-3);
630         res.push_back(tmp + ".eit");
631         return 0;
632 }
633
634 DEFINE_REF(eServiceFactoryDVB)
635
636 eServiceFactoryDVB::eServiceFactoryDVB()
637 {
638         ePtr<eServiceCenter> sc;
639         
640         eServiceCenter::getPrivInstance(sc);
641         if (sc)
642                 sc->addServiceFactory(eServiceFactoryDVB::id, this);
643
644         m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
645         m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
646 }
647
648 eServiceFactoryDVB::~eServiceFactoryDVB()
649 {
650         ePtr<eServiceCenter> sc;
651         
652         eServiceCenter::getPrivInstance(sc);
653         if (sc)
654                 sc->removeServiceFactory(eServiceFactoryDVB::id);
655 }
656
657 DEFINE_REF(eDVBServiceList);
658
659 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
660 {
661 }
662
663 eDVBServiceList::~eDVBServiceList()
664 {
665 }
666
667 RESULT eDVBServiceList::startQuery()
668 {
669         ePtr<iDVBChannelList> db;
670         ePtr<eDVBResourceManager> res;
671         
672         int err;
673         if ((err = eDVBResourceManager::getInstance(res)) != 0)
674         {
675                 eDebug("no resource manager");
676                 return err;
677         }
678         if ((err = res->getChannelList(db)) != 0)
679         {
680                 eDebug("no channel list");
681                 return err;
682         }
683         
684         ePtr<eDVBChannelQuery> q;
685         
686         if (!m_parent.path.empty())
687         {
688                 eDVBChannelQuery::compile(q, m_parent.path);
689                 if (!q)
690                 {
691                         eDebug("compile query failed");
692                         return err;
693                 }
694         }
695         
696         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
697         {
698                 eDebug("startQuery failed");
699                 return err;
700         }
701
702         return 0;
703 }
704
705 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
706 {
707         eServiceReferenceDVB ref;
708         
709         if (!m_query)
710                 return -1;
711
712         while (!m_query->getNextResult(ref))
713                 list.push_back(ref);
714
715         if (sorted)
716                 list.sort(iListableServiceCompare(this));
717
718         return 0;
719 }
720
721 //   The first argument of this function is a format string to specify the order and
722 //   the content of the returned list
723 //   useable format options are
724 //   R = Service Reference (as swig object .. this is very slow)
725 //   S = Service Reference (as python string object .. same as ref.toString())
726 //   C = Service Reference (as python string object .. same as ref.toCompareString())
727 //   N = Service Name (as python string object)
728 //   when exactly one return value per service is selected in the format string,
729 //   then each value is directly a list entry
730 //   when more than one value is returned per service, then the list is a list of
731 //   python tuples
732 //   unknown format string chars are returned as python None values !
733 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
734 {
735         ePyObject ret;
736         std::list<eServiceReference> tmplist;
737         int retcount=1;
738
739         if (!format || !(retcount=strlen(format)))
740                 format = "R"; // just return service reference swig object ...
741
742         if (!getContent(tmplist, sorted))
743         {
744                 int services=tmplist.size();
745                 ePtr<iStaticServiceInformation> sptr;
746                 eServiceCenterPtr service_center;
747
748                 if (strchr(format, 'N'))
749                         eServiceCenter::getPrivInstance(service_center);
750
751                 ret = PyList_New(services);
752                 std::list<eServiceReference>::iterator it(tmplist.begin());
753
754                 for (int cnt=0; cnt < services; ++cnt)
755                 {
756                         eServiceReference &ref=*it++;
757                         ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
758                         for (int i=0; i < retcount; ++i)
759                         {
760                                 ePyObject tmp;
761                                 switch(format[i])
762                                 {
763                                 case 'R':  // service reference (swig)object
764                                         tmp = NEW_eServiceReference(ref);
765                                         break;
766                                 case 'C':  // service reference compare string
767                                         tmp = PyString_FromString(ref.toCompareString().c_str());
768                                         break;
769                                 case 'S':  // service reference string
770                                         tmp = PyString_FromString(ref.toString().c_str());
771                                         break;
772                                 case 'N':  // service name
773                                         if (service_center)
774                                         {
775                                                 service_center->info(ref, sptr);
776                                                 if (sptr)
777                                                 {
778                                                         std::string name;
779                                                         sptr->getName(ref, name);
780                                                         if (name.length())
781                                                                 tmp = PyString_FromString(name.c_str());
782                                                 }
783                                         }
784                                         if (!tmp)
785                                                 tmp = PyString_FromString("<n/a>");
786                                         break;
787                                 default:
788                                         if (tuple)
789                                         {
790                                                 tmp = Py_None;
791                                                 Py_INCREF(Py_None);
792                                         }
793                                         break;
794                                 }
795                                 if (tmp)
796                                 {
797                                         if (tuple)
798                                                 PyTuple_SET_ITEM(tuple, i, tmp);
799                                         else
800                                                 PyList_SET_ITEM(ret, cnt, tmp);
801                                 }
802                         }
803                         if (tuple)
804                                 PyList_SET_ITEM(ret, cnt, tuple);
805                 }
806         }
807         return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
808 }
809
810 RESULT eDVBServiceList::getNext(eServiceReference &ref)
811 {
812         if (!m_query)
813                 return -1;
814         
815         return m_query->getNextResult((eServiceReferenceDVB&)ref);
816 }
817
818 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
819 {
820         if (m_parent.flags & eServiceReference::canDescent) // bouquet
821         {
822                 ePtr<iDVBChannelList> db;
823                 ePtr<eDVBResourceManager> resm;
824
825                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
826                         return -1;
827
828                 if (db->getBouquet(m_parent, m_bouquet) != 0)
829                         return -1;
830
831                 res = this;
832                 
833                 return 0;
834         }
835         res = 0;
836         return -1;
837 }
838
839 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
840 {
841         if (!m_bouquet)
842                 return -1;
843         return m_bouquet->addService(ref, before);
844 }
845
846 RESULT eDVBServiceList::removeService(eServiceReference &ref)
847 {
848         if (!m_bouquet)
849                 return -1;
850         return m_bouquet->removeService(ref);
851 }
852
853 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
854 {
855         if (!m_bouquet)
856                 return -1;
857         return m_bouquet->moveService(ref, pos);
858 }
859
860 RESULT eDVBServiceList::flushChanges()
861 {
862         if (!m_bouquet)
863                 return -1;
864         return m_bouquet->flushChanges();
865 }
866
867 RESULT eDVBServiceList::setListName(const std::string &name)
868 {
869         if (!m_bouquet)
870                 return -1;
871         return m_bouquet->setListName(name);
872 }
873
874 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
875 {
876         ePtr<eDVBService> service;
877         int r = lookupService(service, ref);
878         if (r)
879                 service = 0;
880                 // check resources...
881         ptr = new eDVBServicePlay(ref, service);
882         return 0;
883 }
884
885 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
886 {
887         if (ref.path.empty())
888         {
889                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
890                 return 0;
891         } else
892         {
893                 ptr = 0;
894                 return -1;
895         }
896 }
897
898 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
899 {
900         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
901         if (list->startQuery())
902         {
903                 ptr = 0;
904                 return -1;
905         }
906         
907         ptr = list;
908         return 0;
909 }
910
911 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
912 {
913         /* is a listable service? */
914         if (ref.flags & eServiceReference::canDescent) // bouquet
915         {
916                 if ( !ref.name.empty() )  // satellites or providers list
917                         ptr = m_StaticServiceDVBInfo;
918                 else // a dvb bouquet
919                         ptr = m_StaticServiceDVBBouquetInfo;
920         }
921         else if (!ref.path.empty()) /* do we have a PVR service? */
922                 ptr = new eStaticServiceDVBPVRInformation(ref);
923         else // normal dvb service
924         {
925                 ePtr<eDVBService> service;
926                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
927                         ptr = m_StaticServiceDVBInfo;
928                 else
929                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
930                         ptr = service;
931         }
932         return 0;
933 }
934
935 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
936 {
937         if (ref.path.empty())
938         {
939                 ptr = 0;
940                 return -1;
941         } else
942         {
943                 ptr = new eDVBPVRServiceOfflineOperations(ref);
944                 return 0;
945         }
946 }
947
948 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
949 {
950                         // TODO: handle the listing itself
951         // if (ref.... == -1) .. return "... bouquets ...";
952         // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
953                         // TODO: cache
954         ePtr<iDVBChannelList> db;
955         ePtr<eDVBResourceManager> res;
956         
957         int err;
958         if ((err = eDVBResourceManager::getInstance(res)) != 0)
959         {
960                 eDebug("no resource manager");
961                 return err;
962         }
963         if ((err = res->getChannelList(db)) != 0)
964         {
965                 eDebug("no channel list");
966                 return err;
967         }
968         
969                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
970         if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
971         {
972                 eDebug("getService failed!");
973                 return err;
974         }
975
976         return 0;
977 }
978
979 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
980         m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
981 {
982         memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
983         m_is_primary = 1;
984         m_is_pvr = !m_reference.path.empty();
985         
986         m_timeshift_enabled = m_timeshift_active = 0;
987         m_skipmode = 0;
988         
989         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
990         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
991         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
992
993         m_cuesheet_changed = 0;
994         m_cutlist_enabled = 1;
995         
996         m_subtitle_widget = 0;
997         
998         m_tune_state = -1;
999         
1000         CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1001 }
1002
1003 eDVBServicePlay::~eDVBServicePlay()
1004 {
1005         delete m_subtitle_widget;
1006 }
1007
1008 void eDVBServicePlay::gotNewEvent()
1009 {
1010 #if 0
1011                 // debug only
1012         ePtr<eServiceEvent> m_event_now, m_event_next;
1013         getEvent(m_event_now, 0);
1014         getEvent(m_event_next, 1);
1015
1016         if (m_event_now)
1017                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1018         if (m_event_next)
1019                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1020 #endif
1021         m_event((iPlayableService*)this, evUpdatedEventInfo);
1022 }
1023
1024 void eDVBServicePlay::serviceEvent(int event)
1025 {
1026         m_tune_state = event;
1027
1028         switch (event)
1029         {
1030         case eDVBServicePMTHandler::eventTuned:
1031         {
1032                 ePtr<iDVBDemux> m_demux;
1033                 if (!m_service_handler.getDataDemux(m_demux))
1034                 {
1035                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1036                         int sid = ref.getParentServiceID().get();
1037                         if (!sid)
1038                                 sid = ref.getServiceID().get();
1039                         if ( ref.getParentTransportStreamID().get() &&
1040                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1041                                 m_event_handler.startOther(m_demux, sid);
1042                         else
1043                                 m_event_handler.start(m_demux, sid);
1044                 }
1045                 break;
1046         }
1047         case eDVBServicePMTHandler::eventNoPAT:
1048         case eDVBServicePMTHandler::eventNoPATEntry:
1049         case eDVBServicePMTHandler::eventNoPMT:
1050         case eDVBServicePMTHandler::eventTuneFailed:
1051         {
1052                 eDebug("DVB service failed to tune - error %d", event);
1053                 m_event((iPlayableService*)this, evTuneFailed);
1054                 break;
1055         }
1056         case eDVBServicePMTHandler::eventNewProgramInfo:
1057         {
1058                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1059                 if (m_timeshift_enabled)
1060                         updateTimeshiftPids();
1061                 if (!m_timeshift_active)
1062                         updateDecoder();
1063                 if (m_first_program_info && m_is_pvr)
1064                 {
1065                         m_first_program_info = 0;
1066                         seekTo(0);
1067                 }
1068                 m_event((iPlayableService*)this, evUpdatedInfo);
1069                 break;
1070         }
1071         case eDVBServicePMTHandler::eventEOF:
1072                 m_event((iPlayableService*)this, evEOF);
1073                 break;
1074         case eDVBServicePMTHandler::eventSOF:
1075                 m_event((iPlayableService*)this, evSOF);
1076                 break;
1077         }
1078 }
1079
1080 void eDVBServicePlay::serviceEventTimeshift(int event)
1081 {
1082         switch (event)
1083         {
1084         case eDVBServicePMTHandler::eventNewProgramInfo:
1085                 if (m_timeshift_active)
1086                         updateDecoder();
1087                 break;
1088         case eDVBServicePMTHandler::eventSOF:
1089                 m_event((iPlayableService*)this, evSOF);
1090                 break;
1091         case eDVBServicePMTHandler::eventEOF:
1092                 switchToLive();
1093                 break;
1094         }
1095 }
1096
1097 RESULT eDVBServicePlay::start()
1098 {
1099         int r;
1100                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
1101                    two (one for decoding, one for data source), as we must be prepared
1102                    to start recording from the data demux. */
1103         if (m_is_pvr)
1104                 m_cue = new eCueSheet();
1105
1106         m_first_program_info = 1;
1107         eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1108         r = m_service_handler.tune(service, m_is_pvr, m_cue);
1109
1110                 /* inject EIT if there is a stored one */
1111         if (m_is_pvr)
1112         {
1113                 std::string filename = service.path;
1114                 filename.erase(filename.length()-2, 2);
1115                 filename+="eit";
1116                 ePtr<eServiceEvent> event = new eServiceEvent;
1117                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1118                 {
1119                         ePtr<eServiceEvent> empty;
1120                         m_event_handler.inject(event, 0);
1121                         m_event_handler.inject(empty, 1);
1122                 }
1123         }
1124
1125         if (m_is_pvr)
1126                 loadCuesheet();
1127
1128         m_event(this, evStart);
1129         m_event((iPlayableService*)this, evSeekableStatusChanged);
1130         return 0;
1131 }
1132
1133 RESULT eDVBServicePlay::stop()
1134 {
1135                 /* add bookmark for last play position */
1136         if (m_is_pvr)
1137         {
1138                 pts_t play_position;
1139                 if (!getPlayPosition(play_position))
1140                 {
1141                                 /* remove last position */
1142                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1143                         {
1144                                 if (i->what == 3) /* current play position */
1145                                 {
1146                                         m_cue_entries.erase(i);
1147                                         i = m_cue_entries.begin();
1148                                         continue;
1149                                 } else
1150                                         ++i;
1151                         }
1152                         
1153                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1154                         m_cuesheet_changed = 1;
1155                 }
1156         }
1157
1158         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1159
1160         m_service_handler_timeshift.free();
1161         m_service_handler.free();
1162         
1163         if (m_is_pvr && m_cuesheet_changed)
1164         {
1165                 struct stat s;
1166                                 /* save cuesheet only when main file is accessible. */
1167                 if (!::stat(m_reference.path.c_str(), &s))
1168                         saveCuesheet();
1169         }
1170         
1171         return 0;
1172 }
1173
1174 RESULT eDVBServicePlay::setTarget(int target)
1175 {
1176         m_is_primary = !target;
1177         return 0;
1178 }
1179
1180 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1181 {
1182         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1183         return 0;
1184 }
1185
1186 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1187 {
1188                 /* note: we check for timeshift to be enabled,
1189                    not neccessary active. if you pause when timeshift
1190                    is not active, you should activate it when unpausing */
1191         if ((!m_is_pvr) && (!m_timeshift_enabled))
1192         {
1193                 ptr = 0;
1194                 return -1;
1195         }
1196
1197         ptr = this;
1198         return 0;
1199 }
1200
1201 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1202 {
1203         if (m_decoder)
1204                 return m_decoder->setSlowMotion(ratio);
1205         else
1206                 return -1;
1207 }
1208
1209 RESULT eDVBServicePlay::setFastForward(int ratio)
1210 {
1211         int skipmode, ffratio;
1212         
1213         if (ratio > 8)
1214         {
1215                 skipmode = ratio;
1216                 ffratio = 1;
1217         } else if (ratio > 0)
1218         {
1219                 skipmode = 0;
1220                 ffratio = ratio;
1221         } else if (!ratio)
1222         {
1223                 skipmode = 0;
1224                 ffratio = 0;
1225         } else // if (ratio < 0)
1226         {
1227                 skipmode = ratio;
1228                 ffratio = 1;
1229         }
1230
1231         if (m_skipmode != skipmode)
1232         {
1233                 eDebug("setting cue skipmode to %d", skipmode);
1234                 if (m_cue)
1235                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1236         }
1237         
1238         m_skipmode = skipmode;
1239         
1240         if (!m_decoder)
1241                 return -1;
1242
1243         return m_decoder->setFastForward(ffratio);
1244 }
1245     
1246 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1247 {
1248         if (m_is_pvr || m_timeshift_enabled)
1249         {
1250                 ptr = this;
1251                 return 0;
1252         }
1253         
1254         ptr = 0;
1255         return -1;
1256 }
1257
1258         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1259 RESULT eDVBServicePlay::getLength(pts_t &len)
1260 {
1261         ePtr<iDVBPVRChannel> pvr_channel;
1262         
1263         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1264                 return -1;
1265         
1266         return pvr_channel->getLength(len);
1267 }
1268
1269 RESULT eDVBServicePlay::pause()
1270 {
1271         if (!m_is_paused && m_decoder)
1272         {
1273                 m_is_paused = 1;
1274                 return m_decoder->freeze(0);
1275         } else
1276                 return -1;
1277 }
1278
1279 RESULT eDVBServicePlay::unpause()
1280 {
1281         if (m_is_paused && m_decoder)
1282         {
1283                 m_is_paused = 0;
1284                 return m_decoder->unfreeze();
1285         } else
1286                 return -1;
1287 }
1288
1289 RESULT eDVBServicePlay::seekTo(pts_t to)
1290 {
1291         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1292         
1293         if (!m_decode_demux)
1294                 return -1;
1295
1296         ePtr<iDVBPVRChannel> pvr_channel;
1297         
1298         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1299                 return -1;
1300         
1301         if (!m_cue)
1302                 return -1;
1303         
1304         m_cue->seekTo(0, to);
1305         return 0;
1306 }
1307
1308 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1309 {
1310         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1311         
1312         if (!m_decode_demux)
1313                 return -1;
1314
1315         ePtr<iDVBPVRChannel> pvr_channel;
1316         
1317         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1318                 return -1;
1319         
1320         int mode = 1;
1321         
1322                         /* HACK until we have skip-AP api */
1323         if ((to > 0) && (to < 100))
1324                 mode = 2;
1325         
1326         to *= direction;
1327         
1328         if (!m_cue)
1329                 return 0;
1330         
1331         m_cue->seekTo(mode, to);
1332         return 0;
1333 }
1334
1335 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1336 {
1337         ePtr<iDVBPVRChannel> pvr_channel;
1338         
1339         if (!m_decode_demux)
1340                 return -1;
1341         
1342         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1343                 return -1;
1344         
1345         int r = 0;
1346
1347                 /* if there is a decoder, use audio or video PTS */
1348         if (m_decoder)
1349         {
1350                 r = m_decoder->getPTS(0, pos);
1351                 if (r)
1352                         return r;
1353         }
1354         
1355                 /* fixup */
1356         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1357 }
1358
1359 RESULT eDVBServicePlay::setTrickmode(int trick)
1360 {
1361         if (m_decoder)
1362                 m_decoder->setTrickmode(trick);
1363         return 0;
1364 }
1365
1366 RESULT eDVBServicePlay::isCurrentlySeekable()
1367 {
1368         return m_is_pvr || m_timeshift_active;
1369 }
1370
1371 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1372 {
1373         ptr = this;
1374         return 0;
1375 }
1376
1377 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1378 {
1379         ptr = this;
1380         return 0;
1381 }
1382
1383 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1384 {
1385         ptr = this;
1386         return 0;
1387 }
1388
1389 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1390 {
1391         ptr = this;
1392         return 0;
1393 }
1394
1395 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1396 {
1397         ptr = this;
1398         return 0;
1399 }
1400
1401 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1402 {
1403         ptr = 0;
1404         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1405                 (m_timeshift_enabled || !m_is_pvr))
1406         {
1407                 if (!m_timeshift_enabled)
1408                 {
1409                                 /* we need enough diskspace */
1410                         struct statfs fs;
1411                         if (statfs(TSPATH "/.", &fs) < 0)
1412                         {
1413                                 eDebug("statfs failed!");
1414                                 return -2;
1415                         }
1416                 
1417                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1418                         {
1419                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1420                                 return -3;
1421                         }
1422                 }
1423                 ptr = this;
1424                 return 0;
1425         }
1426         return -1;
1427 }
1428
1429 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1430 {
1431         if (m_is_pvr)
1432         {
1433                 ptr = this;
1434                 return 0;
1435         }
1436         ptr = 0;
1437         return -1;
1438 }
1439
1440 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1441 {
1442         ptr = this;
1443         return 0;
1444 }
1445
1446 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1447 {
1448         ptr = this;
1449         return 0;
1450 }
1451
1452 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1453 {
1454         ptr = this;
1455         return 0;
1456 }
1457
1458 RESULT eDVBServicePlay::getName(std::string &name)
1459 {
1460         if (m_is_pvr)
1461         {
1462                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1463                 return i->getName(m_reference, name);
1464         }
1465         if (m_dvb_service)
1466         {
1467                 m_dvb_service->getName(m_reference, name);
1468                 if (name.empty())
1469                         name = "(...)";
1470         }
1471         else if (!m_reference.name.empty())
1472                 eStaticServiceDVBInformation().getName(m_reference, name);
1473         else
1474                 name = "DVB service";
1475         return 0;
1476 }
1477
1478 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1479 {
1480         return m_event_handler.getEvent(evt, nownext);
1481 }
1482
1483 int eDVBServicePlay::getInfo(int w)
1484 {
1485         eDVBServicePMTHandler::program program;
1486         
1487         if (w == sCAIDs)
1488                 return resIsPyObject;
1489
1490         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1491         
1492         int no_program_info = 0;
1493         
1494         if (h.getProgramInfo(program))
1495                 no_program_info = 1;
1496         
1497         switch (w)
1498         {
1499 #if HAVE_DVB_API_VERSION >= 3
1500         case sVideoHeight:
1501                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1502                         return m_videoEventData.height;
1503                 return -1;
1504         case sVideoWidth:
1505                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1506                         return m_videoEventData.width;
1507                 return -1;
1508 #else
1509 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1510 #endif
1511         case sAspect:
1512 #if HAVE_DVB_API_VERSION >= 3
1513                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1514                         return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1515                 else
1516 #else
1517 #warning "FIXMEE implement sAspect for old DVB API"
1518 #endif
1519                 if (no_program_info)
1520                         return -1; 
1521                 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1522                 {
1523                         ePtr<eServiceEvent> evt;
1524                         if (!m_event_handler.getEvent(evt, 0))
1525                         {
1526                                 ePtr<eComponentData> data;
1527                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1528                                 {
1529                                         if ( data->getStreamContent() == 1 )
1530                                         {
1531                                                 switch(data->getComponentType())
1532                                                 {
1533                                                         // SD
1534                                                         case 1: // 4:3 SD PAL
1535                                                         case 2:
1536                                                         case 3: // 16:9 SD PAL
1537                                                         case 4: // > 16:9 PAL
1538                                                         case 5: // 4:3 SD NTSC
1539                                                         case 6: 
1540                                                         case 7: // 16:9 SD NTSC
1541                                                         case 8: // > 16:9 NTSC
1542
1543                                                         // HD
1544                                                         case 9: // 4:3 HD PAL
1545                                                         case 0xA:
1546                                                         case 0xB: // 16:9 HD PAL
1547                                                         case 0xC: // > 16:9 HD PAL
1548                                                         case 0xD: // 4:3 HD NTSC
1549                                                         case 0xE:
1550                                                         case 0xF: // 16:9 HD NTSC
1551                                                         case 0x10: // > 16:9 HD PAL
1552                                                                 return data->getComponentType();
1553                                                 }
1554                                         }
1555                                 }
1556                         }
1557                 }
1558                 return -1;
1559         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1560         case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1561         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1562         case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1563         case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1564         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1565         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1566         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1567         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1568         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1569         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1570         case sProvider: if (!m_dvb_service) return -1; return -2;
1571         case sServiceref: return resIsString;
1572         case sDVBState: return m_tune_state;
1573         default:
1574                 return -1;
1575         }
1576 }
1577
1578 std::string eDVBServicePlay::getInfoString(int w)
1579 {
1580         switch (w)
1581         {
1582         case sProvider:
1583                 if (!m_dvb_service) return "";
1584                 return m_dvb_service->m_provider_name;
1585         case sServiceref:
1586                 return m_reference.toString();
1587         default:
1588                 break;
1589         }
1590         return iServiceInformation::getInfoString(w);
1591 }
1592
1593 PyObject *eDVBServicePlay::getInfoObject(int w)
1594 {
1595         switch (w)
1596         {
1597         case sCAIDs:
1598                 return m_service_handler.getCaIds();
1599         case sTransponderData:
1600                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1601         default:
1602                 break;
1603         }
1604         return iServiceInformation::getInfoObject(w);
1605 }
1606
1607 int eDVBServicePlay::getNumberOfTracks()
1608 {
1609         eDVBServicePMTHandler::program program;
1610         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1611         if (h.getProgramInfo(program))
1612                 return 0;
1613         return program.audioStreams.size();
1614 }
1615
1616 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1617 {
1618         int ret = selectAudioStream(i);
1619
1620         if (m_decoder->start())
1621                 return -5;
1622
1623         return ret;
1624 }
1625
1626 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1627 {
1628         eDVBServicePMTHandler::program program;
1629         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1630
1631         if (h.getProgramInfo(program))
1632                 return -1;
1633         
1634         if (i >= program.audioStreams.size())
1635                 return -2;
1636         
1637         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1638                 info.m_description = "MPEG";
1639         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1640                 info.m_description = "AC3";
1641         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1642                 info.m_description = "AAC";
1643         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1644                 info.m_description = "DTS";
1645         else
1646                 info.m_description = "???";
1647
1648         if (program.audioStreams[i].component_tag != -1)
1649         {
1650                 ePtr<eServiceEvent> evt;
1651                 if (!m_event_handler.getEvent(evt, 0))
1652                 {
1653                         ePtr<eComponentData> data;
1654                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1655                                 info.m_language = data->getText();
1656                 }
1657         }
1658
1659         if (info.m_language.empty())
1660                 info.m_language = program.audioStreams[i].language_code;
1661         
1662         return 0;
1663 }
1664
1665 int eDVBServicePlay::selectAudioStream(int i)
1666 {
1667         eDVBServicePMTHandler::program program;
1668         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1669
1670         if (h.getProgramInfo(program))
1671                 return -1;
1672         
1673         if ((unsigned int)i >= program.audioStreams.size())
1674                 return -2;
1675         
1676         if (!m_decoder)
1677                 return -3;
1678         
1679         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1680                 return -4;
1681
1682         if (m_radiotext_parser)
1683                 m_radiotext_parser->start(program.audioStreams[i].pid);
1684
1685         if (m_dvb_service && !m_is_pvr)
1686         {
1687                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1688                 {
1689                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1690                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1691                 }
1692                 else
1693                 {
1694                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1695                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1696                 }
1697         }
1698
1699         h.resetCachedProgram();
1700
1701         return 0;
1702 }
1703
1704 int eDVBServicePlay::getCurrentChannel()
1705 {
1706         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1707 }
1708
1709 RESULT eDVBServicePlay::selectChannel(int i)
1710 {
1711         if (i < LEFT || i > RIGHT || i == STEREO)
1712                 i = -1;  // Stereo
1713         if (m_dvb_service)
1714                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1715         if (m_decoder)
1716                 m_decoder->setAudioChannel(i);
1717         return 0;
1718 }
1719
1720 std::string eDVBServicePlay::getRadioText(int x)
1721 {
1722         if (m_radiotext_parser)
1723                 switch(x)
1724                 {
1725                         case 0:
1726                                 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1727                 }
1728         return "";
1729 }
1730
1731 void eDVBServicePlay::radioTextUpdated()
1732 {
1733         m_event((iPlayableService*)this, evUpdatedRadioText);
1734 }
1735
1736 int eDVBServiceBase::getFrontendInfo(int w)
1737 {
1738         eUsePtr<iDVBChannel> channel;
1739         if(m_service_handler.getChannel(channel))
1740                 return 0;
1741         ePtr<iDVBFrontend> fe;
1742         if(channel->getFrontend(fe))
1743                 return 0;
1744         return fe->readFrontendData(w);
1745 }
1746
1747 PyObject *eDVBServiceBase::getFrontendData(bool original)
1748 {
1749         ePyObject ret;
1750
1751         eUsePtr<iDVBChannel> channel;
1752         if(!m_service_handler.getChannel(channel))
1753         {
1754                 ePtr<iDVBFrontend> fe;
1755                 if(!channel->getFrontend(fe))
1756                 {
1757                         ret = fe->readTransponderData(original);
1758                         if (ret)
1759                         {
1760                                 ePtr<iDVBFrontendParameters> feparm;
1761                                 channel->getCurrentFrontendParameters(feparm);
1762                                 if (feparm)
1763                                 {
1764                                         eDVBFrontendParametersSatellite osat;
1765                                         if (!feparm->getDVBS(osat))
1766                                         {
1767                                                 void PutToDict(ePyObject &, const char*, long);
1768                                                 void PutToDict(ePyObject &, const char*, const char*);
1769                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1770                                                 const char *tmp = "UNKNOWN";
1771                                                 switch(osat.polarisation)
1772                                                 {
1773                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1774                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1775                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1776                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1777                                                         default:break;
1778                                                 }
1779                                                 PutToDict(ret, "polarization", tmp);
1780                                         }
1781                                 }
1782                         }
1783                 }
1784         }
1785         if (!ret)
1786                 Py_RETURN_NONE;
1787         return ret;
1788 }
1789
1790 int eDVBServicePlay::getNumberOfSubservices()
1791 {
1792         ePtr<eServiceEvent> evt;
1793         if (!m_event_handler.getEvent(evt, 0))
1794                 return evt->getNumOfLinkageServices();
1795         return 0;
1796 }
1797
1798 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1799 {
1800         ePtr<eServiceEvent> evt;
1801         if (!m_event_handler.getEvent(evt, 0))
1802         {
1803                 if (!evt->getLinkageService(sub, m_reference, n))
1804                         return 0;
1805         }
1806         sub.type=eServiceReference::idInvalid;
1807         return -1;
1808 }
1809
1810 RESULT eDVBServicePlay::startTimeshift()
1811 {
1812         ePtr<iDVBDemux> demux;
1813         
1814         eDebug("Start timeshift!");
1815         
1816         if (m_timeshift_enabled)
1817                 return -1;
1818         
1819                 /* start recording with the data demux. */
1820         if (m_service_handler.getDataDemux(demux))
1821                 return -2;
1822
1823         demux->createTSRecorder(m_record);
1824         if (!m_record)
1825                 return -3;
1826
1827         char templ[]=TSPATH "/timeshift.XXXXXX";
1828         m_timeshift_fd = mkstemp(templ);
1829         m_timeshift_file = templ;
1830         
1831         eDebug("recording to %s", templ);
1832         
1833         if (m_timeshift_fd < 0)
1834         {
1835                 m_record = 0;
1836                 return -4;
1837         }
1838                 
1839         m_record->setTargetFD(m_timeshift_fd);
1840
1841         m_timeshift_enabled = 1;
1842         
1843         updateTimeshiftPids();
1844         m_record->start();
1845
1846         return 0;
1847 }
1848
1849 RESULT eDVBServicePlay::stopTimeshift()
1850 {
1851         if (!m_timeshift_enabled)
1852                 return -1;
1853         
1854         switchToLive();
1855         
1856         m_timeshift_enabled = 0;
1857         
1858         m_record->stop();
1859         m_record = 0;
1860         
1861         close(m_timeshift_fd);
1862         eDebug("remove timeshift file");
1863         remove(m_timeshift_file.c_str());
1864         
1865         return 0;
1866 }
1867
1868 int eDVBServicePlay::isTimeshiftActive()
1869 {
1870         return m_timeshift_enabled && m_timeshift_active;
1871 }
1872
1873 RESULT eDVBServicePlay::activateTimeshift()
1874 {
1875         if (!m_timeshift_enabled)
1876                 return -1;
1877         
1878         if (!m_timeshift_active)
1879         {
1880                 switchToTimeshift();
1881                 return 0;
1882         }
1883         
1884         return -2;
1885 }
1886
1887 PyObject *eDVBServicePlay::getCutList()
1888 {
1889         ePyObject list = PyList_New(0);
1890         
1891         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1892         {
1893                 ePyObject tuple = PyTuple_New(2);
1894                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1895                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1896                 PyList_Append(list, tuple);
1897                 Py_DECREF(tuple);
1898         }
1899         
1900         return list;
1901 }
1902
1903 void eDVBServicePlay::setCutList(ePyObject list)
1904 {
1905         if (!PyList_Check(list))
1906                 return;
1907         int size = PyList_Size(list);
1908         int i;
1909         
1910         m_cue_entries.clear();
1911         
1912         for (i=0; i<size; ++i)
1913         {
1914                 ePyObject tuple = PyList_GET_ITEM(list, i);
1915                 if (!PyTuple_Check(tuple))
1916                 {
1917                         eDebug("non-tuple in cutlist");
1918                         continue;
1919                 }
1920                 if (PyTuple_Size(tuple) != 2)
1921                 {
1922                         eDebug("cutlist entries need to be a 2-tuple");
1923                         continue;
1924                 }
1925                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1926                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1927                 {
1928                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1929                         continue;
1930                 }
1931                 pts_t pts = PyLong_AsLongLong(ppts);
1932                 int type = PyInt_AsLong(ptype);
1933                 m_cue_entries.insert(cueEntry(pts, type));
1934                 eDebug("adding %08llx, %d", pts, type);
1935         }
1936         m_cuesheet_changed = 1;
1937         
1938         cutlistToCuesheet();
1939         m_event((iPlayableService*)this, evCuesheetChanged);
1940 }
1941
1942 void eDVBServicePlay::setCutListEnable(int enable)
1943 {
1944         m_cutlist_enabled = enable;
1945         cutlistToCuesheet();
1946 }
1947
1948 void eDVBServicePlay::updateTimeshiftPids()
1949 {
1950         if (!m_record)
1951                 return;
1952         
1953         eDVBServicePMTHandler::program program;
1954         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1955
1956         if (h.getProgramInfo(program))
1957                 return;
1958         else
1959         {
1960                 std::set<int> pids_to_record;
1961                 pids_to_record.insert(0); // PAT
1962                 if (program.pmtPid != -1)
1963                         pids_to_record.insert(program.pmtPid); // PMT
1964
1965                 if (program.textPid != -1)
1966                         pids_to_record.insert(program.textPid); // Videotext
1967
1968                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1969                         i(program.videoStreams.begin()); 
1970                         i != program.videoStreams.end(); ++i)
1971                         pids_to_record.insert(i->pid);
1972
1973                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1974                         i(program.audioStreams.begin()); 
1975                         i != program.audioStreams.end(); ++i)
1976                                 pids_to_record.insert(i->pid);
1977
1978                 std::set<int> new_pids, obsolete_pids;
1979                 
1980                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1981                                 m_pids_active.begin(), m_pids_active.end(),
1982                                 std::inserter(new_pids, new_pids.begin()));
1983                 
1984                 std::set_difference(
1985                                 m_pids_active.begin(), m_pids_active.end(),
1986                                 pids_to_record.begin(), pids_to_record.end(), 
1987                                 std::inserter(new_pids, new_pids.begin())
1988                                 );
1989
1990                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1991                         m_record->addPID(*i);
1992
1993                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1994                         m_record->removePID(*i);
1995         }
1996 }
1997
1998 void eDVBServicePlay::switchToLive()
1999 {
2000         if (!m_timeshift_active)
2001                 return;
2002         
2003         m_cue = 0;
2004         m_decoder = 0;
2005         m_decode_demux = 0;
2006         m_teletext_parser = 0;
2007         m_radiotext_parser = 0;
2008         m_subtitle_parser = 0;
2009         m_new_dvb_subtitle_page_connection = 0;
2010         m_new_subtitle_page_connection = 0;
2011         m_radiotext_updated_connection = 0;
2012
2013                 /* free the timeshift service handler, we need the resources */
2014         m_service_handler_timeshift.free();
2015         m_timeshift_active = 0;
2016
2017         m_event((iPlayableService*)this, evSeekableStatusChanged);
2018
2019         updateDecoder();
2020 }
2021
2022 void eDVBServicePlay::switchToTimeshift()
2023 {
2024         if (m_timeshift_active)
2025                 return;
2026
2027         m_decode_demux = 0;
2028         m_decoder = 0;
2029         m_teletext_parser = 0;
2030         m_radiotext_parser = 0;
2031         m_subtitle_parser = 0;
2032         m_new_subtitle_page_connection = 0;
2033         m_new_dvb_subtitle_page_connection = 0;
2034         m_radiotext_updated_connection = 0;
2035
2036         m_timeshift_active = 1;
2037
2038         m_event((iPlayableService*)this, evSeekableStatusChanged);
2039
2040         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2041         r.path = m_timeshift_file;
2042
2043         m_cue = new eCueSheet();
2044         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2045         updateDecoder(); /* mainly to switch off PCR */
2046 }
2047
2048 void eDVBServicePlay::updateDecoder()
2049 {
2050         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2051
2052         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2053
2054         bool defaultac3=false;
2055         std::string default_ac3;
2056
2057         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2058                 defaultac3 = default_ac3 == "True";
2059
2060         eDVBServicePMTHandler::program program;
2061         if (h.getProgramInfo(program))
2062                 eDebug("getting program info failed.");
2063         else
2064         {
2065                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2066                 if (!program.videoStreams.empty())
2067                 {
2068                         eDebugNoNewLine(" (");
2069                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2070                                 i(program.videoStreams.begin());
2071                                 i != program.videoStreams.end(); ++i)
2072                         {
2073                                 if (vpid == -1)
2074                                 {
2075                                         vpid = i->pid;
2076                                         vpidtype = i->type;
2077                                 }
2078                                 if (i != program.videoStreams.begin())
2079                                         eDebugNoNewLine(", ");
2080                                 eDebugNoNewLine("%04x", i->pid);
2081                         }
2082                         eDebugNoNewLine(")");
2083                 }
2084                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2085                 if (!program.audioStreams.empty())
2086                 {
2087                         eDebugNoNewLine(" (");
2088                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2089                                 i(program.audioStreams.begin());
2090                                 i != program.audioStreams.end(); ++i)
2091                         {
2092                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2093                                 {
2094                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2095                                         {
2096                                                 apid = i->pid;
2097                                                 apidtype = i->type;
2098                                         }
2099                                 }
2100                                 if (i != program.audioStreams.begin())
2101                                         eDebugNoNewLine(", ");
2102                                 eDebugNoNewLine("%04x", i->pid);
2103                         }
2104                         eDebugNoNewLine(")");
2105                 }
2106                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2107                 pcrpid = program.pcrPid;
2108                 eDebug(", and the text pid is %04x", program.textPid);
2109                 tpid = program.textPid;
2110         }
2111
2112         if (!m_decoder)
2113         {
2114                 h.getDecodeDemux(m_decode_demux);
2115                 if (m_decode_demux)
2116                 {
2117                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2118                         if (m_decoder)
2119                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2120                 }
2121                 if (m_cue)
2122                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2123                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2124                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2125                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2126                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2127         }
2128
2129         if (m_decoder)
2130         {
2131                 if (m_dvb_service)
2132                 {
2133                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2134                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2135                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2136                 }
2137                 else // subservice or recording
2138                 {
2139                         eServiceReferenceDVB ref;
2140                         m_service_handler.getServiceReference(ref);
2141                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2142                         if (!parent)
2143                                 parent = ref;
2144                         if (parent)
2145                         {
2146                                 ePtr<eDVBResourceManager> res_mgr;
2147                                 if (!eDVBResourceManager::getInstance(res_mgr))
2148                                 {
2149                                         ePtr<iDVBChannelList> db;
2150                                         if (!res_mgr->getChannelList(db))
2151                                         {
2152                                                 ePtr<eDVBService> origService;
2153                                                 if (!db->getService(parent, origService))
2154                                                 {
2155                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2156                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2157                                                 }
2158                                         }
2159                                 }
2160                         }
2161                 }
2162                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2163                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2164
2165                 m_decoder->setVideoPID(vpid, vpidtype);
2166                 m_decoder->setAudioPID(apid, apidtype);
2167                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2168                 {
2169                         m_decoder->setSyncPCR(pcrpid);
2170                         if (apid != -1)
2171                         {
2172                                 ePtr<iDVBDemux> data_demux;
2173                                 if (!h.getDataDemux(data_demux))
2174                                 {
2175                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2176                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2177                                         m_radiotext_parser->start(apid);
2178                                 }
2179                         }
2180                 }
2181                 else
2182                         m_decoder->setSyncPCR(-1);
2183
2184                 m_decoder->setTextPID(tpid);
2185
2186                 m_teletext_parser->start(program.textPid);
2187
2188                 if (!m_is_primary)
2189                         m_decoder->setTrickmode(1);
2190
2191                 m_decoder->start();
2192
2193                 if (vpid > 0 && vpid < 0x2000)
2194                         ;
2195                 else
2196                 {
2197                         std::string radio_pic;
2198                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2199                                 m_decoder->setRadioPic(radio_pic);
2200                 }
2201
2202                 m_decoder->setAudioChannel(achannel);
2203
2204 // how we can do this better?
2205 // update cache pid when the user changed the audio track or video track
2206 // TODO handling of difference audio types.. default audio types..
2207                                 
2208                 /* don't worry about non-existing services, nor pvr services */
2209                 if (m_dvb_service && !m_is_pvr)
2210                 {
2211                         if (apidtype == eDVBAudio::aMPEG)
2212                         {
2213                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2214                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2215                         }
2216                         else
2217                         {
2218                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2219                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2220                         }
2221                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2222                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2223                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2224                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2225                 }
2226         }       
2227         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2228 }
2229
2230 void eDVBServicePlay::loadCuesheet()
2231 {
2232         std::string filename = m_reference.path + ".cuts";
2233         
2234         m_cue_entries.clear();
2235
2236         FILE *f = fopen(filename.c_str(), "rb");
2237
2238         if (f)
2239         {
2240                 eDebug("loading cuts..");
2241                 while (1)
2242                 {
2243                         unsigned long long where;
2244                         unsigned int what;
2245                         
2246                         if (!fread(&where, sizeof(where), 1, f))
2247                                 break;
2248                         if (!fread(&what, sizeof(what), 1, f))
2249                                 break;
2250                         
2251 #if BYTE_ORDER == LITTLE_ENDIAN
2252                         where = bswap_64(where);
2253 #endif
2254                         what = ntohl(what);
2255                         
2256                         if (what > 3)
2257                                 break;
2258                         
2259                         m_cue_entries.insert(cueEntry(where, what));
2260                 }
2261                 fclose(f);
2262                 eDebug("%d entries", m_cue_entries.size());
2263         } else
2264                 eDebug("cutfile not found!");
2265         
2266         m_cuesheet_changed = 0;
2267         cutlistToCuesheet();
2268         m_event((iPlayableService*)this, evCuesheetChanged);
2269 }
2270
2271 void eDVBServicePlay::saveCuesheet()
2272 {
2273         std::string filename = m_reference.path + ".cuts";
2274         
2275         FILE *f = fopen(filename.c_str(), "wb");
2276
2277         if (f)
2278         {
2279                 unsigned long long where;
2280                 int what;
2281
2282                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2283                 {
2284 #if BYTE_ORDER == BIG_ENDIAN
2285                         where = i->where;
2286 #else
2287                         where = bswap_64(i->where);
2288 #endif
2289                         what = htonl(i->what);
2290                         fwrite(&where, sizeof(where), 1, f);
2291                         fwrite(&what, sizeof(what), 1, f);
2292                         
2293                 }
2294                 fclose(f);
2295         }
2296         
2297         m_cuesheet_changed = 0;
2298 }
2299
2300 void eDVBServicePlay::cutlistToCuesheet()
2301 {
2302         if (!m_cue)
2303         {
2304                 eDebug("no cue sheet");
2305                 return;
2306         }       
2307         m_cue->clear();
2308         
2309         if (!m_cutlist_enabled)
2310         {
2311                 m_cue->commitSpans();
2312                 eDebug("cutlists were disabled");
2313                 return;
2314         }
2315
2316         pts_t in = 0, out = 0, length = 0;
2317         
2318         getLength(length);
2319                 
2320         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2321         
2322         while (1)
2323         {
2324                 if (i == m_cue_entries.end())
2325                         out = length;
2326                 else {
2327                         if (i->what == 0) /* in */
2328                         {
2329                                 in = i++->where;
2330                                 continue;
2331                         } else if (i->what == 1) /* out */
2332                                 out = i++->where;
2333                         else /* mark (2) or last play position (3) */
2334                         {
2335                                 i++;
2336                                 continue;
2337                         }
2338                 }
2339                 
2340                 if (in != out)
2341                         m_cue->addSourceSpan(in, out);
2342                 
2343                 in = length;
2344                 
2345                 if (i == m_cue_entries.end())
2346                         break;
2347         }
2348         m_cue->commitSpans();
2349 }
2350
2351 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2352 {
2353         if (m_subtitle_widget)
2354                 disableSubtitles(parent);
2355
2356         ePyObject entry;
2357         int tuplesize = PyTuple_Size(tuple);
2358         int type = 0;
2359
2360         if (!PyTuple_Check(tuple))
2361                 goto error_out;
2362
2363         if (tuplesize < 1)
2364                 goto error_out;
2365
2366         entry = PyTuple_GET_ITEM(tuple, 0);
2367
2368         if (!PyInt_Check(entry))
2369                 goto error_out;
2370
2371         type = PyInt_AsLong(entry);
2372
2373         if (type == 1)  // teletext subtitles
2374         {
2375                 int page, magazine, pid;
2376                 if (tuplesize < 4)
2377                         goto error_out;
2378
2379                 if (!m_teletext_parser)
2380                 {
2381                         eDebug("enable teletext subtitles.. no parser !!!");
2382                         return -1;
2383                 }
2384
2385                 entry = PyTuple_GET_ITEM(tuple, 1);
2386                 if (!PyInt_Check(entry))
2387                         goto error_out;
2388                 pid = PyInt_AsLong(entry);
2389
2390                 entry = PyTuple_GET_ITEM(tuple, 2);
2391                 if (!PyInt_Check(entry))
2392                         goto error_out;
2393                 page = PyInt_AsLong(entry);
2394
2395                 entry = PyTuple_GET_ITEM(tuple, 3);
2396                 if (!PyInt_Check(entry))
2397                         goto error_out;
2398                 magazine = PyInt_AsLong(entry);
2399
2400                 m_subtitle_widget = new eSubtitleWidget(parent);
2401                 m_subtitle_widget->resize(parent->size()); /* full size */
2402                 m_teletext_parser->setPageAndMagazine(page, magazine);
2403                 if (m_dvb_service)
2404                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2405         }
2406         else if (type == 0)
2407         {
2408                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2409                 if (!m_subtitle_parser)
2410                 {
2411                         eDebug("enable dvb subtitles.. no parser !!!");
2412                         return -1;
2413                 }
2414                 if (tuplesize < 4)
2415                         goto error_out;
2416
2417                 entry = PyTuple_GET_ITEM(tuple, 1);
2418                 if (!PyInt_Check(entry))
2419                         goto error_out;
2420                 pid = PyInt_AsLong(entry);
2421
2422                 entry = PyTuple_GET_ITEM(tuple, 2);
2423                 if (!PyInt_Check(entry))
2424                         goto error_out;
2425                 composition_page_id = PyInt_AsLong(entry);
2426
2427                 entry = PyTuple_GET_ITEM(tuple, 3);
2428                 if (!PyInt_Check(entry))
2429                         goto error_out;
2430                 ancillary_page_id = PyInt_AsLong(entry);
2431
2432                 m_subtitle_widget = new eSubtitleWidget(parent);
2433                 m_subtitle_widget->resize(parent->size()); /* full size */
2434                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2435                 if (m_dvb_service)
2436                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2437         }
2438         else
2439                 goto error_out;
2440         return 0;
2441 error_out:
2442         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2443                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2444                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2445         return -1;
2446 }
2447
2448 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2449 {
2450         delete m_subtitle_widget;
2451         m_subtitle_widget = 0;
2452         if (m_subtitle_parser)
2453         {
2454                 m_subtitle_parser->stop();
2455                 m_dvb_subtitle_pages.clear();
2456         }
2457         if (m_teletext_parser)
2458         {
2459                 m_teletext_parser->setPageAndMagazine(-1, -1);
2460                 m_subtitle_pages.clear();
2461         }
2462         if (m_dvb_service)
2463                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2464         return 0;
2465 }
2466
2467 PyObject *eDVBServicePlay::getCachedSubtitle()
2468 {
2469         if (m_dvb_service)
2470         {
2471                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2472                 if (tmp != -1)
2473                 {
2474                         unsigned int data = (unsigned int)tmp;
2475                         int pid = (data&0xFFFF0000)>>16;
2476                         ePyObject tuple = PyTuple_New(4);
2477                         eDVBServicePMTHandler::program program;
2478                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2479                         if (!h.getProgramInfo(program))
2480                         {
2481                                 if (program.textPid==pid) // teletext
2482                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2483                                 else
2484                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2485                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2486                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2487                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2488                                 return tuple;
2489                         }
2490                 }
2491         }
2492         Py_RETURN_NONE;
2493 }
2494
2495 PyObject *eDVBServicePlay::getSubtitleList()
2496 {
2497         if (!m_teletext_parser)
2498                 Py_RETURN_NONE;
2499         
2500         ePyObject l = PyList_New(0);
2501         std::set<int> added_ttx_pages;
2502
2503         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2504                 m_teletext_parser->m_found_subtitle_pages;
2505
2506         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2507         eDVBServicePMTHandler::program program;
2508         if (h.getProgramInfo(program))
2509                 eDebug("getting program info failed.");
2510         else
2511         {
2512                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2513                         it != program.subtitleStreams.end(); ++it)
2514                 {
2515                         switch(it->subtitling_type)
2516                         {
2517                                 case 0x01: // ebu teletext subtitles
2518                                 {
2519                                         int page_number = it->teletext_page_number & 0xFF;
2520                                         int magazine_number = it->teletext_magazine_number & 7;
2521                                         int hash = magazine_number << 8 | page_number;
2522                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2523                                         {
2524                                                 ePyObject tuple = PyTuple_New(5);
2525                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2526                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2527                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2528                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2529                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2530                                                 PyList_Append(l, tuple);
2531                                                 Py_DECREF(tuple);
2532                                                 added_ttx_pages.insert(hash);
2533                                         }
2534                                         break;
2535                                 }
2536                                 case 0x10 ... 0x13:
2537                                 case 0x20 ... 0x23: // dvb subtitles
2538                                 {
2539                                         ePyObject tuple = PyTuple_New(5);
2540                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2541                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2542                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2543                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2544                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2545                                         PyList_Insert(l, 0, tuple);
2546                                         Py_DECREF(tuple);
2547                                         break;
2548                                 }
2549                         }
2550                 }
2551         }
2552
2553         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2554                 it != subs.end(); ++it)
2555         {
2556                 int page_number = it->teletext_page_number & 0xFF;
2557                 int magazine_number = it->teletext_magazine_number & 7;
2558                 int hash = magazine_number << 8 | page_number;
2559                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2560                 {
2561                         ePyObject tuple = PyTuple_New(5);
2562                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2563                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2564                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2565                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2566                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2567                         PyList_Append(l, tuple);
2568                         Py_DECREF(tuple);
2569                 }
2570         }
2571
2572         return l;
2573 }
2574
2575 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2576 {
2577         if (m_subtitle_widget)
2578         {
2579                 m_subtitle_pages.push_back(page);
2580                 checkSubtitleTiming();
2581         }
2582 }
2583
2584 void eDVBServicePlay::checkSubtitleTiming()
2585 {
2586 //      eDebug("checkSubtitleTiming");
2587         if (!m_subtitle_widget)
2588                 return;
2589         while (1)
2590         {
2591                 enum { TELETEXT, DVB } type;
2592                 eDVBTeletextSubtitlePage page;
2593                 eDVBSubtitlePage dvb_page;
2594                 pts_t show_time;
2595                 if (!m_subtitle_pages.empty())
2596                 {
2597                         page = m_subtitle_pages.front();
2598                         type = TELETEXT;
2599                         show_time = page.m_pts;
2600                 }
2601                 else if (!m_dvb_subtitle_pages.empty())
2602                 {
2603                         dvb_page = m_dvb_subtitle_pages.front();
2604                         type = DVB;
2605                         show_time = dvb_page.m_show_time;
2606                 }
2607                 else
2608                         return;
2609         
2610                 pts_t pos = 0;
2611         
2612                 if (m_decoder)
2613                         m_decoder->getPTS(0, pos);
2614
2615 //              eDebug("%lld %lld", pos, show_time);
2616                 int diff =  show_time - pos;
2617                 if (diff < 0)
2618                 {
2619                         eDebug("[late (%d ms)]", -diff / 90);
2620                         diff = 0;
2621                 }
2622                 if (diff > 900000)
2623                 {
2624                         eDebug("[invalid]");
2625                         diff = 0;
2626                 }
2627         
2628                 if (!diff)
2629                 {
2630                         if (type == TELETEXT)
2631                         {
2632                                 eDebug("display teletext subtitle page");
2633                                 m_subtitle_widget->setPage(page);
2634                                 m_subtitle_pages.pop_front();
2635                         }
2636                         else
2637                         {
2638                                 eDebug("display dvb subtitle Page");
2639                                 m_subtitle_widget->setPage(dvb_page);
2640                                 m_dvb_subtitle_pages.pop_front();
2641                         }
2642                 } else
2643                 {
2644 //                      eDebug("start subtitle delay %d", diff / 90);
2645                         m_subtitle_sync_timer.start(diff / 90, 1);
2646                         break;
2647                 }
2648         }
2649 }
2650
2651 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2652 {
2653         if (m_subtitle_widget)
2654         {
2655                 m_dvb_subtitle_pages.push_back(p);
2656                 checkSubtitleTiming();
2657         }
2658 }
2659
2660 int eDVBServicePlay::getAC3Delay()
2661 {
2662         if (m_dvb_service)
2663                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2664         else if (m_decoder)
2665                 return m_decoder->getAC3Delay();
2666         else
2667                 return 0;
2668 }
2669
2670 int eDVBServicePlay::getPCMDelay()
2671 {
2672         if (m_dvb_service)
2673                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2674         else if (m_decoder)
2675                 return m_decoder->getPCMDelay();
2676         else
2677                 return 0;
2678 }
2679
2680 void eDVBServicePlay::setAC3Delay(int delay)
2681 {
2682         if (m_dvb_service)
2683                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2684         if (m_decoder)
2685                 m_decoder->setAC3Delay(delay);
2686 }
2687
2688 void eDVBServicePlay::setPCMDelay(int delay)
2689 {
2690         if (m_dvb_service)
2691                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2692         if (m_decoder)
2693                 m_decoder->setPCMDelay(delay);
2694 }
2695
2696 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2697 {
2698         eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2699         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2700         m_event((iPlayableService*)this, evVideoSizeChanged);
2701 }
2702
2703 DEFINE_REF(eDVBServicePlay)
2704
2705 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");