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