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