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