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