add possibility to use ValueRange as ValueEqual Converter
[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         info.m_pid = program.audioStreams[i].pid;
1698
1699         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1700                 info.m_description = "MPEG";
1701         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1702                 info.m_description = "AC3";
1703         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1704                 info.m_description = "AAC";
1705         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1706                 info.m_description = "DTS";
1707         else
1708                 info.m_description = "???";
1709
1710         if (program.audioStreams[i].component_tag != -1)
1711         {
1712                 ePtr<eServiceEvent> evt;
1713                 if (!m_event_handler.getEvent(evt, 0))
1714                 {
1715                         ePtr<eComponentData> data;
1716                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1717                                 info.m_language = data->getText();
1718                 }
1719         }
1720
1721         if (info.m_language.empty())
1722                 info.m_language = program.audioStreams[i].language_code;
1723         
1724         return 0;
1725 }
1726
1727 int eDVBServicePlay::selectAudioStream(int i)
1728 {
1729         eDVBServicePMTHandler::program program;
1730         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1731
1732         if (h.getProgramInfo(program))
1733                 return -1;
1734
1735         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1736                 return -2;
1737
1738         if (!m_decoder)
1739                 return -3;
1740
1741         int stream = i;
1742         if (stream == -1)
1743                 stream = program.defaultAudioStream;
1744
1745         int apid = -1, apidtype = -1;
1746
1747         if (((unsigned int)stream) < program.audioStreams.size())
1748         {
1749                 apid = program.audioStreams[stream].pid;
1750                 apidtype = program.audioStreams[stream].type;
1751         }
1752
1753         m_current_audio_pid = apid;
1754
1755         if (m_decoder->setAudioPID(apid, apidtype))
1756         {
1757                 eDebug("set audio pid failed");
1758                 return -4;
1759         }
1760
1761                 /* 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 */
1762         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1763                 if (!m_rds_decoder)
1764                 {
1765                         ePtr<iDVBDemux> data_demux;
1766                         if (!h.getDataDemux(data_demux))
1767                         {
1768                                 m_rds_decoder = new eDVBRdsDecoder(data_demux);
1769                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1770                         }
1771                 }
1772
1773                 /* if we decided that we need one, update the pid */
1774         if (m_rds_decoder)
1775                 m_rds_decoder->start(apid);
1776
1777                         /* store new pid as default only when:
1778                                 a.) we have an entry in the service db for the current service,
1779                                 b.) we are not playing back something,
1780                                 c.) we are not selecting the default entry. (we wouldn't change 
1781                                     anything in the best case, or destroy the default setting in
1782                                     case the real default is not yet available.)
1783                         */
1784         if (m_dvb_service && !m_is_pvr && (i != -1))
1785         {
1786                 if (apidtype == eDVBAudio::aMPEG)
1787                 {
1788                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1789                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1790                 }
1791                 else
1792                 {
1793                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1794                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1795                 }
1796         }
1797
1798         h.resetCachedProgram();
1799
1800         return 0;
1801 }
1802
1803 int eDVBServicePlay::getCurrentChannel()
1804 {
1805         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1806 }
1807
1808 RESULT eDVBServicePlay::selectChannel(int i)
1809 {
1810         if (i < LEFT || i > RIGHT || i == STEREO)
1811                 i = -1;  // Stereo
1812         if (m_dvb_service)
1813                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1814         if (m_decoder)
1815                 m_decoder->setAudioChannel(i);
1816         return 0;
1817 }
1818
1819 std::string eDVBServicePlay::getText(int x)
1820 {
1821         if (m_rds_decoder)
1822                 switch(x)
1823                 {
1824                         case RadioText:
1825                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1826                         case RtpText:
1827                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1828                 }
1829         return "";
1830 }
1831
1832 void eDVBServicePlay::rdsDecoderEvent(int what)
1833 {
1834         switch(what)
1835         {
1836                 case eDVBRdsDecoder::RadioTextChanged:
1837                         m_event((iPlayableService*)this, evUpdatedRadioText);
1838                         break;
1839                 case eDVBRdsDecoder::RtpTextChanged:
1840                         m_event((iPlayableService*)this, evUpdatedRtpText);
1841                         break;
1842                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1843                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1844                         break;
1845                 case eDVBRdsDecoder::RecvRassSlidePic:
1846                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1847                         break;
1848         }
1849 }
1850
1851 void eDVBServicePlay::showRassSlidePicture()
1852 {
1853         if (m_rds_decoder)
1854         {
1855                 if (m_decoder)
1856                 {
1857                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1858                         if (rass_slide_pic.length())
1859                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1860                         else
1861                                 eDebug("empty filename for rass slide picture received!!");
1862                 }
1863                 else
1864                         eDebug("no MPEG Decoder to show iframes avail");
1865         }
1866         else
1867                 eDebug("showRassSlidePicture called.. but not decoder");
1868 }
1869
1870 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1871 {
1872         if (m_rds_decoder)
1873         {
1874                 if (m_decoder)
1875                 {
1876                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1877                         if (rass_interactive_pic.length())
1878                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1879                         else
1880                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1881                 }
1882                 else
1883                         eDebug("no MPEG Decoder to show iframes avail");
1884         }
1885         else
1886                 eDebug("showRassInteractivePic called.. but not decoder");
1887 }
1888
1889 ePyObject eDVBServicePlay::getRassInteractiveMask()
1890 {
1891         if (m_rds_decoder)
1892                 return m_rds_decoder->getRassPictureMask();
1893         Py_RETURN_NONE;
1894 }
1895
1896 int eDVBServiceBase::getFrontendInfo(int w)
1897 {
1898         eUsePtr<iDVBChannel> channel;
1899         if(m_service_handler.getChannel(channel))
1900                 return 0;
1901         ePtr<iDVBFrontend> fe;
1902         if(channel->getFrontend(fe))
1903                 return 0;
1904         return fe->readFrontendData(w);
1905 }
1906
1907 PyObject *eDVBServiceBase::getFrontendData()
1908 {
1909         ePyObject ret = PyDict_New();
1910         if (ret)
1911         {
1912                 eUsePtr<iDVBChannel> channel;
1913                 if(!m_service_handler.getChannel(channel))
1914                 {
1915                         ePtr<iDVBFrontend> fe;
1916                         if(!channel->getFrontend(fe))
1917                                 fe->getFrontendData(ret);
1918                 }
1919         }
1920         else
1921                 Py_RETURN_NONE;
1922         return ret;
1923 }
1924
1925 PyObject *eDVBServiceBase::getFrontendStatus()
1926 {
1927         ePyObject ret = PyDict_New();
1928         if (ret)
1929         {
1930                 eUsePtr<iDVBChannel> channel;
1931                 if(!m_service_handler.getChannel(channel))
1932                 {
1933                         ePtr<iDVBFrontend> fe;
1934                         if(!channel->getFrontend(fe))
1935                                 fe->getFrontendStatus(ret);
1936                 }
1937         }
1938         else
1939                 Py_RETURN_NONE;
1940         return ret;
1941 }
1942
1943 PyObject *eDVBServiceBase::getTransponderData(bool original)
1944 {
1945         ePyObject ret = PyDict_New();
1946         if (ret)
1947         {
1948                 eUsePtr<iDVBChannel> channel;
1949                 if(!m_service_handler.getChannel(channel))
1950                 {
1951                         ePtr<iDVBFrontend> fe;
1952                         if(!channel->getFrontend(fe))
1953                         {
1954                                 fe->getTransponderData(ret, original);
1955                                 ePtr<iDVBFrontendParameters> feparm;
1956                                 channel->getCurrentFrontendParameters(feparm);
1957                                 if (feparm)
1958                                 {
1959                                         eDVBFrontendParametersSatellite osat;
1960                                         if (!feparm->getDVBS(osat))
1961                                         {
1962                                                 void PutToDict(ePyObject &, const char*, long);
1963                                                 void PutToDict(ePyObject &, const char*, const char*);
1964                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1965                                                 const char *tmp = "UNKNOWN";
1966                                                 switch(osat.polarisation)
1967                                                 {
1968                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1969                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1970                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1971                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1972                                                         default:break;
1973                                                 }
1974                                                 PutToDict(ret, "polarization", tmp);
1975                                         }
1976                                 }
1977                         }
1978                 }
1979         }
1980         else
1981                 Py_RETURN_NONE;
1982         return ret;
1983 }
1984
1985 PyObject *eDVBServiceBase::getAll(bool original)
1986 {
1987         ePyObject ret = getTransponderData(original);
1988         if (ret != Py_None)
1989         {
1990                 eUsePtr<iDVBChannel> channel;
1991                 if(!m_service_handler.getChannel(channel))
1992                 {
1993                         ePtr<iDVBFrontend> fe;
1994                         if(!channel->getFrontend(fe))
1995                         {
1996                                 fe->getFrontendData(ret);
1997                                 fe->getFrontendStatus(ret);
1998                         }
1999                 }
2000         }
2001         return ret;
2002 }
2003
2004 int eDVBServicePlay::getNumberOfSubservices()
2005 {
2006         ePtr<eServiceEvent> evt;
2007         if (!m_event_handler.getEvent(evt, 0))
2008                 return evt->getNumOfLinkageServices();
2009         return 0;
2010 }
2011
2012 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2013 {
2014         ePtr<eServiceEvent> evt;
2015         if (!m_event_handler.getEvent(evt, 0))
2016         {
2017                 if (!evt->getLinkageService(sub, m_reference, n))
2018                         return 0;
2019         }
2020         sub.type=eServiceReference::idInvalid;
2021         return -1;
2022 }
2023
2024 RESULT eDVBServicePlay::startTimeshift()
2025 {
2026         ePtr<iDVBDemux> demux;
2027         
2028         eDebug("Start timeshift!");
2029         
2030         if (m_timeshift_enabled)
2031                 return -1;
2032         
2033                 /* start recording with the data demux. */
2034         if (m_service_handler.getDataDemux(demux))
2035                 return -2;
2036
2037         demux->createTSRecorder(m_record);
2038         if (!m_record)
2039                 return -3;
2040
2041         char templ[]=TSPATH "/timeshift.XXXXXX";
2042         m_timeshift_fd = mkstemp(templ);
2043         m_timeshift_file = templ;
2044         
2045         eDebug("recording to %s", templ);
2046         
2047         if (m_timeshift_fd < 0)
2048         {
2049                 m_record = 0;
2050                 return -4;
2051         }
2052                 
2053         m_record->setTargetFD(m_timeshift_fd);
2054
2055         m_timeshift_enabled = 1;
2056         
2057         updateTimeshiftPids();
2058         m_record->start();
2059
2060         return 0;
2061 }
2062
2063 RESULT eDVBServicePlay::stopTimeshift()
2064 {
2065         if (!m_timeshift_enabled)
2066                 return -1;
2067         
2068         switchToLive();
2069         
2070         m_timeshift_enabled = 0;
2071         
2072         m_record->stop();
2073         m_record = 0;
2074         
2075         close(m_timeshift_fd);
2076         eDebug("remove timeshift file");
2077         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2078         
2079         return 0;
2080 }
2081
2082 int eDVBServicePlay::isTimeshiftActive()
2083 {
2084         return m_timeshift_enabled && m_timeshift_active;
2085 }
2086
2087 RESULT eDVBServicePlay::activateTimeshift()
2088 {
2089         if (!m_timeshift_enabled)
2090                 return -1;
2091         
2092         if (!m_timeshift_active)
2093         {
2094                 switchToTimeshift();
2095                 return 0;
2096         }
2097         
2098         return -2;
2099 }
2100
2101 PyObject *eDVBServicePlay::getCutList()
2102 {
2103         ePyObject list = PyList_New(0);
2104         
2105         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2106         {
2107                 ePyObject tuple = PyTuple_New(2);
2108                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2109                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2110                 PyList_Append(list, tuple);
2111                 Py_DECREF(tuple);
2112         }
2113         
2114         return list;
2115 }
2116
2117 void eDVBServicePlay::setCutList(ePyObject list)
2118 {
2119         if (!PyList_Check(list))
2120                 return;
2121         int size = PyList_Size(list);
2122         int i;
2123         
2124         m_cue_entries.clear();
2125         
2126         for (i=0; i<size; ++i)
2127         {
2128                 ePyObject tuple = PyList_GET_ITEM(list, i);
2129                 if (!PyTuple_Check(tuple))
2130                 {
2131                         eDebug("non-tuple in cutlist");
2132                         continue;
2133                 }
2134                 if (PyTuple_Size(tuple) != 2)
2135                 {
2136                         eDebug("cutlist entries need to be a 2-tuple");
2137                         continue;
2138                 }
2139                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2140                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2141                 {
2142                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2143                         continue;
2144                 }
2145                 pts_t pts = PyLong_AsLongLong(ppts);
2146                 int type = PyInt_AsLong(ptype);
2147                 m_cue_entries.insert(cueEntry(pts, type));
2148                 eDebug("adding %08llx, %d", pts, type);
2149         }
2150         m_cuesheet_changed = 1;
2151         
2152         cutlistToCuesheet();
2153         m_event((iPlayableService*)this, evCuesheetChanged);
2154 }
2155
2156 void eDVBServicePlay::setCutListEnable(int enable)
2157 {
2158         m_cutlist_enabled = enable;
2159         cutlistToCuesheet();
2160 }
2161
2162 void eDVBServicePlay::updateTimeshiftPids()
2163 {
2164         if (!m_record)
2165                 return;
2166         
2167         eDVBServicePMTHandler::program program;
2168         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2169
2170         if (h.getProgramInfo(program))
2171                 return;
2172         else
2173         {
2174                 std::set<int> pids_to_record;
2175                 pids_to_record.insert(0); // PAT
2176                 if (program.pmtPid != -1)
2177                         pids_to_record.insert(program.pmtPid); // PMT
2178
2179                 if (program.textPid != -1)
2180                         pids_to_record.insert(program.textPid); // Videotext
2181
2182                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2183                         i(program.videoStreams.begin()); 
2184                         i != program.videoStreams.end(); ++i)
2185                         pids_to_record.insert(i->pid);
2186
2187                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2188                         i(program.audioStreams.begin()); 
2189                         i != program.audioStreams.end(); ++i)
2190                                 pids_to_record.insert(i->pid);
2191
2192                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2193                         i(program.subtitleStreams.begin());
2194                         i != program.subtitleStreams.end(); ++i)
2195                                 pids_to_record.insert(i->pid);
2196
2197                 std::set<int> new_pids, obsolete_pids;
2198                 
2199                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2200                                 m_pids_active.begin(), m_pids_active.end(),
2201                                 std::inserter(new_pids, new_pids.begin()));
2202                 
2203                 std::set_difference(
2204                                 m_pids_active.begin(), m_pids_active.end(),
2205                                 pids_to_record.begin(), pids_to_record.end(), 
2206                                 std::inserter(new_pids, new_pids.begin())
2207                                 );
2208
2209                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2210                         m_record->addPID(*i);
2211
2212                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2213                         m_record->removePID(*i);
2214         }
2215 }
2216
2217 void eDVBServicePlay::switchToLive()
2218 {
2219         if (!m_timeshift_active)
2220                 return;
2221         
2222         m_cue = 0;
2223         m_decoder = 0;
2224         m_decode_demux = 0;
2225         m_teletext_parser = 0;
2226         m_rds_decoder = 0;
2227         m_subtitle_parser = 0;
2228         m_new_dvb_subtitle_page_connection = 0;
2229         m_new_subtitle_page_connection = 0;
2230         m_rds_decoder_event_connection = 0;
2231         m_video_event_connection = 0;
2232
2233                 /* free the timeshift service handler, we need the resources */
2234         m_service_handler_timeshift.free();
2235         m_timeshift_active = 0;
2236
2237         m_event((iPlayableService*)this, evSeekableStatusChanged);
2238
2239         updateDecoder();
2240 }
2241
2242 void eDVBServicePlay::switchToTimeshift()
2243 {
2244         if (m_timeshift_active)
2245                 return;
2246
2247         m_decode_demux = 0;
2248         m_decoder = 0;
2249         m_teletext_parser = 0;
2250         m_rds_decoder = 0;
2251         m_subtitle_parser = 0;
2252         m_new_subtitle_page_connection = 0;
2253         m_new_dvb_subtitle_page_connection = 0;
2254         m_rds_decoder_event_connection = 0;
2255         m_video_event_connection = 0;
2256
2257         m_timeshift_active = 1;
2258
2259         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2260         r.path = m_timeshift_file;
2261
2262         m_cue = new eCueSheet();
2263         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2264
2265         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2266         pause();
2267         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2268         
2269         m_event((iPlayableService*)this, evSeekableStatusChanged);
2270 }
2271
2272 void eDVBServicePlay::updateDecoder()
2273 {
2274         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2275
2276         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2277
2278         eDVBServicePMTHandler::program program;
2279         if (h.getProgramInfo(program))
2280                 eDebug("getting program info failed.");
2281         else
2282         {
2283                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2284                 if (!program.videoStreams.empty())
2285                 {
2286                         eDebugNoNewLine(" (");
2287                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2288                                 i(program.videoStreams.begin());
2289                                 i != program.videoStreams.end(); ++i)
2290                         {
2291                                 if (vpid == -1)
2292                                 {
2293                                         vpid = i->pid;
2294                                         vpidtype = i->type;
2295                                 }
2296                                 if (i != program.videoStreams.begin())
2297                                         eDebugNoNewLine(", ");
2298                                 eDebugNoNewLine("%04x", i->pid);
2299                         }
2300                         eDebugNoNewLine(")");
2301                 }
2302                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2303                 if (!program.audioStreams.empty())
2304                 {
2305                         eDebugNoNewLine(" (");
2306                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2307                                 i(program.audioStreams.begin());
2308                                 i != program.audioStreams.end(); ++i)
2309                         {
2310                                 if (i != program.audioStreams.begin())
2311                                         eDebugNoNewLine(", ");
2312                                 eDebugNoNewLine("%04x", i->pid);
2313                         }
2314                         eDebugNoNewLine(")");
2315                 }
2316                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2317                 pcrpid = program.pcrPid;
2318                 eDebug(", and the text pid is %04x", program.textPid);
2319                 tpid = program.textPid;
2320         }
2321
2322         if (!m_decoder)
2323         {
2324                 h.getDecodeDemux(m_decode_demux);
2325                 if (m_decode_demux)
2326                 {
2327                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2328                         if (m_decoder)
2329                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2330                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2331                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2332                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2333                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2334                 } else
2335                 {
2336                         m_teletext_parser = 0;
2337                         m_subtitle_parser = 0;
2338                 }
2339
2340                 if (m_cue)
2341                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2342         }
2343
2344         if (m_decoder)
2345         {
2346                 if (m_dvb_service)
2347                 {
2348                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2349                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2350                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2351                 }
2352                 else // subservice or recording
2353                 {
2354                         eServiceReferenceDVB ref;
2355                         m_service_handler.getServiceReference(ref);
2356                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2357                         if (!parent)
2358                                 parent = ref;
2359                         if (parent)
2360                         {
2361                                 ePtr<eDVBResourceManager> res_mgr;
2362                                 if (!eDVBResourceManager::getInstance(res_mgr))
2363                                 {
2364                                         ePtr<iDVBChannelList> db;
2365                                         if (!res_mgr->getChannelList(db))
2366                                         {
2367                                                 ePtr<eDVBService> origService;
2368                                                 if (!db->getService(parent, origService))
2369                                                 {
2370                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2371                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2372                                                 }
2373                                         }
2374                                 }
2375                         }
2376                 }
2377                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2378                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2379
2380                 m_decoder->setVideoPID(vpid, vpidtype);
2381                 selectAudioStream();
2382
2383                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2384                         m_decoder->setSyncPCR(pcrpid);
2385                 else
2386                         m_decoder->setSyncPCR(-1);
2387
2388                 m_decoder->setTextPID(tpid);
2389
2390                 m_teletext_parser->start(program.textPid);
2391
2392                 if (!m_is_primary)
2393                         m_decoder->setTrickmode(1);
2394
2395                 if (m_is_paused)
2396                         m_decoder->preroll();
2397                 else
2398                         m_decoder->start();
2399
2400                 if (vpid > 0 && vpid < 0x2000)
2401                         ;
2402                 else
2403                 {
2404                         std::string radio_pic;
2405                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2406                                 m_decoder->setRadioPic(radio_pic);
2407                 }
2408
2409                 m_decoder->setAudioChannel(achannel);
2410
2411                 /* don't worry about non-existing services, nor pvr services */
2412                 if (m_dvb_service && !m_is_pvr)
2413                 {
2414                                 /* (audio pid will be set in selectAudioTrack */
2415                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2416                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2417                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2418                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2419                 }
2420         }       
2421         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2422 }
2423
2424 void eDVBServicePlay::loadCuesheet()
2425 {
2426         std::string filename = m_reference.path + ".cuts";
2427         
2428         m_cue_entries.clear();
2429
2430         FILE *f = fopen(filename.c_str(), "rb");
2431
2432         if (f)
2433         {
2434                 eDebug("loading cuts..");
2435                 while (1)
2436                 {
2437                         unsigned long long where;
2438                         unsigned int what;
2439                         
2440                         if (!fread(&where, sizeof(where), 1, f))
2441                                 break;
2442                         if (!fread(&what, sizeof(what), 1, f))
2443                                 break;
2444                         
2445 #if BYTE_ORDER == LITTLE_ENDIAN
2446                         where = bswap_64(where);
2447 #endif
2448                         what = ntohl(what);
2449                         
2450                         if (what > 3)
2451                                 break;
2452                         
2453                         m_cue_entries.insert(cueEntry(where, what));
2454                 }
2455                 fclose(f);
2456                 eDebug("%d entries", m_cue_entries.size());
2457         } else
2458                 eDebug("cutfile not found!");
2459         
2460         m_cuesheet_changed = 0;
2461         cutlistToCuesheet();
2462         m_event((iPlayableService*)this, evCuesheetChanged);
2463 }
2464
2465 void eDVBServicePlay::saveCuesheet()
2466 {
2467         std::string filename = m_reference.path + ".cuts";
2468         
2469         FILE *f = fopen(filename.c_str(), "wb");
2470
2471         if (f)
2472         {
2473                 unsigned long long where;
2474                 int what;
2475
2476                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2477                 {
2478 #if BYTE_ORDER == BIG_ENDIAN
2479                         where = i->where;
2480 #else
2481                         where = bswap_64(i->where);
2482 #endif
2483                         what = htonl(i->what);
2484                         fwrite(&where, sizeof(where), 1, f);
2485                         fwrite(&what, sizeof(what), 1, f);
2486                         
2487                 }
2488                 fclose(f);
2489         }
2490         
2491         m_cuesheet_changed = 0;
2492 }
2493
2494 void eDVBServicePlay::cutlistToCuesheet()
2495 {
2496         if (!m_cue)
2497         {
2498                 eDebug("no cue sheet");
2499                 return;
2500         }       
2501         m_cue->clear();
2502         
2503         if (!m_cutlist_enabled)
2504         {
2505                 m_cue->commitSpans();
2506                 eDebug("cutlists were disabled");
2507                 return;
2508         }
2509
2510         pts_t in = 0, out = 0, length = 0;
2511         
2512         getLength(length);
2513                 
2514         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2515         
2516         while (1)
2517         {
2518                 if (i == m_cue_entries.end())
2519                         out = length;
2520                 else {
2521                         if (i->what == 0) /* in */
2522                         {
2523                                 in = i++->where;
2524                                 continue;
2525                         } else if (i->what == 1) /* out */
2526                                 out = i++->where;
2527                         else /* mark (2) or last play position (3) */
2528                         {
2529                                 i++;
2530                                 continue;
2531                         }
2532                 }
2533                 
2534                 if (in != out)
2535                         m_cue->addSourceSpan(in, out);
2536                 
2537                 in = length;
2538                 
2539                 if (i == m_cue_entries.end())
2540                         break;
2541         }
2542         m_cue->commitSpans();
2543 }
2544
2545 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2546 {
2547         if (m_subtitle_widget)
2548                 disableSubtitles(parent);
2549
2550         ePyObject entry;
2551         int tuplesize = PyTuple_Size(tuple);
2552         int type = 0;
2553
2554         if (!PyTuple_Check(tuple))
2555                 goto error_out;
2556
2557         if (tuplesize < 1)
2558                 goto error_out;
2559
2560         entry = PyTuple_GET_ITEM(tuple, 0);
2561
2562         if (!PyInt_Check(entry))
2563                 goto error_out;
2564
2565         type = PyInt_AsLong(entry);
2566
2567         if (type == 1)  // teletext subtitles
2568         {
2569                 int page, magazine, pid;
2570                 if (tuplesize < 4)
2571                         goto error_out;
2572
2573                 if (!m_teletext_parser)
2574                 {
2575                         eDebug("enable teletext subtitles.. no parser !!!");
2576                         return -1;
2577                 }
2578
2579                 entry = PyTuple_GET_ITEM(tuple, 1);
2580                 if (!PyInt_Check(entry))
2581                         goto error_out;
2582                 pid = PyInt_AsLong(entry);
2583
2584                 entry = PyTuple_GET_ITEM(tuple, 2);
2585                 if (!PyInt_Check(entry))
2586                         goto error_out;
2587                 page = PyInt_AsLong(entry);
2588
2589                 entry = PyTuple_GET_ITEM(tuple, 3);
2590                 if (!PyInt_Check(entry))
2591                         goto error_out;
2592                 magazine = PyInt_AsLong(entry);
2593
2594                 m_subtitle_widget = new eSubtitleWidget(parent);
2595                 m_subtitle_widget->resize(parent->size()); /* full size */
2596                 m_teletext_parser->setPageAndMagazine(page, magazine);
2597                 if (m_dvb_service)
2598                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2599         }
2600         else if (type == 0)
2601         {
2602                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2603                 if (!m_subtitle_parser)
2604                 {
2605                         eDebug("enable dvb subtitles.. no parser !!!");
2606                         return -1;
2607                 }
2608                 if (tuplesize < 4)
2609                         goto error_out;
2610
2611                 entry = PyTuple_GET_ITEM(tuple, 1);
2612                 if (!PyInt_Check(entry))
2613                         goto error_out;
2614                 pid = PyInt_AsLong(entry);
2615
2616                 entry = PyTuple_GET_ITEM(tuple, 2);
2617                 if (!PyInt_Check(entry))
2618                         goto error_out;
2619                 composition_page_id = PyInt_AsLong(entry);
2620
2621                 entry = PyTuple_GET_ITEM(tuple, 3);
2622                 if (!PyInt_Check(entry))
2623                         goto error_out;
2624                 ancillary_page_id = PyInt_AsLong(entry);
2625
2626                 m_subtitle_widget = new eSubtitleWidget(parent);
2627                 m_subtitle_widget->resize(parent->size()); /* full size */
2628                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2629                 if (m_dvb_service)
2630                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2631         }
2632         else
2633                 goto error_out;
2634         return 0;
2635 error_out:
2636         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2637                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2638                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2639         return -1;
2640 }
2641
2642 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2643 {
2644         delete m_subtitle_widget;
2645         m_subtitle_widget = 0;
2646         if (m_subtitle_parser)
2647         {
2648                 m_subtitle_parser->stop();
2649                 m_dvb_subtitle_pages.clear();
2650         }
2651         if (m_teletext_parser)
2652         {
2653                 m_teletext_parser->setPageAndMagazine(-1, -1);
2654                 m_subtitle_pages.clear();
2655         }
2656         if (m_dvb_service)
2657                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2658         return 0;
2659 }
2660
2661 PyObject *eDVBServicePlay::getCachedSubtitle()
2662 {
2663         if (m_dvb_service)
2664         {
2665                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2666                 if (tmp != -1)
2667                 {
2668                         unsigned int data = (unsigned int)tmp;
2669                         int pid = (data&0xFFFF0000)>>16;
2670                         ePyObject tuple = PyTuple_New(4);
2671                         eDVBServicePMTHandler::program program;
2672                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2673                         if (!h.getProgramInfo(program))
2674                         {
2675                                 if (program.textPid==pid) // teletext
2676                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2677                                 else
2678                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2679                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2680                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2681                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2682                                 return tuple;
2683                         }
2684                 }
2685         }
2686         Py_RETURN_NONE;
2687 }
2688
2689 PyObject *eDVBServicePlay::getSubtitleList()
2690 {
2691         if (!m_teletext_parser)
2692                 Py_RETURN_NONE;
2693         
2694         ePyObject l = PyList_New(0);
2695         std::set<int> added_ttx_pages;
2696
2697         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2698                 m_teletext_parser->m_found_subtitle_pages;
2699
2700         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2701         eDVBServicePMTHandler::program program;
2702         if (h.getProgramInfo(program))
2703                 eDebug("getting program info failed.");
2704         else
2705         {
2706                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2707                         it != program.subtitleStreams.end(); ++it)
2708                 {
2709                         switch(it->subtitling_type)
2710                         {
2711                                 case 0x01: // ebu teletext subtitles
2712                                 {
2713                                         int page_number = it->teletext_page_number & 0xFF;
2714                                         int magazine_number = it->teletext_magazine_number & 7;
2715                                         int hash = magazine_number << 8 | page_number;
2716                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2717                                         {
2718                                                 ePyObject tuple = PyTuple_New(5);
2719                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2720                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2721                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2722                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2723                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2724                                                 PyList_Append(l, tuple);
2725                                                 Py_DECREF(tuple);
2726                                                 added_ttx_pages.insert(hash);
2727                                         }
2728                                         break;
2729                                 }
2730                                 case 0x10 ... 0x13:
2731                                 case 0x20 ... 0x23: // dvb subtitles
2732                                 {
2733                                         ePyObject tuple = PyTuple_New(5);
2734                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2735                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2736                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2737                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2738                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2739                                         PyList_Insert(l, 0, tuple);
2740                                         Py_DECREF(tuple);
2741                                         break;
2742                                 }
2743                         }
2744                 }
2745         }
2746
2747         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2748                 it != subs.end(); ++it)
2749         {
2750                 int page_number = it->teletext_page_number & 0xFF;
2751                 int magazine_number = it->teletext_magazine_number & 7;
2752                 int hash = magazine_number << 8 | page_number;
2753                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2754                 {
2755                         ePyObject tuple = PyTuple_New(5);
2756                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2757                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2758                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2759                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2760                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2761                         PyList_Append(l, tuple);
2762                         Py_DECREF(tuple);
2763                 }
2764         }
2765
2766         return l;
2767 }
2768
2769 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2770 {
2771         if (m_subtitle_widget)
2772         {
2773                 m_subtitle_pages.push_back(page);
2774                 checkSubtitleTiming();
2775         }
2776 }
2777
2778 void eDVBServicePlay::checkSubtitleTiming()
2779 {
2780 //      eDebug("checkSubtitleTiming");
2781         if (!m_subtitle_widget)
2782                 return;
2783         while (1)
2784         {
2785                 enum { TELETEXT, DVB } type;
2786                 eDVBTeletextSubtitlePage page;
2787                 eDVBSubtitlePage dvb_page;
2788                 pts_t show_time;
2789                 if (!m_subtitle_pages.empty())
2790                 {
2791                         page = m_subtitle_pages.front();
2792                         type = TELETEXT;
2793                         show_time = page.m_pts;
2794                 }
2795                 else if (!m_dvb_subtitle_pages.empty())
2796                 {
2797                         dvb_page = m_dvb_subtitle_pages.front();
2798                         type = DVB;
2799                         show_time = dvb_page.m_show_time;
2800                 }
2801                 else
2802                         return;
2803         
2804                 pts_t pos = 0;
2805         
2806                 if (m_decoder)
2807                         m_decoder->getPTS(0, pos);
2808
2809 //              eDebug("%lld %lld", pos, show_time);
2810                 int diff =  show_time - pos;
2811                 if (diff < 0)
2812                 {
2813 //                      eDebug("[late (%d ms)]", -diff / 90);
2814                         diff = 0;
2815                 }
2816 //              if (diff > 900000)
2817 //              {
2818 //                      eDebug("[invalid]");
2819 //                      diff = 0;
2820 //              }
2821         
2822                 if (!diff)
2823                 {
2824                         if (type == TELETEXT)
2825                         {
2826 //                              eDebug("display teletext subtitle page");
2827                                 m_subtitle_widget->setPage(page);
2828                                 m_subtitle_pages.pop_front();
2829                         }
2830                         else
2831                         {
2832 //                              eDebug("display dvb subtitle Page %lld", show_time);
2833                                 m_subtitle_widget->setPage(dvb_page);
2834                                 m_dvb_subtitle_pages.pop_front();
2835                         }
2836                 } else
2837                 {
2838 //                      eDebug("start subtitle delay %d", diff / 90);
2839                         m_subtitle_sync_timer.start(diff / 90, 1);
2840                         break;
2841                 }
2842         }
2843 }
2844
2845 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2846 {
2847         if (m_subtitle_widget)
2848         {
2849                 m_dvb_subtitle_pages.push_back(p);
2850                 checkSubtitleTiming();
2851         }
2852 }
2853
2854 int eDVBServicePlay::getAC3Delay()
2855 {
2856         if (m_dvb_service)
2857                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2858         else if (m_decoder)
2859                 return m_decoder->getAC3Delay();
2860         else
2861                 return 0;
2862 }
2863
2864 int eDVBServicePlay::getPCMDelay()
2865 {
2866         if (m_dvb_service)
2867                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2868         else if (m_decoder)
2869                 return m_decoder->getPCMDelay();
2870         else
2871                 return 0;
2872 }
2873
2874 void eDVBServicePlay::setAC3Delay(int delay)
2875 {
2876         if (m_dvb_service)
2877                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2878         if (m_decoder)
2879                 m_decoder->setAC3Delay(delay);
2880 }
2881
2882 void eDVBServicePlay::setPCMDelay(int delay)
2883 {
2884         if (m_dvb_service)
2885                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2886         if (m_decoder)
2887                 m_decoder->setPCMDelay(delay);
2888 }
2889
2890 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2891 {
2892         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2893         m_event((iPlayableService*)this, evVideoSizeChanged);
2894 }
2895
2896 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2897 {
2898         ptr = this;
2899         return 0;
2900 }
2901
2902 PyObject *eDVBServicePlay::getStreamingData()
2903 {
2904         eDVBServicePMTHandler::program program;
2905         if (m_service_handler.getProgramInfo(program))
2906         {
2907                 Py_INCREF(Py_None);
2908                 return Py_None;
2909         }
2910
2911         PyObject *r = program.createPythonObject();
2912         ePtr<iDVBDemux> demux;
2913         if (!m_service_handler.getDataDemux(demux))
2914         {
2915                 uint8_t demux_id;
2916                 demux->getCADemuxID(demux_id);
2917                 
2918                 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2919         }
2920
2921         return r;
2922 }
2923
2924
2925 DEFINE_REF(eDVBServicePlay)
2926
2927 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2928 {
2929         switch (w)
2930         {
2931         case iServiceInformation::sTransponderData:
2932                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2933         default:
2934                 break;
2935         }
2936         return iStaticServiceInformation::getInfoObject(ref, w);
2937 }
2938
2939 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");