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