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