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