send evStart before tuneFailed Events..
[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
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                 loadCuesheet();
1135
1136         m_event((iPlayableService*)this, evSeekableStatusChanged);
1137         return 0;
1138 }
1139
1140 RESULT eDVBServicePlay::stop()
1141 {
1142                 /* add bookmark for last play position */
1143         if (m_is_pvr)
1144         {
1145                 pts_t play_position;
1146                 if (!getPlayPosition(play_position))
1147                 {
1148                                 /* remove last position */
1149                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1150                         {
1151                                 if (i->what == 3) /* current play position */
1152                                 {
1153                                         m_cue_entries.erase(i);
1154                                         i = m_cue_entries.begin();
1155                                         continue;
1156                                 } else
1157                                         ++i;
1158                         }
1159                         
1160                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1161                         m_cuesheet_changed = 1;
1162                 }
1163         }
1164
1165         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1166
1167         m_service_handler_timeshift.free();
1168         m_service_handler.free();
1169         
1170         if (m_is_pvr && m_cuesheet_changed)
1171         {
1172                 struct stat s;
1173                                 /* save cuesheet only when main file is accessible. */
1174                 if (!::stat(m_reference.path.c_str(), &s))
1175                         saveCuesheet();
1176         }
1177         
1178         return 0;
1179 }
1180
1181 RESULT eDVBServicePlay::setTarget(int target)
1182 {
1183         m_is_primary = !target;
1184         return 0;
1185 }
1186
1187 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1188 {
1189         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1190         return 0;
1191 }
1192
1193 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1194 {
1195                 /* note: we check for timeshift to be enabled,
1196                    not neccessary active. if you pause when timeshift
1197                    is not active, you should activate it when unpausing */
1198         if ((!m_is_pvr) && (!m_timeshift_enabled))
1199         {
1200                 ptr = 0;
1201                 return -1;
1202         }
1203
1204         ptr = this;
1205         return 0;
1206 }
1207
1208 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1209 {
1210         if (m_decoder)
1211                 return m_decoder->setSlowMotion(ratio);
1212         else
1213                 return -1;
1214 }
1215
1216 RESULT eDVBServicePlay::setFastForward(int ratio)
1217 {
1218         int skipmode, ffratio;
1219         
1220         if (ratio > 8)
1221         {
1222                 skipmode = ratio;
1223                 ffratio = 1;
1224         } else if (ratio > 0)
1225         {
1226                 skipmode = 0;
1227                 ffratio = ratio;
1228         } else if (!ratio)
1229         {
1230                 skipmode = 0;
1231                 ffratio = 0;
1232         } else // if (ratio < 0)
1233         {
1234                 skipmode = ratio;
1235                 ffratio = 1;
1236         }
1237
1238         if (m_skipmode != skipmode)
1239         {
1240                 eDebug("setting cue skipmode to %d", skipmode);
1241                 if (m_cue)
1242                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1243         }
1244         
1245         m_skipmode = skipmode;
1246         
1247         if (!m_decoder)
1248                 return -1;
1249
1250         return m_decoder->setFastForward(ffratio);
1251 }
1252     
1253 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1254 {
1255         if (m_is_pvr || m_timeshift_enabled)
1256         {
1257                 ptr = this;
1258                 return 0;
1259         }
1260         
1261         ptr = 0;
1262         return -1;
1263 }
1264
1265         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1266 RESULT eDVBServicePlay::getLength(pts_t &len)
1267 {
1268         ePtr<iDVBPVRChannel> pvr_channel;
1269         
1270         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1271                 return -1;
1272         
1273         return pvr_channel->getLength(len);
1274 }
1275
1276 RESULT eDVBServicePlay::pause()
1277 {
1278         if (!m_is_paused && m_decoder)
1279         {
1280                 m_is_paused = 1;
1281                 return m_decoder->freeze(0);
1282         } else
1283                 return -1;
1284 }
1285
1286 RESULT eDVBServicePlay::unpause()
1287 {
1288         if (m_is_paused && m_decoder)
1289         {
1290                 m_is_paused = 0;
1291                 return m_decoder->unfreeze();
1292         } else
1293                 return -1;
1294 }
1295
1296 RESULT eDVBServicePlay::seekTo(pts_t to)
1297 {
1298         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1299         
1300         if (!m_decode_demux)
1301                 return -1;
1302
1303         ePtr<iDVBPVRChannel> pvr_channel;
1304         
1305         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1306                 return -1;
1307         
1308         if (!m_cue)
1309                 return -1;
1310         
1311         m_cue->seekTo(0, to);
1312         return 0;
1313 }
1314
1315 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1316 {
1317         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1318         
1319         if (!m_decode_demux)
1320                 return -1;
1321
1322         ePtr<iDVBPVRChannel> pvr_channel;
1323         
1324         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1325                 return -1;
1326         
1327         int mode = 1;
1328         
1329                         /* HACK until we have skip-AP api */
1330         if ((to > 0) && (to < 100))
1331                 mode = 2;
1332         
1333         to *= direction;
1334         
1335         if (!m_cue)
1336                 return 0;
1337         
1338         m_cue->seekTo(mode, to);
1339         return 0;
1340 }
1341
1342 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1343 {
1344         ePtr<iDVBPVRChannel> pvr_channel;
1345         
1346         if (!m_decode_demux)
1347                 return -1;
1348         
1349         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1350                 return -1;
1351         
1352         int r = 0;
1353
1354                 /* if there is a decoder, use audio or video PTS */
1355         if (m_decoder)
1356         {
1357                 r = m_decoder->getPTS(0, pos);
1358                 if (r)
1359                         return r;
1360         }
1361         
1362                 /* fixup */
1363         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1364 }
1365
1366 RESULT eDVBServicePlay::setTrickmode(int trick)
1367 {
1368         if (m_decoder)
1369                 m_decoder->setTrickmode(trick);
1370         return 0;
1371 }
1372
1373 RESULT eDVBServicePlay::isCurrentlySeekable()
1374 {
1375         return m_is_pvr || m_timeshift_active;
1376 }
1377
1378 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1379 {
1380         ptr = this;
1381         return 0;
1382 }
1383
1384 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1385 {
1386         ptr = this;
1387         return 0;
1388 }
1389
1390 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1391 {
1392         ptr = this;
1393         return 0;
1394 }
1395
1396 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1397 {
1398         ptr = this;
1399         return 0;
1400 }
1401
1402 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1403 {
1404         ptr = this;
1405         return 0;
1406 }
1407
1408 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1409 {
1410         ptr = 0;
1411         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1412                 (m_timeshift_enabled || !m_is_pvr))
1413         {
1414                 if (!m_timeshift_enabled)
1415                 {
1416                                 /* we need enough diskspace */
1417                         struct statfs fs;
1418                         if (statfs(TSPATH "/.", &fs) < 0)
1419                         {
1420                                 eDebug("statfs failed!");
1421                                 return -2;
1422                         }
1423                 
1424                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1425                         {
1426                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1427                                 return -3;
1428                         }
1429                 }
1430                 ptr = this;
1431                 return 0;
1432         }
1433         return -1;
1434 }
1435
1436 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1437 {
1438         if (m_is_pvr)
1439         {
1440                 ptr = this;
1441                 return 0;
1442         }
1443         ptr = 0;
1444         return -1;
1445 }
1446
1447 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1448 {
1449         ptr = this;
1450         return 0;
1451 }
1452
1453 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1454 {
1455         ptr = this;
1456         return 0;
1457 }
1458
1459 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1460 {
1461         ptr = this;
1462         return 0;
1463 }
1464
1465 RESULT eDVBServicePlay::getName(std::string &name)
1466 {
1467         if (m_is_pvr)
1468         {
1469                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1470                 return i->getName(m_reference, name);
1471         }
1472         if (m_dvb_service)
1473         {
1474                 m_dvb_service->getName(m_reference, name);
1475                 if (name.empty())
1476                         name = "(...)";
1477         }
1478         else if (!m_reference.name.empty())
1479                 eStaticServiceDVBInformation().getName(m_reference, name);
1480         else
1481                 name = "DVB service";
1482         return 0;
1483 }
1484
1485 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1486 {
1487         return m_event_handler.getEvent(evt, nownext);
1488 }
1489
1490 int eDVBServicePlay::getInfo(int w)
1491 {
1492         eDVBServicePMTHandler::program program;
1493         
1494         if (w == sCAIDs)
1495                 return resIsPyObject;
1496
1497         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1498         
1499         int no_program_info = 0;
1500         
1501         if (h.getProgramInfo(program))
1502                 no_program_info = 1;
1503         
1504         switch (w)
1505         {
1506 #if HAVE_DVB_API_VERSION >= 3
1507         case sVideoHeight:
1508                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1509                         return m_videoEventData.height;
1510                 return -1;
1511         case sVideoWidth:
1512                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1513                         return m_videoEventData.width;
1514                 return -1;
1515 #else
1516 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1517 #endif
1518         case sAspect:
1519 #if HAVE_DVB_API_VERSION >= 3
1520                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1521                         return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1522                 else
1523 #else
1524 #warning "FIXMEE implement sAspect for old DVB API"
1525 #endif
1526                 if (no_program_info)
1527                         return -1; 
1528                 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1529                 {
1530                         ePtr<eServiceEvent> evt;
1531                         if (!m_event_handler.getEvent(evt, 0))
1532                         {
1533                                 ePtr<eComponentData> data;
1534                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1535                                 {
1536                                         if ( data->getStreamContent() == 1 )
1537                                         {
1538                                                 switch(data->getComponentType())
1539                                                 {
1540                                                         // SD
1541                                                         case 1: // 4:3 SD PAL
1542                                                         case 2:
1543                                                         case 3: // 16:9 SD PAL
1544                                                         case 4: // > 16:9 PAL
1545                                                         case 5: // 4:3 SD NTSC
1546                                                         case 6: 
1547                                                         case 7: // 16:9 SD NTSC
1548                                                         case 8: // > 16:9 NTSC
1549
1550                                                         // HD
1551                                                         case 9: // 4:3 HD PAL
1552                                                         case 0xA:
1553                                                         case 0xB: // 16:9 HD PAL
1554                                                         case 0xC: // > 16:9 HD PAL
1555                                                         case 0xD: // 4:3 HD NTSC
1556                                                         case 0xE:
1557                                                         case 0xF: // 16:9 HD NTSC
1558                                                         case 0x10: // > 16:9 HD PAL
1559                                                                 return data->getComponentType();
1560                                                 }
1561                                         }
1562                                 }
1563                         }
1564                 }
1565                 return -1;
1566         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1567         case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1568         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1569         case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1570         case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1571         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1572         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1573         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1574         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1575         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1576         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1577         case sProvider: if (!m_dvb_service) return -1; return -2;
1578         case sServiceref: return resIsString;
1579         case sDVBState: return m_tune_state;
1580         default:
1581                 return -1;
1582         }
1583 }
1584
1585 std::string eDVBServicePlay::getInfoString(int w)
1586 {
1587         switch (w)
1588         {
1589         case sProvider:
1590                 if (!m_dvb_service) return "";
1591                 return m_dvb_service->m_provider_name;
1592         case sServiceref:
1593                 return m_reference.toString();
1594         default:
1595                 break;
1596         }
1597         return iServiceInformation::getInfoString(w);
1598 }
1599
1600 PyObject *eDVBServicePlay::getInfoObject(int w)
1601 {
1602         switch (w)
1603         {
1604         case sCAIDs:
1605                 return m_service_handler.getCaIds();
1606         case sTransponderData:
1607                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1608         default:
1609                 break;
1610         }
1611         return iServiceInformation::getInfoObject(w);
1612 }
1613
1614 int eDVBServicePlay::getNumberOfTracks()
1615 {
1616         eDVBServicePMTHandler::program program;
1617         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1618         if (h.getProgramInfo(program))
1619                 return 0;
1620         return program.audioStreams.size();
1621 }
1622
1623 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1624 {
1625         int ret = selectAudioStream(i);
1626
1627         if (m_decoder->start())
1628                 return -5;
1629
1630         return ret;
1631 }
1632
1633 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1634 {
1635         eDVBServicePMTHandler::program program;
1636         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1637
1638         if (h.getProgramInfo(program))
1639                 return -1;
1640         
1641         if (i >= program.audioStreams.size())
1642                 return -2;
1643         
1644         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1645                 info.m_description = "MPEG";
1646         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1647                 info.m_description = "AC3";
1648         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1649                 info.m_description = "AAC";
1650         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1651                 info.m_description = "DTS";
1652         else
1653                 info.m_description = "???";
1654
1655         if (program.audioStreams[i].component_tag != -1)
1656         {
1657                 ePtr<eServiceEvent> evt;
1658                 if (!m_event_handler.getEvent(evt, 0))
1659                 {
1660                         ePtr<eComponentData> data;
1661                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1662                                 info.m_language = data->getText();
1663                 }
1664         }
1665
1666         if (info.m_language.empty())
1667                 info.m_language = program.audioStreams[i].language_code;
1668         
1669         return 0;
1670 }
1671
1672 int eDVBServicePlay::selectAudioStream(int i)
1673 {
1674         eDVBServicePMTHandler::program program;
1675         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1676
1677         if (h.getProgramInfo(program))
1678                 return -1;
1679         
1680         if ((unsigned int)i >= program.audioStreams.size())
1681                 return -2;
1682         
1683         if (!m_decoder)
1684                 return -3;
1685         
1686         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1687                 return -4;
1688
1689         if (m_radiotext_parser)
1690                 m_radiotext_parser->start(program.audioStreams[i].pid);
1691
1692         if (m_dvb_service && !m_is_pvr)
1693         {
1694                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1695                 {
1696                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1697                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1698                 }
1699                 else
1700                 {
1701                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1702                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1703                 }
1704         }
1705
1706         h.resetCachedProgram();
1707
1708         return 0;
1709 }
1710
1711 int eDVBServicePlay::getCurrentChannel()
1712 {
1713         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1714 }
1715
1716 RESULT eDVBServicePlay::selectChannel(int i)
1717 {
1718         if (i < LEFT || i > RIGHT || i == STEREO)
1719                 i = -1;  // Stereo
1720         if (m_dvb_service)
1721                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1722         if (m_decoder)
1723                 m_decoder->setAudioChannel(i);
1724         return 0;
1725 }
1726
1727 std::string eDVBServicePlay::getRadioText(int x)
1728 {
1729         if (m_radiotext_parser)
1730                 switch(x)
1731                 {
1732                         case 0:
1733                                 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1734                 }
1735         return "";
1736 }
1737
1738 void eDVBServicePlay::radioTextUpdated()
1739 {
1740         m_event((iPlayableService*)this, evUpdatedRadioText);
1741 }
1742
1743 int eDVBServiceBase::getFrontendInfo(int w)
1744 {
1745         eUsePtr<iDVBChannel> channel;
1746         if(m_service_handler.getChannel(channel))
1747                 return 0;
1748         ePtr<iDVBFrontend> fe;
1749         if(channel->getFrontend(fe))
1750                 return 0;
1751         return fe->readFrontendData(w);
1752 }
1753
1754 PyObject *eDVBServiceBase::getFrontendData(bool original)
1755 {
1756         ePyObject ret;
1757
1758         eUsePtr<iDVBChannel> channel;
1759         if(!m_service_handler.getChannel(channel))
1760         {
1761                 ePtr<iDVBFrontend> fe;
1762                 if(!channel->getFrontend(fe))
1763                 {
1764                         ret = fe->readTransponderData(original);
1765                         if (ret)
1766                         {
1767                                 ePtr<iDVBFrontendParameters> feparm;
1768                                 channel->getCurrentFrontendParameters(feparm);
1769                                 if (feparm)
1770                                 {
1771                                         eDVBFrontendParametersSatellite osat;
1772                                         if (!feparm->getDVBS(osat))
1773                                         {
1774                                                 void PutToDict(ePyObject &, const char*, long);
1775                                                 void PutToDict(ePyObject &, const char*, const char*);
1776                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1777                                                 const char *tmp = "UNKNOWN";
1778                                                 switch(osat.polarisation)
1779                                                 {
1780                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1781                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1782                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1783                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1784                                                         default:break;
1785                                                 }
1786                                                 PutToDict(ret, "polarization", tmp);
1787                                         }
1788                                 }
1789                         }
1790                 }
1791         }
1792         if (!ret)
1793                 Py_RETURN_NONE;
1794         return ret;
1795 }
1796
1797 int eDVBServicePlay::getNumberOfSubservices()
1798 {
1799         ePtr<eServiceEvent> evt;
1800         if (!m_event_handler.getEvent(evt, 0))
1801                 return evt->getNumOfLinkageServices();
1802         return 0;
1803 }
1804
1805 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1806 {
1807         ePtr<eServiceEvent> evt;
1808         if (!m_event_handler.getEvent(evt, 0))
1809         {
1810                 if (!evt->getLinkageService(sub, m_reference, n))
1811                         return 0;
1812         }
1813         sub.type=eServiceReference::idInvalid;
1814         return -1;
1815 }
1816
1817 RESULT eDVBServicePlay::startTimeshift()
1818 {
1819         ePtr<iDVBDemux> demux;
1820         
1821         eDebug("Start timeshift!");
1822         
1823         if (m_timeshift_enabled)
1824                 return -1;
1825         
1826                 /* start recording with the data demux. */
1827         if (m_service_handler.getDataDemux(demux))
1828                 return -2;
1829
1830         demux->createTSRecorder(m_record);
1831         if (!m_record)
1832                 return -3;
1833
1834         char templ[]=TSPATH "/timeshift.XXXXXX";
1835         m_timeshift_fd = mkstemp(templ);
1836         m_timeshift_file = templ;
1837         
1838         eDebug("recording to %s", templ);
1839         
1840         if (m_timeshift_fd < 0)
1841         {
1842                 m_record = 0;
1843                 return -4;
1844         }
1845                 
1846         m_record->setTargetFD(m_timeshift_fd);
1847
1848         m_timeshift_enabled = 1;
1849         
1850         updateTimeshiftPids();
1851         m_record->start();
1852
1853         return 0;
1854 }
1855
1856 RESULT eDVBServicePlay::stopTimeshift()
1857 {
1858         if (!m_timeshift_enabled)
1859                 return -1;
1860         
1861         switchToLive();
1862         
1863         m_timeshift_enabled = 0;
1864         
1865         m_record->stop();
1866         m_record = 0;
1867         
1868         close(m_timeshift_fd);
1869         eDebug("remove timeshift file");
1870         remove(m_timeshift_file.c_str());
1871         
1872         return 0;
1873 }
1874
1875 int eDVBServicePlay::isTimeshiftActive()
1876 {
1877         return m_timeshift_enabled && m_timeshift_active;
1878 }
1879
1880 RESULT eDVBServicePlay::activateTimeshift()
1881 {
1882         if (!m_timeshift_enabled)
1883                 return -1;
1884         
1885         if (!m_timeshift_active)
1886         {
1887                 switchToTimeshift();
1888                 return 0;
1889         }
1890         
1891         return -2;
1892 }
1893
1894 PyObject *eDVBServicePlay::getCutList()
1895 {
1896         ePyObject list = PyList_New(0);
1897         
1898         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1899         {
1900                 ePyObject tuple = PyTuple_New(2);
1901                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1902                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1903                 PyList_Append(list, tuple);
1904                 Py_DECREF(tuple);
1905         }
1906         
1907         return list;
1908 }
1909
1910 void eDVBServicePlay::setCutList(ePyObject list)
1911 {
1912         if (!PyList_Check(list))
1913                 return;
1914         int size = PyList_Size(list);
1915         int i;
1916         
1917         m_cue_entries.clear();
1918         
1919         for (i=0; i<size; ++i)
1920         {
1921                 ePyObject tuple = PyList_GET_ITEM(list, i);
1922                 if (!PyTuple_Check(tuple))
1923                 {
1924                         eDebug("non-tuple in cutlist");
1925                         continue;
1926                 }
1927                 if (PyTuple_Size(tuple) != 2)
1928                 {
1929                         eDebug("cutlist entries need to be a 2-tuple");
1930                         continue;
1931                 }
1932                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1933                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1934                 {
1935                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1936                         continue;
1937                 }
1938                 pts_t pts = PyLong_AsLongLong(ppts);
1939                 int type = PyInt_AsLong(ptype);
1940                 m_cue_entries.insert(cueEntry(pts, type));
1941                 eDebug("adding %08llx, %d", pts, type);
1942         }
1943         m_cuesheet_changed = 1;
1944         
1945         cutlistToCuesheet();
1946         m_event((iPlayableService*)this, evCuesheetChanged);
1947 }
1948
1949 void eDVBServicePlay::setCutListEnable(int enable)
1950 {
1951         m_cutlist_enabled = enable;
1952         cutlistToCuesheet();
1953 }
1954
1955 void eDVBServicePlay::updateTimeshiftPids()
1956 {
1957         if (!m_record)
1958                 return;
1959         
1960         eDVBServicePMTHandler::program program;
1961         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1962
1963         if (h.getProgramInfo(program))
1964                 return;
1965         else
1966         {
1967                 std::set<int> pids_to_record;
1968                 pids_to_record.insert(0); // PAT
1969                 if (program.pmtPid != -1)
1970                         pids_to_record.insert(program.pmtPid); // PMT
1971
1972                 if (program.textPid != -1)
1973                         pids_to_record.insert(program.textPid); // Videotext
1974
1975                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1976                         i(program.videoStreams.begin()); 
1977                         i != program.videoStreams.end(); ++i)
1978                         pids_to_record.insert(i->pid);
1979
1980                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1981                         i(program.audioStreams.begin()); 
1982                         i != program.audioStreams.end(); ++i)
1983                                 pids_to_record.insert(i->pid);
1984
1985                 std::set<int> new_pids, obsolete_pids;
1986                 
1987                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1988                                 m_pids_active.begin(), m_pids_active.end(),
1989                                 std::inserter(new_pids, new_pids.begin()));
1990                 
1991                 std::set_difference(
1992                                 m_pids_active.begin(), m_pids_active.end(),
1993                                 pids_to_record.begin(), pids_to_record.end(), 
1994                                 std::inserter(new_pids, new_pids.begin())
1995                                 );
1996
1997                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1998                         m_record->addPID(*i);
1999
2000                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2001                         m_record->removePID(*i);
2002         }
2003 }
2004
2005 void eDVBServicePlay::switchToLive()
2006 {
2007         if (!m_timeshift_active)
2008                 return;
2009         
2010         m_cue = 0;
2011         m_decoder = 0;
2012         m_decode_demux = 0;
2013         m_teletext_parser = 0;
2014         m_radiotext_parser = 0;
2015         m_subtitle_parser = 0;
2016         m_new_dvb_subtitle_page_connection = 0;
2017         m_new_subtitle_page_connection = 0;
2018         m_radiotext_updated_connection = 0;
2019
2020                 /* free the timeshift service handler, we need the resources */
2021         m_service_handler_timeshift.free();
2022         m_timeshift_active = 0;
2023
2024         m_event((iPlayableService*)this, evSeekableStatusChanged);
2025
2026         updateDecoder();
2027 }
2028
2029 void eDVBServicePlay::switchToTimeshift()
2030 {
2031         if (m_timeshift_active)
2032                 return;
2033
2034         m_decode_demux = 0;
2035         m_decoder = 0;
2036         m_teletext_parser = 0;
2037         m_radiotext_parser = 0;
2038         m_subtitle_parser = 0;
2039         m_new_subtitle_page_connection = 0;
2040         m_new_dvb_subtitle_page_connection = 0;
2041         m_radiotext_updated_connection = 0;
2042
2043         m_timeshift_active = 1;
2044
2045         m_event((iPlayableService*)this, evSeekableStatusChanged);
2046
2047         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2048         r.path = m_timeshift_file;
2049
2050         m_cue = new eCueSheet();
2051         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2052         updateDecoder(); /* mainly to switch off PCR */
2053 }
2054
2055 void eDVBServicePlay::updateDecoder()
2056 {
2057         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2058
2059         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2060
2061         bool defaultac3=false;
2062         std::string default_ac3;
2063
2064         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2065                 defaultac3 = default_ac3 == "True";
2066
2067         eDVBServicePMTHandler::program program;
2068         if (h.getProgramInfo(program))
2069                 eDebug("getting program info failed.");
2070         else
2071         {
2072                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2073                 if (!program.videoStreams.empty())
2074                 {
2075                         eDebugNoNewLine(" (");
2076                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2077                                 i(program.videoStreams.begin());
2078                                 i != program.videoStreams.end(); ++i)
2079                         {
2080                                 if (vpid == -1)
2081                                 {
2082                                         vpid = i->pid;
2083                                         vpidtype = i->type;
2084                                 }
2085                                 if (i != program.videoStreams.begin())
2086                                         eDebugNoNewLine(", ");
2087                                 eDebugNoNewLine("%04x", i->pid);
2088                         }
2089                         eDebugNoNewLine(")");
2090                 }
2091                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2092                 if (!program.audioStreams.empty())
2093                 {
2094                         eDebugNoNewLine(" (");
2095                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2096                                 i(program.audioStreams.begin());
2097                                 i != program.audioStreams.end(); ++i)
2098                         {
2099                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2100                                 {
2101                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2102                                         {
2103                                                 apid = i->pid;
2104                                                 apidtype = i->type;
2105                                         }
2106                                 }
2107                                 if (i != program.audioStreams.begin())
2108                                         eDebugNoNewLine(", ");
2109                                 eDebugNoNewLine("%04x", i->pid);
2110                         }
2111                         eDebugNoNewLine(")");
2112                 }
2113                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2114                 pcrpid = program.pcrPid;
2115                 eDebug(", and the text pid is %04x", program.textPid);
2116                 tpid = program.textPid;
2117         }
2118
2119         if (!m_decoder)
2120         {
2121                 h.getDecodeDemux(m_decode_demux);
2122                 if (m_decode_demux)
2123                 {
2124                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2125                         if (m_decoder)
2126                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2127                 }
2128                 if (m_cue)
2129                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2130                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2131                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2132                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2133                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2134         }
2135
2136         if (m_decoder)
2137         {
2138                 if (m_dvb_service)
2139                 {
2140                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2141                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2142                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2143                 }
2144                 else // subservice or recording
2145                 {
2146                         eServiceReferenceDVB ref;
2147                         m_service_handler.getServiceReference(ref);
2148                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2149                         if (!parent)
2150                                 parent = ref;
2151                         if (parent)
2152                         {
2153                                 ePtr<eDVBResourceManager> res_mgr;
2154                                 if (!eDVBResourceManager::getInstance(res_mgr))
2155                                 {
2156                                         ePtr<iDVBChannelList> db;
2157                                         if (!res_mgr->getChannelList(db))
2158                                         {
2159                                                 ePtr<eDVBService> origService;
2160                                                 if (!db->getService(parent, origService))
2161                                                 {
2162                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2163                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2164                                                 }
2165                                         }
2166                                 }
2167                         }
2168                 }
2169                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2170                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2171
2172                 m_decoder->setVideoPID(vpid, vpidtype);
2173                 m_decoder->setAudioPID(apid, apidtype);
2174                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2175                 {
2176                         m_decoder->setSyncPCR(pcrpid);
2177                         if (apid != -1)
2178                         {
2179                                 ePtr<iDVBDemux> data_demux;
2180                                 if (!h.getDataDemux(data_demux))
2181                                 {
2182                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2183                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2184                                         m_radiotext_parser->start(apid);
2185                                 }
2186                         }
2187                 }
2188                 else
2189                         m_decoder->setSyncPCR(-1);
2190
2191                 m_decoder->setTextPID(tpid);
2192
2193                 m_teletext_parser->start(program.textPid);
2194
2195                 if (!m_is_primary)
2196                         m_decoder->setTrickmode(1);
2197
2198                 m_decoder->start();
2199
2200                 if (vpid > 0 && vpid < 0x2000)
2201                         ;
2202                 else
2203                 {
2204                         std::string radio_pic;
2205                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2206                                 m_decoder->setRadioPic(radio_pic);
2207                 }
2208
2209                 m_decoder->setAudioChannel(achannel);
2210
2211 // how we can do this better?
2212 // update cache pid when the user changed the audio track or video track
2213 // TODO handling of difference audio types.. default audio types..
2214                                 
2215                 /* don't worry about non-existing services, nor pvr services */
2216                 if (m_dvb_service && !m_is_pvr)
2217                 {
2218                         if (apidtype == eDVBAudio::aMPEG)
2219                         {
2220                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2221                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2222                         }
2223                         else
2224                         {
2225                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2226                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2227                         }
2228                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2229                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2230                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2231                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2232                 }
2233         }       
2234         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2235 }
2236
2237 void eDVBServicePlay::loadCuesheet()
2238 {
2239         std::string filename = m_reference.path + ".cuts";
2240         
2241         m_cue_entries.clear();
2242
2243         FILE *f = fopen(filename.c_str(), "rb");
2244
2245         if (f)
2246         {
2247                 eDebug("loading cuts..");
2248                 while (1)
2249                 {
2250                         unsigned long long where;
2251                         unsigned int what;
2252                         
2253                         if (!fread(&where, sizeof(where), 1, f))
2254                                 break;
2255                         if (!fread(&what, sizeof(what), 1, f))
2256                                 break;
2257                         
2258 #if BYTE_ORDER == LITTLE_ENDIAN
2259                         where = bswap_64(where);
2260 #endif
2261                         what = ntohl(what);
2262                         
2263                         if (what > 3)
2264                                 break;
2265                         
2266                         m_cue_entries.insert(cueEntry(where, what));
2267                 }
2268                 fclose(f);
2269                 eDebug("%d entries", m_cue_entries.size());
2270         } else
2271                 eDebug("cutfile not found!");
2272         
2273         m_cuesheet_changed = 0;
2274         cutlistToCuesheet();
2275         m_event((iPlayableService*)this, evCuesheetChanged);
2276 }
2277
2278 void eDVBServicePlay::saveCuesheet()
2279 {
2280         std::string filename = m_reference.path + ".cuts";
2281         
2282         FILE *f = fopen(filename.c_str(), "wb");
2283
2284         if (f)
2285         {
2286                 unsigned long long where;
2287                 int what;
2288
2289                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2290                 {
2291 #if BYTE_ORDER == BIG_ENDIAN
2292                         where = i->where;
2293 #else
2294                         where = bswap_64(i->where);
2295 #endif
2296                         what = htonl(i->what);
2297                         fwrite(&where, sizeof(where), 1, f);
2298                         fwrite(&what, sizeof(what), 1, f);
2299                         
2300                 }
2301                 fclose(f);
2302         }
2303         
2304         m_cuesheet_changed = 0;
2305 }
2306
2307 void eDVBServicePlay::cutlistToCuesheet()
2308 {
2309         if (!m_cue)
2310         {
2311                 eDebug("no cue sheet");
2312                 return;
2313         }       
2314         m_cue->clear();
2315         
2316         if (!m_cutlist_enabled)
2317         {
2318                 m_cue->commitSpans();
2319                 eDebug("cutlists were disabled");
2320                 return;
2321         }
2322
2323         pts_t in = 0, out = 0, length = 0;
2324         
2325         getLength(length);
2326                 
2327         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2328         
2329         while (1)
2330         {
2331                 if (i == m_cue_entries.end())
2332                         out = length;
2333                 else {
2334                         if (i->what == 0) /* in */
2335                         {
2336                                 in = i++->where;
2337                                 continue;
2338                         } else if (i->what == 1) /* out */
2339                                 out = i++->where;
2340                         else /* mark (2) or last play position (3) */
2341                         {
2342                                 i++;
2343                                 continue;
2344                         }
2345                 }
2346                 
2347                 if (in != out)
2348                         m_cue->addSourceSpan(in, out);
2349                 
2350                 in = length;
2351                 
2352                 if (i == m_cue_entries.end())
2353                         break;
2354         }
2355         m_cue->commitSpans();
2356 }
2357
2358 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2359 {
2360         if (m_subtitle_widget)
2361                 disableSubtitles(parent);
2362
2363         ePyObject entry;
2364         int tuplesize = PyTuple_Size(tuple);
2365         int type = 0;
2366
2367         if (!PyTuple_Check(tuple))
2368                 goto error_out;
2369
2370         if (tuplesize < 1)
2371                 goto error_out;
2372
2373         entry = PyTuple_GET_ITEM(tuple, 0);
2374
2375         if (!PyInt_Check(entry))
2376                 goto error_out;
2377
2378         type = PyInt_AsLong(entry);
2379
2380         if (type == 1)  // teletext subtitles
2381         {
2382                 int page, magazine, pid;
2383                 if (tuplesize < 4)
2384                         goto error_out;
2385
2386                 if (!m_teletext_parser)
2387                 {
2388                         eDebug("enable teletext subtitles.. no parser !!!");
2389                         return -1;
2390                 }
2391
2392                 entry = PyTuple_GET_ITEM(tuple, 1);
2393                 if (!PyInt_Check(entry))
2394                         goto error_out;
2395                 pid = PyInt_AsLong(entry);
2396
2397                 entry = PyTuple_GET_ITEM(tuple, 2);
2398                 if (!PyInt_Check(entry))
2399                         goto error_out;
2400                 page = PyInt_AsLong(entry);
2401
2402                 entry = PyTuple_GET_ITEM(tuple, 3);
2403                 if (!PyInt_Check(entry))
2404                         goto error_out;
2405                 magazine = PyInt_AsLong(entry);
2406
2407                 m_subtitle_widget = new eSubtitleWidget(parent);
2408                 m_subtitle_widget->resize(parent->size()); /* full size */
2409                 m_teletext_parser->setPageAndMagazine(page, magazine);
2410                 if (m_dvb_service)
2411                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2412         }
2413         else if (type == 0)
2414         {
2415                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2416                 if (!m_subtitle_parser)
2417                 {
2418                         eDebug("enable dvb subtitles.. no parser !!!");
2419                         return -1;
2420                 }
2421                 if (tuplesize < 4)
2422                         goto error_out;
2423
2424                 entry = PyTuple_GET_ITEM(tuple, 1);
2425                 if (!PyInt_Check(entry))
2426                         goto error_out;
2427                 pid = PyInt_AsLong(entry);
2428
2429                 entry = PyTuple_GET_ITEM(tuple, 2);
2430                 if (!PyInt_Check(entry))
2431                         goto error_out;
2432                 composition_page_id = PyInt_AsLong(entry);
2433
2434                 entry = PyTuple_GET_ITEM(tuple, 3);
2435                 if (!PyInt_Check(entry))
2436                         goto error_out;
2437                 ancillary_page_id = PyInt_AsLong(entry);
2438
2439                 m_subtitle_widget = new eSubtitleWidget(parent);
2440                 m_subtitle_widget->resize(parent->size()); /* full size */
2441                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2442                 if (m_dvb_service)
2443                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2444         }
2445         else
2446                 goto error_out;
2447         return 0;
2448 error_out:
2449         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2450                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2451                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2452         return -1;
2453 }
2454
2455 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2456 {
2457         delete m_subtitle_widget;
2458         m_subtitle_widget = 0;
2459         if (m_subtitle_parser)
2460         {
2461                 m_subtitle_parser->stop();
2462                 m_dvb_subtitle_pages.clear();
2463         }
2464         if (m_teletext_parser)
2465         {
2466                 m_teletext_parser->setPageAndMagazine(-1, -1);
2467                 m_subtitle_pages.clear();
2468         }
2469         if (m_dvb_service)
2470                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2471         return 0;
2472 }
2473
2474 PyObject *eDVBServicePlay::getCachedSubtitle()
2475 {
2476         if (m_dvb_service)
2477         {
2478                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2479                 if (tmp != -1)
2480                 {
2481                         unsigned int data = (unsigned int)tmp;
2482                         int pid = (data&0xFFFF0000)>>16;
2483                         ePyObject tuple = PyTuple_New(4);
2484                         eDVBServicePMTHandler::program program;
2485                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2486                         if (!h.getProgramInfo(program))
2487                         {
2488                                 if (program.textPid==pid) // teletext
2489                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2490                                 else
2491                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2492                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2493                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2494                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2495                                 return tuple;
2496                         }
2497                 }
2498         }
2499         Py_RETURN_NONE;
2500 }
2501
2502 PyObject *eDVBServicePlay::getSubtitleList()
2503 {
2504         if (!m_teletext_parser)
2505                 Py_RETURN_NONE;
2506         
2507         ePyObject l = PyList_New(0);
2508         std::set<int> added_ttx_pages;
2509
2510         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2511                 m_teletext_parser->m_found_subtitle_pages;
2512
2513         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2514         eDVBServicePMTHandler::program program;
2515         if (h.getProgramInfo(program))
2516                 eDebug("getting program info failed.");
2517         else
2518         {
2519                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2520                         it != program.subtitleStreams.end(); ++it)
2521                 {
2522                         switch(it->subtitling_type)
2523                         {
2524                                 case 0x01: // ebu teletext subtitles
2525                                 {
2526                                         int page_number = it->teletext_page_number & 0xFF;
2527                                         int magazine_number = it->teletext_magazine_number & 7;
2528                                         int hash = magazine_number << 8 | page_number;
2529                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2530                                         {
2531                                                 ePyObject tuple = PyTuple_New(5);
2532                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2533                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2534                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2535                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2536                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2537                                                 PyList_Append(l, tuple);
2538                                                 Py_DECREF(tuple);
2539                                                 added_ttx_pages.insert(hash);
2540                                         }
2541                                         break;
2542                                 }
2543                                 case 0x10 ... 0x13:
2544                                 case 0x20 ... 0x23: // dvb subtitles
2545                                 {
2546                                         ePyObject tuple = PyTuple_New(5);
2547                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2548                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2549                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2550                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2551                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2552                                         PyList_Insert(l, 0, tuple);
2553                                         Py_DECREF(tuple);
2554                                         break;
2555                                 }
2556                         }
2557                 }
2558         }
2559
2560         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2561                 it != subs.end(); ++it)
2562         {
2563                 int page_number = it->teletext_page_number & 0xFF;
2564                 int magazine_number = it->teletext_magazine_number & 7;
2565                 int hash = magazine_number << 8 | page_number;
2566                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2567                 {
2568                         ePyObject tuple = PyTuple_New(5);
2569                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2570                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2571                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2572                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2573                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2574                         PyList_Append(l, tuple);
2575                         Py_DECREF(tuple);
2576                 }
2577         }
2578
2579         return l;
2580 }
2581
2582 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2583 {
2584         if (m_subtitle_widget)
2585         {
2586                 m_subtitle_pages.push_back(page);
2587                 checkSubtitleTiming();
2588         }
2589 }
2590
2591 void eDVBServicePlay::checkSubtitleTiming()
2592 {
2593 //      eDebug("checkSubtitleTiming");
2594         if (!m_subtitle_widget)
2595                 return;
2596         while (1)
2597         {
2598                 enum { TELETEXT, DVB } type;
2599                 eDVBTeletextSubtitlePage page;
2600                 eDVBSubtitlePage dvb_page;
2601                 pts_t show_time;
2602                 if (!m_subtitle_pages.empty())
2603                 {
2604                         page = m_subtitle_pages.front();
2605                         type = TELETEXT;
2606                         show_time = page.m_pts;
2607                 }
2608                 else if (!m_dvb_subtitle_pages.empty())
2609                 {
2610                         dvb_page = m_dvb_subtitle_pages.front();
2611                         type = DVB;
2612                         show_time = dvb_page.m_show_time;
2613                 }
2614                 else
2615                         return;
2616         
2617                 pts_t pos = 0;
2618         
2619                 if (m_decoder)
2620                         m_decoder->getPTS(0, pos);
2621
2622 //              eDebug("%lld %lld", pos, show_time);
2623                 int diff =  show_time - pos;
2624                 if (diff < 0)
2625                 {
2626                         eDebug("[late (%d ms)]", -diff / 90);
2627                         diff = 0;
2628                 }
2629                 if (diff > 900000)
2630                 {
2631                         eDebug("[invalid]");
2632                         diff = 0;
2633                 }
2634         
2635                 if (!diff)
2636                 {
2637                         if (type == TELETEXT)
2638                         {
2639                                 eDebug("display teletext subtitle page");
2640                                 m_subtitle_widget->setPage(page);
2641                                 m_subtitle_pages.pop_front();
2642                         }
2643                         else
2644                         {
2645                                 eDebug("display dvb subtitle Page");
2646                                 m_subtitle_widget->setPage(dvb_page);
2647                                 m_dvb_subtitle_pages.pop_front();
2648                         }
2649                 } else
2650                 {
2651 //                      eDebug("start subtitle delay %d", diff / 90);
2652                         m_subtitle_sync_timer.start(diff / 90, 1);
2653                         break;
2654                 }
2655         }
2656 }
2657
2658 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2659 {
2660         if (m_subtitle_widget)
2661         {
2662                 m_dvb_subtitle_pages.push_back(p);
2663                 checkSubtitleTiming();
2664         }
2665 }
2666
2667 int eDVBServicePlay::getAC3Delay()
2668 {
2669         if (m_dvb_service)
2670                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2671         else if (m_decoder)
2672                 return m_decoder->getAC3Delay();
2673         else
2674                 return 0;
2675 }
2676
2677 int eDVBServicePlay::getPCMDelay()
2678 {
2679         if (m_dvb_service)
2680                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2681         else if (m_decoder)
2682                 return m_decoder->getPCMDelay();
2683         else
2684                 return 0;
2685 }
2686
2687 void eDVBServicePlay::setAC3Delay(int delay)
2688 {
2689         if (m_dvb_service)
2690                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2691         if (m_decoder)
2692                 m_decoder->setAC3Delay(delay);
2693 }
2694
2695 void eDVBServicePlay::setPCMDelay(int delay)
2696 {
2697         if (m_dvb_service)
2698                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2699         if (m_decoder)
2700                 m_decoder->setPCMDelay(delay);
2701 }
2702
2703 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2704 {
2705         eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2706         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2707         m_event((iPlayableService*)this, evVideoSizeChanged);
2708 }
2709
2710 DEFINE_REF(eDVBServicePlay)
2711
2712 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2713 {
2714         switch (w)
2715         {
2716         case iServiceInformation::sTransponderData:
2717                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2718         default:
2719                 break;
2720         }
2721         return iStaticServiceInformation::getInfoObject(ref, w);
2722 }
2723
2724 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");