774e3f6bf412f3760e166c09c48e4e04a5a49769
[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                                         {
69                                                 // just show short name
70                                                 unsigned int pos = name.find("\xc2\x86");
71                                                 if ( pos != std::string::npos )
72                                                         name.erase(0, pos+2);
73                                                 pos = name.find("\xc2\x87");
74                                                 if ( pos != std::string::npos )
75                                                         name.erase(pos);
76                                                 name+=" - ";
77                                         }
78                                 }
79                         }
80                 }
81                 else
82                         name="";
83                 name += ref.name;
84                 return 0;
85         }
86         else
87                 return -1;
88 }
89
90 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
91 {
92         return -1;
93 }
94
95 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
96 {
97         ePtr<eDVBResourceManager> res_mgr;
98         if ( eDVBResourceManager::getInstance( res_mgr ) )
99                 eDebug("isPlayable... no res manager!!");
100         else
101         {
102                 eDVBChannelID chid, chid_ignore;
103                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
104                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
105                 return res_mgr->canAllocateChannel(chid, chid_ignore);
106         }
107         return false;
108 }
109
110 static void PutToDict(ePyObject &dict, const char*key, long value)
111 {
112         ePyObject item = PyString_FromFormat("%d", value);
113         if (item)
114         {
115                 if (PyDict_SetItemString(dict, key, item))
116                         eDebug("put %s to dict failed", key);
117                 Py_DECREF(item);
118         }
119         else
120                 eDebug("could not create PyObject for %s", key);
121 }
122
123 extern void PutToDict(ePyObject &dict, const char*key, const char *value);
124
125 void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
126 {
127         const char *tmp=0;
128         PutToDict(dict, "type", "satellite");
129         PutToDict(dict, "frequency", feparm.frequency);
130         PutToDict(dict, "symbolrate", feparm.symbol_rate);
131         PutToDict(dict, "orbital position", feparm.orbital_position);
132         switch (feparm.inversion)
133         {
134                 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
135                 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
136                 default:
137                 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
138         }
139         PutToDict(dict, "inversion", tmp);
140         switch (feparm.fec)
141         {
142                 case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
143                 case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
144                 case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
145                 case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
146                 case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
147                 case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
148                 case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
149                 case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
150                 case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
151                 case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
152                 default:
153                 case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
154         }
155         PutToDict(dict, "fec inner", tmp);
156         switch (feparm.modulation)
157         {
158                 case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
159                 case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
160                 case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
161                 case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
162         }
163         PutToDict(dict, "modulation", tmp);
164         switch(feparm.polarisation)
165         {
166                 case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
167                 case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
168                 case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
169                 default:
170                 case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
171         }
172         PutToDict(dict, "polarization", tmp);
173         switch(feparm.system)
174         {
175                 default:
176                 case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
177                 case eDVBFrontendParametersSatellite::System::DVB_S2:
178                         switch(feparm.roll_off)
179                         {
180                                 case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
181                                 case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
182                                 case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
183                                 default:
184                                 case eDVBFrontendParametersSatellite::RollOff::alpha_auto: tmp="AUTO"; break;
185                         }
186                         PutToDict(dict, "roll off", tmp);
187                         tmp="DVB-S2";
188                         break;
189         }
190         PutToDict(dict, "system", tmp);
191 }
192
193 void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
194 {
195         PutToDict(dict, "type", "terrestrial");
196         PutToDict(dict, "frequency", feparm.frequency);
197         const char *tmp=0;
198         switch (feparm.bandwidth)
199         {
200         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
201         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
202         case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
203         default:
204         case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
205         }
206         PutToDict(dict, "bandwidth", tmp);
207         switch (feparm.code_rate_LP)
208         {
209         case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
210         case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
211         case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
212         case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
213         case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
214         default:
215         case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
216         }
217         PutToDict(dict, "code rate lp", tmp);
218         switch (feparm.code_rate_HP)
219         {
220         case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
221         case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
222         case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
223         case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
224         case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
225         default:
226         case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
227         }
228         PutToDict(dict, "code rate hp", tmp);
229         switch (feparm.modulation)
230         {
231         case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
232         case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
233         case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
234         default:
235         case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
236         }
237         PutToDict(dict, "constellation", tmp);
238         switch (feparm.transmission_mode)
239         {
240         case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
241         case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
242         default:
243         case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
244         }
245         PutToDict(dict, "transmission mode", tmp);
246         switch (feparm.guard_interval)
247         {
248                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
249                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
250                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
251                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
252                 default:
253                 case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
254         }
255         PutToDict(dict, "guard interval", tmp);
256         switch (feparm.hierarchy)
257         {
258                 case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
259                 case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
260                 case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
261                 case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
262                 default:
263                 case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
264         }
265         PutToDict(dict, "hierarchy", tmp);
266         switch (feparm.inversion)
267         {
268                 case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
269                 case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
270                 default:
271                 case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
272         }
273         PutToDict(dict, "inversion", tmp);
274 }
275
276 void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
277 {
278         const char *tmp=0;
279         PutToDict(dict, "type", "cable");
280         PutToDict(dict, "frequency", feparm.frequency);
281         PutToDict(dict, "symbolrate", feparm.symbol_rate);
282         switch (feparm.modulation)
283         {
284         case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
285         case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
286         case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
287         case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
288         case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
289         default:
290         case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
291         }
292         PutToDict(dict, "modulation", tmp);
293         switch (feparm.inversion)
294         {
295         case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
296         case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
297         default:
298         case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
299         }
300         PutToDict(dict, "inversion", tmp);
301         switch (feparm.fec_inner)
302         {
303         case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
304         case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
305         case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
306         case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
307         case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
308         case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
309         case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
310         default:
311         case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
312         }
313         PutToDict(dict, "fec inner", tmp);
314 }
315
316 PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
317 {
318         if (r.type == eServiceReference::idDVB)
319         {
320                 const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)r;
321                 switch(what)
322                 {
323                         case iServiceInformation::sTransponderData:
324                         {
325                                 ePtr<eDVBResourceManager> res;
326                                 if (!eDVBResourceManager::getInstance(res))
327                                 {
328                                         ePtr<iDVBChannelList> db;
329                                         if (!res->getChannelList(db))
330                                         {
331                                                 eDVBChannelID chid;
332                                                 ref.getChannelID(chid);
333                                                 ePtr<iDVBFrontendParameters> feparm;
334                                                 if (!db->getChannelFrontendData(chid, feparm))
335                                                 {
336                                                         int system;
337                                                         if (!feparm->getSystem(system))
338                                                         {
339                                                                 ePyObject dict = PyDict_New();
340                                                                 switch(system)
341                                                                 {
342                                                                         case iDVBFrontend::feSatellite:
343                                                                         {
344                                                                                 eDVBFrontendParametersSatellite s;
345                                                                                 feparm->getDVBS(s);
346                                                                                 PutSatelliteDataToDict(dict, s);
347                                                                                 break;
348                                                                         }
349                                                                         case iDVBFrontend::feTerrestrial:
350                                                                         {
351                                                                                 eDVBFrontendParametersTerrestrial t;
352                                                                                 feparm->getDVBT(t);
353                                                                                 PutTerrestrialDataToDict(dict, t);
354                                                                                 break;
355                                                                         }
356                                                                         case iDVBFrontend::feCable:
357                                                                         {
358                                                                                 eDVBFrontendParametersCable c;
359                                                                                 feparm->getDVBC(c);
360                                                                                 PutCableDataToDict(dict, c);
361                                                                                 break;
362                                                                         }
363                                                                         default:
364                                                                                 eDebug("unknown frontend type %d", system);
365                                                                                 Py_DECREF(dict);
366                                                                                 break;
367                                                                 }
368                                                                 return dict;
369                                                         }
370                                                 }
371                                         }
372                                 }
373                         }
374                 }
375         }
376         Py_RETURN_NONE;
377 }
378
379 DEFINE_REF(eStaticServiceDVBBouquetInformation);
380
381 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
382 {
383         ePtr<iDVBChannelList> db;
384         ePtr<eDVBResourceManager> res;
385
386         int err;
387         if ((err = eDVBResourceManager::getInstance(res)) != 0)
388         {
389                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
390                 return err;
391         }
392         if ((err = res->getChannelList(db)) != 0)
393         {
394                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
395                 return err;
396         }
397
398         eBouquet *bouquet=0;
399         if ((err = db->getBouquet(ref, bouquet)) != 0)
400         {
401                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
402                 return -1;
403         }
404
405         if ( bouquet && bouquet->m_bouquet_name.length() )
406         {
407                 name = bouquet->m_bouquet_name;
408                 return 0;
409         }
410         else
411                 return -1;
412 }
413
414 int eStaticServiceDVBBouquetInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
415 {
416         if (ref.flags & eServiceReference::isGroup)
417         {
418                 ePtr<iDVBChannelList> db;
419                 ePtr<eDVBResourceManager> res;
420
421                 if (eDVBResourceManager::getInstance(res))
422                 {
423                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no resource manager!");
424                         return 0;
425                 }
426
427                 if (res->getChannelList(db))
428                 {
429                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. no channel list!");
430                         return 0;
431                 }
432
433                 eBouquet *bouquet=0;
434                 if (db->getBouquet(ref, bouquet))
435                 {
436                         eDebug("eStaticServiceDVBBouquetInformation::isPlayable failed.. getBouquet failed!");
437                         return 0;
438                 }
439
440                 int cur=0;
441                 eDVBChannelID chid, chid_ignore;
442                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
443                 for (std::list<eServiceReference>::iterator it(bouquet->m_services.begin()); it != bouquet->m_services.end(); ++it)
444                 {
445                         ((const eServiceReferenceDVB&)*it).getChannelID(chid);
446                         int tmp=res->canAllocateChannel(chid, chid_ignore);
447                         if (tmp > cur)
448                         {
449                                 m_playable_service = *it;
450                                 cur = tmp;
451                         }
452                 }
453                 if (cur)
454                         return cur;
455         }
456         m_playable_service = eServiceReference();
457         return 0;
458 }
459
460 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
461 {
462         return -1;
463 }
464
465 #include <lib/dvb/epgcache.h>
466
467 RESULT eStaticServiceDVBBouquetInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &ptr, time_t start_time)
468 {
469         return eEPGCache::getInstance()->lookupEventTime(ref, start_time, ptr);
470 }
471
472 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
473 {
474         DECLARE_REF(eStaticServiceDVBPVRInformation);
475         eServiceReference m_ref;
476         eDVBMetaParser m_parser;
477 public:
478         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
479         RESULT getName(const eServiceReference &ref, std::string &name);
480         int getLength(const eServiceReference &ref);
481         RESULT getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &SWIG_OUTPUT, time_t start_time);
482         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore) { return 1; }
483         int getInfo(const eServiceReference &ref, int w);
484         std::string getInfoString(const eServiceReference &ref,int w);
485 };
486
487 DEFINE_REF(eStaticServiceDVBPVRInformation);
488
489 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
490 {
491         m_ref = ref;
492         m_parser.parseFile(ref.path);
493 }
494
495 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
496 {
497         ASSERT(ref == m_ref);
498         name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
499         return 0;
500 }
501
502 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
503 {
504         ASSERT(ref == m_ref);
505         
506         eDVBTSTools tstools;
507         
508         if (tstools.openFile(ref.path.c_str()))
509                 return 0;
510
511         pts_t len;
512         if (tstools.calcLen(len))
513                 return 0;
514
515         return len / 90000;
516 }
517
518 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
519 {
520         switch (w)
521         {
522         case iServiceInformation::sDescription:
523                 return iServiceInformation::resIsString;
524         case iServiceInformation::sServiceref:
525                 return iServiceInformation::resIsString;
526         case iServiceInformation::sTimeCreate:
527                 if (m_parser.m_time_create)
528                         return m_parser.m_time_create;
529                 else
530                         return iServiceInformation::resNA;
531         default:
532                 return iServiceInformation::resNA;
533         }
534 }
535
536 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
537 {
538         switch (w)
539         {
540         case iServiceInformation::sDescription:
541                 return m_parser.m_description;
542         case iServiceInformation::sServiceref:
543                 return m_parser.m_ref.toString();
544         case iServiceInformation::sTags:
545                 return m_parser.m_tags;
546         default:
547                 return "";
548         }
549 }
550
551 RESULT eStaticServiceDVBPVRInformation::getEvent(const eServiceReference &ref, ePtr<eServiceEvent> &evt, time_t start_time)
552 {
553         if (!ref.path.empty())
554         {
555                 ePtr<eServiceEvent> event = new eServiceEvent;
556                 std::string filename = ref.path;
557                 filename.erase(filename.length()-2, 2);
558                 filename+="eit";
559                 if (!event->parseFrom(filename, (m_parser.m_ref.getTransportStreamID().get()<<16)|m_parser.m_ref.getOriginalNetworkID().get()))
560                 {
561                         evt = event;
562                         return 0;
563                 }
564         }
565         evt = 0;
566         return -1;
567 }
568
569 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
570 {
571         DECLARE_REF(eDVBPVRServiceOfflineOperations);
572         eServiceReferenceDVB m_ref;
573 public:
574         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
575         
576         RESULT deleteFromDisk(int simulate);
577         RESULT getListOfFilenames(std::list<std::string> &);
578 };
579
580 DEFINE_REF(eDVBPVRServiceOfflineOperations);
581
582 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
583 {
584 }
585
586 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
587 {
588         if (simulate)
589                 return 0;
590         else
591         {
592                 std::list<std::string> res;
593                 if (getListOfFilenames(res))
594                         return -1;
595                 
596                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
597                 if (!eraser)
598                         eDebug("FATAL !! can't get background file eraser");
599                 
600                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
601                 {
602                         eDebug("Removing %s...", i->c_str());
603                         if (eraser)
604                                 eraser->erase(i->c_str());
605                         else
606                                 ::unlink(i->c_str());
607                 }
608                 
609                 return 0;
610         }
611 }
612
613 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
614 {
615         res.clear();
616         res.push_back(m_ref.path);
617
618 // handling for old splitted recordings (enigma 1)
619         char buf[255];
620         int slice=1;
621         while(true)
622         {
623                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
624                 struct stat s;
625                 if (stat(buf, &s) < 0)
626                         break;
627                 res.push_back(buf);
628         }       
629
630         res.push_back(m_ref.path + ".meta");
631         res.push_back(m_ref.path + ".ap");
632         res.push_back(m_ref.path + ".cuts");
633         std::string tmp = m_ref.path;
634         tmp.erase(m_ref.path.length()-3);
635         res.push_back(tmp + ".eit");
636         return 0;
637 }
638
639 DEFINE_REF(eServiceFactoryDVB)
640
641 eServiceFactoryDVB::eServiceFactoryDVB()
642 {
643         ePtr<eServiceCenter> sc;
644         
645         eServiceCenter::getPrivInstance(sc);
646         if (sc)
647                 sc->addServiceFactory(eServiceFactoryDVB::id, this);
648
649         m_StaticServiceDVBInfo = new eStaticServiceDVBInformation;
650         m_StaticServiceDVBBouquetInfo = new eStaticServiceDVBBouquetInformation;
651 }
652
653 eServiceFactoryDVB::~eServiceFactoryDVB()
654 {
655         ePtr<eServiceCenter> sc;
656         
657         eServiceCenter::getPrivInstance(sc);
658         if (sc)
659                 sc->removeServiceFactory(eServiceFactoryDVB::id);
660 }
661
662 DEFINE_REF(eDVBServiceList);
663
664 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
665 {
666 }
667
668 eDVBServiceList::~eDVBServiceList()
669 {
670 }
671
672 RESULT eDVBServiceList::startQuery()
673 {
674         ePtr<iDVBChannelList> db;
675         ePtr<eDVBResourceManager> res;
676         
677         int err;
678         if ((err = eDVBResourceManager::getInstance(res)) != 0)
679         {
680                 eDebug("no resource manager");
681                 return err;
682         }
683         if ((err = res->getChannelList(db)) != 0)
684         {
685                 eDebug("no channel list");
686                 return err;
687         }
688         
689         ePtr<eDVBChannelQuery> q;
690         
691         if (!m_parent.path.empty())
692         {
693                 eDVBChannelQuery::compile(q, m_parent.path);
694                 if (!q)
695                 {
696                         eDebug("compile query failed");
697                         return err;
698                 }
699         }
700         
701         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
702         {
703                 eDebug("startQuery failed");
704                 return err;
705         }
706
707         return 0;
708 }
709
710 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
711 {
712         eServiceReferenceDVB ref;
713         
714         if (!m_query)
715                 return -1;
716
717         while (!m_query->getNextResult(ref))
718                 list.push_back(ref);
719
720         if (sorted)
721                 list.sort(iListableServiceCompare(this));
722
723         return 0;
724 }
725
726 //   The first argument of this function is a format string to specify the order and
727 //   the content of the returned list
728 //   useable format options are
729 //   R = Service Reference (as swig object .. this is very slow)
730 //   S = Service Reference (as python string object .. same as ref.toString())
731 //   C = Service Reference (as python string object .. same as ref.toCompareString())
732 //   N = Service Name (as python string object)
733 //   when exactly one return value per service is selected in the format string,
734 //   then each value is directly a list entry
735 //   when more than one value is returned per service, then the list is a list of
736 //   python tuples
737 //   unknown format string chars are returned as python None values !
738 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
739 {
740         ePyObject ret;
741         std::list<eServiceReference> tmplist;
742         int retcount=1;
743
744         if (!format || !(retcount=strlen(format)))
745                 format = "R"; // just return service reference swig object ...
746
747         if (!getContent(tmplist, sorted))
748         {
749                 int services=tmplist.size();
750                 ePtr<iStaticServiceInformation> sptr;
751                 eServiceCenterPtr service_center;
752
753                 if (strchr(format, 'N'))
754                         eServiceCenter::getPrivInstance(service_center);
755
756                 ret = PyList_New(services);
757                 std::list<eServiceReference>::iterator it(tmplist.begin());
758
759                 for (int cnt=0; cnt < services; ++cnt)
760                 {
761                         eServiceReference &ref=*it++;
762                         ePyObject tuple = retcount > 1 ? PyTuple_New(retcount) : ePyObject();
763                         for (int i=0; i < retcount; ++i)
764                         {
765                                 ePyObject tmp;
766                                 switch(format[i])
767                                 {
768                                 case 'R':  // service reference (swig)object
769                                         tmp = NEW_eServiceReference(ref);
770                                         break;
771                                 case 'C':  // service reference compare string
772                                         tmp = PyString_FromString(ref.toCompareString().c_str());
773                                         break;
774                                 case 'S':  // service reference string
775                                         tmp = PyString_FromString(ref.toString().c_str());
776                                         break;
777                                 case 'N':  // service name
778                                         if (service_center)
779                                         {
780                                                 service_center->info(ref, sptr);
781                                                 if (sptr)
782                                                 {
783                                                         std::string name;
784                                                         sptr->getName(ref, name);
785                                                         if (name.length())
786                                                                 tmp = PyString_FromString(name.c_str());
787                                                 }
788                                         }
789                                         if (!tmp)
790                                                 tmp = PyString_FromString("<n/a>");
791                                         break;
792                                 default:
793                                         if (tuple)
794                                         {
795                                                 tmp = Py_None;
796                                                 Py_INCREF(Py_None);
797                                         }
798                                         break;
799                                 }
800                                 if (tmp)
801                                 {
802                                         if (tuple)
803                                                 PyTuple_SET_ITEM(tuple, i, tmp);
804                                         else
805                                                 PyList_SET_ITEM(ret, cnt, tmp);
806                                 }
807                         }
808                         if (tuple)
809                                 PyList_SET_ITEM(ret, cnt, tuple);
810                 }
811         }
812         return ret ? (PyObject*)ret : (PyObject*)PyList_New(0);
813 }
814
815 RESULT eDVBServiceList::getNext(eServiceReference &ref)
816 {
817         if (!m_query)
818                 return -1;
819         
820         return m_query->getNextResult((eServiceReferenceDVB&)ref);
821 }
822
823 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
824 {
825         if (m_parent.flags & eServiceReference::canDescent) // bouquet
826         {
827                 ePtr<iDVBChannelList> db;
828                 ePtr<eDVBResourceManager> resm;
829
830                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
831                         return -1;
832
833                 if (db->getBouquet(m_parent, m_bouquet) != 0)
834                         return -1;
835
836                 res = this;
837                 
838                 return 0;
839         }
840         res = 0;
841         return -1;
842 }
843
844 RESULT eDVBServiceList::addService(eServiceReference &ref, eServiceReference before)
845 {
846         if (!m_bouquet)
847                 return -1;
848         return m_bouquet->addService(ref, before);
849 }
850
851 RESULT eDVBServiceList::removeService(eServiceReference &ref)
852 {
853         if (!m_bouquet)
854                 return -1;
855         return m_bouquet->removeService(ref);
856 }
857
858 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
859 {
860         if (!m_bouquet)
861                 return -1;
862         return m_bouquet->moveService(ref, pos);
863 }
864
865 RESULT eDVBServiceList::flushChanges()
866 {
867         if (!m_bouquet)
868                 return -1;
869         return m_bouquet->flushChanges();
870 }
871
872 RESULT eDVBServiceList::setListName(const std::string &name)
873 {
874         if (!m_bouquet)
875                 return -1;
876         return m_bouquet->setListName(name);
877 }
878
879 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
880 {
881         ePtr<eDVBService> service;
882         int r = lookupService(service, ref);
883         if (r)
884                 service = 0;
885                 // check resources...
886         ptr = new eDVBServicePlay(ref, service);
887         return 0;
888 }
889
890 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
891 {
892         if (ref.path.empty())
893         {
894                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
895                 return 0;
896         } else
897         {
898                 ptr = 0;
899                 return -1;
900         }
901 }
902
903 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
904 {
905         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
906         if (list->startQuery())
907         {
908                 ptr = 0;
909                 return -1;
910         }
911         
912         ptr = list;
913         return 0;
914 }
915
916 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
917 {
918         /* is a listable service? */
919         if (ref.flags & eServiceReference::canDescent) // bouquet
920         {
921                 if ( !ref.name.empty() )  // satellites or providers list
922                         ptr = m_StaticServiceDVBInfo;
923                 else // a dvb bouquet
924                         ptr = m_StaticServiceDVBBouquetInfo;
925         }
926         else if (!ref.path.empty()) /* do we have a PVR service? */
927                 ptr = new eStaticServiceDVBPVRInformation(ref);
928         else // normal dvb service
929         {
930                 ePtr<eDVBService> service;
931                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
932                         ptr = m_StaticServiceDVBInfo;
933                 else
934                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
935                         ptr = service;
936         }
937         return 0;
938 }
939
940 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
941 {
942         if (ref.path.empty())
943         {
944                 ptr = 0;
945                 return -1;
946         } else
947         {
948                 ptr = new eDVBPVRServiceOfflineOperations(ref);
949                 return 0;
950         }
951 }
952
953 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
954 {
955                         // TODO: handle the listing itself
956         // if (ref.... == -1) .. return "... bouquets ...";
957         // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
958                         // TODO: cache
959         ePtr<iDVBChannelList> db;
960         ePtr<eDVBResourceManager> res;
961         
962         int err;
963         if ((err = eDVBResourceManager::getInstance(res)) != 0)
964         {
965                 eDebug("no resource manager");
966                 return err;
967         }
968         if ((err = res->getChannelList(db)) != 0)
969         {
970                 eDebug("no channel list");
971                 return err;
972         }
973         
974                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
975         if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
976         {
977                 eDebug("getService failed!");
978                 return err;
979         }
980
981         return 0;
982 }
983
984 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
985         m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
986 {
987         memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
988         m_is_primary = 1;
989         m_is_pvr = !m_reference.path.empty();
990         
991         m_timeshift_enabled = m_timeshift_active = 0;
992         m_skipmode = 0;
993         
994         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
995         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
996         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
997
998         m_cuesheet_changed = 0;
999         m_cutlist_enabled = 1;
1000         
1001         m_subtitle_widget = 0;
1002         
1003         m_tune_state = -1;
1004         
1005         CONNECT(m_subtitle_sync_timer.timeout, eDVBServicePlay::checkSubtitleTiming);
1006 }
1007
1008 eDVBServicePlay::~eDVBServicePlay()
1009 {
1010         delete m_subtitle_widget;
1011 }
1012
1013 void eDVBServicePlay::gotNewEvent()
1014 {
1015 #if 0
1016                 // debug only
1017         ePtr<eServiceEvent> m_event_now, m_event_next;
1018         getEvent(m_event_now, 0);
1019         getEvent(m_event_next, 1);
1020
1021         if (m_event_now)
1022                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
1023         if (m_event_next)
1024                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
1025 #endif
1026         m_event((iPlayableService*)this, evUpdatedEventInfo);
1027 }
1028
1029 void eDVBServicePlay::serviceEvent(int event)
1030 {
1031         m_tune_state = event;
1032
1033         switch (event)
1034         {
1035         case eDVBServicePMTHandler::eventTuned:
1036         {
1037                 ePtr<iDVBDemux> m_demux;
1038                 if (!m_service_handler.getDataDemux(m_demux))
1039                 {
1040                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
1041                         int sid = ref.getParentServiceID().get();
1042                         if (!sid)
1043                                 sid = ref.getServiceID().get();
1044                         if ( ref.getParentTransportStreamID().get() &&
1045                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
1046                                 m_event_handler.startOther(m_demux, sid);
1047                         else
1048                                 m_event_handler.start(m_demux, sid);
1049                 }
1050                 break;
1051         }
1052         case eDVBServicePMTHandler::eventNoPAT:
1053         case eDVBServicePMTHandler::eventNoPATEntry:
1054         case eDVBServicePMTHandler::eventNoPMT:
1055         case eDVBServicePMTHandler::eventTuneFailed:
1056         {
1057                 eDebug("DVB service failed to tune - error %d", event);
1058                 m_event((iPlayableService*)this, evTuneFailed);
1059                 break;
1060         }
1061         case eDVBServicePMTHandler::eventNewProgramInfo:
1062         {
1063                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
1064                 if (m_timeshift_enabled)
1065                         updateTimeshiftPids();
1066                 if (!m_timeshift_active)
1067                         updateDecoder();
1068                 if (m_first_program_info && m_is_pvr)
1069                 {
1070                         m_first_program_info = 0;
1071                         seekTo(0);
1072                 }
1073                 m_event((iPlayableService*)this, evUpdatedInfo);
1074                 break;
1075         }
1076         case eDVBServicePMTHandler::eventEOF:
1077                 m_event((iPlayableService*)this, evEOF);
1078                 break;
1079         case eDVBServicePMTHandler::eventSOF:
1080                 m_event((iPlayableService*)this, evSOF);
1081                 break;
1082         }
1083 }
1084
1085 void eDVBServicePlay::serviceEventTimeshift(int event)
1086 {
1087         switch (event)
1088         {
1089         case eDVBServicePMTHandler::eventNewProgramInfo:
1090                 if (m_timeshift_active)
1091                         updateDecoder();
1092                 break;
1093         case eDVBServicePMTHandler::eventSOF:
1094                 m_event((iPlayableService*)this, evSOF);
1095                 break;
1096         case eDVBServicePMTHandler::eventEOF:
1097                 switchToLive();
1098                 break;
1099         }
1100 }
1101
1102 RESULT eDVBServicePlay::start()
1103 {
1104         int r;
1105                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
1106                    two (one for decoding, one for data source), as we must be prepared
1107                    to start recording from the data demux. */
1108         if (m_is_pvr)
1109                 m_cue = new eCueSheet();
1110
1111         m_first_program_info = 1;
1112         eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
1113         r = m_service_handler.tune(service, m_is_pvr, m_cue);
1114
1115                 /* inject EIT if there is a stored one */
1116         if (m_is_pvr)
1117         {
1118                 std::string filename = service.path;
1119                 filename.erase(filename.length()-2, 2);
1120                 filename+="eit";
1121                 ePtr<eServiceEvent> event = new eServiceEvent;
1122                 if (!event->parseFrom(filename, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get()))
1123                 {
1124                         ePtr<eServiceEvent> empty;
1125                         m_event_handler.inject(event, 0);
1126                         m_event_handler.inject(empty, 1);
1127                 }
1128         }
1129
1130         if (m_is_pvr)
1131                 loadCuesheet();
1132
1133         m_event(this, evStart);
1134         m_event((iPlayableService*)this, evSeekableStatusChanged);
1135         return 0;
1136 }
1137
1138 RESULT eDVBServicePlay::stop()
1139 {
1140                 /* add bookmark for last play position */
1141         if (m_is_pvr)
1142         {
1143                 pts_t play_position;
1144                 if (!getPlayPosition(play_position))
1145                 {
1146                                 /* remove last position */
1147                         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end();)
1148                         {
1149                                 if (i->what == 3) /* current play position */
1150                                 {
1151                                         m_cue_entries.erase(i);
1152                                         i = m_cue_entries.begin();
1153                                         continue;
1154                                 } else
1155                                         ++i;
1156                         }
1157                         
1158                         m_cue_entries.insert(cueEntry(play_position, 3)); /* last play position */
1159                         m_cuesheet_changed = 1;
1160                 }
1161         }
1162
1163         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
1164
1165         m_service_handler_timeshift.free();
1166         m_service_handler.free();
1167         
1168         if (m_is_pvr && m_cuesheet_changed)
1169         {
1170                 struct stat s;
1171                                 /* save cuesheet only when main file is accessible. */
1172                 if (!::stat(m_reference.path.c_str(), &s))
1173                         saveCuesheet();
1174         }
1175         
1176         return 0;
1177 }
1178
1179 RESULT eDVBServicePlay::setTarget(int target)
1180 {
1181         m_is_primary = !target;
1182         return 0;
1183 }
1184
1185 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
1186 {
1187         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
1188         return 0;
1189 }
1190
1191 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
1192 {
1193                 /* note: we check for timeshift to be enabled,
1194                    not neccessary active. if you pause when timeshift
1195                    is not active, you should activate it when unpausing */
1196         if ((!m_is_pvr) && (!m_timeshift_enabled))
1197         {
1198                 ptr = 0;
1199                 return -1;
1200         }
1201
1202         ptr = this;
1203         return 0;
1204 }
1205
1206 RESULT eDVBServicePlay::setSlowMotion(int ratio)
1207 {
1208         if (m_decoder)
1209                 return m_decoder->setSlowMotion(ratio);
1210         else
1211                 return -1;
1212 }
1213
1214 RESULT eDVBServicePlay::setFastForward(int ratio)
1215 {
1216         int skipmode, ffratio;
1217         
1218         if (ratio > 8)
1219         {
1220                 skipmode = ratio;
1221                 ffratio = 1;
1222         } else if (ratio > 0)
1223         {
1224                 skipmode = 0;
1225                 ffratio = ratio;
1226         } else if (!ratio)
1227         {
1228                 skipmode = 0;
1229                 ffratio = 0;
1230         } else // if (ratio < 0)
1231         {
1232                 skipmode = ratio;
1233                 ffratio = 1;
1234         }
1235
1236         if (m_skipmode != skipmode)
1237         {
1238                 eDebug("setting cue skipmode to %d", skipmode);
1239                 if (m_cue)
1240                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
1241         }
1242         
1243         m_skipmode = skipmode;
1244         
1245         if (!m_decoder)
1246                 return -1;
1247
1248         return m_decoder->setFastForward(ffratio);
1249 }
1250     
1251 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
1252 {
1253         if (m_is_pvr || m_timeshift_enabled)
1254         {
1255                 ptr = this;
1256                 return 0;
1257         }
1258         
1259         ptr = 0;
1260         return -1;
1261 }
1262
1263         /* TODO: when timeshift is enabled but not active, this doesn't work. */
1264 RESULT eDVBServicePlay::getLength(pts_t &len)
1265 {
1266         ePtr<iDVBPVRChannel> pvr_channel;
1267         
1268         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1269                 return -1;
1270         
1271         return pvr_channel->getLength(len);
1272 }
1273
1274 RESULT eDVBServicePlay::pause()
1275 {
1276         if (!m_is_paused && m_decoder)
1277         {
1278                 m_is_paused = 1;
1279                 return m_decoder->freeze(0);
1280         } else
1281                 return -1;
1282 }
1283
1284 RESULT eDVBServicePlay::unpause()
1285 {
1286         if (m_is_paused && m_decoder)
1287         {
1288                 m_is_paused = 0;
1289                 return m_decoder->unfreeze();
1290         } else
1291                 return -1;
1292 }
1293
1294 RESULT eDVBServicePlay::seekTo(pts_t to)
1295 {
1296         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1297         
1298         if (!m_decode_demux)
1299                 return -1;
1300
1301         ePtr<iDVBPVRChannel> pvr_channel;
1302         
1303         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1304                 return -1;
1305         
1306         if (!m_cue)
1307                 return -1;
1308         
1309         m_cue->seekTo(0, to);
1310         return 0;
1311 }
1312
1313 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1314 {
1315         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, 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         int mode = 1;
1326         
1327                         /* HACK until we have skip-AP api */
1328         if ((to > 0) && (to < 100))
1329                 mode = 2;
1330         
1331         to *= direction;
1332         
1333         if (!m_cue)
1334                 return 0;
1335         
1336         m_cue->seekTo(mode, to);
1337         return 0;
1338 }
1339
1340 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1341 {
1342         ePtr<iDVBPVRChannel> pvr_channel;
1343         
1344         if (!m_decode_demux)
1345                 return -1;
1346         
1347         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1348                 return -1;
1349         
1350         int r = 0;
1351
1352                 /* if there is a decoder, use audio or video PTS */
1353         if (m_decoder)
1354         {
1355                 r = m_decoder->getPTS(0, pos);
1356                 if (r)
1357                         return r;
1358         }
1359         
1360                 /* fixup */
1361         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1362 }
1363
1364 RESULT eDVBServicePlay::setTrickmode(int trick)
1365 {
1366         if (m_decoder)
1367                 m_decoder->setTrickmode(trick);
1368         return 0;
1369 }
1370
1371 RESULT eDVBServicePlay::isCurrentlySeekable()
1372 {
1373         return m_is_pvr || m_timeshift_active;
1374 }
1375
1376 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1377 {
1378         ptr = this;
1379         return 0;
1380 }
1381
1382 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1383 {
1384         ptr = this;
1385         return 0;
1386 }
1387
1388 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1389 {
1390         ptr = this;
1391         return 0;
1392 }
1393
1394 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1395 {
1396         ptr = this;
1397         return 0;
1398 }
1399
1400 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1401 {
1402         ptr = this;
1403         return 0;
1404 }
1405
1406 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1407 {
1408         ptr = 0;
1409         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1410                 (m_timeshift_enabled || !m_is_pvr))
1411         {
1412                 if (!m_timeshift_enabled)
1413                 {
1414                                 /* we need enough diskspace */
1415                         struct statfs fs;
1416                         if (statfs(TSPATH "/.", &fs) < 0)
1417                         {
1418                                 eDebug("statfs failed!");
1419                                 return -2;
1420                         }
1421                 
1422                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1423                         {
1424                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1425                                 return -3;
1426                         }
1427                 }
1428                 ptr = this;
1429                 return 0;
1430         }
1431         return -1;
1432 }
1433
1434 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1435 {
1436         if (m_is_pvr)
1437         {
1438                 ptr = this;
1439                 return 0;
1440         }
1441         ptr = 0;
1442         return -1;
1443 }
1444
1445 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1446 {
1447         ptr = this;
1448         return 0;
1449 }
1450
1451 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1452 {
1453         ptr = this;
1454         return 0;
1455 }
1456
1457 RESULT eDVBServicePlay::radioText(ePtr<iRadioText> &ptr)
1458 {
1459         ptr = this;
1460         return 0;
1461 }
1462
1463 RESULT eDVBServicePlay::getName(std::string &name)
1464 {
1465         if (m_is_pvr)
1466         {
1467                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1468                 return i->getName(m_reference, name);
1469         }
1470         if (m_dvb_service)
1471         {
1472                 m_dvb_service->getName(m_reference, name);
1473                 if (name.empty())
1474                         name = "(...)";
1475         }
1476         else if (!m_reference.name.empty())
1477                 eStaticServiceDVBInformation().getName(m_reference, name);
1478         else
1479                 name = "DVB service";
1480         return 0;
1481 }
1482
1483 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1484 {
1485         return m_event_handler.getEvent(evt, nownext);
1486 }
1487
1488 int eDVBServicePlay::getInfo(int w)
1489 {
1490         eDVBServicePMTHandler::program program;
1491         
1492         if (w == sCAIDs)
1493                 return resIsPyObject;
1494
1495         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1496         
1497         int no_program_info = 0;
1498         
1499         if (h.getProgramInfo(program))
1500                 no_program_info = 1;
1501         
1502         switch (w)
1503         {
1504 #if HAVE_DVB_API_VERSION >= 3
1505         case sVideoHeight:
1506                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1507                         return m_videoEventData.height;
1508                 return -1;
1509         case sVideoWidth:
1510                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1511                         return m_videoEventData.width;
1512                 return -1;
1513 #else
1514 #warning "FIXMEE implement sVideoHeight, sVideoWidth for old DVB API"
1515 #endif
1516         case sAspect:
1517 #if HAVE_DVB_API_VERSION >= 3
1518                 if (m_videoEventData.type != iTSMPEGDecoder::videoEvent::eventUnknown)
1519                         return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
1520                 else
1521 #else
1522 #warning "FIXMEE implement sAspect for old DVB API"
1523 #endif
1524                 if (no_program_info)
1525                         return -1; 
1526                 else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1527                 {
1528                         ePtr<eServiceEvent> evt;
1529                         if (!m_event_handler.getEvent(evt, 0))
1530                         {
1531                                 ePtr<eComponentData> data;
1532                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1533                                 {
1534                                         if ( data->getStreamContent() == 1 )
1535                                         {
1536                                                 switch(data->getComponentType())
1537                                                 {
1538                                                         // SD
1539                                                         case 1: // 4:3 SD PAL
1540                                                         case 2:
1541                                                         case 3: // 16:9 SD PAL
1542                                                         case 4: // > 16:9 PAL
1543                                                         case 5: // 4:3 SD NTSC
1544                                                         case 6: 
1545                                                         case 7: // 16:9 SD NTSC
1546                                                         case 8: // > 16:9 NTSC
1547
1548                                                         // HD
1549                                                         case 9: // 4:3 HD PAL
1550                                                         case 0xA:
1551                                                         case 0xB: // 16:9 HD PAL
1552                                                         case 0xC: // > 16:9 HD PAL
1553                                                         case 0xD: // 4:3 HD NTSC
1554                                                         case 0xE:
1555                                                         case 0xF: // 16:9 HD NTSC
1556                                                         case 0x10: // > 16:9 HD PAL
1557                                                                 return data->getComponentType();
1558                                                 }
1559                                         }
1560                                 }
1561                         }
1562                 }
1563                 return -1;
1564         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1565         case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1566         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1567         case sAudioPID: if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1568         case sPCRPID: if (no_program_info) return -1; return program.pcrPid;
1569         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1570         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1571         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1572         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1573         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1574         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1575         case sProvider: if (!m_dvb_service) return -1; return -2;
1576         case sServiceref: return resIsString;
1577         case sDVBState: return m_tune_state;
1578         default:
1579                 return -1;
1580         }
1581 }
1582
1583 std::string eDVBServicePlay::getInfoString(int w)
1584 {
1585         switch (w)
1586         {
1587         case sProvider:
1588                 if (!m_dvb_service) return "";
1589                 return m_dvb_service->m_provider_name;
1590         case sServiceref:
1591                 return m_reference.toString();
1592         default:
1593                 break;
1594         }
1595         return iServiceInformation::getInfoString(w);
1596 }
1597
1598 PyObject *eDVBServicePlay::getInfoObject(int w)
1599 {
1600         switch (w)
1601         {
1602         case sCAIDs:
1603                 return m_service_handler.getCaIds();
1604         case sTransponderData:
1605                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1606         default:
1607                 break;
1608         }
1609         return iServiceInformation::getInfoObject(w);
1610 }
1611
1612 int eDVBServicePlay::getNumberOfTracks()
1613 {
1614         eDVBServicePMTHandler::program program;
1615         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1616         if (h.getProgramInfo(program))
1617                 return 0;
1618         return program.audioStreams.size();
1619 }
1620
1621 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1622 {
1623         int ret = selectAudioStream(i);
1624
1625         if (m_decoder->start())
1626                 return -5;
1627
1628         return ret;
1629 }
1630
1631 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1632 {
1633         eDVBServicePMTHandler::program program;
1634         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1635
1636         if (h.getProgramInfo(program))
1637                 return -1;
1638         
1639         if (i >= program.audioStreams.size())
1640                 return -2;
1641         
1642         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1643                 info.m_description = "MPEG";
1644         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1645                 info.m_description = "AC3";
1646         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1647                 info.m_description = "AAC";
1648         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1649                 info.m_description = "DTS";
1650         else
1651                 info.m_description = "???";
1652
1653         if (program.audioStreams[i].component_tag != -1)
1654         {
1655                 ePtr<eServiceEvent> evt;
1656                 if (!m_event_handler.getEvent(evt, 0))
1657                 {
1658                         ePtr<eComponentData> data;
1659                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1660                                 info.m_language = data->getText();
1661                 }
1662         }
1663
1664         if (info.m_language.empty())
1665                 info.m_language = program.audioStreams[i].language_code;
1666         
1667         return 0;
1668 }
1669
1670 int eDVBServicePlay::selectAudioStream(int i)
1671 {
1672         eDVBServicePMTHandler::program program;
1673         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1674
1675         if (h.getProgramInfo(program))
1676                 return -1;
1677         
1678         if ((unsigned int)i >= program.audioStreams.size())
1679                 return -2;
1680         
1681         if (!m_decoder)
1682                 return -3;
1683         
1684         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1685                 return -4;
1686
1687         if (m_radiotext_parser)
1688                 m_radiotext_parser->start(program.audioStreams[i].pid);
1689
1690         if (m_dvb_service && !m_is_pvr)
1691         {
1692                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1693                 {
1694                         m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid);
1695                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1696                 }
1697                 else
1698                 {
1699                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1700                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid);
1701                 }
1702         }
1703
1704         h.resetCachedProgram();
1705
1706         return 0;
1707 }
1708
1709 int eDVBServicePlay::getCurrentChannel()
1710 {
1711         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1712 }
1713
1714 RESULT eDVBServicePlay::selectChannel(int i)
1715 {
1716         if (i < LEFT || i > RIGHT || i == STEREO)
1717                 i = -1;  // Stereo
1718         if (m_dvb_service)
1719                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1720         if (m_decoder)
1721                 m_decoder->setAudioChannel(i);
1722         return 0;
1723 }
1724
1725 std::string eDVBServicePlay::getRadioText(int x)
1726 {
1727         if (m_radiotext_parser)
1728                 switch(x)
1729                 {
1730                         case 0:
1731                                 return convertLatin1UTF8(m_radiotext_parser->getCurrentText());
1732                 }
1733         return "";
1734 }
1735
1736 void eDVBServicePlay::radioTextUpdated()
1737 {
1738         m_event((iPlayableService*)this, evUpdatedRadioText);
1739 }
1740
1741 int eDVBServiceBase::getFrontendInfo(int w)
1742 {
1743         eUsePtr<iDVBChannel> channel;
1744         if(m_service_handler.getChannel(channel))
1745                 return 0;
1746         ePtr<iDVBFrontend> fe;
1747         if(channel->getFrontend(fe))
1748                 return 0;
1749         return fe->readFrontendData(w);
1750 }
1751
1752 PyObject *eDVBServiceBase::getFrontendData(bool original)
1753 {
1754         ePyObject ret;
1755
1756         eUsePtr<iDVBChannel> channel;
1757         if(!m_service_handler.getChannel(channel))
1758         {
1759                 ePtr<iDVBFrontend> fe;
1760                 if(!channel->getFrontend(fe))
1761                 {
1762                         ret = fe->readTransponderData(original);
1763                         if (ret)
1764                         {
1765                                 ePtr<iDVBFrontendParameters> feparm;
1766                                 channel->getCurrentFrontendParameters(feparm);
1767                                 if (feparm)
1768                                 {
1769                                         eDVBFrontendParametersSatellite osat;
1770                                         if (!feparm->getDVBS(osat))
1771                                         {
1772                                                 void PutToDict(ePyObject &, const char*, long);
1773                                                 void PutToDict(ePyObject &, const char*, const char*);
1774                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1775                                                 const char *tmp = "UNKNOWN";
1776                                                 switch(osat.polarisation)
1777                                                 {
1778                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1779                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1780                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1781                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1782                                                         default:break;
1783                                                 }
1784                                                 PutToDict(ret, "polarization", tmp);
1785                                         }
1786                                 }
1787                         }
1788                 }
1789         }
1790         if (!ret)
1791                 Py_RETURN_NONE;
1792         return ret;
1793 }
1794
1795 int eDVBServicePlay::getNumberOfSubservices()
1796 {
1797         ePtr<eServiceEvent> evt;
1798         if (!m_event_handler.getEvent(evt, 0))
1799                 return evt->getNumOfLinkageServices();
1800         return 0;
1801 }
1802
1803 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1804 {
1805         ePtr<eServiceEvent> evt;
1806         if (!m_event_handler.getEvent(evt, 0))
1807         {
1808                 if (!evt->getLinkageService(sub, m_reference, n))
1809                         return 0;
1810         }
1811         sub.type=eServiceReference::idInvalid;
1812         return -1;
1813 }
1814
1815 RESULT eDVBServicePlay::startTimeshift()
1816 {
1817         ePtr<iDVBDemux> demux;
1818         
1819         eDebug("Start timeshift!");
1820         
1821         if (m_timeshift_enabled)
1822                 return -1;
1823         
1824                 /* start recording with the data demux. */
1825         if (m_service_handler.getDataDemux(demux))
1826                 return -2;
1827
1828         demux->createTSRecorder(m_record);
1829         if (!m_record)
1830                 return -3;
1831
1832         char templ[]=TSPATH "/timeshift.XXXXXX";
1833         m_timeshift_fd = mkstemp(templ);
1834         m_timeshift_file = templ;
1835         
1836         eDebug("recording to %s", templ);
1837         
1838         if (m_timeshift_fd < 0)
1839         {
1840                 m_record = 0;
1841                 return -4;
1842         }
1843                 
1844         m_record->setTargetFD(m_timeshift_fd);
1845
1846         m_timeshift_enabled = 1;
1847         
1848         updateTimeshiftPids();
1849         m_record->start();
1850
1851         return 0;
1852 }
1853
1854 RESULT eDVBServicePlay::stopTimeshift()
1855 {
1856         if (!m_timeshift_enabled)
1857                 return -1;
1858         
1859         switchToLive();
1860         
1861         m_timeshift_enabled = 0;
1862         
1863         m_record->stop();
1864         m_record = 0;
1865         
1866         close(m_timeshift_fd);
1867         eDebug("remove timeshift file");
1868         remove(m_timeshift_file.c_str());
1869         
1870         return 0;
1871 }
1872
1873 int eDVBServicePlay::isTimeshiftActive()
1874 {
1875         return m_timeshift_enabled && m_timeshift_active;
1876 }
1877
1878 RESULT eDVBServicePlay::activateTimeshift()
1879 {
1880         if (!m_timeshift_enabled)
1881                 return -1;
1882         
1883         if (!m_timeshift_active)
1884         {
1885                 switchToTimeshift();
1886                 return 0;
1887         }
1888         
1889         return -2;
1890 }
1891
1892 PyObject *eDVBServicePlay::getCutList()
1893 {
1894         ePyObject list = PyList_New(0);
1895         
1896         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1897         {
1898                 ePyObject tuple = PyTuple_New(2);
1899                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1900                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1901                 PyList_Append(list, tuple);
1902                 Py_DECREF(tuple);
1903         }
1904         
1905         return list;
1906 }
1907
1908 void eDVBServicePlay::setCutList(ePyObject list)
1909 {
1910         if (!PyList_Check(list))
1911                 return;
1912         int size = PyList_Size(list);
1913         int i;
1914         
1915         m_cue_entries.clear();
1916         
1917         for (i=0; i<size; ++i)
1918         {
1919                 ePyObject tuple = PyList_GET_ITEM(list, i);
1920                 if (!PyTuple_Check(tuple))
1921                 {
1922                         eDebug("non-tuple in cutlist");
1923                         continue;
1924                 }
1925                 if (PyTuple_Size(tuple) != 2)
1926                 {
1927                         eDebug("cutlist entries need to be a 2-tuple");
1928                         continue;
1929                 }
1930                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
1931                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1932                 {
1933                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1934                         continue;
1935                 }
1936                 pts_t pts = PyLong_AsLongLong(ppts);
1937                 int type = PyInt_AsLong(ptype);
1938                 m_cue_entries.insert(cueEntry(pts, type));
1939                 eDebug("adding %08llx, %d", pts, type);
1940         }
1941         m_cuesheet_changed = 1;
1942         
1943         cutlistToCuesheet();
1944         m_event((iPlayableService*)this, evCuesheetChanged);
1945 }
1946
1947 void eDVBServicePlay::setCutListEnable(int enable)
1948 {
1949         m_cutlist_enabled = enable;
1950         cutlistToCuesheet();
1951 }
1952
1953 void eDVBServicePlay::updateTimeshiftPids()
1954 {
1955         if (!m_record)
1956                 return;
1957         
1958         eDVBServicePMTHandler::program program;
1959         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1960
1961         if (h.getProgramInfo(program))
1962                 return;
1963         else
1964         {
1965                 std::set<int> pids_to_record;
1966                 pids_to_record.insert(0); // PAT
1967                 if (program.pmtPid != -1)
1968                         pids_to_record.insert(program.pmtPid); // PMT
1969
1970                 if (program.textPid != -1)
1971                         pids_to_record.insert(program.textPid); // Videotext
1972
1973                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1974                         i(program.videoStreams.begin()); 
1975                         i != program.videoStreams.end(); ++i)
1976                         pids_to_record.insert(i->pid);
1977
1978                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1979                         i(program.audioStreams.begin()); 
1980                         i != program.audioStreams.end(); ++i)
1981                                 pids_to_record.insert(i->pid);
1982
1983                 std::set<int> new_pids, obsolete_pids;
1984                 
1985                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1986                                 m_pids_active.begin(), m_pids_active.end(),
1987                                 std::inserter(new_pids, new_pids.begin()));
1988                 
1989                 std::set_difference(
1990                                 m_pids_active.begin(), m_pids_active.end(),
1991                                 pids_to_record.begin(), pids_to_record.end(), 
1992                                 std::inserter(new_pids, new_pids.begin())
1993                                 );
1994
1995                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1996                         m_record->addPID(*i);
1997
1998                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1999                         m_record->removePID(*i);
2000         }
2001 }
2002
2003 void eDVBServicePlay::switchToLive()
2004 {
2005         if (!m_timeshift_active)
2006                 return;
2007         
2008         m_cue = 0;
2009         m_decoder = 0;
2010         m_decode_demux = 0;
2011         m_teletext_parser = 0;
2012         m_radiotext_parser = 0;
2013         m_subtitle_parser = 0;
2014         m_new_dvb_subtitle_page_connection = 0;
2015         m_new_subtitle_page_connection = 0;
2016         m_radiotext_updated_connection = 0;
2017
2018                 /* free the timeshift service handler, we need the resources */
2019         m_service_handler_timeshift.free();
2020         m_timeshift_active = 0;
2021
2022         m_event((iPlayableService*)this, evSeekableStatusChanged);
2023
2024         updateDecoder();
2025 }
2026
2027 void eDVBServicePlay::switchToTimeshift()
2028 {
2029         if (m_timeshift_active)
2030                 return;
2031
2032         m_decode_demux = 0;
2033         m_decoder = 0;
2034         m_teletext_parser = 0;
2035         m_radiotext_parser = 0;
2036         m_subtitle_parser = 0;
2037         m_new_subtitle_page_connection = 0;
2038         m_new_dvb_subtitle_page_connection = 0;
2039         m_radiotext_updated_connection = 0;
2040
2041         m_timeshift_active = 1;
2042
2043         m_event((iPlayableService*)this, evSeekableStatusChanged);
2044
2045         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2046         r.path = m_timeshift_file;
2047
2048         m_cue = new eCueSheet();
2049         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
2050         updateDecoder(); /* mainly to switch off PCR */
2051 }
2052
2053 void eDVBServicePlay::updateDecoder()
2054 {
2055         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2056
2057         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2058
2059         bool defaultac3=false;
2060         std::string default_ac3;
2061
2062         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
2063                 defaultac3 = default_ac3 == "True";
2064
2065         eDVBServicePMTHandler::program program;
2066         if (h.getProgramInfo(program))
2067                 eDebug("getting program info failed.");
2068         else
2069         {
2070                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2071                 if (!program.videoStreams.empty())
2072                 {
2073                         eDebugNoNewLine(" (");
2074                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2075                                 i(program.videoStreams.begin());
2076                                 i != program.videoStreams.end(); ++i)
2077                         {
2078                                 if (vpid == -1)
2079                                 {
2080                                         vpid = i->pid;
2081                                         vpidtype = i->type;
2082                                 }
2083                                 if (i != program.videoStreams.begin())
2084                                         eDebugNoNewLine(", ");
2085                                 eDebugNoNewLine("%04x", i->pid);
2086                         }
2087                         eDebugNoNewLine(")");
2088                 }
2089                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2090                 if (!program.audioStreams.empty())
2091                 {
2092                         eDebugNoNewLine(" (");
2093                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2094                                 i(program.audioStreams.begin());
2095                                 i != program.audioStreams.end(); ++i)
2096                         {
2097                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
2098                                 {
2099                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
2100                                         {
2101                                                 apid = i->pid;
2102                                                 apidtype = i->type;
2103                                         }
2104                                 }
2105                                 if (i != program.audioStreams.begin())
2106                                         eDebugNoNewLine(", ");
2107                                 eDebugNoNewLine("%04x", i->pid);
2108                         }
2109                         eDebugNoNewLine(")");
2110                 }
2111                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2112                 pcrpid = program.pcrPid;
2113                 eDebug(", and the text pid is %04x", program.textPid);
2114                 tpid = program.textPid;
2115         }
2116
2117         if (!m_decoder)
2118         {
2119                 h.getDecodeDemux(m_decode_demux);
2120                 if (m_decode_demux)
2121                 {
2122                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2123                         if (m_decoder)
2124                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2125                 }
2126                 if (m_cue)
2127                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2128                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2129                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2130                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2131                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2132         }
2133
2134         if (m_decoder)
2135         {
2136                 if (m_dvb_service)
2137                 {
2138                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2139                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2140                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2141                 }
2142                 else // subservice or recording
2143                 {
2144                         eServiceReferenceDVB ref;
2145                         m_service_handler.getServiceReference(ref);
2146                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2147                         if (!parent)
2148                                 parent = ref;
2149                         if (parent)
2150                         {
2151                                 ePtr<eDVBResourceManager> res_mgr;
2152                                 if (!eDVBResourceManager::getInstance(res_mgr))
2153                                 {
2154                                         ePtr<iDVBChannelList> db;
2155                                         if (!res_mgr->getChannelList(db))
2156                                         {
2157                                                 ePtr<eDVBService> origService;
2158                                                 if (!db->getService(parent, origService))
2159                                                 {
2160                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2161                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2162                                                 }
2163                                         }
2164                                 }
2165                         }
2166                 }
2167                 m_decoder->setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2168                 m_decoder->setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2169
2170                 m_decoder->setVideoPID(vpid, vpidtype);
2171                 m_decoder->setAudioPID(apid, apidtype);
2172                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2173                 {
2174                         m_decoder->setSyncPCR(pcrpid);
2175                         if (apid != -1)
2176                         {
2177                                 ePtr<iDVBDemux> data_demux;
2178                                 if (!h.getDataDemux(data_demux))
2179                                 {
2180                                         m_radiotext_parser = new eDVBRadioTextParser(data_demux);
2181                                         m_radiotext_parser->connectUpdatedRadiotext(slot(*this, &eDVBServicePlay::radioTextUpdated), m_radiotext_updated_connection);
2182                                         m_radiotext_parser->start(apid);
2183                                 }
2184                         }
2185                 }
2186                 else
2187                         m_decoder->setSyncPCR(-1);
2188
2189                 m_decoder->setTextPID(tpid);
2190
2191                 m_teletext_parser->start(program.textPid);
2192
2193                 if (!m_is_primary)
2194                         m_decoder->setTrickmode(1);
2195
2196                 m_decoder->start();
2197
2198                 if (vpid > 0 && vpid < 0x2000)
2199                         ;
2200                 else
2201                 {
2202                         std::string radio_pic;
2203                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2204                                 m_decoder->setRadioPic(radio_pic);
2205                 }
2206
2207                 m_decoder->setAudioChannel(achannel);
2208
2209 // how we can do this better?
2210 // update cache pid when the user changed the audio track or video track
2211 // TODO handling of difference audio types.. default audio types..
2212                                 
2213                 /* don't worry about non-existing services, nor pvr services */
2214                 if (m_dvb_service && !m_is_pvr)
2215                 {
2216                         if (apidtype == eDVBAudio::aMPEG)
2217                         {
2218                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
2219                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
2220                         }
2221                         else
2222                         {
2223                                 m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
2224                                 m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
2225                         }
2226                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2227                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2228                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2229                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2230                 }
2231         }       
2232         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2233 }
2234
2235 void eDVBServicePlay::loadCuesheet()
2236 {
2237         std::string filename = m_reference.path + ".cuts";
2238         
2239         m_cue_entries.clear();
2240
2241         FILE *f = fopen(filename.c_str(), "rb");
2242
2243         if (f)
2244         {
2245                 eDebug("loading cuts..");
2246                 while (1)
2247                 {
2248                         unsigned long long where;
2249                         unsigned int what;
2250                         
2251                         if (!fread(&where, sizeof(where), 1, f))
2252                                 break;
2253                         if (!fread(&what, sizeof(what), 1, f))
2254                                 break;
2255                         
2256 #if BYTE_ORDER == LITTLE_ENDIAN
2257                         where = bswap_64(where);
2258 #endif
2259                         what = ntohl(what);
2260                         
2261                         if (what > 3)
2262                                 break;
2263                         
2264                         m_cue_entries.insert(cueEntry(where, what));
2265                 }
2266                 fclose(f);
2267                 eDebug("%d entries", m_cue_entries.size());
2268         } else
2269                 eDebug("cutfile not found!");
2270         
2271         m_cuesheet_changed = 0;
2272         cutlistToCuesheet();
2273         m_event((iPlayableService*)this, evCuesheetChanged);
2274 }
2275
2276 void eDVBServicePlay::saveCuesheet()
2277 {
2278         std::string filename = m_reference.path + ".cuts";
2279         
2280         FILE *f = fopen(filename.c_str(), "wb");
2281
2282         if (f)
2283         {
2284                 unsigned long long where;
2285                 int what;
2286
2287                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2288                 {
2289 #if BYTE_ORDER == BIG_ENDIAN
2290                         where = i->where;
2291 #else
2292                         where = bswap_64(i->where);
2293 #endif
2294                         what = htonl(i->what);
2295                         fwrite(&where, sizeof(where), 1, f);
2296                         fwrite(&what, sizeof(what), 1, f);
2297                         
2298                 }
2299                 fclose(f);
2300         }
2301         
2302         m_cuesheet_changed = 0;
2303 }
2304
2305 void eDVBServicePlay::cutlistToCuesheet()
2306 {
2307         if (!m_cue)
2308         {
2309                 eDebug("no cue sheet");
2310                 return;
2311         }       
2312         m_cue->clear();
2313         
2314         if (!m_cutlist_enabled)
2315         {
2316                 m_cue->commitSpans();
2317                 eDebug("cutlists were disabled");
2318                 return;
2319         }
2320
2321         pts_t in = 0, out = 0, length = 0;
2322         
2323         getLength(length);
2324                 
2325         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2326         
2327         while (1)
2328         {
2329                 if (i == m_cue_entries.end())
2330                         out = length;
2331                 else {
2332                         if (i->what == 0) /* in */
2333                         {
2334                                 in = i++->where;
2335                                 continue;
2336                         } else if (i->what == 1) /* out */
2337                                 out = i++->where;
2338                         else /* mark (2) or last play position (3) */
2339                         {
2340                                 i++;
2341                                 continue;
2342                         }
2343                 }
2344                 
2345                 if (in != out)
2346                         m_cue->addSourceSpan(in, out);
2347                 
2348                 in = length;
2349                 
2350                 if (i == m_cue_entries.end())
2351                         break;
2352         }
2353         m_cue->commitSpans();
2354 }
2355
2356 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2357 {
2358         if (m_subtitle_widget)
2359                 disableSubtitles(parent);
2360
2361         ePyObject entry;
2362         int tuplesize = PyTuple_Size(tuple);
2363         int type = 0;
2364
2365         if (!PyTuple_Check(tuple))
2366                 goto error_out;
2367
2368         if (tuplesize < 1)
2369                 goto error_out;
2370
2371         entry = PyTuple_GET_ITEM(tuple, 0);
2372
2373         if (!PyInt_Check(entry))
2374                 goto error_out;
2375
2376         type = PyInt_AsLong(entry);
2377
2378         if (type == 1)  // teletext subtitles
2379         {
2380                 int page, magazine, pid;
2381                 if (tuplesize < 4)
2382                         goto error_out;
2383
2384                 if (!m_teletext_parser)
2385                 {
2386                         eDebug("enable teletext subtitles.. no parser !!!");
2387                         return -1;
2388                 }
2389
2390                 entry = PyTuple_GET_ITEM(tuple, 1);
2391                 if (!PyInt_Check(entry))
2392                         goto error_out;
2393                 pid = PyInt_AsLong(entry);
2394
2395                 entry = PyTuple_GET_ITEM(tuple, 2);
2396                 if (!PyInt_Check(entry))
2397                         goto error_out;
2398                 page = PyInt_AsLong(entry);
2399
2400                 entry = PyTuple_GET_ITEM(tuple, 3);
2401                 if (!PyInt_Check(entry))
2402                         goto error_out;
2403                 magazine = PyInt_AsLong(entry);
2404
2405                 m_subtitle_widget = new eSubtitleWidget(parent);
2406                 m_subtitle_widget->resize(parent->size()); /* full size */
2407                 m_teletext_parser->setPageAndMagazine(page, magazine);
2408                 if (m_dvb_service)
2409                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2410         }
2411         else if (type == 0)
2412         {
2413                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2414                 if (!m_subtitle_parser)
2415                 {
2416                         eDebug("enable dvb subtitles.. no parser !!!");
2417                         return -1;
2418                 }
2419                 if (tuplesize < 4)
2420                         goto error_out;
2421
2422                 entry = PyTuple_GET_ITEM(tuple, 1);
2423                 if (!PyInt_Check(entry))
2424                         goto error_out;
2425                 pid = PyInt_AsLong(entry);
2426
2427                 entry = PyTuple_GET_ITEM(tuple, 2);
2428                 if (!PyInt_Check(entry))
2429                         goto error_out;
2430                 composition_page_id = PyInt_AsLong(entry);
2431
2432                 entry = PyTuple_GET_ITEM(tuple, 3);
2433                 if (!PyInt_Check(entry))
2434                         goto error_out;
2435                 ancillary_page_id = PyInt_AsLong(entry);
2436
2437                 m_subtitle_widget = new eSubtitleWidget(parent);
2438                 m_subtitle_widget->resize(parent->size()); /* full size */
2439                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2440                 if (m_dvb_service)
2441                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2442         }
2443         else
2444                 goto error_out;
2445         return 0;
2446 error_out:
2447         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2448                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2449                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2450         return -1;
2451 }
2452
2453 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2454 {
2455         delete m_subtitle_widget;
2456         m_subtitle_widget = 0;
2457         if (m_subtitle_parser)
2458         {
2459                 m_subtitle_parser->stop();
2460                 m_dvb_subtitle_pages.clear();
2461         }
2462         if (m_teletext_parser)
2463         {
2464                 m_teletext_parser->setPageAndMagazine(-1, -1);
2465                 m_subtitle_pages.clear();
2466         }
2467         if (m_dvb_service)
2468                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2469         return 0;
2470 }
2471
2472 PyObject *eDVBServicePlay::getCachedSubtitle()
2473 {
2474         if (m_dvb_service)
2475         {
2476                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2477                 if (tmp != -1)
2478                 {
2479                         unsigned int data = (unsigned int)tmp;
2480                         int pid = (data&0xFFFF0000)>>16;
2481                         ePyObject tuple = PyTuple_New(4);
2482                         eDVBServicePMTHandler::program program;
2483                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2484                         if (!h.getProgramInfo(program))
2485                         {
2486                                 if (program.textPid==pid) // teletext
2487                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2488                                 else
2489                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2490                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((data&0xFFFF0000)>>16)); // pid
2491                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2492                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2493                                 return tuple;
2494                         }
2495                 }
2496         }
2497         Py_RETURN_NONE;
2498 }
2499
2500 PyObject *eDVBServicePlay::getSubtitleList()
2501 {
2502         if (!m_teletext_parser)
2503                 Py_RETURN_NONE;
2504         
2505         ePyObject l = PyList_New(0);
2506         std::set<int> added_ttx_pages;
2507
2508         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2509                 m_teletext_parser->m_found_subtitle_pages;
2510
2511         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2512         eDVBServicePMTHandler::program program;
2513         if (h.getProgramInfo(program))
2514                 eDebug("getting program info failed.");
2515         else
2516         {
2517                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2518                         it != program.subtitleStreams.end(); ++it)
2519                 {
2520                         switch(it->subtitling_type)
2521                         {
2522                                 case 0x01: // ebu teletext subtitles
2523                                 {
2524                                         int page_number = it->teletext_page_number & 0xFF;
2525                                         int magazine_number = it->teletext_magazine_number & 7;
2526                                         int hash = magazine_number << 8 | page_number;
2527                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2528                                         {
2529                                                 ePyObject tuple = PyTuple_New(5);
2530                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2531                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2532                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2533                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2534                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2535                                                 PyList_Append(l, tuple);
2536                                                 Py_DECREF(tuple);
2537                                                 added_ttx_pages.insert(hash);
2538                                         }
2539                                         break;
2540                                 }
2541                                 case 0x10 ... 0x13:
2542                                 case 0x20 ... 0x23: // dvb subtitles
2543                                 {
2544                                         ePyObject tuple = PyTuple_New(5);
2545                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2546                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2547                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2548                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2549                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2550                                         PyList_Insert(l, 0, tuple);
2551                                         Py_DECREF(tuple);
2552                                         break;
2553                                 }
2554                         }
2555                 }
2556         }
2557
2558         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2559                 it != subs.end(); ++it)
2560         {
2561                 int page_number = it->teletext_page_number & 0xFF;
2562                 int magazine_number = it->teletext_magazine_number & 7;
2563                 int hash = magazine_number << 8 | page_number;
2564                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2565                 {
2566                         ePyObject tuple = PyTuple_New(5);
2567                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2568                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2569                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2570                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2571                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2572                         PyList_Append(l, tuple);
2573                         Py_DECREF(tuple);
2574                 }
2575         }
2576
2577         return l;
2578 }
2579
2580 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2581 {
2582         if (m_subtitle_widget)
2583         {
2584                 m_subtitle_pages.push_back(page);
2585                 checkSubtitleTiming();
2586         }
2587 }
2588
2589 void eDVBServicePlay::checkSubtitleTiming()
2590 {
2591 //      eDebug("checkSubtitleTiming");
2592         if (!m_subtitle_widget)
2593                 return;
2594         while (1)
2595         {
2596                 enum { TELETEXT, DVB } type;
2597                 eDVBTeletextSubtitlePage page;
2598                 eDVBSubtitlePage dvb_page;
2599                 pts_t show_time;
2600                 if (!m_subtitle_pages.empty())
2601                 {
2602                         page = m_subtitle_pages.front();
2603                         type = TELETEXT;
2604                         show_time = page.m_pts;
2605                 }
2606                 else if (!m_dvb_subtitle_pages.empty())
2607                 {
2608                         dvb_page = m_dvb_subtitle_pages.front();
2609                         type = DVB;
2610                         show_time = dvb_page.m_show_time;
2611                 }
2612                 else
2613                         return;
2614         
2615                 pts_t pos = 0;
2616         
2617                 if (m_decoder)
2618                         m_decoder->getPTS(0, pos);
2619
2620 //              eDebug("%lld %lld", pos, show_time);
2621                 int diff =  show_time - pos;
2622                 if (diff < 0)
2623                 {
2624                         eDebug("[late (%d ms)]", -diff / 90);
2625                         diff = 0;
2626                 }
2627                 if (diff > 900000)
2628                 {
2629                         eDebug("[invalid]");
2630                         diff = 0;
2631                 }
2632         
2633                 if (!diff)
2634                 {
2635                         if (type == TELETEXT)
2636                         {
2637                                 eDebug("display teletext subtitle page");
2638                                 m_subtitle_widget->setPage(page);
2639                                 m_subtitle_pages.pop_front();
2640                         }
2641                         else
2642                         {
2643                                 eDebug("display dvb subtitle Page");
2644                                 m_subtitle_widget->setPage(dvb_page);
2645                                 m_dvb_subtitle_pages.pop_front();
2646                         }
2647                 } else
2648                 {
2649 //                      eDebug("start subtitle delay %d", diff / 90);
2650                         m_subtitle_sync_timer.start(diff / 90, 1);
2651                         break;
2652                 }
2653         }
2654 }
2655
2656 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2657 {
2658         if (m_subtitle_widget)
2659         {
2660                 m_dvb_subtitle_pages.push_back(p);
2661                 checkSubtitleTiming();
2662         }
2663 }
2664
2665 int eDVBServicePlay::getAC3Delay()
2666 {
2667         if (m_dvb_service)
2668                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2669         else if (m_decoder)
2670                 return m_decoder->getAC3Delay();
2671         else
2672                 return 0;
2673 }
2674
2675 int eDVBServicePlay::getPCMDelay()
2676 {
2677         if (m_dvb_service)
2678                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2679         else if (m_decoder)
2680                 return m_decoder->getPCMDelay();
2681         else
2682                 return 0;
2683 }
2684
2685 void eDVBServicePlay::setAC3Delay(int delay)
2686 {
2687         if (m_dvb_service)
2688                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2689         if (m_decoder)
2690                 m_decoder->setAC3Delay(delay);
2691 }
2692
2693 void eDVBServicePlay::setPCMDelay(int delay)
2694 {
2695         if (m_dvb_service)
2696                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2697         if (m_decoder)
2698                 m_decoder->setPCMDelay(delay);
2699 }
2700
2701 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2702 {
2703         eDebug("!!!!!!!!!! Video Event type %d, aspect %d, %dx%d", event.type, event.aspect, event.width, event.height);
2704         memcpy(&m_videoEventData, &event, sizeof(iTSMPEGDecoder::videoEvent));
2705         m_event((iPlayableService*)this, evVideoSizeChanged);
2706 }
2707
2708 DEFINE_REF(eDVBServicePlay)
2709
2710 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
2711 {
2712         switch (w)
2713         {
2714         case iServiceInformation::sTransponderData:
2715                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
2716         default:
2717                 break;
2718         }
2719         return iStaticServiceInformation::getInfoObject(ref, w);
2720 }
2721
2722 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");