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