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