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