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