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