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