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