rework decoder states
[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         assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
1285         eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
1286         setFastForward_internal(0);
1287         if (m_decoder)
1288                 return m_decoder->setSlowMotion(ratio);
1289         else
1290                 return -1;
1291 }
1292
1293 RESULT eDVBServicePlay::setFastForward(int ratio)
1294 {
1295         eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
1296         assert(ratio);
1297         return setFastForward_internal(ratio);
1298 }
1299
1300 RESULT eDVBServicePlay::setFastForward_internal(int ratio)
1301 {
1302         int skipmode, ffratio;
1303         
1304         if (ratio > 8)
1305         {
1306                 skipmode = ratio;
1307                 ffratio = 1;
1308         } else if (ratio > 0)
1309         {
1310                 skipmode = 0;
1311                 ffratio = ratio;
1312         } else if (!ratio)
1313         {
1314                 skipmode = 0;
1315                 ffratio = 0;
1316         } else // if (ratio < 0)
1317         {
1318                 skipmode = ratio;
1319                 ffratio = 1;
1320         }
1321
1322         if (m_skipmode != skipmode)
1323         {
1324                 eDebug("setting cue skipmode to %d", skipmode);
1325                 if (m_cue)
1326                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1327         }
1328         
1329         m_skipmode = skipmode;
1330         
1331         if (!m_decoder)
1332                 return -1;
1333
1334         if (ffratio == 0)
1335                 return 0;
1336         else if (ffratio != 1)
1337                 return m_decoder->setFastForward(ffratio);
1338         else
1339                 return m_decoder->setTrickmode();
1340 }
1341
1342 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1343 {
1344         if (m_is_pvr || m_timeshift_enabled)
1345         {
1346                 ptr = this;
1347                 return 0;
1348         }
1349         
1350         ptr = 0;
1351         return -1;
1352 }
1353
1354         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1355 RESULT eDVBServicePlay::getLength(pts_t &len)
1356 {
1357         ePtr<iDVBPVRChannel> pvr_channel;
1358         
1359         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1360                 return -1;
1361         
1362         return pvr_channel->getLength(len);
1363 }
1364
1365 RESULT eDVBServicePlay::pause()
1366 {
1367         eDebug("eDVBServicePlay::pause");
1368         setFastForward_internal(0);
1369         if (m_decoder)
1370         {
1371                 return m_decoder->pause();
1372         } else
1373                 return -1;
1374 }
1375
1376 RESULT eDVBServicePlay::unpause()
1377 {
1378         eDebug("eDVBServicePlay::unpause");
1379         setFastForward_internal(0);
1380         if (m_decoder)
1381         {
1382                 return m_decoder->play();
1383         } else
1384                 return -1;
1385 }
1386
1387 RESULT eDVBServicePlay::seekTo(pts_t to)
1388 {
1389         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1390         
1391         if (!m_decode_demux)
1392                 return -1;
1393
1394         ePtr<iDVBPVRChannel> pvr_channel;
1395         
1396         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1397                 return -1;
1398         
1399         if (!m_cue)
1400                 return -1;
1401         
1402         m_cue->seekTo(0, to);
1403         m_dvb_subtitle_pages.clear();
1404         m_subtitle_pages.clear();
1405
1406         return 0;
1407 }
1408
1409 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1410 {
1411         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1412         
1413         if (!m_decode_demux)
1414                 return -1;
1415
1416         ePtr<iDVBPVRChannel> pvr_channel;
1417         
1418         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1419                 return -1;
1420         
1421         int mode = 1;
1422         
1423                         /* HACK until we have skip-AP api */
1424         if ((to > 0) && (to < 100))
1425                 mode = 2;
1426         
1427         to *= direction;
1428         
1429         if (!m_cue)
1430                 return 0;
1431         
1432         m_cue->seekTo(mode, to);
1433         m_dvb_subtitle_pages.clear();
1434         m_subtitle_pages.clear();
1435         return 0;
1436 }
1437
1438 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1439 {
1440         ePtr<iDVBPVRChannel> pvr_channel;
1441         
1442         if (!m_decode_demux)
1443                 return -1;
1444         
1445         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1446                 return -1;
1447         
1448         int r = 0;
1449
1450                 /* if there is a decoder, use audio or video PTS */
1451         if (m_decoder)
1452         {
1453                 r = m_decoder->getPTS(0, pos);
1454                 if (r)
1455                         return r;
1456         }
1457         
1458                 /* fixup */
1459         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1460 }
1461
1462 RESULT eDVBServicePlay::setTrickmode(int trick)
1463 {
1464                 /* currently unimplemented */
1465         return -1;
1466 }
1467
1468 RESULT eDVBServicePlay::isCurrentlySeekable()
1469 {
1470         return m_is_pvr || m_timeshift_active;
1471 }
1472
1473 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1474 {
1475         ptr = this;
1476         return 0;
1477 }
1478
1479 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1480 {
1481         ptr = this;
1482         return 0;
1483 }
1484
1485 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1486 {
1487         ptr = this;
1488         return 0;
1489 }
1490
1491 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1492 {
1493         ptr = this;
1494         return 0;
1495 }
1496
1497 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1498 {
1499         ptr = this;
1500         return 0;
1501 }
1502
1503 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1504 {
1505         ptr = 0;
1506         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1507                 (m_timeshift_enabled || !m_is_pvr))
1508         {
1509                 if (!m_timeshift_enabled)
1510                 {
1511                         /* query config path */
1512                         std::string tspath;
1513                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1514                                 eDebug("could not query ts path from config");
1515                                 return -4;
1516                         }
1517                         tspath.append("/");
1518                         /* we need enough diskspace */
1519                         struct statfs fs;
1520                         if (statfs(tspath.c_str(), &fs) < 0)
1521                         {
1522                                 eDebug("statfs failed!");
1523                                 return -2;
1524                         }
1525                 
1526                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1527                         {
1528                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1529                                 return -3;
1530                         }
1531                 }
1532                 ptr = this;
1533                 return 0;
1534         }
1535         return -1;
1536 }
1537
1538 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1539 {
1540         if (m_is_pvr)
1541         {
1542                 ptr = this;
1543                 return 0;
1544         }
1545         ptr = 0;
1546         return -1;
1547 }
1548
1549 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1550 {
1551         ptr = this;
1552         return 0;
1553 }
1554
1555 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1556 {
1557         ptr = this;
1558         return 0;
1559 }
1560
1561 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1562 {
1563         ptr = this;
1564         return 0;
1565 }
1566
1567 RESULT eDVBServicePlay::getName(std::string &name)
1568 {
1569         if (m_is_pvr)
1570         {
1571                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1572                 return i->getName(m_reference, name);
1573         }
1574         if (m_dvb_service)
1575         {
1576                 m_dvb_service->getName(m_reference, name);
1577                 if (name.empty())
1578                         name = "(...)";
1579         }
1580         else if (!m_reference.name.empty())
1581                 eStaticServiceDVBInformation().getName(m_reference, name);
1582         else
1583                 name = "DVB service";
1584         return 0;
1585 }
1586
1587 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1588 {
1589         return m_event_handler.getEvent(evt, nownext);
1590 }
1591
1592 static int readMpegProc(char *str, int decoder)
1593 {
1594         int val = -1;
1595         char tmp[64];
1596         sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
1597         FILE *f = fopen(tmp, "r");
1598         if (f)
1599         {
1600                 fscanf(f, "%x", &val);
1601                 fclose(f);
1602         }
1603         return val;
1604 }
1605
1606 int eDVBServicePlay::getInfo(int w)
1607 {
1608         eDVBServicePMTHandler::program program;
1609
1610         if (w == sCAIDs)
1611                 return resIsPyObject;
1612
1613         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1614
1615         int no_program_info = 0;
1616
1617         if (h.getProgramInfo(program))
1618                 no_program_info = 1;
1619
1620         switch (w)
1621         {
1622 #if HAVE_DVB_API_VERSION >= 3
1623         case sVideoHeight:
1624                 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1625                         return m_videoEventData.height;
1626                 else
1627                         return readMpegProc("yres", !m_is_primary);
1628         case sVideoWidth:
1629                 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1630                         return m_videoEventData.width;
1631                 else
1632                         return readMpegProc("xres", !m_is_primary);
1633         case sFrameRate:
1634                 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
1635                         return m_videoEventData.framerate;
1636                 else
1637                         return readMpegProc("framerate", !m_is_primary);
1638         case sProgressive:
1639                 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
1640                         return m_videoEventData.progressive;
1641                 return readMpegProc("progressive", !m_is_primary);
1642 #else
1643 #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
1644 #endif
1645         case sAspect:
1646         {
1647                 int val;
1648 #if HAVE_DVB_API_VERSION >= 3
1649                 if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
1650                         return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1651                 else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
1652                         return val;
1653                 else
1654 #else
1655 #warning "FIXMEE implement sAspect for old DVB API"
1656 #endif
1657                 if (no_program_info)
1658                         return -1; 
1659                 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1660                 {
1661                         ePtr<eServiceEvent> evt;
1662                         if (!m_event_handler.getEvent(evt, 0))
1663                         {
1664                                 ePtr<eComponentData> data;
1665                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1666                                 {
1667                                         if ( data->getStreamContent() == 1 )
1668                                         {
1669                                                 switch(data->getComponentType())
1670                                                 {
1671                                                         // SD
1672                                                         case 1: // 4:3 SD PAL
1673                                                         case 2:
1674                                                         case 3: // 16:9 SD PAL
1675                                                         case 4: // > 16:9 PAL
1676                                                         case 5: // 4:3 SD NTSC
1677                                                         case 6: 
1678                                                         case 7: // 16:9 SD NTSC
1679                                                         case 8: // > 16:9 NTSC
1680
1681                                                         // HD
1682                                                         case 9: // 4:3 HD PAL
1683                                                         case 0xA:
1684                                                         case 0xB: // 16:9 HD PAL
1685                                                         case 0xC: // > 16:9 HD PAL
1686                                                         case 0xD: // 4:3 HD NTSC
1687                                                         case 0xE:
1688                                                         case 0xF: // 16:9 HD NTSC
1689                                                         case 0x10: // > 16:9 HD PAL
1690                                                                 return data->getComponentType();
1691                                                 }
1692                                         }
1693                                 }
1694                         }
1695                 }
1696                 return -1;
1697         }
1698         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1699         case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1700         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1701         case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1702         case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1703         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1704         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1705         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1706         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1707         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1708         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1709         case sProvider: if (!m_dvb_service) return -1; return -2;
1710         case sServiceref: return resIsString;
1711         case sDVBState: return m_tune_state;
1712         default:
1713                 return -1;
1714         }
1715 }
1716
1717 std::string eDVBServicePlay::getInfoString(int w)
1718 {
1719         switch (w)
1720         {
1721         case sProvider:
1722                 if (!m_dvb_service) return "";
1723                 return m_dvb_service->m_provider_name;
1724         case sServiceref:
1725                 return m_reference.toString();
1726         default:
1727                 break;
1728         }
1729         return iServiceInformation::getInfoString(w);
1730 }
1731
1732 PyObject *eDVBServicePlay::getInfoObject(int w)
1733 {
1734         switch (w)
1735         {
1736         case sCAIDs:
1737                 return m_service_handler.getCaIds();
1738         case sTransponderData:
1739                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1740         default:
1741                 break;
1742         }
1743         return iServiceInformation::getInfoObject(w);
1744 }
1745
1746 int eDVBServicePlay::getNumberOfTracks()
1747 {
1748         eDVBServicePMTHandler::program program;
1749         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1750         if (h.getProgramInfo(program))
1751                 return 0;
1752         return program.audioStreams.size();
1753 }
1754
1755 int eDVBServicePlay::getCurrentTrack()
1756 {
1757         eDVBServicePMTHandler::program program;
1758         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1759         if (h.getProgramInfo(program))
1760                 return 0;
1761
1762         int max = program.audioStreams.size();
1763         int i;
1764
1765         for (i = 0; i < max; ++i)
1766                 if (program.audioStreams[i].pid == m_current_audio_pid)
1767                         return i;
1768
1769         return 0;
1770 }
1771
1772 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1773 {
1774         int ret = selectAudioStream(i);
1775
1776         if (m_decoder->play())
1777                 return -5;
1778
1779         return ret;
1780 }
1781
1782 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1783 {
1784         eDVBServicePMTHandler::program program;
1785         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1786
1787         if (h.getProgramInfo(program))
1788                 return -1;
1789         
1790         if (i >= program.audioStreams.size())
1791                 return -2;
1792         
1793         info.m_pid = program.audioStreams[i].pid;
1794
1795         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1796                 info.m_description = "MPEG";
1797         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1798                 info.m_description = "AC3";
1799         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1800                 info.m_description = "AAC";
1801         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1802                 info.m_description = "DTS";
1803         else
1804                 info.m_description = "???";
1805
1806         if (program.audioStreams[i].component_tag != -1)
1807         {
1808                 ePtr<eServiceEvent> evt;
1809                 if (!m_event_handler.getEvent(evt, 0))
1810                 {
1811                         ePtr<eComponentData> data;
1812                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1813                                 info.m_language = data->getText();
1814                 }
1815         }
1816
1817         if (info.m_language.empty())
1818                 info.m_language = program.audioStreams[i].language_code;
1819         
1820         return 0;
1821 }
1822
1823 int eDVBServicePlay::selectAudioStream(int i)
1824 {
1825         eDVBServicePMTHandler::program program;
1826         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1827
1828         if (h.getProgramInfo(program))
1829                 return -1;
1830
1831         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1832                 return -2;
1833
1834         if (!m_decoder)
1835                 return -3;
1836
1837         int stream = i;
1838         if (stream == -1)
1839                 stream = program.defaultAudioStream;
1840
1841         int apid = -1, apidtype = -1;
1842
1843         if (((unsigned int)stream) < program.audioStreams.size())
1844         {
1845                 apid = program.audioStreams[stream].pid;
1846                 apidtype = program.audioStreams[stream].type;
1847         }
1848
1849         m_current_audio_pid = apid;
1850
1851         if (m_decoder->setAudioPID(apid, apidtype))
1852         {
1853                 eDebug("set audio pid failed");
1854                 return -4;
1855         }
1856
1857                 /* 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 */
1858         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1859                 if (!m_rds_decoder)
1860                 {
1861                         ePtr<iDVBDemux> data_demux;
1862                         if (!h.getDataDemux(data_demux))
1863                         {
1864                                 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1865                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1866                         }
1867                 }
1868
1869                 /* if we decided that we need one, update the pid */
1870         if (m_rds_decoder)
1871                 m_rds_decoder->start(apid);
1872
1873                         /* store new pid as default only when:
1874                                 a.) we have an entry in the service db for the current service,
1875                                 b.) we are not playing back something,
1876                                 c.) we are not selecting the default entry. (we wouldn't change 
1877                                     anything in the best case, or destroy the default setting in
1878                                     case the real default is not yet available.)
1879                         */
1880         if (m_dvb_service && !m_is_pvr && ((i != -1)
1881                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1882         {
1883                 if (apidtype == eDVBAudio::aMPEG)
1884                 {
1885                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1886                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1887                 }
1888                 else
1889                 {
1890                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1891                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1892                 }
1893         }
1894
1895         h.resetCachedProgram();
1896
1897         return 0;
1898 }
1899
1900 int eDVBServicePlay::getCurrentChannel()
1901 {
1902         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1903 }
1904
1905 RESULT eDVBServicePlay::selectChannel(int i)
1906 {
1907         if (i < LEFT || i > RIGHT || i == STEREO)
1908                 i = -1;  // Stereo
1909         if (m_dvb_service)
1910                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1911         if (m_decoder)
1912                 m_decoder->setAudioChannel(i);
1913         return 0;
1914 }
1915
1916 std::string eDVBServicePlay::getText(int x)
1917 {
1918         if (m_rds_decoder)
1919                 switch(x)
1920                 {
1921                         case RadioText:
1922                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1923                         case RtpText:
1924                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1925                 }
1926         return "";
1927 }
1928
1929 void eDVBServicePlay::rdsDecoderEvent(int what)
1930 {
1931         switch(what)
1932         {
1933                 case eDVBRdsDecoder::RadioTextChanged:
1934                         m_event((iPlayableService*)this, evUpdatedRadioText);
1935                         break;
1936                 case eDVBRdsDecoder::RtpTextChanged:
1937                         m_event((iPlayableService*)this, evUpdatedRtpText);
1938                         break;
1939                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1940                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1941                         break;
1942                 case eDVBRdsDecoder::RecvRassSlidePic:
1943                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1944                         break;
1945         }
1946 }
1947
1948 void eDVBServicePlay::showRassSlidePicture()
1949 {
1950         if (m_rds_decoder)
1951         {
1952                 if (m_decoder)
1953                 {
1954                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1955                         if (rass_slide_pic.length())
1956                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1957                         else
1958                                 eDebug("empty filename for rass slide picture received!!");
1959                 }
1960                 else
1961                         eDebug("no MPEG Decoder to show iframes avail");
1962         }
1963         else
1964                 eDebug("showRassSlidePicture called.. but not decoder");
1965 }
1966
1967 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1968 {
1969         if (m_rds_decoder)
1970         {
1971                 if (m_decoder)
1972                 {
1973                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1974                         if (rass_interactive_pic.length())
1975                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1976                         else
1977                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1978                 }
1979                 else
1980                         eDebug("no MPEG Decoder to show iframes avail");
1981         }
1982         else
1983                 eDebug("showRassInteractivePic called.. but not decoder");
1984 }
1985
1986 ePyObject eDVBServicePlay::getRassInteractiveMask()
1987 {
1988         if (m_rds_decoder)
1989                 return m_rds_decoder->getRassPictureMask();
1990         Py_RETURN_NONE;
1991 }
1992
1993 int eDVBServiceBase::getFrontendInfo(int w)
1994 {
1995         eUsePtr<iDVBChannel> channel;
1996         if(m_service_handler.getChannel(channel))
1997                 return 0;
1998         ePtr<iDVBFrontend> fe;
1999         if(channel->getFrontend(fe))
2000                 return 0;
2001         return fe->readFrontendData(w);
2002 }
2003
2004 PyObject *eDVBServiceBase::getFrontendData()
2005 {
2006         ePyObject ret = PyDict_New();
2007         if (ret)
2008         {
2009                 eUsePtr<iDVBChannel> channel;
2010                 if(!m_service_handler.getChannel(channel))
2011                 {
2012                         ePtr<iDVBFrontend> fe;
2013                         if(!channel->getFrontend(fe))
2014                                 fe->getFrontendData(ret);
2015                 }
2016         }
2017         else
2018                 Py_RETURN_NONE;
2019         return ret;
2020 }
2021
2022 PyObject *eDVBServiceBase::getFrontendStatus()
2023 {
2024         ePyObject ret = PyDict_New();
2025         if (ret)
2026         {
2027                 eUsePtr<iDVBChannel> channel;
2028                 if(!m_service_handler.getChannel(channel))
2029                 {
2030                         ePtr<iDVBFrontend> fe;
2031                         if(!channel->getFrontend(fe))
2032                                 fe->getFrontendStatus(ret);
2033                 }
2034         }
2035         else
2036                 Py_RETURN_NONE;
2037         return ret;
2038 }
2039
2040 PyObject *eDVBServiceBase::getTransponderData(bool original)
2041 {
2042         ePyObject ret = PyDict_New();
2043         if (ret)
2044         {
2045                 eUsePtr<iDVBChannel> channel;
2046                 if(!m_service_handler.getChannel(channel))
2047                 {
2048                         ePtr<iDVBFrontend> fe;
2049                         if(!channel->getFrontend(fe))
2050                         {
2051                                 fe->getTransponderData(ret, original);
2052                                 ePtr<iDVBFrontendParameters> feparm;
2053                                 channel->getCurrentFrontendParameters(feparm);
2054                                 if (feparm)
2055                                 {
2056                                         eDVBFrontendParametersSatellite osat;
2057                                         if (!feparm->getDVBS(osat))
2058                                         {
2059                                                 void PutToDict(ePyObject &, const char*, long);
2060                                                 void PutToDict(ePyObject &, const char*, const char*);
2061                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
2062                                                 const char *tmp = "UNKNOWN";
2063                                                 switch(osat.polarisation)
2064                                                 {
2065                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
2066                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
2067                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
2068                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
2069                                                         default:break;
2070                                                 }
2071                                                 PutToDict(ret, "polarization", tmp);
2072                                         }
2073                                 }
2074                         }
2075                 }
2076         }
2077         else
2078                 Py_RETURN_NONE;
2079         return ret;
2080 }
2081
2082 PyObject *eDVBServiceBase::getAll(bool original)
2083 {
2084         ePyObject ret = getTransponderData(original);
2085         if (ret != Py_None)
2086         {
2087                 eUsePtr<iDVBChannel> channel;
2088                 if(!m_service_handler.getChannel(channel))
2089                 {
2090                         ePtr<iDVBFrontend> fe;
2091                         if(!channel->getFrontend(fe))
2092                         {
2093                                 fe->getFrontendData(ret);
2094                                 fe->getFrontendStatus(ret);
2095                         }
2096                 }
2097         }
2098         return ret;
2099 }
2100
2101 int eDVBServicePlay::getNumberOfSubservices()
2102 {
2103         ePtr<eServiceEvent> evt;
2104         if (!m_event_handler.getEvent(evt, 0))
2105                 return evt->getNumOfLinkageServices();
2106         return 0;
2107 }
2108
2109 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2110 {
2111         ePtr<eServiceEvent> evt;
2112         if (!m_event_handler.getEvent(evt, 0))
2113         {
2114                 if (!evt->getLinkageService(sub, m_reference, n))
2115                         return 0;
2116         }
2117         sub.type=eServiceReference::idInvalid;
2118         return -1;
2119 }
2120
2121 RESULT eDVBServicePlay::startTimeshift()
2122 {
2123         ePtr<iDVBDemux> demux;
2124         
2125         eDebug("Start timeshift!");
2126         
2127         if (m_timeshift_enabled)
2128                 return -1;
2129         
2130                 /* start recording with the data demux. */
2131         if (m_service_handler.getDataDemux(demux))
2132                 return -2;
2133
2134         demux->createTSRecorder(m_record);
2135         if (!m_record)
2136                 return -3;
2137
2138         std::string tspath;
2139         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2140                 eDebug("could not query ts path");
2141                 return -5;
2142         }
2143         tspath.append("/timeshift.XXXXXX");
2144         char* templ;
2145         templ = new char[tspath.length() + 1];
2146         strcpy(templ, tspath.c_str());
2147
2148         m_timeshift_fd = mkstemp(templ);
2149         m_timeshift_file = std::string(templ);
2150
2151         eDebug("recording to %s", templ);
2152
2153         delete [] templ;
2154
2155         if (m_timeshift_fd < 0)
2156         {
2157                 m_record = 0;
2158                 return -4;
2159         }
2160                 
2161         m_record->setTargetFD(m_timeshift_fd);
2162
2163         m_timeshift_enabled = 1;
2164         
2165         updateTimeshiftPids();
2166         m_record->start();
2167
2168         return 0;
2169 }
2170
2171 RESULT eDVBServicePlay::stopTimeshift()
2172 {
2173         if (!m_timeshift_enabled)
2174                 return -1;
2175         
2176         switchToLive();
2177         
2178         m_timeshift_enabled = 0;
2179         
2180         m_record->stop();
2181         m_record = 0;
2182         
2183         close(m_timeshift_fd);
2184         eDebug("remove timeshift file");
2185         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2186         
2187         return 0;
2188 }
2189
2190 int eDVBServicePlay::isTimeshiftActive()
2191 {
2192         return m_timeshift_enabled && m_timeshift_active;
2193 }
2194
2195 RESULT eDVBServicePlay::activateTimeshift()
2196 {
2197         if (!m_timeshift_enabled)
2198                 return -1;
2199         
2200         if (!m_timeshift_active)
2201         {
2202                 switchToTimeshift();
2203                 return 0;
2204         }
2205         
2206         return -2;
2207 }
2208
2209 PyObject *eDVBServicePlay::getCutList()
2210 {
2211         ePyObject list = PyList_New(0);
2212         
2213         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2214         {
2215                 ePyObject tuple = PyTuple_New(2);
2216                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2217                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2218                 PyList_Append(list, tuple);
2219                 Py_DECREF(tuple);
2220         }
2221         
2222         return list;
2223 }
2224
2225 void eDVBServicePlay::setCutList(ePyObject list)
2226 {
2227         if (!PyList_Check(list))
2228                 return;
2229         int size = PyList_Size(list);
2230         int i;
2231         
2232         m_cue_entries.clear();
2233         
2234         for (i=0; i<size; ++i)
2235         {
2236                 ePyObject tuple = PyList_GET_ITEM(list, i);
2237                 if (!PyTuple_Check(tuple))
2238                 {
2239                         eDebug("non-tuple in cutlist");
2240                         continue;
2241                 }
2242                 if (PyTuple_Size(tuple) != 2)
2243                 {
2244                         eDebug("cutlist entries need to be a 2-tuple");
2245                         continue;
2246                 }
2247                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2248                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2249                 {
2250                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2251                         continue;
2252                 }
2253                 pts_t pts = PyLong_AsLongLong(ppts);
2254                 int type = PyInt_AsLong(ptype);
2255                 m_cue_entries.insert(cueEntry(pts, type));
2256                 eDebug("adding %08llx, %d", pts, type);
2257         }
2258         m_cuesheet_changed = 1;
2259         
2260         cutlistToCuesheet();
2261         m_event((iPlayableService*)this, evCuesheetChanged);
2262 }
2263
2264 void eDVBServicePlay::setCutListEnable(int enable)
2265 {
2266         m_cutlist_enabled = enable;
2267         cutlistToCuesheet();
2268 }
2269
2270 void eDVBServicePlay::updateTimeshiftPids()
2271 {
2272         if (!m_record)
2273                 return;
2274         
2275         eDVBServicePMTHandler::program program;
2276         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2277
2278         if (h.getProgramInfo(program))
2279                 return;
2280         else
2281         {
2282                 std::set<int> pids_to_record;
2283                 pids_to_record.insert(0); // PAT
2284                 if (program.pmtPid != -1)
2285                         pids_to_record.insert(program.pmtPid); // PMT
2286
2287                 if (program.textPid != -1)
2288                         pids_to_record.insert(program.textPid); // Videotext
2289
2290                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2291                         i(program.videoStreams.begin()); 
2292                         i != program.videoStreams.end(); ++i)
2293                         pids_to_record.insert(i->pid);
2294
2295                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2296                         i(program.audioStreams.begin()); 
2297                         i != program.audioStreams.end(); ++i)
2298                                 pids_to_record.insert(i->pid);
2299
2300                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2301                         i(program.subtitleStreams.begin());
2302                         i != program.subtitleStreams.end(); ++i)
2303                                 pids_to_record.insert(i->pid);
2304
2305                 std::set<int> new_pids, obsolete_pids;
2306                 
2307                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2308                                 m_pids_active.begin(), m_pids_active.end(),
2309                                 std::inserter(new_pids, new_pids.begin()));
2310                 
2311                 std::set_difference(
2312                                 m_pids_active.begin(), m_pids_active.end(),
2313                                 pids_to_record.begin(), pids_to_record.end(), 
2314                                 std::inserter(new_pids, new_pids.begin())
2315                                 );
2316
2317                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2318                         m_record->addPID(*i);
2319
2320                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2321                         m_record->removePID(*i);
2322         }
2323 }
2324
2325 void eDVBServicePlay::switchToLive()
2326 {
2327         if (!m_timeshift_active)
2328                 return;
2329         
2330         m_cue = 0;
2331         m_decoder = 0;
2332         m_decode_demux = 0;
2333         m_teletext_parser = 0;
2334         m_rds_decoder = 0;
2335         m_subtitle_parser = 0;
2336         m_new_dvb_subtitle_page_connection = 0;
2337         m_new_subtitle_page_connection = 0;
2338         m_rds_decoder_event_connection = 0;
2339         m_video_event_connection = 0;
2340
2341                 /* free the timeshift service handler, we need the resources */
2342         m_service_handler_timeshift.free();
2343         m_timeshift_active = 0;
2344
2345         m_event((iPlayableService*)this, evSeekableStatusChanged);
2346
2347         updateDecoder();
2348 }
2349
2350 void eDVBServicePlay::switchToTimeshift()
2351 {
2352         if (m_timeshift_active)
2353                 return;
2354
2355         m_decode_demux = 0;
2356         m_decoder = 0;
2357         m_teletext_parser = 0;
2358         m_rds_decoder = 0;
2359         m_subtitle_parser = 0;
2360         m_new_subtitle_page_connection = 0;
2361         m_new_dvb_subtitle_page_connection = 0;
2362         m_rds_decoder_event_connection = 0;
2363         m_video_event_connection = 0;
2364
2365         m_timeshift_active = 1;
2366
2367         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2368         r.path = m_timeshift_file;
2369
2370         m_cue = new eCueSheet();
2371         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2372
2373         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2374         pause();
2375         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2376         
2377         m_event((iPlayableService*)this, evSeekableStatusChanged);
2378 }
2379
2380 void eDVBServicePlay::updateDecoder()
2381 {
2382         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2383
2384         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2385
2386         eDVBServicePMTHandler::program program;
2387         if (h.getProgramInfo(program))
2388                 eDebug("getting program info failed.");
2389         else
2390         {
2391                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2392                 if (!program.videoStreams.empty())
2393                 {
2394                         eDebugNoNewLine(" (");
2395                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2396                                 i(program.videoStreams.begin());
2397                                 i != program.videoStreams.end(); ++i)
2398                         {
2399                                 if (vpid == -1)
2400                                 {
2401                                         vpid = i->pid;
2402                                         vpidtype = i->type;
2403                                 }
2404                                 if (i != program.videoStreams.begin())
2405                                         eDebugNoNewLine(", ");
2406                                 eDebugNoNewLine("%04x", i->pid);
2407                         }
2408                         eDebugNoNewLine(")");
2409                 }
2410                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2411                 if (!program.audioStreams.empty())
2412                 {
2413                         eDebugNoNewLine(" (");
2414                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2415                                 i(program.audioStreams.begin());
2416                                 i != program.audioStreams.end(); ++i)
2417                         {
2418                                 if (i != program.audioStreams.begin())
2419                                         eDebugNoNewLine(", ");
2420                                 eDebugNoNewLine("%04x", i->pid);
2421                         }
2422                         eDebugNoNewLine(")");
2423                 }
2424                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2425                 pcrpid = program.pcrPid;
2426                 eDebug(", and the text pid is %04x", program.textPid);
2427                 tpid = program.textPid;
2428         }
2429
2430         if (!m_decoder)
2431         {
2432                 h.getDecodeDemux(m_decode_demux);
2433                 if (m_decode_demux)
2434                 {
2435                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2436                         if (m_decoder)
2437                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2438                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2439                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2440                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2441                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2442                 } else
2443                 {
2444                         m_teletext_parser = 0;
2445                         m_subtitle_parser = 0;
2446                 }
2447
2448                 if (m_cue)
2449                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2450         }
2451
2452         if (m_decoder)
2453         {
2454                 if (m_dvb_service)
2455                 {
2456                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2457                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2458                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2459                 }
2460                 else // subservice or recording
2461                 {
2462                         eServiceReferenceDVB ref;
2463                         m_service_handler.getServiceReference(ref);
2464                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2465                         if (!parent)
2466                                 parent = ref;
2467                         if (parent)
2468                         {
2469                                 ePtr<eDVBResourceManager> res_mgr;
2470                                 if (!eDVBResourceManager::getInstance(res_mgr))
2471                                 {
2472                                         ePtr<iDVBChannelList> db;
2473                                         if (!res_mgr->getChannelList(db))
2474                                         {
2475                                                 ePtr<eDVBService> origService;
2476                                                 if (!db->getService(parent, origService))
2477                                                 {
2478                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2479                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2480                                                 }
2481                                         }
2482                                 }
2483                         }
2484                 }
2485                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2486                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2487
2488                 m_decoder->setVideoPID(vpid, vpidtype);
2489                 selectAudioStream();
2490
2491                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2492                         m_decoder->setSyncPCR(pcrpid);
2493                 else
2494                         m_decoder->setSyncPCR(-1);
2495
2496                 m_decoder->setTextPID(tpid);
2497
2498                 m_teletext_parser->start(program.textPid);
2499
2500                 if (!m_is_primary)
2501                         m_decoder->setTrickmode();
2502
2503                 if (m_is_paused)
2504                         m_decoder->pause();
2505                 else
2506                         m_decoder->play();
2507
2508                 if (vpid > 0 && vpid < 0x2000)
2509                         ;
2510                 else
2511                 {
2512                         std::string radio_pic;
2513                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2514                                 m_decoder->setRadioPic(radio_pic);
2515                 }
2516
2517                 m_decoder->setAudioChannel(achannel);
2518
2519                 /* don't worry about non-existing services, nor pvr services */
2520                 if (m_dvb_service && !m_is_pvr)
2521                 {
2522                                 /* (audio pid will be set in selectAudioTrack */
2523                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2524                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2525                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2526                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2527                 }
2528         }       
2529         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2530 }
2531
2532 void eDVBServicePlay::loadCuesheet()
2533 {
2534         std::string filename = m_reference.path + ".cuts";
2535         
2536         m_cue_entries.clear();
2537
2538         FILE *f = fopen(filename.c_str(), "rb");
2539
2540         if (f)
2541         {
2542                 eDebug("loading cuts..");
2543                 while (1)
2544                 {
2545                         unsigned long long where;
2546                         unsigned int what;
2547                         
2548                         if (!fread(&where, sizeof(where), 1, f))
2549                                 break;
2550                         if (!fread(&what, sizeof(what), 1, f))
2551                                 break;
2552                         
2553 #if BYTE_ORDER == LITTLE_ENDIAN
2554                         where = bswap_64(where);
2555 #endif
2556                         what = ntohl(what);
2557                         
2558                         if (what > 3)
2559                                 break;
2560                         
2561                         m_cue_entries.insert(cueEntry(where, what));
2562                 }
2563                 fclose(f);
2564                 eDebug("%d entries", m_cue_entries.size());
2565         } else
2566                 eDebug("cutfile not found!");
2567         
2568         m_cuesheet_changed = 0;
2569         cutlistToCuesheet();
2570         m_event((iPlayableService*)this, evCuesheetChanged);
2571 }
2572
2573 void eDVBServicePlay::saveCuesheet()
2574 {
2575         std::string filename = m_reference.path + ".cuts";
2576         
2577         FILE *f = fopen(filename.c_str(), "wb");
2578
2579         if (f)
2580         {
2581                 unsigned long long where;
2582                 int what;
2583
2584                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2585                 {
2586 #if BYTE_ORDER == BIG_ENDIAN
2587                         where = i->where;
2588 #else
2589                         where = bswap_64(i->where);
2590 #endif
2591                         what = htonl(i->what);
2592                         fwrite(&where, sizeof(where), 1, f);
2593                         fwrite(&what, sizeof(what), 1, f);
2594                         
2595                 }
2596                 fclose(f);
2597         }
2598         
2599         m_cuesheet_changed = 0;
2600 }
2601
2602 void eDVBServicePlay::cutlistToCuesheet()
2603 {
2604         if (!m_cue)
2605         {
2606                 eDebug("no cue sheet");
2607                 return;
2608         }       
2609         m_cue->clear();
2610         
2611         if (!m_cutlist_enabled)
2612         {
2613                 m_cue->commitSpans();
2614                 eDebug("cutlists were disabled");
2615                 return;
2616         }
2617
2618         pts_t in = 0, out = 0, length = 0;
2619         
2620         getLength(length);
2621                 
2622         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2623         
2624         while (1)
2625         {
2626                 if (i == m_cue_entries.end())
2627                         out = length;
2628                 else {
2629                         if (i->what == 0) /* in */
2630                         {
2631                                 in = i++->where;
2632                                 continue;
2633                         } else if (i->what == 1) /* out */
2634                                 out = i++->where;
2635                         else /* mark (2) or last play position (3) */
2636                         {
2637                                 i++;
2638                                 continue;
2639                         }
2640                 }
2641                 
2642                 if (in < 0)
2643                         in = 0;
2644                 if (out < 0)
2645                         out = 0;
2646                 if (in > length)
2647                         in = length;
2648                 if (out > length)
2649                         out = length;
2650                 
2651                 if (in < out)
2652                         m_cue->addSourceSpan(in, out);
2653                 
2654                 in = length;
2655                 
2656                 if (i == m_cue_entries.end())
2657                         break;
2658         }
2659         m_cue->commitSpans();
2660 }
2661
2662 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2663 {
2664         if (m_subtitle_widget)
2665                 disableSubtitles(parent);
2666
2667         ePyObject entry;
2668         int tuplesize = PyTuple_Size(tuple);
2669         int type = 0;
2670
2671         if (!PyTuple_Check(tuple))
2672                 goto error_out;
2673
2674         if (tuplesize < 1)
2675                 goto error_out;
2676
2677         entry = PyTuple_GET_ITEM(tuple, 0);
2678
2679         if (!PyInt_Check(entry))
2680                 goto error_out;
2681
2682         type = PyInt_AsLong(entry);
2683
2684         if (type == 1)  // teletext subtitles
2685         {
2686                 int page, magazine, pid;
2687                 if (tuplesize < 4)
2688                         goto error_out;
2689
2690                 if (!m_teletext_parser)
2691                 {
2692                         eDebug("enable teletext subtitles.. no parser !!!");
2693                         return -1;
2694                 }
2695
2696                 entry = PyTuple_GET_ITEM(tuple, 1);
2697                 if (!PyInt_Check(entry))
2698                         goto error_out;
2699                 pid = PyInt_AsLong(entry);
2700
2701                 entry = PyTuple_GET_ITEM(tuple, 2);
2702                 if (!PyInt_Check(entry))
2703                         goto error_out;
2704                 page = PyInt_AsLong(entry);
2705
2706                 entry = PyTuple_GET_ITEM(tuple, 3);
2707                 if (!PyInt_Check(entry))
2708                         goto error_out;
2709                 magazine = PyInt_AsLong(entry);
2710
2711                 m_subtitle_widget = new eSubtitleWidget(parent);
2712                 m_subtitle_widget->resize(parent->size()); /* full size */
2713                 m_teletext_parser->setPageAndMagazine(page, magazine);
2714                 if (m_dvb_service)
2715                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2716         }
2717         else if (type == 0)
2718         {
2719                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2720                 if (!m_subtitle_parser)
2721                 {
2722                         eDebug("enable dvb subtitles.. no parser !!!");
2723                         return -1;
2724                 }
2725                 if (tuplesize < 4)
2726                         goto error_out;
2727
2728                 entry = PyTuple_GET_ITEM(tuple, 1);
2729                 if (!PyInt_Check(entry))
2730                         goto error_out;
2731                 pid = PyInt_AsLong(entry);
2732
2733                 entry = PyTuple_GET_ITEM(tuple, 2);
2734                 if (!PyInt_Check(entry))
2735                         goto error_out;
2736                 composition_page_id = PyInt_AsLong(entry);
2737
2738                 entry = PyTuple_GET_ITEM(tuple, 3);
2739                 if (!PyInt_Check(entry))
2740                         goto error_out;
2741                 ancillary_page_id = PyInt_AsLong(entry);
2742
2743                 m_subtitle_widget = new eSubtitleWidget(parent);
2744                 m_subtitle_widget->resize(parent->size()); /* full size */
2745                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2746                 if (m_dvb_service)
2747                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2748         }
2749         else
2750                 goto error_out;
2751         return 0;
2752 error_out:
2753         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2754                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2755                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2756         return -1;
2757 }
2758
2759 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2760 {
2761         delete m_subtitle_widget;
2762         m_subtitle_widget = 0;
2763         if (m_subtitle_parser)
2764         {
2765                 m_subtitle_parser->stop();
2766                 m_dvb_subtitle_pages.clear();
2767         }
2768         if (m_teletext_parser)
2769         {
2770                 m_teletext_parser->setPageAndMagazine(-1, -1);
2771                 m_subtitle_pages.clear();
2772         }
2773         if (m_dvb_service)
2774                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2775         return 0;
2776 }
2777
2778 PyObject *eDVBServicePlay::getCachedSubtitle()
2779 {
2780         if (m_dvb_service)
2781         {
2782                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2783                 if (tmp != -1)
2784                 {
2785                         unsigned int data = (unsigned int)tmp;
2786                         int pid = (data&0xFFFF0000)>>16;
2787                         ePyObject tuple = PyTuple_New(4);
2788                         eDVBServicePMTHandler::program program;
2789                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2790                         if (!h.getProgramInfo(program))
2791                         {
2792                                 if (program.textPid==pid) // teletext
2793                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2794                                 else
2795                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2796                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2797                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2798                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2799                                 return tuple;
2800                         }
2801                 }
2802         }
2803         Py_RETURN_NONE;
2804 }
2805
2806 PyObject *eDVBServicePlay::getSubtitleList()
2807 {
2808         if (!m_teletext_parser)
2809                 Py_RETURN_NONE;
2810         
2811         ePyObject l = PyList_New(0);
2812         std::set<int> added_ttx_pages;
2813
2814         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2815                 m_teletext_parser->m_found_subtitle_pages;
2816
2817         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2818         eDVBServicePMTHandler::program program;
2819         if (h.getProgramInfo(program))
2820                 eDebug("getting program info failed.");
2821         else
2822         {
2823                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2824                         it != program.subtitleStreams.end(); ++it)
2825                 {
2826                         switch(it->subtitling_type)
2827                         {
2828                                 case 0x01: // ebu teletext subtitles
2829                                 {
2830                                         int page_number = it->teletext_page_number & 0xFF;
2831                                         int magazine_number = it->teletext_magazine_number & 7;
2832                                         int hash = magazine_number << 8 | page_number;
2833                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2834                                         {
2835                                                 ePyObject tuple = PyTuple_New(5);
2836                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2837                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2838                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2839                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2840                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2841                                                 PyList_Append(l, tuple);
2842                                                 Py_DECREF(tuple);
2843                                                 added_ttx_pages.insert(hash);
2844                                         }
2845                                         break;
2846                                 }
2847                                 case 0x10 ... 0x13:
2848                                 case 0x20 ... 0x23: // dvb subtitles
2849                                 {
2850                                         ePyObject tuple = PyTuple_New(5);
2851                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2852                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2853                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2854                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2855                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2856                                         PyList_Insert(l, 0, tuple);
2857                                         Py_DECREF(tuple);
2858                                         break;
2859                                 }
2860                         }
2861                 }
2862         }
2863
2864         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2865                 it != subs.end(); ++it)
2866         {
2867                 int page_number = it->teletext_page_number & 0xFF;
2868                 int magazine_number = it->teletext_magazine_number & 7;
2869                 int hash = magazine_number << 8 | page_number;
2870                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2871                 {
2872                         ePyObject tuple = PyTuple_New(5);
2873                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2874                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2875                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2876                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2877                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2878                         PyList_Append(l, tuple);
2879                         Py_DECREF(tuple);
2880                 }
2881         }
2882
2883         return l;
2884 }
2885
2886 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2887 {
2888         if (m_subtitle_widget)
2889         {
2890                 pts_t pos = 0;
2891                 if (m_decoder)
2892                         m_decoder->getPTS(0, pos);
2893                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2894                 m_subtitle_pages.push_back(page);
2895                 checkSubtitleTiming();
2896         }
2897 }
2898
2899 void eDVBServicePlay::checkSubtitleTiming()
2900 {
2901         eDebug("checkSubtitleTiming");
2902         if (!m_subtitle_widget)
2903                 return;
2904         while (1)
2905         {
2906                 enum { TELETEXT, DVB } type;
2907                 eDVBTeletextSubtitlePage page;
2908                 eDVBSubtitlePage dvb_page;
2909                 pts_t show_time;
2910                 if (!m_subtitle_pages.empty())
2911                 {
2912                         page = m_subtitle_pages.front();
2913                         type = TELETEXT;
2914                         show_time = page.m_pts;
2915                 }
2916                 else if (!m_dvb_subtitle_pages.empty())
2917                 {
2918                         dvb_page = m_dvb_subtitle_pages.front();
2919                         type = DVB;
2920                         show_time = dvb_page.m_show_time;
2921                 }
2922                 else
2923                         return;
2924         
2925                 pts_t pos = 0;
2926         
2927                 if (m_decoder)
2928                         m_decoder->getPTS(0, pos);
2929
2930                 eDebug("%lld %lld", pos, show_time);
2931                 int diff =  show_time - pos;
2932                 if (diff < 0)
2933                 {
2934                         eDebug("[late (%d ms)]", -diff / 90);
2935                         diff = 0;
2936                 }
2937 //              if (diff > 900000)
2938 //              {
2939 //                      eDebug("[invalid]");
2940 //                      diff = 0;
2941 //              }
2942         
2943                 if ((diff/90)<20)
2944                 {
2945                         if (type == TELETEXT)
2946                         {
2947                                 eDebug("display teletext subtitle page %lld", show_time);
2948                                 m_subtitle_widget->setPage(page);
2949                                 m_subtitle_pages.pop_front();
2950                         }
2951                         else
2952                         {
2953                                 eDebug("display dvb subtitle Page %lld", show_time);
2954                                 m_subtitle_widget->setPage(dvb_page);
2955                                 m_dvb_subtitle_pages.pop_front();
2956                         }
2957                 } else
2958                 {
2959                         eDebug("start subtitle delay %d", diff / 90);
2960                         m_subtitle_sync_timer->start(diff / 90, 1);
2961                         break;
2962                 }
2963         }
2964 }
2965
2966 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2967 {
2968         if (m_subtitle_widget)
2969         {
2970                 pts_t pos = 0;
2971                 if (m_decoder)
2972                         m_decoder->getPTS(0, pos);
2973                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2974                 m_dvb_subtitle_pages.push_back(p);
2975                 checkSubtitleTiming();
2976         }
2977 }
2978
2979 int eDVBServicePlay::getAC3Delay()
2980 {
2981         if (m_dvb_service)
2982                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2983         else if (m_decoder)
2984                 return m_decoder->getAC3Delay();
2985         else
2986                 return 0;
2987 }
2988
2989 int eDVBServicePlay::getPCMDelay()
2990 {
2991         if (m_dvb_service)
2992                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2993         else if (m_decoder)
2994                 return m_decoder->getPCMDelay();
2995         else
2996                 return 0;
2997 }
2998
2999 void eDVBServicePlay::setAC3Delay(int delay)
3000 {
3001         if (m_dvb_service)
3002                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
3003         if (m_decoder)
3004                 m_decoder->setAC3Delay(delay);
3005 }
3006
3007 void eDVBServicePlay::setPCMDelay(int delay)
3008 {
3009         if (m_dvb_service)
3010                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
3011         if (m_decoder)
3012                 m_decoder->setPCMDelay(delay);
3013 }
3014
3015 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
3016 {
3017         memcpy(&m_videoEventData, &event, sizeof(event));
3018         switch(event.type) {
3019                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
3020                         m_event((iPlayableService*)this, evVideoSizeChanged);
3021                         break;
3022                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
3023                         m_event((iPlayableService*)this, evVideoFramerateChanged);
3024                         break;
3025                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
3026                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
3027                         break;
3028                 default:
3029                         break;
3030         }
3031 }
3032
3033 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
3034 {
3035         ptr = this;
3036         return 0;
3037 }
3038
3039 PyObject *eDVBServicePlay::getStreamingData()
3040 {
3041         eDVBServicePMTHandler::program program;
3042         if (m_service_handler.getProgramInfo(program))
3043         {
3044                 Py_INCREF(Py_None);
3045                 return Py_None;
3046         }
3047
3048         PyObject *r = program.createPythonObject();
3049         ePtr<iDVBDemux> demux;
3050         if (!m_service_handler.getDataDemux(demux))
3051         {
3052                 uint8_t demux_id;
3053                 demux->getCADemuxID(demux_id);
3054                 
3055                 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
3056         }
3057
3058         return r;
3059 }
3060
3061
3062 DEFINE_REF(eDVBServicePlay)
3063
3064 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3065 {
3066         switch (w)
3067         {
3068         case iServiceInformation::sTransponderData:
3069                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3070         default:
3071                 break;
3072         }
3073         return iStaticServiceInformation::getInfoObject(ref, w);
3074 }
3075
3076 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");