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