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