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