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