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