790ca2f7bd736a92a2c175ab63aba7b7eb9a4f3a
[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/base/nconfig.h> // access to python config
10 #include <lib/dvb/dvb.h>
11 #include <lib/dvb/db.h>
12 #include <lib/dvb/decoder.h>
13
14 #include <lib/components/file_eraser.h>
15 #include <lib/service/servicedvbrecord.h>
16 #include <lib/service/event.h>
17 #include <lib/dvb/metaparser.h>
18 #include <lib/dvb/tstools.h>
19 #include <lib/python/python.h>
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         return 0;
1349 }
1350
1351 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1352 {
1353         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1354         
1355         if (!m_decode_demux)
1356                 return -1;
1357
1358         ePtr<iDVBPVRChannel> pvr_channel;
1359         
1360         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1361                 return -1;
1362         
1363         int mode = 1;
1364         
1365                         /* HACK until we have skip-AP api */
1366         if ((to > 0) && (to < 100))
1367                 mode = 2;
1368         
1369         to *= direction;
1370         
1371         if (!m_cue)
1372                 return 0;
1373         
1374         m_cue->seekTo(mode, to);
1375         return 0;
1376 }
1377
1378 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1379 {
1380         ePtr<iDVBPVRChannel> pvr_channel;
1381         
1382         if (!m_decode_demux)
1383                 return -1;
1384         
1385         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1386                 return -1;
1387         
1388         int r = 0;
1389
1390                 /* if there is a decoder, use audio or video PTS */
1391         if (m_decoder)
1392         {
1393                 r = m_decoder->getPTS(0, pos);
1394                 if (r)
1395                         return r;
1396         }
1397         
1398                 /* fixup */
1399         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1400 }
1401
1402 RESULT eDVBServicePlay::setTrickmode(int trick)
1403 {
1404         if (m_decoder)
1405                 m_decoder->setTrickmode(trick);
1406         return 0;
1407 }
1408
1409 RESULT eDVBServicePlay::isCurrentlySeekable()
1410 {
1411         return m_is_pvr || m_timeshift_active;
1412 }
1413
1414 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1415 {
1416         ptr = this;
1417         return 0;
1418 }
1419
1420 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1421 {
1422         ptr = this;
1423         return 0;
1424 }
1425
1426 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1427 {
1428         ptr = this;
1429         return 0;
1430 }
1431
1432 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1433 {
1434         ptr = this;
1435         return 0;
1436 }
1437
1438 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1439 {
1440         ptr = this;
1441         return 0;
1442 }
1443
1444 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1445 {
1446         ptr = 0;
1447         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1448                 (m_timeshift_enabled || !m_is_pvr))
1449         {
1450                 if (!m_timeshift_enabled)
1451                 {
1452                                 /* we need enough diskspace */
1453                         struct statfs fs;
1454                         if (statfs(TSPATH "/.", &fs) < 0)
1455                         {
1456                                 eDebug("statfs failed!");
1457                                 return -2;
1458                         }
1459                 
1460                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1461                         {
1462                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1463                                 return -3;
1464                         }
1465                 }
1466                 ptr = this;
1467                 return 0;
1468         }
1469         return -1;
1470 }
1471
1472 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1473 {
1474         if (m_is_pvr)
1475         {
1476                 ptr = this;
1477                 return 0;
1478         }
1479         ptr = 0;
1480         return -1;
1481 }
1482
1483 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1484 {
1485         ptr = this;
1486         return 0;
1487 }
1488
1489 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1490 {
1491         ptr = this;
1492         return 0;
1493 }
1494
1495 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1496 {
1497         ptr = this;
1498         return 0;
1499 }
1500
1501 RESULT eDVBServicePlay::getName(std::string &name)
1502 {
1503         if (m_is_pvr)
1504         {
1505                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1506                 return i->getName(m_reference, name);
1507         }
1508         if (m_dvb_service)
1509         {
1510                 m_dvb_service->getName(m_reference, name);
1511                 if (name.empty())
1512                         name = "(...)";
1513         }
1514         else if (!m_reference.name.empty())
1515                 eStaticServiceDVBInformation().getName(m_reference, name);
1516         else
1517                 name = "DVB service";
1518         return 0;
1519 }
1520
1521 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1522 {
1523         return m_event_handler.getEvent(evt, nownext);
1524 }
1525
1526 int eDVBServicePlay::getInfo(int w)
1527 {
1528         eDVBServicePMTHandler::program program;
1529         
1530         if (w == sCAIDs)
1531                 return resIsPyObject;
1532
1533         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1534         
1535         int no_program_info = 0;
1536         
1537         if (h.getProgramInfo(program))
1538                 no_program_info = 1;
1539         
1540         switch (w)
1541         {
1542 #if HAVE_DVB_API_VERSION >= 3
1543         case sVideoHeight:
1544                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1545                         return m_videoEventData.height;
1546                 return -1;
1547         case sVideoWidth:
1548                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1549                         return m_videoEventData.width;
1550                 return -1;
1551 #else
1552 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1553 #endif
1554         case sAspect:
1555 #if HAVE_DVB_API_VERSION >= 3
1556                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1557                         return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1558                 else
1559 #else
1560 #warning "FIXMEE implement sAspect for old DVB API"
1561 #endif
1562                 if (no_program_info)
1563                         return -1; 
1564                 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1565                 {
1566                         ePtr<eServiceEvent> evt;
1567                         if (!m_event_handler.getEvent(evt, 0))
1568                         {
1569                                 ePtr<eComponentData> data;
1570                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1571                                 {
1572                                         if ( data->getStreamContent() == 1 )
1573                                         {
1574                                                 switch(data->getComponentType())
1575                                                 {
1576                                                         // SD
1577                                                         case 1: // 4:3 SD PAL
1578                                                         case 2:
1579                                                         case 3: // 16:9 SD PAL
1580                                                         case 4: // > 16:9 PAL
1581                                                         case 5: // 4:3 SD NTSC
1582                                                         case 6: 
1583                                                         case 7: // 16:9 SD NTSC
1584                                                         case 8: // > 16:9 NTSC
1585
1586                                                         // HD
1587                                                         case 9: // 4:3 HD PAL
1588                                                         case 0xA:
1589                                                         case 0xB: // 16:9 HD PAL
1590                                                         case 0xC: // > 16:9 HD PAL
1591                                                         case 0xD: // 4:3 HD NTSC
1592                                                         case 0xE:
1593                                                         case 0xF: // 16:9 HD NTSC
1594                                                         case 0x10: // > 16:9 HD PAL
1595                                                                 return data->getComponentType();
1596                                                 }
1597                                         }
1598                                 }
1599                         }
1600                 }
1601                 return -1;
1602         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1603         case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1604         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1605         case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1606         case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1607         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1608         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1609         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1610         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1611         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1612         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1613         case sProvider: if (!m_dvb_service) return -1; return -2;
1614         case sServiceref: return resIsString;
1615         case sDVBState: return m_tune_state;
1616         default:
1617                 return -1;
1618         }
1619 }
1620
1621 std::string eDVBServicePlay::getInfoString(int w)
1622 {
1623         switch (w)
1624         {
1625         case sProvider:
1626                 if (!m_dvb_service) return "";
1627                 return m_dvb_service->m_provider_name;
1628         case sServiceref:
1629                 return m_reference.toString();
1630         default:
1631                 break;
1632         }
1633         return iServiceInformation::getInfoString(w);
1634 }
1635
1636 PyObject *eDVBServicePlay::getInfoObject(int w)
1637 {
1638         switch (w)
1639         {
1640         case sCAIDs:
1641                 return m_service_handler.getCaIds();
1642         case sTransponderData:
1643                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1644         default:
1645                 break;
1646         }
1647         return iServiceInformation::getInfoObject(w);
1648 }
1649
1650 int eDVBServicePlay::getNumberOfTracks()
1651 {
1652         eDVBServicePMTHandler::program program;
1653         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1654         if (h.getProgramInfo(program))
1655                 return 0;
1656         return program.audioStreams.size();
1657 }
1658
1659 int eDVBServicePlay::getCurrentTrack()
1660 {
1661         eDVBServicePMTHandler::program program;
1662         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1663         if (h.getProgramInfo(program))
1664                 return 0;
1665
1666         int max = program.audioStreams.size();
1667         int i;
1668
1669         for (i = 0; i < max; ++i)
1670                 if (program.audioStreams[i].pid == m_current_audio_pid)
1671                         return i;
1672
1673         return 0;
1674 }
1675
1676 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1677 {
1678         int ret = selectAudioStream(i);
1679
1680         if (m_decoder->start())
1681                 return -5;
1682
1683         return ret;
1684 }
1685
1686 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1687 {
1688         eDVBServicePMTHandler::program program;
1689         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1690
1691         if (h.getProgramInfo(program))
1692                 return -1;
1693         
1694         if (i >= program.audioStreams.size())
1695                 return -2;
1696         
1697         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1698                 info.m_description = "MPEG";
1699         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1700                 info.m_description = "AC3";
1701         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1702                 info.m_description = "AAC";
1703         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1704                 info.m_description = "DTS";
1705         else
1706                 info.m_description = "???";
1707
1708         if (program.audioStreams[i].component_tag != -1)
1709         {
1710                 ePtr<eServiceEvent> evt;
1711                 if (!m_event_handler.getEvent(evt, 0))
1712                 {
1713                         ePtr<eComponentData> data;
1714                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1715                                 info.m_language = data->getText();
1716                 }
1717         }
1718
1719         if (info.m_language.empty())
1720                 info.m_language = program.audioStreams[i].language_code;
1721         
1722         return 0;
1723 }
1724
1725 int eDVBServicePlay::selectAudioStream(int i)
1726 {
1727         eDVBServicePMTHandler::program program;
1728         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1729
1730         if (h.getProgramInfo(program))
1731                 return -1;
1732
1733         if ((unsigned int)i >= program.audioStreams.size())
1734                 return -2;
1735
1736         if (!m_decoder)
1737                 return -3;
1738
1739         int stream = i;
1740         if (stream == -1)
1741                 stream = program.defaultAudioStream;
1742
1743         m_current_audio_pid = program.audioStreams[stream].pid;
1744
1745         if (m_decoder->setAudioPID(program.audioStreams[stream].pid, program.audioStreams[stream].type))
1746         {
1747                 eDebug("set audio pid failed");
1748                 return -4;
1749         }
1750
1751         if (m_rds_decoder)
1752                 m_rds_decoder->start(program.audioStreams[stream].pid);
1753
1754                         /* store new pid as default only when:
1755                                 a.) we have an entry in the service db for the current service,
1756                                 b.) we are not playing back something,
1757                                 c.) we are not selecting the default entry. (we wouldn't change 
1758                                     anything in the best case, or destroy the default setting in
1759                                     case the real default is not yet available.)
1760                         */
1761         if (m_dvb_service && !m_is_pvr && (i != -1))
1762         {
1763                 if (program.audioStreams[stream].type == eDVBAudio::aMPEG)
1764                 {
1765                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[stream].pid);
1766                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1767                 }
1768                 else
1769                 {
1770                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1771                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[stream].pid);
1772                 }
1773         }
1774
1775         h.resetCachedProgram();
1776
1777         return 0;
1778 }
1779
1780 int eDVBServicePlay::getCurrentChannel()
1781 {
1782         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1783 }
1784
1785 RESULT eDVBServicePlay::selectChannel(int i)
1786 {
1787         if (i < LEFT || i > RIGHT || i == STEREO)
1788                 i = -1;  // Stereo
1789         if (m_dvb_service)
1790                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1791         if (m_decoder)
1792                 m_decoder->setAudioChannel(i);
1793         return 0;
1794 }
1795
1796 std::string eDVBServicePlay::getText(int x)
1797 {
1798         if (m_rds_decoder)
1799                 switch(x)
1800                 {
1801                         case RadioText:
1802                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1803                         case RtpText:
1804                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1805                 }
1806         return "";
1807 }
1808
1809 void eDVBServicePlay::rdsDecoderEvent(int what)
1810 {
1811         switch(what)
1812         {
1813                 case eDVBRdsDecoder::RadioTextChanged:
1814                         m_event((iPlayableService*)this, evUpdatedRadioText);
1815                         break;
1816                 case eDVBRdsDecoder::RtpTextChanged:
1817                         m_event((iPlayableService*)this, evUpdatedRtpText);
1818                         break;
1819                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1820                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1821                         break;
1822                 case eDVBRdsDecoder::RecvRassSlidePic:
1823                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1824                         break;
1825         }
1826 }
1827
1828 void eDVBServicePlay::showRassSlidePicture()
1829 {
1830         if (m_rds_decoder)
1831         {
1832                 if (m_decoder)
1833                 {
1834                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1835                         if (rass_slide_pic.length())
1836                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1837                         else
1838                                 eDebug("empty filename for rass slide picture received!!");
1839                 }
1840                 else
1841                         eDebug("no MPEG Decoder to show iframes avail");
1842         }
1843         else
1844                 eDebug("showRassSlidePicture called.. but not decoder");
1845 }
1846
1847 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1848 {
1849         if (m_rds_decoder)
1850         {
1851                 if (m_decoder)
1852                 {
1853                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1854                         if (rass_interactive_pic.length())
1855                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1856                         else
1857                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1858                 }
1859                 else
1860                         eDebug("no MPEG Decoder to show iframes avail");
1861         }
1862         else
1863                 eDebug("showRassInteractivePic called.. but not decoder");
1864 }
1865
1866 ePyObject eDVBServicePlay::getRassInteractiveMask()
1867 {
1868         if (m_rds_decoder)
1869                 return m_rds_decoder->getRassPictureMask();
1870         Py_RETURN_NONE;
1871 }
1872
1873 int eDVBServiceBase::getFrontendInfo(int w)
1874 {
1875         eUsePtr<iDVBChannel> channel;
1876         if(m_service_handler.getChannel(channel))
1877                 return 0;
1878         ePtr<iDVBFrontend> fe;
1879         if(channel->getFrontend(fe))
1880                 return 0;
1881         return fe->readFrontendData(w);
1882 }
1883
1884 PyObject *eDVBServiceBase::getFrontendData()
1885 {
1886         ePyObject ret = PyDict_New();
1887         if (ret)
1888         {
1889                 eUsePtr<iDVBChannel> channel;
1890                 if(!m_service_handler.getChannel(channel))
1891                 {
1892                         ePtr<iDVBFrontend> fe;
1893                         if(!channel->getFrontend(fe))
1894                                 fe->getFrontendData(ret);
1895                 }
1896         }
1897         else
1898                 Py_RETURN_NONE;
1899         return ret;
1900 }
1901
1902 PyObject *eDVBServiceBase::getFrontendStatus()
1903 {
1904         ePyObject ret = PyDict_New();
1905         if (ret)
1906         {
1907                 eUsePtr<iDVBChannel> channel;
1908                 if(!m_service_handler.getChannel(channel))
1909                 {
1910                         ePtr<iDVBFrontend> fe;
1911                         if(!channel->getFrontend(fe))
1912                                 fe->getFrontendStatus(ret);
1913                 }
1914         }
1915         else
1916                 Py_RETURN_NONE;
1917         return ret;
1918 }
1919
1920 PyObject *eDVBServiceBase::getTransponderData(bool original)
1921 {
1922         ePyObject ret = PyDict_New();
1923         if (ret)
1924         {
1925                 eUsePtr<iDVBChannel> channel;
1926                 if(!m_service_handler.getChannel(channel))
1927                 {
1928                         ePtr<iDVBFrontend> fe;
1929                         if(!channel->getFrontend(fe))
1930                         {
1931                                 fe->getTransponderData(ret, original);
1932                                 ePtr<iDVBFrontendParameters> feparm;
1933                                 channel->getCurrentFrontendParameters(feparm);
1934                                 if (feparm)
1935                                 {
1936                                         eDVBFrontendParametersSatellite osat;
1937                                         if (!feparm->getDVBS(osat))
1938                                         {
1939                                                 void PutToDict(ePyObject &, const char*, long);
1940                                                 void PutToDict(ePyObject &, const char*, const char*);
1941                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1942                                                 const char *tmp = "UNKNOWN";
1943                                                 switch(osat.polarisation)
1944                                                 {
1945                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1946                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1947                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1948                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1949                                                         default:break;
1950                                                 }
1951                                                 PutToDict(ret, "polarization", tmp);
1952                                         }
1953                                 }
1954                         }
1955                 }
1956         }
1957         else
1958                 Py_RETURN_NONE;
1959         return ret;
1960 }
1961
1962 PyObject *eDVBServiceBase::getAll(bool original)
1963 {
1964         ePyObject ret = getTransponderData(original);
1965         if (ret != Py_None)
1966         {
1967                 eUsePtr<iDVBChannel> channel;
1968                 if(!m_service_handler.getChannel(channel))
1969                 {
1970                         ePtr<iDVBFrontend> fe;
1971                         if(!channel->getFrontend(fe))
1972                         {
1973                                 fe->getFrontendData(ret);
1974                                 fe->getFrontendStatus(ret);
1975                         }
1976                 }
1977         }
1978         return ret;
1979 }
1980
1981 int eDVBServicePlay::getNumberOfSubservices()
1982 {
1983         ePtr<eServiceEvent> evt;
1984         if (!m_event_handler.getEvent(evt, 0))
1985                 return evt->getNumOfLinkageServices();
1986         return 0;
1987 }
1988
1989 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1990 {
1991         ePtr<eServiceEvent> evt;
1992         if (!m_event_handler.getEvent(evt, 0))
1993         {
1994                 if (!evt->getLinkageService(sub, m_reference, n))
1995                         return 0;
1996         }
1997         sub.type=eServiceReference::idInvalid;
1998         return -1;
1999 }
2000
2001 RESULT eDVBServicePlay::startTimeshift()
2002 {
2003         ePtr<iDVBDemux> demux;
2004         
2005         eDebug("Start timeshift!");
2006         
2007         if (m_timeshift_enabled)
2008                 return -1;
2009         
2010                 /* start recording with the data demux. */
2011         if (m_service_handler.getDataDemux(demux))
2012                 return -2;
2013
2014         demux->createTSRecorder(m_record);
2015         if (!m_record)
2016                 return -3;
2017
2018         char templ[]=TSPATH "/timeshift.XXXXXX";
2019         m_timeshift_fd = mkstemp(templ);
2020         m_timeshift_file = templ;
2021         
2022         eDebug("recording to %s", templ);
2023         
2024         if (m_timeshift_fd < 0)
2025         {
2026                 m_record = 0;
2027                 return -4;
2028         }
2029                 
2030         m_record->setTargetFD(m_timeshift_fd);
2031
2032         m_timeshift_enabled = 1;
2033         
2034         updateTimeshiftPids();
2035         m_record->start();
2036
2037         return 0;
2038 }
2039
2040 RESULT eDVBServicePlay::stopTimeshift()
2041 {
2042         if (!m_timeshift_enabled)
2043                 return -1;
2044         
2045         switchToLive();
2046         
2047         m_timeshift_enabled = 0;
2048         
2049         m_record->stop();
2050         m_record = 0;
2051         
2052         close(m_timeshift_fd);
2053         eDebug("remove timeshift file");
2054         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2055         
2056         return 0;
2057 }
2058
2059 int eDVBServicePlay::isTimeshiftActive()
2060 {
2061         return m_timeshift_enabled && m_timeshift_active;
2062 }
2063
2064 RESULT eDVBServicePlay::activateTimeshift()
2065 {
2066         if (!m_timeshift_enabled)
2067                 return -1;
2068         
2069         if (!m_timeshift_active)
2070         {
2071                 switchToTimeshift();
2072                 return 0;
2073         }
2074         
2075         return -2;
2076 }
2077
2078 PyObject *eDVBServicePlay::getCutList()
2079 {
2080         ePyObject list = PyList_New(0);
2081         
2082         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2083         {
2084                 ePyObject tuple = PyTuple_New(2);
2085                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
2086                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
2087                 PyList_Append(list, tuple);
2088                 Py_DECREF(tuple);
2089         }
2090         
2091         return list;
2092 }
2093
2094 void eDVBServicePlay::setCutList(ePyObject list)
2095 {
2096         if (!PyList_Check(list))
2097                 return;
2098         int size = PyList_Size(list);
2099         int i;
2100         
2101         m_cue_entries.clear();
2102         
2103         for (i=0; i<size; ++i)
2104         {
2105                 ePyObject tuple = PyList_GET_ITEM(list, i);
2106                 if (!PyTuple_Check(tuple))
2107                 {
2108                         eDebug("non-tuple in cutlist");
2109                         continue;
2110                 }
2111                 if (PyTuple_Size(tuple) != 2)
2112                 {
2113                         eDebug("cutlist entries need to be a 2-tuple");
2114                         continue;
2115                 }
2116                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2117                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2118                 {
2119                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2120                         continue;
2121                 }
2122                 pts_t pts = PyLong_AsLongLong(ppts);
2123                 int type = PyInt_AsLong(ptype);
2124                 m_cue_entries.insert(cueEntry(pts, type));
2125                 eDebug("adding %08llx, %d", pts, type);
2126         }
2127         m_cuesheet_changed = 1;
2128         
2129         cutlistToCuesheet();
2130         m_event((iPlayableService*)this, evCuesheetChanged);
2131 }
2132
2133 void eDVBServicePlay::setCutListEnable(int enable)
2134 {
2135         m_cutlist_enabled = enable;
2136         cutlistToCuesheet();
2137 }
2138
2139 void eDVBServicePlay::updateTimeshiftPids()
2140 {
2141         if (!m_record)
2142                 return;
2143         
2144         eDVBServicePMTHandler::program program;
2145         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2146
2147         if (h.getProgramInfo(program))
2148                 return;
2149         else
2150         {
2151                 std::set<int> pids_to_record;
2152                 pids_to_record.insert(0); // PAT
2153                 if (program.pmtPid != -1)
2154                         pids_to_record.insert(program.pmtPid); // PMT
2155
2156                 if (program.textPid != -1)
2157                         pids_to_record.insert(program.textPid); // Videotext
2158
2159                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2160                         i(program.videoStreams.begin()); 
2161                         i != program.videoStreams.end(); ++i)
2162                         pids_to_record.insert(i->pid);
2163
2164                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2165                         i(program.audioStreams.begin()); 
2166                         i != program.audioStreams.end(); ++i)
2167                                 pids_to_record.insert(i->pid);
2168
2169                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2170                         i(program.subtitleStreams.begin());
2171                         i != program.subtitleStreams.end(); ++i)
2172                                 pids_to_record.insert(i->pid);
2173
2174                 std::set<int> new_pids, obsolete_pids;
2175                 
2176                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2177                                 m_pids_active.begin(), m_pids_active.end(),
2178                                 std::inserter(new_pids, new_pids.begin()));
2179                 
2180                 std::set_difference(
2181                                 m_pids_active.begin(), m_pids_active.end(),
2182                                 pids_to_record.begin(), pids_to_record.end(), 
2183                                 std::inserter(new_pids, new_pids.begin())
2184                                 );
2185
2186                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2187                         m_record->addPID(*i);
2188
2189                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2190                         m_record->removePID(*i);
2191         }
2192 }
2193
2194 void eDVBServicePlay::switchToLive()
2195 {
2196         if (!m_timeshift_active)
2197                 return;
2198         
2199         m_cue = 0;
2200         m_decoder = 0;
2201         m_decode_demux = 0;
2202         m_teletext_parser = 0;
2203         m_rds_decoder = 0;
2204         m_subtitle_parser = 0;
2205         m_new_dvb_subtitle_page_connection = 0;
2206         m_new_subtitle_page_connection = 0;
2207         m_rds_decoder_event_connection = 0;
2208         m_video_event_connection = 0;
2209
2210                 /* free the timeshift service handler, we need the resources */
2211         m_service_handler_timeshift.free();
2212         m_timeshift_active = 0;
2213
2214         m_event((iPlayableService*)this, evSeekableStatusChanged);
2215
2216         updateDecoder();
2217 }
2218
2219 void eDVBServicePlay::switchToTimeshift()
2220 {
2221         if (m_timeshift_active)
2222                 return;
2223
2224         m_decode_demux = 0;
2225         m_decoder = 0;
2226         m_teletext_parser = 0;
2227         m_rds_decoder = 0;
2228         m_subtitle_parser = 0;
2229         m_new_subtitle_page_connection = 0;
2230         m_new_dvb_subtitle_page_connection = 0;
2231         m_rds_decoder_event_connection = 0;
2232         m_video_event_connection = 0;
2233
2234         m_timeshift_active = 1;
2235
2236         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2237         r.path = m_timeshift_file;
2238
2239         m_cue = new eCueSheet();
2240         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2241
2242         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2243         pause();
2244         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2245         
2246         m_event((iPlayableService*)this, evSeekableStatusChanged);
2247 }
2248
2249 void eDVBServicePlay::updateDecoder()
2250 {
2251         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2252
2253         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2254
2255         bool defaultac3=false;
2256         std::string default_ac3;
2257
2258         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2259                 defaultac3 = default_ac3 == "True";
2260
2261         eDVBServicePMTHandler::program program;
2262         if (h.getProgramInfo(program))
2263                 eDebug("getting program info failed.");
2264         else
2265         {
2266                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2267                 if (!program.videoStreams.empty())
2268                 {
2269                         eDebugNoNewLine(" (");
2270                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2271                                 i(program.videoStreams.begin());
2272                                 i != program.videoStreams.end(); ++i)
2273                         {
2274                                 if (vpid == -1)
2275                                 {
2276                                         vpid = i->pid;
2277                                         vpidtype = i->type;
2278                                 }
2279                                 if (i != program.videoStreams.begin())
2280                                         eDebugNoNewLine(", ");
2281                                 eDebugNoNewLine("%04x", i->pid);
2282                         }
2283                         eDebugNoNewLine(")");
2284                 }
2285                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2286                 if (!program.audioStreams.empty())
2287                 {
2288                         eDebugNoNewLine(" (");
2289                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2290                                 i(program.audioStreams.begin());
2291                                 i != program.audioStreams.end(); ++i)
2292                         {
2293                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2294                                 {
2295                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2296                                         {
2297                                                 apid = i->pid;
2298                                                 apidtype = i->type;
2299                                         }
2300                                 }
2301                                 if (i != program.audioStreams.begin())
2302                                         eDebugNoNewLine(", ");
2303                                 eDebugNoNewLine("%04x", i->pid);
2304                         }
2305                         eDebugNoNewLine(")");
2306                 }
2307                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2308                 pcrpid = program.pcrPid;
2309                 eDebug(", and the text pid is %04x", program.textPid);
2310                 tpid = program.textPid;
2311         }
2312
2313         if (!m_decoder)
2314         {
2315                 h.getDecodeDemux(m_decode_demux);
2316                 if (m_decode_demux)
2317                 {
2318                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2319                         if (m_decoder)
2320                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2321                         m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2322                         m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2323                         m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2324                         m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2325                 } else
2326                 {
2327                         m_teletext_parser = 0;
2328                         m_subtitle_parser = 0;
2329                 }
2330
2331                 if (m_cue)
2332                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2333         }
2334
2335         if (m_decoder)
2336         {
2337                 if (m_dvb_service)
2338                 {
2339                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2340                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2341                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2342                 }
2343                 else // subservice or recording
2344                 {
2345                         eServiceReferenceDVB ref;
2346                         m_service_handler.getServiceReference(ref);
2347                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2348                         if (!parent)
2349                                 parent = ref;
2350                         if (parent)
2351                         {
2352                                 ePtr<eDVBResourceManager> res_mgr;
2353                                 if (!eDVBResourceManager::getInstance(res_mgr))
2354                                 {
2355                                         ePtr<iDVBChannelList> db;
2356                                         if (!res_mgr->getChannelList(db))
2357                                         {
2358                                                 ePtr<eDVBService> origService;
2359                                                 if (!db->getService(parent, origService))
2360                                                 {
2361                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2362                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2363                                                 }
2364                                         }
2365                                 }
2366                         }
2367                 }
2368                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2369                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2370
2371                 m_decoder->setVideoPID(vpid, vpidtype);
2372                 selectAudioStream();
2373
2374                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2375                 {
2376                         m_decoder->setSyncPCR(pcrpid);
2377                         if (apid != -1)
2378                         {
2379                                 ePtr<iDVBDemux> data_demux;
2380                                 if (!h.getDataDemux(data_demux))
2381                                 {
2382                                         m_rds_decoder = new eDVBRdsDecoder(data_demux);
2383                                         m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
2384                                         m_rds_decoder->start(apid);
2385                                 }
2386                         }
2387                 }
2388                 else
2389                         m_decoder->setSyncPCR(-1);
2390
2391                 m_decoder->setTextPID(tpid);
2392
2393                 m_teletext_parser->start(program.textPid);
2394
2395                 if (!m_is_primary)
2396                         m_decoder->setTrickmode(1);
2397
2398                 if (m_is_paused)
2399                         m_decoder->preroll();
2400                 else
2401                         m_decoder->start();
2402
2403                 if (vpid > 0 && vpid < 0x2000)
2404                         ;
2405                 else
2406                 {
2407                         std::string radio_pic;
2408                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2409                                 m_decoder->setRadioPic(radio_pic);
2410                 }
2411
2412                 m_decoder->setAudioChannel(achannel);
2413
2414 // how we can do this better?
2415 // update cache pid when the user changed the audio track or video track
2416 // TODO handling of difference audio types.. default audio types..
2417
2418                 /* don't worry about non-existing services, nor pvr services */
2419                 if (m_dvb_service && !m_is_pvr)
2420                 {
2421                         if (apidtype == eDVBAudio::aMPEG)
2422                         {
2423                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2424                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2425                         }
2426                         else
2427                         {
2428                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2429                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2430                         }
2431                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2432                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2433                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2434                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2435                 }
2436         }       
2437         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2438 }
2439
2440 void eDVBServicePlay::loadCuesheet()
2441 {
2442         std::string filename = m_reference.path + ".cuts";
2443         
2444         m_cue_entries.clear();
2445
2446         FILE *f = fopen(filename.c_str(), "rb");
2447
2448         if (f)
2449         {
2450                 eDebug("loading cuts..");
2451                 while (1)
2452                 {
2453                         unsigned long long where;
2454                         unsigned int what;
2455                         
2456                         if (!fread(&where, sizeof(where), 1, f))
2457                                 break;
2458                         if (!fread(&what, sizeof(what), 1, f))
2459                                 break;
2460                         
2461 #if BYTE_ORDER == LITTLE_ENDIAN
2462                         where = bswap_64(where);
2463 #endif
2464                         what = ntohl(what);
2465                         
2466                         if (what > 3)
2467                                 break;
2468                         
2469                         m_cue_entries.insert(cueEntry(where, what));
2470                 }
2471                 fclose(f);
2472                 eDebug("%d entries", m_cue_entries.size());
2473         } else
2474                 eDebug("cutfile not found!");
2475         
2476         m_cuesheet_changed = 0;
2477         cutlistToCuesheet();
2478         m_event((iPlayableService*)this, evCuesheetChanged);
2479 }
2480
2481 void eDVBServicePlay::saveCuesheet()
2482 {
2483         std::string filename = m_reference.path + ".cuts";
2484         
2485         FILE *f = fopen(filename.c_str(), "wb");
2486
2487         if (f)
2488         {
2489                 unsigned long long where;
2490                 int what;
2491
2492                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2493                 {
2494 #if BYTE_ORDER == BIG_ENDIAN
2495                         where = i->where;
2496 #else
2497                         where = bswap_64(i->where);
2498 #endif
2499                         what = htonl(i->what);
2500                         fwrite(&where, sizeof(where), 1, f);
2501                         fwrite(&what, sizeof(what), 1, f);
2502                         
2503                 }
2504                 fclose(f);
2505         }
2506         
2507         m_cuesheet_changed = 0;
2508 }
2509
2510 void eDVBServicePlay::cutlistToCuesheet()
2511 {
2512         if (!m_cue)
2513         {
2514                 eDebug("no cue sheet");
2515                 return;
2516         }       
2517         m_cue->clear();
2518         
2519         if (!m_cutlist_enabled)
2520         {
2521                 m_cue->commitSpans();
2522                 eDebug("cutlists were disabled");
2523                 return;
2524         }
2525
2526         pts_t in = 0, out = 0, length = 0;
2527         
2528         getLength(length);
2529                 
2530         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2531         
2532         while (1)
2533         {
2534                 if (i == m_cue_entries.end())
2535                         out = length;
2536                 else {
2537                         if (i->what == 0) /* in */
2538                         {
2539                                 in = i++->where;
2540                                 continue;
2541                         } else if (i->what == 1) /* out */
2542                                 out = i++->where;
2543                         else /* mark (2) or last play position (3) */
2544                         {
2545                                 i++;
2546                                 continue;
2547                         }
2548                 }
2549                 
2550                 if (in != out)
2551                         m_cue->addSourceSpan(in, out);
2552                 
2553                 in = length;
2554                 
2555                 if (i == m_cue_entries.end())
2556                         break;
2557         }
2558         m_cue->commitSpans();
2559 }
2560
2561 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2562 {
2563         if (m_subtitle_widget)
2564                 disableSubtitles(parent);
2565
2566         ePyObject entry;
2567         int tuplesize = PyTuple_Size(tuple);
2568         int type = 0;
2569
2570         if (!PyTuple_Check(tuple))
2571                 goto error_out;
2572
2573         if (tuplesize < 1)
2574                 goto error_out;
2575
2576         entry = PyTuple_GET_ITEM(tuple, 0);
2577
2578         if (!PyInt_Check(entry))
2579                 goto error_out;
2580
2581         type = PyInt_AsLong(entry);
2582
2583         if (type == 1)  // teletext subtitles
2584         {
2585                 int page, magazine, pid;
2586                 if (tuplesize < 4)
2587                         goto error_out;
2588
2589                 if (!m_teletext_parser)
2590                 {
2591                         eDebug("enable teletext subtitles.. no parser !!!");
2592                         return -1;
2593                 }
2594
2595                 entry = PyTuple_GET_ITEM(tuple, 1);
2596                 if (!PyInt_Check(entry))
2597                         goto error_out;
2598                 pid = PyInt_AsLong(entry);
2599
2600                 entry = PyTuple_GET_ITEM(tuple, 2);
2601                 if (!PyInt_Check(entry))
2602                         goto error_out;
2603                 page = PyInt_AsLong(entry);
2604
2605                 entry = PyTuple_GET_ITEM(tuple, 3);
2606                 if (!PyInt_Check(entry))
2607                         goto error_out;
2608                 magazine = PyInt_AsLong(entry);
2609
2610                 m_subtitle_widget = new eSubtitleWidget(parent);
2611                 m_subtitle_widget->resize(parent->size()); /* full size */
2612                 m_teletext_parser->setPageAndMagazine(page, magazine);
2613                 if (m_dvb_service)
2614                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2615         }
2616         else if (type == 0)
2617         {
2618                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2619                 if (!m_subtitle_parser)
2620                 {
2621                         eDebug("enable dvb subtitles.. no parser !!!");
2622                         return -1;
2623                 }
2624                 if (tuplesize < 4)
2625                         goto error_out;
2626
2627                 entry = PyTuple_GET_ITEM(tuple, 1);
2628                 if (!PyInt_Check(entry))
2629                         goto error_out;
2630                 pid = PyInt_AsLong(entry);
2631
2632                 entry = PyTuple_GET_ITEM(tuple, 2);
2633                 if (!PyInt_Check(entry))
2634                         goto error_out;
2635                 composition_page_id = PyInt_AsLong(entry);
2636
2637                 entry = PyTuple_GET_ITEM(tuple, 3);
2638                 if (!PyInt_Check(entry))
2639                         goto error_out;
2640                 ancillary_page_id = PyInt_AsLong(entry);
2641
2642                 m_subtitle_widget = new eSubtitleWidget(parent);
2643                 m_subtitle_widget->resize(parent->size()); /* full size */
2644                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2645                 if (m_dvb_service)
2646                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2647         }
2648         else
2649                 goto error_out;
2650         return 0;
2651 error_out:
2652         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2653                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2654                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2655         return -1;
2656 }
2657
2658 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2659 {
2660         delete m_subtitle_widget;
2661         m_subtitle_widget = 0;
2662         if (m_subtitle_parser)
2663         {
2664                 m_subtitle_parser->stop();
2665                 m_dvb_subtitle_pages.clear();
2666         }
2667         if (m_teletext_parser)
2668         {
2669                 m_teletext_parser->setPageAndMagazine(-1, -1);
2670                 m_subtitle_pages.clear();
2671         }
2672         if (m_dvb_service)
2673                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2674         return 0;
2675 }
2676
2677 PyObject *eDVBServicePlay::getCachedSubtitle()
2678 {
2679         if (m_dvb_service)
2680         {
2681                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2682                 if (tmp != -1)
2683                 {
2684                         unsigned int data = (unsigned int)tmp;
2685                         int pid = (data&0xFFFF0000)>>16;
2686                         ePyObject tuple = PyTuple_New(4);
2687                         eDVBServicePMTHandler::program program;
2688                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2689                         if (!h.getProgramInfo(program))
2690                         {
2691                                 if (program.textPid==pid) // teletext
2692                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2693                                 else
2694                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2695                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2696                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2697                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2698                                 return tuple;
2699                         }
2700                 }
2701         }
2702         Py_RETURN_NONE;
2703 }
2704
2705 PyObject *eDVBServicePlay::getSubtitleList()
2706 {
2707         if (!m_teletext_parser)
2708                 Py_RETURN_NONE;
2709         
2710         ePyObject l = PyList_New(0);
2711         std::set<int> added_ttx_pages;
2712
2713         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2714                 m_teletext_parser->m_found_subtitle_pages;
2715
2716         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2717         eDVBServicePMTHandler::program program;
2718         if (h.getProgramInfo(program))
2719                 eDebug("getting program info failed.");
2720         else
2721         {
2722                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2723                         it != program.subtitleStreams.end(); ++it)
2724                 {
2725                         switch(it->subtitling_type)
2726                         {
2727                                 case 0x01: // ebu teletext subtitles
2728                                 {
2729                                         int page_number = it->teletext_page_number & 0xFF;
2730                                         int magazine_number = it->teletext_magazine_number & 7;
2731                                         int hash = magazine_number << 8 | page_number;
2732                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2733                                         {
2734                                                 ePyObject tuple = PyTuple_New(5);
2735                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2736                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2737                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2738                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2739                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2740                                                 PyList_Append(l, tuple);
2741                                                 Py_DECREF(tuple);
2742                                                 added_ttx_pages.insert(hash);
2743                                         }
2744                                         break;
2745                                 }
2746                                 case 0x10 ... 0x13:
2747                                 case 0x20 ... 0x23: // dvb subtitles
2748                                 {
2749                                         ePyObject tuple = PyTuple_New(5);
2750                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2751                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2752                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2753                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2754                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2755                                         PyList_Insert(l, 0, tuple);
2756                                         Py_DECREF(tuple);
2757                                         break;
2758                                 }
2759                         }
2760                 }
2761         }
2762
2763         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2764                 it != subs.end(); ++it)
2765         {
2766                 int page_number = it->teletext_page_number & 0xFF;
2767                 int magazine_number = it->teletext_magazine_number & 7;
2768                 int hash = magazine_number << 8 | page_number;
2769                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2770                 {
2771                         ePyObject tuple = PyTuple_New(5);
2772                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2773                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2774                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2775                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2776                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2777                         PyList_Append(l, tuple);
2778                         Py_DECREF(tuple);
2779                 }
2780         }
2781
2782         return l;
2783 }
2784
2785 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2786 {
2787         if (m_subtitle_widget)
2788         {
2789                 m_subtitle_pages.push_back(page);
2790                 checkSubtitleTiming();
2791         }
2792 }
2793
2794 void eDVBServicePlay::checkSubtitleTiming()
2795 {
2796 //      eDebug("checkSubtitleTiming");
2797         if (!m_subtitle_widget)
2798                 return;
2799         while (1)
2800         {
2801                 enum { TELETEXT, DVB } type;
2802                 eDVBTeletextSubtitlePage page;
2803                 eDVBSubtitlePage dvb_page;
2804                 pts_t show_time;
2805                 if (!m_subtitle_pages.empty())
2806                 {
2807                         page = m_subtitle_pages.front();
2808                         type = TELETEXT;
2809                         show_time = page.m_pts;
2810                 }
2811                 else if (!m_dvb_subtitle_pages.empty())
2812                 {
2813                         dvb_page = m_dvb_subtitle_pages.front();
2814                         type = DVB;
2815                         show_time = dvb_page.m_show_time;
2816                 }
2817                 else
2818                         return;
2819         
2820                 pts_t pos = 0;
2821         
2822                 if (m_decoder)
2823                         m_decoder->getPTS(0, pos);
2824
2825 //              eDebug("%lld %lld", pos, show_time);
2826                 int diff =  show_time - pos;
2827                 if (diff < 0)
2828                 {
2829                         eDebug("[late (%d ms)]", -diff / 90);
2830                         diff = 0;
2831                 }
2832                 if (diff > 900000)
2833                 {
2834                         eDebug("[invalid]");
2835                         diff = 0;
2836                 }
2837         
2838                 if (!diff)
2839                 {
2840                         if (type == TELETEXT)
2841                         {
2842                                 eDebug("display teletext subtitle page");
2843                                 m_subtitle_widget->setPage(page);
2844                                 m_subtitle_pages.pop_front();
2845                         }
2846                         else
2847                         {
2848                                 eDebug("display dvb subtitle Page");
2849                                 m_subtitle_widget->setPage(dvb_page);
2850                                 m_dvb_subtitle_pages.pop_front();
2851                         }
2852                 } else
2853                 {
2854 //                      eDebug("start subtitle delay %d", diff / 90);
2855                         m_subtitle_sync_timer.start(diff / 90, 1);
2856                         break;
2857                 }
2858         }
2859 }
2860
2861 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2862 {
2863         if (m_subtitle_widget)
2864         {
2865                 m_dvb_subtitle_pages.push_back(p);
2866                 checkSubtitleTiming();
2867         }
2868 }
2869
2870 int eDVBServicePlay::getAC3Delay()
2871 {
2872         if (m_dvb_service)
2873                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2874         else if (m_decoder)
2875                 return m_decoder->getAC3Delay();
2876         else
2877                 return 0;
2878 }
2879
2880 int eDVBServicePlay::getPCMDelay()
2881 {
2882         if (m_dvb_service)
2883                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2884         else if (m_decoder)
2885                 return m_decoder->getPCMDelay();
2886         else
2887                 return 0;
2888 }
2889
2890 void eDVBServicePlay::setAC3Delay(int delay)
2891 {
2892         if (m_dvb_service)
2893                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2894         if (m_decoder)
2895                 m_decoder->setAC3Delay(delay);
2896 }
2897
2898 void eDVBServicePlay::setPCMDelay(int delay)
2899 {
2900         if (m_dvb_service)
2901                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2902         if (m_decoder)
2903                 m_decoder->setPCMDelay(delay);
2904 }
2905
2906 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2907 {
2908         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2909         m_event((iPlayableService*)this, evVideoSizeChanged);
2910 }
2911
2912 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2913 {
2914         ptr = this;
2915         return 0;
2916 }
2917
2918 PyObject *eDVBServicePlay::getStreamingData()
2919 {
2920         eDVBServicePMTHandler::program program;
2921         if (m_service_handler.getProgramInfo(program))
2922         {
2923                 Py_INCREF(Py_None);
2924                 return Py_None;
2925         }
2926
2927         PyObject *r = program.createPythonObject();
2928         ePtr<iDVBDemux> demux;
2929         if (!m_service_handler.getDataDemux(demux))
2930         {
2931                 uint8_t demux_id;
2932                 demux->getCADemuxID(demux_id);
2933                 
2934                 PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
2935         }
2936
2937         return r;
2938 }
2939
2940
2941 DEFINE_REF(eDVBServicePlay)
2942
2943 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2944 {
2945         switch (w)
2946         {
2947         case iServiceInformation::sTransponderData:
2948                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2949         default:
2950                 break;
2951         }
2952         return iStaticServiceInformation::getInfoObject(ref, w);
2953 }
2954
2955 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");