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