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