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