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