clear non processed subtitles on skip forward / backward
[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         {
1791                 if (apidtype == eDVBAudio::aMPEG)
1792                 {
1793                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1794                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1795                 }
1796                 else
1797                 {
1798                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1799                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1800                 }
1801         }
1802
1803         h.resetCachedProgram();
1804
1805         return 0;
1806 }
1807
1808 int eDVBServicePlay::getCurrentChannel()
1809 {
1810         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1811 }
1812
1813 RESULT eDVBServicePlay::selectChannel(int i)
1814 {
1815         if (i < LEFT || i > RIGHT || i == STEREO)
1816                 i = -1;  // Stereo
1817         if (m_dvb_service)
1818                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1819         if (m_decoder)
1820                 m_decoder->setAudioChannel(i);
1821         return 0;
1822 }
1823
1824 std::string eDVBServicePlay::getText(int x)
1825 {
1826         if (m_rds_decoder)
1827                 switch(x)
1828                 {
1829                         case RadioText:
1830                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1831                         case RtpText:
1832                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1833                 }
1834         return "";
1835 }
1836
1837 void eDVBServicePlay::rdsDecoderEvent(int what)
1838 {
1839         switch(what)
1840         {
1841                 case eDVBRdsDecoder::RadioTextChanged:
1842                         m_event((iPlayableService*)this, evUpdatedRadioText);
1843                         break;
1844                 case eDVBRdsDecoder::RtpTextChanged:
1845                         m_event((iPlayableService*)this, evUpdatedRtpText);
1846                         break;
1847                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1848                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1849                         break;
1850                 case eDVBRdsDecoder::RecvRassSlidePic:
1851                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1852                         break;
1853         }
1854 }
1855
1856 void eDVBServicePlay::showRassSlidePicture()
1857 {
1858         if (m_rds_decoder)
1859         {
1860                 if (m_decoder)
1861                 {
1862                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1863                         if (rass_slide_pic.length())
1864                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1865                         else
1866                                 eDebug("empty filename for rass slide picture received!!");
1867                 }
1868                 else
1869                         eDebug("no MPEG Decoder to show iframes avail");
1870         }
1871         else
1872                 eDebug("showRassSlidePicture called.. but not decoder");
1873 }
1874
1875 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1876 {
1877         if (m_rds_decoder)
1878         {
1879                 if (m_decoder)
1880                 {
1881                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1882                         if (rass_interactive_pic.length())
1883                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1884                         else
1885                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1886                 }
1887                 else
1888                         eDebug("no MPEG Decoder to show iframes avail");
1889         }
1890         else
1891                 eDebug("showRassInteractivePic called.. but not decoder");
1892 }
1893
1894 ePyObject eDVBServicePlay::getRassInteractiveMask()
1895 {
1896         if (m_rds_decoder)
1897                 return m_rds_decoder->getRassPictureMask();
1898         Py_RETURN_NONE;
1899 }
1900
1901 int eDVBServiceBase::getFrontendInfo(int w)
1902 {
1903         eUsePtr<iDVBChannel> channel;
1904         if(m_service_handler.getChannel(channel))
1905                 return 0;
1906         ePtr<iDVBFrontend> fe;
1907         if(channel->getFrontend(fe))
1908                 return 0;
1909         return fe->readFrontendData(w);
1910 }
1911
1912 PyObject *eDVBServiceBase::getFrontendData()
1913 {
1914         ePyObject ret = PyDict_New();
1915         if (ret)
1916         {
1917                 eUsePtr<iDVBChannel> channel;
1918                 if(!m_service_handler.getChannel(channel))
1919                 {
1920                         ePtr<iDVBFrontend> fe;
1921                         if(!channel->getFrontend(fe))
1922                                 fe->getFrontendData(ret);
1923                 }
1924         }
1925         else
1926                 Py_RETURN_NONE;
1927         return ret;
1928 }
1929
1930 PyObject *eDVBServiceBase::getFrontendStatus()
1931 {
1932         ePyObject ret = PyDict_New();
1933         if (ret)
1934         {
1935                 eUsePtr<iDVBChannel> channel;
1936                 if(!m_service_handler.getChannel(channel))
1937                 {
1938                         ePtr<iDVBFrontend> fe;
1939                         if(!channel->getFrontend(fe))
1940                                 fe->getFrontendStatus(ret);
1941                 }
1942         }
1943         else
1944                 Py_RETURN_NONE;
1945         return ret;
1946 }
1947
1948 PyObject *eDVBServiceBase::getTransponderData(bool original)
1949 {
1950         ePyObject ret = PyDict_New();
1951         if (ret)
1952         {
1953                 eUsePtr<iDVBChannel> channel;
1954                 if(!m_service_handler.getChannel(channel))
1955                 {
1956                         ePtr<iDVBFrontend> fe;
1957                         if(!channel->getFrontend(fe))
1958                         {
1959                                 fe->getTransponderData(ret, original);
1960                                 ePtr<iDVBFrontendParameters> feparm;
1961                                 channel->getCurrentFrontendParameters(feparm);
1962                                 if (feparm)
1963                                 {
1964                                         eDVBFrontendParametersSatellite osat;
1965                                         if (!feparm->getDVBS(osat))
1966                                         {
1967                                                 void PutToDict(ePyObject &, const char*, long);
1968                                                 void PutToDict(ePyObject &, const char*, const char*);
1969                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1970                                                 const char *tmp = "UNKNOWN";
1971                                                 switch(osat.polarisation)
1972                                                 {
1973                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1974                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1975                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1976                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1977                                                         default:break;
1978                                                 }
1979                                                 PutToDict(ret, "polarization", tmp);
1980                                         }
1981                                 }
1982                         }
1983                 }
1984         }
1985         else
1986                 Py_RETURN_NONE;
1987         return ret;
1988 }
1989
1990 PyObject *eDVBServiceBase::getAll(bool original)
1991 {
1992         ePyObject ret = getTransponderData(original);
1993         if (ret != Py_None)
1994         {
1995                 eUsePtr<iDVBChannel> channel;
1996                 if(!m_service_handler.getChannel(channel))
1997                 {
1998                         ePtr<iDVBFrontend> fe;
1999                         if(!channel->getFrontend(fe))
2000                         {
2001                                 fe->getFrontendData(ret);
2002                                 fe->getFrontendStatus(ret);
2003                         }
2004                 }
2005         }
2006         return ret;
2007 }
2008
2009 int eDVBServicePlay::getNumberOfSubservices()
2010 {
2011         ePtr<eServiceEvent> evt;
2012         if (!m_event_handler.getEvent(evt, 0))
2013                 return evt->getNumOfLinkageServices();
2014         return 0;
2015 }
2016
2017 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2018 {
2019         ePtr<eServiceEvent> evt;
2020         if (!m_event_handler.getEvent(evt, 0))
2021         {
2022                 if (!evt->getLinkageService(sub, m_reference, n))
2023                         return 0;
2024         }
2025         sub.type=eServiceReference::idInvalid;
2026         return -1;
2027 }
2028
2029 RESULT eDVBServicePlay::startTimeshift()
2030 {
2031         ePtr<iDVBDemux> demux;
2032         
2033         eDebug("Start timeshift!");
2034         
2035         if (m_timeshift_enabled)
2036                 return -1;
2037         
2038                 /* start recording with the data demux. */
2039         if (m_service_handler.getDataDemux(demux))
2040                 return -2;
2041
2042         demux->createTSRecorder(m_record);
2043         if (!m_record)
2044                 return -3;
2045
2046         char templ[]=TSPATH "/timeshift.XXXXXX";
2047         m_timeshift_fd = mkstemp(templ);
2048         m_timeshift_file = templ;
2049         
2050         eDebug("recording to %s", templ);
2051         
2052         if (m_timeshift_fd < 0)
2053         {
2054                 m_record = 0;
2055                 return -4;
2056         }
2057                 
2058         m_record->setTargetFD(m_timeshift_fd);
2059
2060         m_timeshift_enabled = 1;
2061         
2062         updateTimeshiftPids();
2063         m_record->start();
2064
2065         return 0;
2066 }
2067
2068 RESULT eDVBServicePlay::stopTimeshift()
2069 {
2070         if (!m_timeshift_enabled)
2071                 return -1;
2072         
2073         switchToLive();
2074         
2075         m_timeshift_enabled = 0;
2076         
2077         m_record->stop();
2078         m_record = 0;
2079         
2080         close(m_timeshift_fd);
2081         eDebug("remove timeshift file");
2082         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2083         
2084         return 0;
2085 }
2086
2087 int eDVBServicePlay::isTimeshiftActive()
2088 {
2089         return m_timeshift_enabled && m_timeshift_active;
2090 }
2091
2092 RESULT eDVBServicePlay::activateTimeshift()
2093 {
2094         if (!m_timeshift_enabled)
2095                 return -1;
2096         
2097         if (!m_timeshift_active)
2098         {
2099                 switchToTimeshift();
2100                 return 0;
2101         }
2102         
2103         return -2;
2104 }
2105
2106 PyObject *eDVBServicePlay::getCutList()
2107 {
2108         ePyObject list = PyList_New(0);
2109         
2110         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2111         {
2112                 ePyObject tuple = PyTuple_New(2);
2113                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2114                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2115                 PyList_Append(list, tuple);
2116                 Py_DECREF(tuple);
2117         }
2118         
2119         return list;
2120 }
2121
2122 void eDVBServicePlay::setCutList(ePyObject list)
2123 {
2124         if (!PyList_Check(list))
2125                 return;
2126         int size = PyList_Size(list);
2127         int i;
2128         
2129         m_cue_entries.clear();
2130         
2131         for (i=0; i<size; ++i)
2132         {
2133                 ePyObject tuple = PyList_GET_ITEM(list, i);
2134                 if (!PyTuple_Check(tuple))
2135                 {
2136                         eDebug("non-tuple in cutlist");
2137                         continue;
2138                 }
2139                 if (PyTuple_Size(tuple) != 2)
2140                 {
2141                         eDebug("cutlist entries need to be a 2-tuple");
2142                         continue;
2143                 }
2144                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2145                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2146                 {
2147                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2148                         continue;
2149                 }
2150                 pts_t pts = PyLong_AsLongLong(ppts);
2151                 int type = PyInt_AsLong(ptype);
2152                 m_cue_entries.insert(cueEntry(pts, type));
2153                 eDebug("adding %08llx, %d", pts, type);
2154         }
2155         m_cuesheet_changed = 1;
2156         
2157         cutlistToCuesheet();
2158         m_event((iPlayableService*)this, evCuesheetChanged);
2159 }
2160
2161 void eDVBServicePlay::setCutListEnable(int enable)
2162 {
2163         m_cutlist_enabled = enable;
2164         cutlistToCuesheet();
2165 }
2166
2167 void eDVBServicePlay::updateTimeshiftPids()
2168 {
2169         if (!m_record)
2170                 return;
2171         
2172         eDVBServicePMTHandler::program program;
2173         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2174
2175         if (h.getProgramInfo(program))
2176                 return;
2177         else
2178         {
2179                 std::set<int> pids_to_record;
2180                 pids_to_record.insert(0); // PAT
2181                 if (program.pmtPid != -1)
2182                         pids_to_record.insert(program.pmtPid); // PMT
2183
2184                 if (program.textPid != -1)
2185                         pids_to_record.insert(program.textPid); // Videotext
2186
2187                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2188                         i(program.videoStreams.begin()); 
2189                         i != program.videoStreams.end(); ++i)
2190                         pids_to_record.insert(i->pid);
2191
2192                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2193                         i(program.audioStreams.begin()); 
2194                         i != program.audioStreams.end(); ++i)
2195                                 pids_to_record.insert(i->pid);
2196
2197                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2198                         i(program.subtitleStreams.begin());
2199                         i != program.subtitleStreams.end(); ++i)
2200                                 pids_to_record.insert(i->pid);
2201
2202                 std::set<int> new_pids, obsolete_pids;
2203                 
2204                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2205                                 m_pids_active.begin(), m_pids_active.end(),
2206                                 std::inserter(new_pids, new_pids.begin()));
2207                 
2208                 std::set_difference(
2209                                 m_pids_active.begin(), m_pids_active.end(),
2210                                 pids_to_record.begin(), pids_to_record.end(), 
2211                                 std::inserter(new_pids, new_pids.begin())
2212                                 );
2213
2214                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2215                         m_record->addPID(*i);
2216
2217                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2218                         m_record->removePID(*i);
2219         }
2220 }
2221
2222 void eDVBServicePlay::switchToLive()
2223 {
2224         if (!m_timeshift_active)
2225                 return;
2226         
2227         m_cue = 0;
2228         m_decoder = 0;
2229         m_decode_demux = 0;
2230         m_teletext_parser = 0;
2231         m_rds_decoder = 0;
2232         m_subtitle_parser = 0;
2233         m_new_dvb_subtitle_page_connection = 0;
2234         m_new_subtitle_page_connection = 0;
2235         m_rds_decoder_event_connection = 0;
2236         m_video_event_connection = 0;
2237
2238                 /* free the timeshift service handler, we need the resources */
2239         m_service_handler_timeshift.free();
2240         m_timeshift_active = 0;
2241
2242         m_event((iPlayableService*)this, evSeekableStatusChanged);
2243
2244         updateDecoder();
2245 }
2246
2247 void eDVBServicePlay::switchToTimeshift()
2248 {
2249         if (m_timeshift_active)
2250                 return;
2251
2252         m_decode_demux = 0;
2253         m_decoder = 0;
2254         m_teletext_parser = 0;
2255         m_rds_decoder = 0;
2256         m_subtitle_parser = 0;
2257         m_new_subtitle_page_connection = 0;
2258         m_new_dvb_subtitle_page_connection = 0;
2259         m_rds_decoder_event_connection = 0;
2260         m_video_event_connection = 0;
2261
2262         m_timeshift_active = 1;
2263
2264         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2265         r.path = m_timeshift_file;
2266
2267         m_cue = new eCueSheet();
2268         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2269
2270         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2271         pause();
2272         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2273         
2274         m_event((iPlayableService*)this, evSeekableStatusChanged);
2275 }
2276
2277 void eDVBServicePlay::updateDecoder()
2278 {
2279         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2280
2281         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2282
2283         eDVBServicePMTHandler::program program;
2284         if (h.getProgramInfo(program))
2285                 eDebug("getting program info failed.");
2286         else
2287         {
2288                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2289                 if (!program.videoStreams.empty())
2290                 {
2291                         eDebugNoNewLine(" (");
2292                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2293                                 i(program.videoStreams.begin());
2294                                 i != program.videoStreams.end(); ++i)
2295                         {
2296                                 if (vpid == -1)
2297                                 {
2298                                         vpid = i->pid;
2299                                         vpidtype = i->type;
2300                                 }
2301                                 if (i != program.videoStreams.begin())
2302                                         eDebugNoNewLine(", ");
2303                                 eDebugNoNewLine("%04x", i->pid);
2304                         }
2305                         eDebugNoNewLine(")");
2306                 }
2307                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2308                 if (!program.audioStreams.empty())
2309                 {
2310                         eDebugNoNewLine(" (");
2311                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2312                                 i(program.audioStreams.begin());
2313                                 i != program.audioStreams.end(); ++i)
2314                         {
2315                                 if (i != program.audioStreams.begin())
2316                                         eDebugNoNewLine(", ");
2317                                 eDebugNoNewLine("%04x", i->pid);
2318                         }
2319                         eDebugNoNewLine(")");
2320                 }
2321                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2322                 pcrpid = program.pcrPid;
2323                 eDebug(", and the text pid is %04x", program.textPid);
2324                 tpid = program.textPid;
2325         }
2326
2327         if (!m_decoder)
2328         {
2329                 h.getDecodeDemux(m_decode_demux);
2330                 if (m_decode_demux)
2331                 {
2332                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2333                         if (m_decoder)
2334                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2335                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2336                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2337                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2338                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2339                 } else
2340                 {
2341                         m_teletext_parser = 0;
2342                         m_subtitle_parser = 0;
2343                 }
2344
2345                 if (m_cue)
2346                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2347         }
2348
2349         if (m_decoder)
2350         {
2351                 if (m_dvb_service)
2352                 {
2353                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2354                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2355                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2356                 }
2357                 else // subservice or recording
2358                 {
2359                         eServiceReferenceDVB ref;
2360                         m_service_handler.getServiceReference(ref);
2361                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2362                         if (!parent)
2363                                 parent = ref;
2364                         if (parent)
2365                         {
2366                                 ePtr<eDVBResourceManager> res_mgr;
2367                                 if (!eDVBResourceManager::getInstance(res_mgr))
2368                                 {
2369                                         ePtr<iDVBChannelList> db;
2370                                         if (!res_mgr->getChannelList(db))
2371                                         {
2372                                                 ePtr<eDVBService> origService;
2373                                                 if (!db->getService(parent, origService))
2374                                                 {
2375                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2376                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2377                                                 }
2378                                         }
2379                                 }
2380                         }
2381                 }
2382                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2383                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2384
2385                 m_decoder->setVideoPID(vpid, vpidtype);
2386                 selectAudioStream();
2387
2388                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2389                         m_decoder->setSyncPCR(pcrpid);
2390                 else
2391                         m_decoder->setSyncPCR(-1);
2392
2393                 m_decoder->setTextPID(tpid);
2394
2395                 m_teletext_parser->start(program.textPid);
2396
2397                 if (!m_is_primary)
2398                         m_decoder->setTrickmode(1);
2399
2400                 if (m_is_paused)
2401                         m_decoder->preroll();
2402                 else
2403                         m_decoder->start();
2404
2405                 if (vpid > 0 && vpid < 0x2000)
2406                         ;
2407                 else
2408                 {
2409                         std::string radio_pic;
2410                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2411                                 m_decoder->setRadioPic(radio_pic);
2412                 }
2413
2414                 m_decoder->setAudioChannel(achannel);
2415
2416                 /* don't worry about non-existing services, nor pvr services */
2417                 if (m_dvb_service && !m_is_pvr)
2418                 {
2419                                 /* (audio pid will be set in selectAudioTrack */
2420                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2421                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2422                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2423                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2424                 }
2425         }       
2426         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2427 }
2428
2429 void eDVBServicePlay::loadCuesheet()
2430 {
2431         std::string filename = m_reference.path + ".cuts";
2432         
2433         m_cue_entries.clear();
2434
2435         FILE *f = fopen(filename.c_str(), "rb");
2436
2437         if (f)
2438         {
2439                 eDebug("loading cuts..");
2440                 while (1)
2441                 {
2442                         unsigned long long where;
2443                         unsigned int what;
2444                         
2445                         if (!fread(&where, sizeof(where), 1, f))
2446                                 break;
2447                         if (!fread(&what, sizeof(what), 1, f))
2448                                 break;
2449                         
2450 #if BYTE_ORDER == LITTLE_ENDIAN
2451                         where = bswap_64(where);
2452 #endif
2453                         what = ntohl(what);
2454                         
2455                         if (what > 3)
2456                                 break;
2457                         
2458                         m_cue_entries.insert(cueEntry(where, what));
2459                 }
2460                 fclose(f);
2461                 eDebug("%d entries", m_cue_entries.size());
2462         } else
2463                 eDebug("cutfile not found!");
2464         
2465         m_cuesheet_changed = 0;
2466         cutlistToCuesheet();
2467         m_event((iPlayableService*)this, evCuesheetChanged);
2468 }
2469
2470 void eDVBServicePlay::saveCuesheet()
2471 {
2472         std::string filename = m_reference.path + ".cuts";
2473         
2474         FILE *f = fopen(filename.c_str(), "wb");
2475
2476         if (f)
2477         {
2478                 unsigned long long where;
2479                 int what;
2480
2481                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2482                 {
2483 #if BYTE_ORDER == BIG_ENDIAN
2484                         where = i->where;
2485 #else
2486                         where = bswap_64(i->where);
2487 #endif
2488                         what = htonl(i->what);
2489                         fwrite(&where, sizeof(where), 1, f);
2490                         fwrite(&what, sizeof(what), 1, f);
2491                         
2492                 }
2493                 fclose(f);
2494         }
2495         
2496         m_cuesheet_changed = 0;
2497 }
2498
2499 void eDVBServicePlay::cutlistToCuesheet()
2500 {
2501         if (!m_cue)
2502         {
2503                 eDebug("no cue sheet");
2504                 return;
2505         }       
2506         m_cue->clear();
2507         
2508         if (!m_cutlist_enabled)
2509         {
2510                 m_cue->commitSpans();
2511                 eDebug("cutlists were disabled");
2512                 return;
2513         }
2514
2515         pts_t in = 0, out = 0, length = 0;
2516         
2517         getLength(length);
2518                 
2519         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2520         
2521         while (1)
2522         {
2523                 if (i == m_cue_entries.end())
2524                         out = length;
2525                 else {
2526                         if (i->what == 0) /* in */
2527                         {
2528                                 in = i++->where;
2529                                 continue;
2530                         } else if (i->what == 1) /* out */
2531                                 out = i++->where;
2532                         else /* mark (2) or last play position (3) */
2533                         {
2534                                 i++;
2535                                 continue;
2536                         }
2537                 }
2538                 
2539                 if (in != out)
2540                         m_cue->addSourceSpan(in, out);
2541                 
2542                 in = length;
2543                 
2544                 if (i == m_cue_entries.end())
2545                         break;
2546         }
2547         m_cue->commitSpans();
2548 }
2549
2550 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2551 {
2552         if (m_subtitle_widget)
2553                 disableSubtitles(parent);
2554
2555         ePyObject entry;
2556         int tuplesize = PyTuple_Size(tuple);
2557         int type = 0;
2558
2559         if (!PyTuple_Check(tuple))
2560                 goto error_out;
2561
2562         if (tuplesize < 1)
2563                 goto error_out;
2564
2565         entry = PyTuple_GET_ITEM(tuple, 0);
2566
2567         if (!PyInt_Check(entry))
2568                 goto error_out;
2569
2570         type = PyInt_AsLong(entry);
2571
2572         if (type == 1)  // teletext subtitles
2573         {
2574                 int page, magazine, pid;
2575                 if (tuplesize < 4)
2576                         goto error_out;
2577
2578                 if (!m_teletext_parser)
2579                 {
2580                         eDebug("enable teletext subtitles.. no parser !!!");
2581                         return -1;
2582                 }
2583
2584                 entry = PyTuple_GET_ITEM(tuple, 1);
2585                 if (!PyInt_Check(entry))
2586                         goto error_out;
2587                 pid = PyInt_AsLong(entry);
2588
2589                 entry = PyTuple_GET_ITEM(tuple, 2);
2590                 if (!PyInt_Check(entry))
2591                         goto error_out;
2592                 page = PyInt_AsLong(entry);
2593
2594                 entry = PyTuple_GET_ITEM(tuple, 3);
2595                 if (!PyInt_Check(entry))
2596                         goto error_out;
2597                 magazine = PyInt_AsLong(entry);
2598
2599                 m_subtitle_widget = new eSubtitleWidget(parent);
2600                 m_subtitle_widget->resize(parent->size()); /* full size */
2601                 m_teletext_parser->setPageAndMagazine(page, magazine);
2602                 if (m_dvb_service)
2603                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2604         }
2605         else if (type == 0)
2606         {
2607                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2608                 if (!m_subtitle_parser)
2609                 {
2610                         eDebug("enable dvb subtitles.. no parser !!!");
2611                         return -1;
2612                 }
2613                 if (tuplesize < 4)
2614                         goto error_out;
2615
2616                 entry = PyTuple_GET_ITEM(tuple, 1);
2617                 if (!PyInt_Check(entry))
2618                         goto error_out;
2619                 pid = PyInt_AsLong(entry);
2620
2621                 entry = PyTuple_GET_ITEM(tuple, 2);
2622                 if (!PyInt_Check(entry))
2623                         goto error_out;
2624                 composition_page_id = PyInt_AsLong(entry);
2625
2626                 entry = PyTuple_GET_ITEM(tuple, 3);
2627                 if (!PyInt_Check(entry))
2628                         goto error_out;
2629                 ancillary_page_id = PyInt_AsLong(entry);
2630
2631                 m_subtitle_widget = new eSubtitleWidget(parent);
2632                 m_subtitle_widget->resize(parent->size()); /* full size */
2633                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2634                 if (m_dvb_service)
2635                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2636         }
2637         else
2638                 goto error_out;
2639         return 0;
2640 error_out:
2641         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2642                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2643                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2644         return -1;
2645 }
2646
2647 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2648 {
2649         delete m_subtitle_widget;
2650         m_subtitle_widget = 0;
2651         if (m_subtitle_parser)
2652         {
2653                 m_subtitle_parser->stop();
2654                 m_dvb_subtitle_pages.clear();
2655         }
2656         if (m_teletext_parser)
2657         {
2658                 m_teletext_parser->setPageAndMagazine(-1, -1);
2659                 m_subtitle_pages.clear();
2660         }
2661         if (m_dvb_service)
2662                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2663         return 0;
2664 }
2665
2666 PyObject *eDVBServicePlay::getCachedSubtitle()
2667 {
2668         if (m_dvb_service)
2669         {
2670                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2671                 if (tmp != -1)
2672                 {
2673                         unsigned int data = (unsigned int)tmp;
2674                         int pid = (data&0xFFFF0000)>>16;
2675                         ePyObject tuple = PyTuple_New(4);
2676                         eDVBServicePMTHandler::program program;
2677                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2678                         if (!h.getProgramInfo(program))
2679                         {
2680                                 if (program.textPid==pid) // teletext
2681                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2682                                 else
2683                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2684                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2685                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2686                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2687                                 return tuple;
2688                         }
2689                 }
2690         }
2691         Py_RETURN_NONE;
2692 }
2693
2694 PyObject *eDVBServicePlay::getSubtitleList()
2695 {
2696         if (!m_teletext_parser)
2697                 Py_RETURN_NONE;
2698         
2699         ePyObject l = PyList_New(0);
2700         std::set<int> added_ttx_pages;
2701
2702         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2703                 m_teletext_parser->m_found_subtitle_pages;
2704
2705         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2706         eDVBServicePMTHandler::program program;
2707         if (h.getProgramInfo(program))
2708                 eDebug("getting program info failed.");
2709         else
2710         {
2711                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2712                         it != program.subtitleStreams.end(); ++it)
2713                 {
2714                         switch(it->subtitling_type)
2715                         {
2716                                 case 0x01: // ebu teletext subtitles
2717                                 {
2718                                         int page_number = it->teletext_page_number & 0xFF;
2719                                         int magazine_number = it->teletext_magazine_number & 7;
2720                                         int hash = magazine_number << 8 | page_number;
2721                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2722                                         {
2723                                                 ePyObject tuple = PyTuple_New(5);
2724                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2725                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2726                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2727                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2728                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2729                                                 PyList_Append(l, tuple);
2730                                                 Py_DECREF(tuple);
2731                                                 added_ttx_pages.insert(hash);
2732                                         }
2733                                         break;
2734                                 }
2735                                 case 0x10 ... 0x13:
2736                                 case 0x20 ... 0x23: // dvb subtitles
2737                                 {
2738                                         ePyObject tuple = PyTuple_New(5);
2739                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2740                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2741                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2742                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2743                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2744                                         PyList_Insert(l, 0, tuple);
2745                                         Py_DECREF(tuple);
2746                                         break;
2747                                 }
2748                         }
2749                 }
2750         }
2751
2752         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2753                 it != subs.end(); ++it)
2754         {
2755                 int page_number = it->teletext_page_number & 0xFF;
2756                 int magazine_number = it->teletext_magazine_number & 7;
2757                 int hash = magazine_number << 8 | page_number;
2758                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2759                 {
2760                         ePyObject tuple = PyTuple_New(5);
2761                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2762                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2763                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2764                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2765                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2766                         PyList_Append(l, tuple);
2767                         Py_DECREF(tuple);
2768                 }
2769         }
2770
2771         return l;
2772 }
2773
2774 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2775 {
2776         if (m_subtitle_widget)
2777         {
2778                 m_subtitle_pages.push_back(page);
2779                 checkSubtitleTiming();
2780         }
2781 }
2782
2783 void eDVBServicePlay::checkSubtitleTiming()
2784 {
2785 //      eDebug("checkSubtitleTiming");
2786         if (!m_subtitle_widget)
2787                 return;
2788         while (1)
2789         {
2790                 enum { TELETEXT, DVB } type;
2791                 eDVBTeletextSubtitlePage page;
2792                 eDVBSubtitlePage dvb_page;
2793                 pts_t show_time;
2794                 if (!m_subtitle_pages.empty())
2795                 {
2796                         page = m_subtitle_pages.front();
2797                         type = TELETEXT;
2798                         show_time = page.m_pts;
2799                 }
2800                 else if (!m_dvb_subtitle_pages.empty())
2801                 {
2802                         dvb_page = m_dvb_subtitle_pages.front();
2803                         type = DVB;
2804                         show_time = dvb_page.m_show_time;
2805                 }
2806                 else
2807                         return;
2808         
2809                 pts_t pos = 0;
2810         
2811                 if (m_decoder)
2812                         m_decoder->getPTS(0, pos);
2813
2814 //              eDebug("%lld %lld", pos, show_time);
2815                 int diff =  show_time - pos;
2816                 if (diff < 0)
2817                 {
2818 //                      eDebug("[late (%d ms)]", -diff / 90);
2819                         diff = 0;
2820                 }
2821 //              if (diff > 900000)
2822 //              {
2823 //                      eDebug("[invalid]");
2824 //                      diff = 0;
2825 //              }
2826         
2827                 if (!diff)
2828                 {
2829                         if (type == TELETEXT)
2830                         {
2831 //                              eDebug("display teletext subtitle page");
2832                                 m_subtitle_widget->setPage(page);
2833                                 m_subtitle_pages.pop_front();
2834                         }
2835                         else
2836                         {
2837 //                              eDebug("display dvb subtitle Page %lld", show_time);
2838                                 m_subtitle_widget->setPage(dvb_page);
2839                                 m_dvb_subtitle_pages.pop_front();
2840                         }
2841                 } else
2842                 {
2843 //                      eDebug("start subtitle delay %d", diff / 90);
2844                         m_subtitle_sync_timer.start(diff / 90, 1);
2845                         break;
2846                 }
2847         }
2848 }
2849
2850 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2851 {
2852         if (m_subtitle_widget)
2853         {
2854                 m_dvb_subtitle_pages.push_back(p);
2855                 checkSubtitleTiming();
2856         }
2857 }
2858
2859 int eDVBServicePlay::getAC3Delay()
2860 {
2861         if (m_dvb_service)
2862                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2863         else if (m_decoder)
2864                 return m_decoder->getAC3Delay();
2865         else
2866                 return 0;
2867 }
2868
2869 int eDVBServicePlay::getPCMDelay()
2870 {
2871         if (m_dvb_service)
2872                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2873         else if (m_decoder)
2874                 return m_decoder->getPCMDelay();
2875         else
2876                 return 0;
2877 }
2878
2879 void eDVBServicePlay::setAC3Delay(int delay)
2880 {
2881         if (m_dvb_service)
2882                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2883         if (m_decoder)
2884                 m_decoder->setAC3Delay(delay);
2885 }
2886
2887 void eDVBServicePlay::setPCMDelay(int delay)
2888 {
2889         if (m_dvb_service)
2890                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2891         if (m_decoder)
2892                 m_decoder->setPCMDelay(delay);
2893 }
2894
2895 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2896 {
2897         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2898         m_event((iPlayableService*)this, evVideoSizeChanged);
2899 }
2900
2901 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2902 {
2903         ptr = this;
2904         return 0;
2905 }
2906
2907 PyObject *eDVBServicePlay::getStreamingData()
2908 {
2909         eDVBServicePMTHandler::program program;
2910         if (m_service_handler.getProgramInfo(program))
2911         {
2912                 Py_INCREF(Py_None);
2913                 return Py_None;
2914         }
2915
2916         PyObject *r = program.createPythonObject();
2917         ePtr<iDVBDemux> demux;
2918         if (!m_service_handler.getDataDemux(demux))
2919         {
2920                 uint8_t demux_id;
2921                 demux->getCADemuxID(demux_id);
2922                 
2923                 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2924         }
2925
2926         return r;
2927 }
2928
2929
2930 DEFINE_REF(eDVBServicePlay)
2931
2932 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2933 {
2934         switch (w)
2935         {
2936         case iServiceInformation::sTransponderData:
2937                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2938         default:
2939                 break;
2940         }
2941         return iStaticServiceInformation::getInfoObject(ref, w);
2942 }
2943
2944 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");