servicedvb.cpp: more exact resume after seek and slowmotion
[vuplus_dvbapp] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/estring.h>
7 #include <lib/base/init_num.h>
8 #include <lib/base/init.h>
9 #include <lib/dvb/dvb.h>
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/decoder.h>
12
13 #include <lib/components/file_eraser.h>
14 #include <lib/service/servicedvbrecord.h>
15 #include <lib/service/event.h>
16 #include <lib/dvb/metaparser.h>
17 #include <lib/dvb/tstools.h>
18 #include <lib/python/python.h>
19 #include <lib/base/nconfig.h> // access to python config
20
21                 /* for subtitles */
22 #include <lib/gui/esubtitle.h>
23
24 #include <sys/vfs.h>
25 #include <sys/stat.h>
26
27 #include <byteswap.h>
28 #include <netinet/in.h>
29
30 #ifndef BYTE_ORDER
31 #error no byte order defined!
32 #endif
33
34 class eStaticServiceDVBInformation: public iStaticServiceInformation
35 {
36         DECLARE_REF(eStaticServiceDVBInformation);
37 public:
38         RESULT getName(const eServiceReference &ref, std::string &name);
39         int getLength(const eServiceReference &ref);
40         int isPlayable(const eServiceReference &ref, const eServiceReference &ignore);
41         PyObject *getInfoObject(const eServiceReference &ref, int);
42 };
43
44 DEFINE_REF(eStaticServiceDVBInformation);
45
46 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
47 {
48         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
49         if ( !ref.name.empty() )
50         {
51                 if (service.getParentTransportStreamID().get()) // linkage subservice
52                 {
53                         ePtr<iServiceHandler> service_center;
54                         if (!eServiceCenter::getInstance(service_center))
55                         {
56                                 eServiceReferenceDVB parent = service;
57                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
58                                 parent.setServiceID( service.getParentServiceID() );
59                                 parent.setParentTransportStreamID(eTransportStreamID(0));
60                                 parent.setParentServiceID(eServiceID(0));
61                                 parent.name="";
62                                 ePtr<iStaticServiceInformation> service_info;
63                                 if (!service_center->info(parent, service_info))
64                                 {
65                                         if (!service_info->getName(parent, name))
66                                                 name=buildShortName(name) + " - ";
67                                 }
68                         }
69                 }
70                 else
71                         name="";
72                 name += ref.name;
73                 return 0;
74         }
75         else
76                 return -1;
77 }
78
79 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
80 {
81         return -1;
82 }
83
84 int eStaticServiceDVBInformation::isPlayable(const eServiceReference &ref, const eServiceReference &ignore)
85 {
86         ePtr<eDVBResourceManager> res_mgr;
87         if ( eDVBResourceManager::getInstance( res_mgr ) )
88                 eDebug("isPlayable... no res manager!!");
89         else
90         {
91                 eDVBChannelID chid, chid_ignore;
92                 ((const eServiceReferenceDVB&)ref).getChannelID(chid);
93                 ((const eServiceReferenceDVB&)ignore).getChannelID(chid_ignore);
94                 return res_mgr->canAllocateChannel(chid, chid_ignore);
95         }
96         return false;
97 }
98
99 extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
100 extern void 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);
1283         if (m_decoder)
1284         {
1285                 m_is_paused = 1;
1286                 return m_decoder->pause();
1287         } else
1288                 return -1;
1289 }
1290
1291 RESULT eDVBServicePlay::unpause()
1292 {
1293         eDebug("eDVBServicePlay::unpause");
1294         setFastForward_internal(0, m_slowmotion || m_fastforward > 1);
1295         if (m_decoder)
1296         {
1297                 m_slowmotion = 0;
1298                 m_is_paused = 0;
1299                 return m_decoder->play();
1300         } else
1301                 return -1;
1302 }
1303
1304 RESULT eDVBServicePlay::seekTo(pts_t to)
1305 {
1306         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
1307         
1308         if (!m_decode_demux)
1309                 return -1;
1310
1311         ePtr<iDVBPVRChannel> pvr_channel;
1312         
1313         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1314                 return -1;
1315         
1316         if (!m_cue)
1317                 return -1;
1318         
1319         m_cue->seekTo(0, to);
1320         m_dvb_subtitle_pages.clear();
1321         m_subtitle_pages.clear();
1322
1323         return 0;
1324 }
1325
1326 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
1327 {
1328         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
1329         
1330         if (!m_decode_demux)
1331                 return -1;
1332
1333         ePtr<iDVBPVRChannel> pvr_channel;
1334         
1335         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1336                 return -1;
1337         
1338         int mode = 1;
1339         
1340                         /* HACK until we have skip-AP api */
1341         if ((to > 0) && (to < 100))
1342                 mode = 2;
1343         
1344         to *= direction;
1345         
1346         if (!m_cue)
1347                 return 0;
1348         
1349         m_cue->seekTo(mode, to);
1350         m_dvb_subtitle_pages.clear();
1351         m_subtitle_pages.clear();
1352         return 0;
1353 }
1354
1355 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
1356 {
1357         ePtr<iDVBPVRChannel> pvr_channel;
1358         
1359         if (!m_decode_demux)
1360                 return -1;
1361         
1362         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
1363                 return -1;
1364         
1365         int r = 0;
1366
1367                 /* if there is a decoder, use audio or video PTS */
1368         if (m_decoder)
1369         {
1370                 r = m_decoder->getPTS(0, pos);
1371                 if (r)
1372                         return r;
1373         }
1374         
1375                 /* fixup */
1376         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
1377 }
1378
1379 RESULT eDVBServicePlay::setTrickmode(int trick)
1380 {
1381                 /* currently unimplemented */
1382         return -1;
1383 }
1384
1385 RESULT eDVBServicePlay::isCurrentlySeekable()
1386 {
1387         return m_is_pvr || m_timeshift_active;
1388 }
1389
1390 RESULT eDVBServicePlay::frontendInfo(ePtr<iFrontendInformation> &ptr)
1391 {
1392         ptr = this;
1393         return 0;
1394 }
1395
1396 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
1397 {
1398         ptr = this;
1399         return 0;
1400 }
1401
1402 RESULT eDVBServicePlay::audioChannel(ePtr<iAudioChannelSelection> &ptr)
1403 {
1404         ptr = this;
1405         return 0;
1406 }
1407
1408 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1409 {
1410         ptr = this;
1411         return 0;
1412 }
1413
1414 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1415 {
1416         ptr = this;
1417         return 0;
1418 }
1419
1420 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1421 {
1422         ptr = 0;
1423         if (m_have_video_pid &&  // HACK !!! FIXMEE !! temporary no timeshift on radio services !!
1424                 (m_timeshift_enabled || !m_is_pvr))
1425         {
1426                 if (!m_timeshift_enabled)
1427                 {
1428                         /* query config path */
1429                         std::string tspath;
1430                         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){
1431                                 eDebug("could not query ts path from config");
1432                                 return -4;
1433                         }
1434                         tspath.append("/");
1435                         /* we need enough diskspace */
1436                         struct statfs fs;
1437                         if (statfs(tspath.c_str(), &fs) < 0)
1438                         {
1439                                 eDebug("statfs failed!");
1440                                 return -2;
1441                         }
1442                 
1443                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1444                         {
1445                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1446                                 return -3;
1447                         }
1448                 }
1449                 ptr = this;
1450                 return 0;
1451         }
1452         return -1;
1453 }
1454
1455 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1456 {
1457         if (m_is_pvr)
1458         {
1459                 ptr = this;
1460                 return 0;
1461         }
1462         ptr = 0;
1463         return -1;
1464 }
1465
1466 RESULT eDVBServicePlay::subtitle(ePtr<iSubtitleOutput> &ptr)
1467 {
1468         ptr = this;
1469         return 0;
1470 }
1471
1472 RESULT eDVBServicePlay::audioDelay(ePtr<iAudioDelay> &ptr)
1473 {
1474         ptr = this;
1475         return 0;
1476 }
1477
1478 RESULT eDVBServicePlay::rdsDecoder(ePtr<iRdsDecoder> &ptr)
1479 {
1480         ptr = this;
1481         return 0;
1482 }
1483
1484 RESULT eDVBServicePlay::getName(std::string &name)
1485 {
1486         if (m_is_pvr)
1487         {
1488                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1489                 return i->getName(m_reference, name);
1490         }
1491         else if (m_dvb_service)
1492         {
1493                 m_dvb_service->getName(m_reference, name);
1494                 if (name.empty())
1495                         name = "(...)";
1496         }
1497         else if (!m_reference.name.empty())
1498                 eStaticServiceDVBInformation().getName(m_reference, name);
1499         else
1500                 name = "DVB service";
1501         return 0;
1502 }
1503
1504 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1505 {
1506         return m_event_handler.getEvent(evt, nownext);
1507 }
1508
1509 int eDVBServicePlay::getInfo(int w)
1510 {
1511         eDVBServicePMTHandler::program program;
1512
1513         if (w == sCAIDs)
1514                 return resIsPyObject;
1515
1516         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1517
1518         int no_program_info = 0;
1519
1520         if (h.getProgramInfo(program))
1521                 no_program_info = 1;
1522
1523         switch (w)
1524         {
1525         case sVideoHeight:
1526                 if (m_decoder)
1527                         return m_decoder->getVideoHeight();
1528                 break;
1529         case sVideoWidth:
1530                 if (m_decoder)
1531                         return m_decoder->getVideoWidth();
1532                 break;
1533         case sFrameRate:
1534                 if (m_decoder)
1535                         return m_decoder->getVideoFrameRate();
1536                 break;
1537         case sProgressive:
1538                 if (m_decoder)
1539                         return m_decoder->getVideoProgressive();
1540                 break;
1541         case sAspect:
1542         {
1543                 int aspect = -1;
1544                 if (m_decoder)
1545                         aspect = m_decoder->getVideoAspect();
1546                 if (aspect == -1 && no_program_info)
1547                         break;
1548                 else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1549                 {
1550                         ePtr<eServiceEvent> evt;
1551                         if (!m_event_handler.getEvent(evt, 0))
1552                         {
1553                                 ePtr<eComponentData> data;
1554                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1555                                 {
1556                                         if ( data->getStreamContent() == 1 )
1557                                         {
1558                                                 switch(data->getComponentType())
1559                                                 {
1560                                                         // SD
1561                                                         case 1: // 4:3 SD PAL
1562                                                         case 2:
1563                                                         case 3: // 16:9 SD PAL
1564                                                         case 4: // > 16:9 PAL
1565                                                         case 5: // 4:3 SD NTSC
1566                                                         case 6: 
1567                                                         case 7: // 16:9 SD NTSC
1568                                                         case 8: // > 16:9 NTSC
1569
1570                                                         // HD
1571                                                         case 9: // 4:3 HD PAL
1572                                                         case 0xA:
1573                                                         case 0xB: // 16:9 HD PAL
1574                                                         case 0xC: // > 16:9 HD PAL
1575                                                         case 0xD: // 4:3 HD NTSC
1576                                                         case 0xE:
1577                                                         case 0xF: // 16:9 HD NTSC
1578                                                         case 0x10: // > 16:9 HD PAL
1579                                                                 return data->getComponentType();
1580                                                 }
1581                                         }
1582                                 }
1583                         }
1584                 }
1585                 else
1586                         return aspect;
1587                 break;
1588         }
1589         case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
1590         case sVideoPID:
1591                 if (m_dvb_service)
1592                 {
1593                         int vpid = m_dvb_service->getCacheEntry(eDVBService::cVPID);
1594                         if (vpid != -1)
1595                                 return vpid;
1596                 }
1597                 if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1598         case sVideoType: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1599         case sAudioPID:
1600                 if (m_dvb_service)
1601                 {
1602                         int apid = m_dvb_service->getCacheEntry(eDVBService::cAPID);
1603                         if (apid != -1)
1604                                 return apid;
1605                         apid = m_dvb_service->getCacheEntry(eDVBService::cAC3PID);
1606                         if (apid != -1)
1607                                 return apid;
1608                 }
1609                 if (no_program_info) return -1; if (program.audioStreams.empty()) return -1; return program.audioStreams[0].pid;
1610         case sPCRPID:
1611                 if (m_dvb_service)
1612                 {
1613                         int pcrpid = m_dvb_service->getCacheEntry(eDVBService::cPCRPID);
1614                         if (pcrpid != -1)
1615                                 return pcrpid;
1616                 }
1617                 if (no_program_info) return -1; return program.pcrPid;
1618         case sPMTPID: if (no_program_info) return -1; return program.pmtPid;
1619         case sTXTPID: if (no_program_info) return -1; return program.textPid;
1620         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1621         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1622         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1623         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1624         case sProvider: if (!m_dvb_service) return -1; return -2;
1625         case sServiceref: return resIsString;
1626         case sDVBState: return m_tune_state;
1627         default:
1628                 break;
1629         }
1630         return -1;
1631 }
1632
1633 std::string eDVBServicePlay::getInfoString(int w)
1634 {
1635         switch (w)
1636         {
1637         case sProvider:
1638                 if (!m_dvb_service) return "";
1639                 return m_dvb_service->m_provider_name;
1640         case sServiceref:
1641                 return m_reference.toString();
1642         default:
1643                 break;
1644         }
1645         return iServiceInformation::getInfoString(w);
1646 }
1647
1648 PyObject *eDVBServicePlay::getInfoObject(int w)
1649 {
1650         switch (w)
1651         {
1652         case sCAIDs:
1653                 return m_service_handler.getCaIds();
1654         case sTransponderData:
1655                 return eStaticServiceDVBInformation().getInfoObject(m_reference, w);
1656         default:
1657                 break;
1658         }
1659         return iServiceInformation::getInfoObject(w);
1660 }
1661
1662 int eDVBServicePlay::getNumberOfTracks()
1663 {
1664         eDVBServicePMTHandler::program program;
1665         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1666         if (h.getProgramInfo(program))
1667                 return 0;
1668         return program.audioStreams.size();
1669 }
1670
1671 int eDVBServicePlay::getCurrentTrack()
1672 {
1673         eDVBServicePMTHandler::program program;
1674         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1675         if (h.getProgramInfo(program))
1676                 return 0;
1677
1678         int max = program.audioStreams.size();
1679         int i;
1680
1681         for (i = 0; i < max; ++i)
1682                 if (program.audioStreams[i].pid == m_current_audio_pid)
1683                         return i;
1684
1685         return 0;
1686 }
1687
1688 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1689 {
1690         int ret = selectAudioStream(i);
1691
1692         if (m_decoder->set())
1693                 return -5;
1694
1695         return ret;
1696 }
1697
1698 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1699 {
1700         eDVBServicePMTHandler::program program;
1701         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1702
1703         if (h.getProgramInfo(program))
1704                 return -1;
1705         
1706         if (i >= program.audioStreams.size())
1707                 return -2;
1708         
1709         info.m_pid = program.audioStreams[i].pid;
1710
1711         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1712                 info.m_description = "MPEG";
1713         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1714                 info.m_description = "AC3";
1715         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
1716                 info.m_description = "AAC";
1717         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
1718                 info.m_description = "AAC-HE";
1719         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1720                 info.m_description = "DTS";
1721         else
1722                 info.m_description = "???";
1723
1724         if (program.audioStreams[i].component_tag != -1)
1725         {
1726                 ePtr<eServiceEvent> evt;
1727                 if (!m_event_handler.getEvent(evt, 0))
1728                 {
1729                         ePtr<eComponentData> data;
1730                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1731                                 info.m_language = data->getText();
1732                 }
1733         }
1734
1735         if (info.m_language.empty())
1736                 info.m_language = program.audioStreams[i].language_code;
1737         
1738         return 0;
1739 }
1740
1741 int eDVBServicePlay::selectAudioStream(int i)
1742 {
1743         eDVBServicePMTHandler::program program;
1744         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1745
1746         if (h.getProgramInfo(program))
1747                 return -1;
1748
1749         if ((i != -1) && ((unsigned int)i >= program.audioStreams.size()))
1750                 return -2;
1751
1752         if (!m_decoder)
1753                 return -3;
1754
1755         int stream = i;
1756         if (stream == -1)
1757                 stream = program.defaultAudioStream;
1758
1759         int apid = -1, apidtype = -1;
1760
1761         if (((unsigned int)stream) < program.audioStreams.size())
1762         {
1763                 apid = program.audioStreams[stream].pid;
1764                 apidtype = program.audioStreams[stream].type;
1765         }
1766
1767         m_current_audio_pid = apid;
1768
1769         if (m_is_primary && m_decoder->setAudioPID(apid, apidtype))
1770         {
1771                 eDebug("set audio pid failed");
1772                 return -4;
1773         }
1774
1775         int rdsPid = apid;
1776
1777                 /* 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 */
1778         if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1779         {
1780                 int different_pid = program.videoStreams.empty() && program.audioStreams.size() == 1 && program.audioStreams[stream].rdsPid != -1;
1781                 if (different_pid)
1782                         rdsPid = program.audioStreams[stream].rdsPid;
1783                 if (!m_rds_decoder || m_rds_decoder->getPid() != rdsPid)
1784                 {
1785                         m_rds_decoder = 0;
1786                         ePtr<iDVBDemux> data_demux;
1787                         if (!h.getDataDemux(data_demux))
1788                         {
1789                                 m_rds_decoder = new eDVBRdsDecoder(data_demux, different_pid);
1790                                 m_rds_decoder->connectEvent(slot(*this, &eDVBServicePlay::rdsDecoderEvent), m_rds_decoder_event_connection);
1791                                 m_rds_decoder->start(rdsPid);
1792                         }
1793                 }
1794         }
1795
1796                         /* store new pid as default only when:
1797                                 a.) we have an entry in the service db for the current service,
1798                                 b.) we are not playing back something,
1799                                 c.) we are not selecting the default entry. (we wouldn't change 
1800                                     anything in the best case, or destroy the default setting in
1801                                     case the real default is not yet available.)
1802                         */
1803         if (m_dvb_service && ((i != -1)
1804                 || ((m_dvb_service->getCacheEntry(eDVBService::cAPID) == -1) && (m_dvb_service->getCacheEntry(eDVBService::cAC3PID)==-1))))
1805         {
1806                 if (apidtype == eDVBAudio::aMPEG)
1807                 {
1808                         m_dvb_service->setCacheEntry(eDVBService::cAPID, apid);
1809                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1810                 }
1811                 else if (apidtype == eDVBAudio::aAC3)
1812                 {
1813                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1814                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid);
1815                 }
1816                 else
1817                 {
1818                         m_dvb_service->setCacheEntry(eDVBService::cAPID, -1);
1819                         m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1);
1820                 }
1821         }
1822
1823         h.resetCachedProgram();
1824
1825         return 0;
1826 }
1827
1828 int eDVBServicePlay::getCurrentChannel()
1829 {
1830         return m_decoder ? m_decoder->getAudioChannel() : STEREO;
1831 }
1832
1833 RESULT eDVBServicePlay::selectChannel(int i)
1834 {
1835         if (i < LEFT || i > RIGHT || i == STEREO)
1836                 i = -1;  // Stereo
1837         if (m_dvb_service)
1838                 m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i);
1839         if (m_decoder)
1840                 m_decoder->setAudioChannel(i);
1841         return 0;
1842 }
1843
1844 std::string eDVBServicePlay::getText(int x)
1845 {
1846         if (m_rds_decoder)
1847                 switch(x)
1848                 {
1849                         case RadioText:
1850                                 return convertLatin1UTF8(m_rds_decoder->getRadioText());
1851                         case RtpText:
1852                                 return convertLatin1UTF8(m_rds_decoder->getRtpText());
1853                 }
1854         return "";
1855 }
1856
1857 void eDVBServicePlay::rdsDecoderEvent(int what)
1858 {
1859         switch(what)
1860         {
1861                 case eDVBRdsDecoder::RadioTextChanged:
1862                         m_event((iPlayableService*)this, evUpdatedRadioText);
1863                         break;
1864                 case eDVBRdsDecoder::RtpTextChanged:
1865                         m_event((iPlayableService*)this, evUpdatedRtpText);
1866                         break;
1867                 case eDVBRdsDecoder::RassInteractivePicMaskChanged:
1868                         m_event((iPlayableService*)this, evUpdatedRassInteractivePicMask);
1869                         break;
1870                 case eDVBRdsDecoder::RecvRassSlidePic:
1871                         m_event((iPlayableService*)this, evUpdatedRassSlidePic);
1872                         break;
1873         }
1874 }
1875
1876 void eDVBServicePlay::showRassSlidePicture()
1877 {
1878         if (m_rds_decoder)
1879         {
1880                 if (m_decoder)
1881                 {
1882                         std::string rass_slide_pic = m_rds_decoder->getRassSlideshowPicture();
1883                         if (rass_slide_pic.length())
1884                                 m_decoder->showSinglePic(rass_slide_pic.c_str());
1885                         else
1886                                 eDebug("empty filename for rass slide picture received!!");
1887                 }
1888                 else
1889                         eDebug("no MPEG Decoder to show iframes avail");
1890         }
1891         else
1892                 eDebug("showRassSlidePicture called.. but not decoder");
1893 }
1894
1895 void eDVBServicePlay::showRassInteractivePic(int page, int subpage)
1896 {
1897         if (m_rds_decoder)
1898         {
1899                 if (m_decoder)
1900                 {
1901                         std::string rass_interactive_pic = m_rds_decoder->getRassPicture(page, subpage);
1902                         if (rass_interactive_pic.length())
1903                                 m_decoder->showSinglePic(rass_interactive_pic.c_str());
1904                         else
1905                                 eDebug("empty filename for rass interactive picture %d/%d received!!", page, subpage);
1906                 }
1907                 else
1908                         eDebug("no MPEG Decoder to show iframes avail");
1909         }
1910         else
1911                 eDebug("showRassInteractivePic called.. but not decoder");
1912 }
1913
1914 ePyObject eDVBServicePlay::getRassInteractiveMask()
1915 {
1916         if (m_rds_decoder)
1917                 return m_rds_decoder->getRassPictureMask();
1918         Py_RETURN_NONE;
1919 }
1920
1921 int eDVBServiceBase::getFrontendInfo(int w)
1922 {
1923         eUsePtr<iDVBChannel> channel;
1924         if(m_service_handler.getChannel(channel))
1925                 return 0;
1926         ePtr<iDVBFrontend> fe;
1927         if(channel->getFrontend(fe))
1928                 return 0;
1929         return fe->readFrontendData(w);
1930 }
1931
1932 PyObject *eDVBServiceBase::getFrontendData()
1933 {
1934         ePyObject ret = PyDict_New();
1935         if (ret)
1936         {
1937                 eUsePtr<iDVBChannel> channel;
1938                 if(!m_service_handler.getChannel(channel))
1939                 {
1940                         ePtr<iDVBFrontend> fe;
1941                         if(!channel->getFrontend(fe))
1942                                 fe->getFrontendData(ret);
1943                 }
1944         }
1945         else
1946                 Py_RETURN_NONE;
1947         return ret;
1948 }
1949
1950 PyObject *eDVBServiceBase::getFrontendStatus()
1951 {
1952         ePyObject ret = PyDict_New();
1953         if (ret)
1954         {
1955                 eUsePtr<iDVBChannel> channel;
1956                 if(!m_service_handler.getChannel(channel))
1957                 {
1958                         ePtr<iDVBFrontend> fe;
1959                         if(!channel->getFrontend(fe))
1960                                 fe->getFrontendStatus(ret);
1961                 }
1962         }
1963         else
1964                 Py_RETURN_NONE;
1965         return ret;
1966 }
1967
1968 PyObject *eDVBServiceBase::getTransponderData(bool original)
1969 {
1970         ePyObject ret = PyDict_New();
1971         if (ret)
1972         {
1973                 eUsePtr<iDVBChannel> channel;
1974                 if(!m_service_handler.getChannel(channel))
1975                 {
1976                         ePtr<iDVBFrontend> fe;
1977                         if(!channel->getFrontend(fe))
1978                                 fe->getTransponderData(ret, original);
1979                 }
1980         }
1981         else
1982                 Py_RETURN_NONE;
1983         return ret;
1984 }
1985
1986 PyObject *eDVBServiceBase::getAll(bool original)
1987 {
1988         ePyObject ret = getTransponderData(original);
1989         if (ret != Py_None)
1990         {
1991                 eUsePtr<iDVBChannel> channel;
1992                 if(!m_service_handler.getChannel(channel))
1993                 {
1994                         ePtr<iDVBFrontend> fe;
1995                         if(!channel->getFrontend(fe))
1996                         {
1997                                 fe->getFrontendData(ret);
1998                                 fe->getFrontendStatus(ret);
1999                         }
2000                 }
2001         }
2002         return ret;
2003 }
2004
2005 int eDVBServicePlay::getNumberOfSubservices()
2006 {
2007         ePtr<eServiceEvent> evt;
2008         if (!m_event_handler.getEvent(evt, 0))
2009                 return evt->getNumOfLinkageServices();
2010         return 0;
2011 }
2012
2013 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
2014 {
2015         ePtr<eServiceEvent> evt;
2016         if (!m_event_handler.getEvent(evt, 0))
2017         {
2018                 if (!evt->getLinkageService(sub, m_reference, n))
2019                         return 0;
2020         }
2021         sub.type=eServiceReference::idInvalid;
2022         return -1;
2023 }
2024
2025 RESULT eDVBServicePlay::startTimeshift()
2026 {
2027         ePtr<iDVBDemux> demux;
2028         
2029         eDebug("Start timeshift!");
2030         
2031         if (m_timeshift_enabled)
2032                 return -1;
2033         
2034                 /* start recording with the data demux. */
2035         if (m_service_handler.getDataDemux(demux))
2036                 return -2;
2037
2038         demux->createTSRecorder(m_record);
2039         if (!m_record)
2040                 return -3;
2041
2042         std::string tspath;
2043         if(ePythonConfigQuery::getConfigValue("config.usage.timeshift_path", tspath) == -1){ 
2044                 eDebug("could not query ts path");
2045                 return -5;
2046         }
2047         tspath.append("/timeshift.XXXXXX");
2048         char* templ;
2049         templ = new char[tspath.length() + 1];
2050         strcpy(templ, tspath.c_str());
2051
2052         m_timeshift_fd = mkstemp(templ);
2053         m_timeshift_file = std::string(templ);
2054
2055         eDebug("recording to %s", templ);
2056
2057         delete [] templ;
2058
2059         if (m_timeshift_fd < 0)
2060         {
2061                 m_record = 0;
2062                 return -4;
2063         }
2064                 
2065         m_record->setTargetFD(m_timeshift_fd);
2066
2067         m_timeshift_enabled = 1;
2068         
2069         updateTimeshiftPids();
2070         m_record->start();
2071
2072         return 0;
2073 }
2074
2075 RESULT eDVBServicePlay::stopTimeshift()
2076 {
2077         if (!m_timeshift_enabled)
2078                 return -1;
2079         
2080         switchToLive();
2081         
2082         m_timeshift_enabled = 0;
2083         
2084         m_record->stop();
2085         m_record = 0;
2086         
2087         close(m_timeshift_fd);
2088         eDebug("remove timeshift file");
2089         eBackgroundFileEraser::getInstance()->erase(m_timeshift_file.c_str());
2090         
2091         return 0;
2092 }
2093
2094 int eDVBServicePlay::isTimeshiftActive()
2095 {
2096         return m_timeshift_enabled && m_timeshift_active;
2097 }
2098
2099 RESULT eDVBServicePlay::activateTimeshift()
2100 {
2101         if (!m_timeshift_enabled)
2102                 return -1;
2103         
2104         if (!m_timeshift_active)
2105         {
2106                 switchToTimeshift();
2107                 return 0;
2108         }
2109         
2110         return -2;
2111 }
2112
2113 PyObject *eDVBServicePlay::getCutList()
2114 {
2115         ePyObject list = PyList_New(0);
2116         
2117         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2118         {
2119                 ePyObject tuple = PyTuple_New(2);
2120                 PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
2121                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
2122                 PyList_Append(list, tuple);
2123                 Py_DECREF(tuple);
2124         }
2125         
2126         return list;
2127 }
2128
2129 void eDVBServicePlay::setCutList(ePyObject list)
2130 {
2131         if (!PyList_Check(list))
2132                 return;
2133         int size = PyList_Size(list);
2134         int i;
2135         
2136         m_cue_entries.clear();
2137         
2138         for (i=0; i<size; ++i)
2139         {
2140                 ePyObject tuple = PyList_GET_ITEM(list, i);
2141                 if (!PyTuple_Check(tuple))
2142                 {
2143                         eDebug("non-tuple in cutlist");
2144                         continue;
2145                 }
2146                 if (PyTuple_Size(tuple) != 2)
2147                 {
2148                         eDebug("cutlist entries need to be a 2-tuple");
2149                         continue;
2150                 }
2151                 ePyObject ppts = PyTuple_GET_ITEM(tuple, 0), ptype = PyTuple_GET_ITEM(tuple, 1);
2152                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
2153                 {
2154                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
2155                         continue;
2156                 }
2157                 pts_t pts = PyLong_AsLongLong(ppts);
2158                 int type = PyInt_AsLong(ptype);
2159                 m_cue_entries.insert(cueEntry(pts, type));
2160                 eDebug("adding %08llx, %d", pts, type);
2161         }
2162         m_cuesheet_changed = 1;
2163         
2164         cutlistToCuesheet();
2165         m_event((iPlayableService*)this, evCuesheetChanged);
2166 }
2167
2168 void eDVBServicePlay::setCutListEnable(int enable)
2169 {
2170         m_cutlist_enabled = enable;
2171         cutlistToCuesheet();
2172 }
2173
2174 void eDVBServicePlay::updateTimeshiftPids()
2175 {
2176         if (!m_record)
2177                 return;
2178         
2179         eDVBServicePMTHandler::program program;
2180         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2181
2182         if (h.getProgramInfo(program))
2183                 return;
2184         else
2185         {
2186                 std::set<int> pids_to_record;
2187                 pids_to_record.insert(0); // PAT
2188                 if (program.pmtPid != -1)
2189                         pids_to_record.insert(program.pmtPid); // PMT
2190
2191                 if (program.textPid != -1)
2192                         pids_to_record.insert(program.textPid); // Videotext
2193
2194                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2195                         i(program.videoStreams.begin()); 
2196                         i != program.videoStreams.end(); ++i)
2197                         pids_to_record.insert(i->pid);
2198
2199                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2200                         i(program.audioStreams.begin()); 
2201                         i != program.audioStreams.end(); ++i)
2202                                 pids_to_record.insert(i->pid);
2203
2204                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::const_iterator
2205                         i(program.subtitleStreams.begin());
2206                         i != program.subtitleStreams.end(); ++i)
2207                                 pids_to_record.insert(i->pid);
2208
2209                 std::set<int> new_pids, obsolete_pids;
2210                 
2211                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
2212                                 m_pids_active.begin(), m_pids_active.end(),
2213                                 std::inserter(new_pids, new_pids.begin()));
2214                 
2215                 std::set_difference(
2216                                 m_pids_active.begin(), m_pids_active.end(),
2217                                 pids_to_record.begin(), pids_to_record.end(), 
2218                                 std::inserter(new_pids, new_pids.begin())
2219                                 );
2220
2221                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
2222                         m_record->addPID(*i);
2223
2224                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
2225                         m_record->removePID(*i);
2226         }
2227 }
2228
2229 void eDVBServicePlay::switchToLive()
2230 {
2231         if (!m_timeshift_active)
2232                 return;
2233         
2234         eDebug("SwitchToLive");
2235         
2236         m_cue = 0;
2237         m_decoder = 0;
2238         m_decode_demux = 0;
2239         m_teletext_parser = 0;
2240         m_rds_decoder = 0;
2241         m_subtitle_parser = 0;
2242         m_new_dvb_subtitle_page_connection = 0;
2243         m_new_subtitle_page_connection = 0;
2244         m_rds_decoder_event_connection = 0;
2245         m_video_event_connection = 0;
2246         m_is_paused = m_skipmode = m_fastforward = m_slowmotion = 0; /* not supported in live mode */
2247
2248                 /* free the timeshift service handler, we need the resources */
2249         m_service_handler_timeshift.free();
2250         m_timeshift_active = 0;
2251         m_timeshift_changed = 1;
2252
2253         m_event((iPlayableService*)this, evSeekableStatusChanged);
2254
2255         updateDecoder();
2256 }
2257
2258 void eDVBServicePlay::switchToTimeshift()
2259 {
2260         if (m_timeshift_active)
2261                 return;
2262
2263         m_decode_demux = 0;
2264         m_decoder = 0;
2265         m_teletext_parser = 0;
2266         m_rds_decoder = 0;
2267         m_subtitle_parser = 0;
2268         m_new_subtitle_page_connection = 0;
2269         m_new_dvb_subtitle_page_connection = 0;
2270         m_rds_decoder_event_connection = 0;
2271         m_video_event_connection = 0;
2272
2273         m_timeshift_active = 1;
2274         m_timeshift_changed = 1;
2275
2276         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
2277         r.path = m_timeshift_file;
2278
2279         m_cue = new eCueSheet();
2280         m_service_handler_timeshift.tune(r, 1, m_cue, 0, m_dvb_service); /* use the decoder demux for everything */
2281
2282         eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now.");
2283         pause();
2284         updateDecoder(); /* mainly to switch off PCR, and to set pause */
2285         
2286         m_event((iPlayableService*)this, evSeekableStatusChanged);
2287 }
2288
2289 void eDVBServicePlay::updateDecoder()
2290 {
2291         int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1;
2292
2293         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2294
2295         eDVBServicePMTHandler::program program;
2296         if (h.getProgramInfo(program))
2297                 eDebug("getting program info failed.");
2298         else
2299         {
2300                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
2301                 if (!program.videoStreams.empty())
2302                 {
2303                         eDebugNoNewLine(" (");
2304                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
2305                                 i(program.videoStreams.begin());
2306                                 i != program.videoStreams.end(); ++i)
2307                         {
2308                                 if (vpid == -1)
2309                                 {
2310                                         vpid = i->pid;
2311                                         vpidtype = i->type;
2312                                 }
2313                                 if (i != program.videoStreams.begin())
2314                                         eDebugNoNewLine(", ");
2315                                 eDebugNoNewLine("%04x", i->pid);
2316                         }
2317                         eDebugNoNewLine(")");
2318                 }
2319                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
2320                 if (!program.audioStreams.empty())
2321                 {
2322                         eDebugNoNewLine(" (");
2323                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
2324                                 i(program.audioStreams.begin());
2325                                 i != program.audioStreams.end(); ++i)
2326                         {
2327                                 if (i != program.audioStreams.begin())
2328                                         eDebugNoNewLine(", ");
2329                                 eDebugNoNewLine("%04x", i->pid);
2330                         }
2331                         eDebugNoNewLine(")");
2332                 }
2333                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
2334                 pcrpid = program.pcrPid;
2335                 eDebug(", and the text pid is %04x", program.textPid);
2336                 tpid = program.textPid;
2337         }
2338
2339         if (!m_decoder)
2340         {
2341                 h.getDecodeDemux(m_decode_demux);
2342                 if (m_timeshift_changed)
2343                         m_decoder = 0;
2344                 if (m_decode_demux)
2345                 {
2346                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
2347                         if (m_decoder)
2348                                 m_decoder->connectVideoEvent(slot(*this, &eDVBServicePlay::video_event), m_video_event_connection);
2349                         if (m_is_primary)
2350                         {
2351                                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
2352                                 m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection);
2353                                 m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux);
2354                                 m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection);
2355                                 if (m_timeshift_changed)
2356                                 {
2357                                         ePyObject subs = getCachedSubtitle();
2358                                         if (subs != Py_None)
2359                                         {
2360                                                 int type = PyInt_AsLong(PyTuple_GET_ITEM(subs, 0)),
2361                                                     pid = PyInt_AsLong(PyTuple_GET_ITEM(subs, 1)),
2362                                                     comp_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 2)), // ttx page
2363                                                     anc_page = PyInt_AsLong(PyTuple_GET_ITEM(subs, 3)); // ttx magazine
2364                                                 if (type == 0) // dvb
2365                                                         m_subtitle_parser->start(pid, comp_page, anc_page);
2366                                                 else if (type == 1) // ttx
2367                                                         m_teletext_parser->setPageAndMagazine(comp_page, anc_page);
2368                                         }
2369                                         Py_DECREF(subs);
2370                                 }
2371                         }
2372                         m_decoder->play(); /* pids will be set later */
2373                 }
2374                 if (m_cue)
2375                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
2376                 m_decoder->play(); /* pids will be set later. */
2377         }
2378
2379         m_timeshift_changed = 0;
2380
2381         if (m_decoder)
2382         {
2383                 if (m_dvb_service)
2384                 {
2385                         achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL);
2386                         ac3_delay = m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2387                         pcm_delay = m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2388                 }
2389                 else // subservice
2390                 {
2391                         eServiceReferenceDVB ref;
2392                         m_service_handler.getServiceReference(ref);
2393                         eServiceReferenceDVB parent = ref.getParentServiceReference();
2394                         if (!parent)
2395                                 parent = ref;
2396                         if (parent)
2397                         {
2398                                 ePtr<eDVBResourceManager> res_mgr;
2399                                 if (!eDVBResourceManager::getInstance(res_mgr))
2400                                 {
2401                                         ePtr<iDVBChannelList> db;
2402                                         if (!res_mgr->getChannelList(db))
2403                                         {
2404                                                 ePtr<eDVBService> origService;
2405                                                 if (!db->getService(parent, origService))
2406                                                 {
2407                                                         ac3_delay = origService->getCacheEntry(eDVBService::cAC3DELAY);
2408                                                         pcm_delay = origService->getCacheEntry(eDVBService::cPCMDELAY);
2409                                                 }
2410                                         }
2411                                 }
2412                         }
2413                 }
2414
2415                 setAC3Delay(ac3_delay == -1 ? 0 : ac3_delay);
2416                 setPCMDelay(pcm_delay == -1 ? 0 : pcm_delay);
2417
2418                 m_decoder->setVideoPID(vpid, vpidtype);
2419                 selectAudioStream();
2420
2421                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
2422                         m_decoder->setSyncPCR(pcrpid);
2423                 else
2424                         m_decoder->setSyncPCR(-1);
2425
2426                 if (m_is_primary)
2427                 {
2428                         m_decoder->setTextPID(tpid);
2429                         m_teletext_parser->start(program.textPid);
2430                 }
2431
2432                 if (vpid > 0 && vpid < 0x2000)
2433                         ;
2434                 else
2435                 {
2436                         std::string radio_pic;
2437                         if (!ePythonConfigQuery::getConfigValue("config.misc.radiopic", radio_pic))
2438                                 m_decoder->setRadioPic(radio_pic);
2439                 }
2440
2441                 m_decoder->set();
2442                 m_decoder->setAudioChannel(achannel);
2443
2444                 /* don't worry about non-existing services, nor pvr services */
2445                 if (m_dvb_service)
2446                 {
2447                                 /* (audio pid will be set in selectAudioTrack */
2448                         m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid);
2449                         m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype == eDVBVideo::MPEG2 ? -1 : vpidtype);
2450                         m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid);
2451                         m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid);
2452                 }
2453         }
2454         m_have_video_pid = (vpid > 0 && vpid < 0x2000);
2455 }
2456
2457 void eDVBServicePlay::loadCuesheet()
2458 {
2459         std::string filename = m_reference.path + ".cuts";
2460         
2461         m_cue_entries.clear();
2462
2463         FILE *f = fopen(filename.c_str(), "rb");
2464
2465         if (f)
2466         {
2467                 eDebug("loading cuts..");
2468                 while (1)
2469                 {
2470                         unsigned long long where;
2471                         unsigned int what;
2472                         
2473                         if (!fread(&where, sizeof(where), 1, f))
2474                                 break;
2475                         if (!fread(&what, sizeof(what), 1, f))
2476                                 break;
2477                         
2478 #if BYTE_ORDER == LITTLE_ENDIAN
2479                         where = bswap_64(where);
2480 #endif
2481                         what = ntohl(what);
2482                         
2483                         if (what > 3)
2484                                 break;
2485                         
2486                         m_cue_entries.insert(cueEntry(where, what));
2487                 }
2488                 fclose(f);
2489                 eDebug("%d entries", m_cue_entries.size());
2490         } else
2491                 eDebug("cutfile not found!");
2492         
2493         m_cuesheet_changed = 0;
2494         cutlistToCuesheet();
2495         m_event((iPlayableService*)this, evCuesheetChanged);
2496 }
2497
2498 void eDVBServicePlay::saveCuesheet()
2499 {
2500         std::string filename = m_reference.path + ".cuts";
2501         
2502         FILE *f = fopen(filename.c_str(), "wb");
2503
2504         if (f)
2505         {
2506                 unsigned long long where;
2507                 int what;
2508
2509                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
2510                 {
2511 #if BYTE_ORDER == BIG_ENDIAN
2512                         where = i->where;
2513 #else
2514                         where = bswap_64(i->where);
2515 #endif
2516                         what = htonl(i->what);
2517                         fwrite(&where, sizeof(where), 1, f);
2518                         fwrite(&what, sizeof(what), 1, f);
2519                         
2520                 }
2521                 fclose(f);
2522         }
2523         
2524         m_cuesheet_changed = 0;
2525 }
2526
2527 void eDVBServicePlay::cutlistToCuesheet()
2528 {
2529         if (!m_cue)
2530         {
2531                 eDebug("no cue sheet");
2532                 return;
2533         }       
2534         m_cue->clear();
2535         
2536         if (!m_cutlist_enabled)
2537         {
2538                 m_cue->commitSpans();
2539                 eDebug("cutlists were disabled");
2540                 return;
2541         }
2542
2543         pts_t in = 0, out = 0, length = 0;
2544         
2545         getLength(length);
2546                 
2547         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
2548         
2549         int have_any_span = 0;
2550         
2551         while (1)
2552         {
2553                 if (i == m_cue_entries.end())
2554                 {
2555                         if (!have_any_span)
2556                                 break;
2557                         out = length;
2558                 } else {
2559                         if (i->what == 0) /* in */
2560                         {
2561                                 in = i++->where;
2562                                 continue;
2563                         } else if (i->what == 1) /* out */
2564                                 out = i++->where;
2565                         else /* mark (2) or last play position (3) */
2566                         {
2567                                 i++;
2568                                 continue;
2569                         }
2570                 }
2571                 
2572                 if (in < 0)
2573                         in = 0;
2574                 if (out < 0)
2575                         out = 0;
2576                 if (in > length)
2577                         in = length;
2578                 if (out > length)
2579                         out = length;
2580                 
2581                 if (in < out)
2582                 {
2583                         have_any_span = 1;
2584                         m_cue->addSourceSpan(in, out);
2585                 }
2586                 
2587                 in = length;
2588                 
2589                 if (i == m_cue_entries.end())
2590                         break;
2591         }
2592         m_cue->commitSpans();
2593 }
2594
2595 RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, ePyObject tuple)
2596 {
2597         if (m_subtitle_widget)
2598                 disableSubtitles(parent);
2599
2600         ePyObject entry;
2601         int tuplesize = PyTuple_Size(tuple);
2602         int type = 0;
2603
2604         if (!PyTuple_Check(tuple))
2605                 goto error_out;
2606
2607         if (tuplesize < 1)
2608                 goto error_out;
2609
2610         entry = PyTuple_GET_ITEM(tuple, 0);
2611
2612         if (!PyInt_Check(entry))
2613                 goto error_out;
2614
2615         type = PyInt_AsLong(entry);
2616
2617         if (type == 1)  // teletext subtitles
2618         {
2619                 int page, magazine, pid;
2620                 if (tuplesize < 4)
2621                         goto error_out;
2622
2623                 if (!m_teletext_parser)
2624                 {
2625                         eDebug("enable teletext subtitles.. no parser !!!");
2626                         return -1;
2627                 }
2628
2629                 entry = PyTuple_GET_ITEM(tuple, 1);
2630                 if (!PyInt_Check(entry))
2631                         goto error_out;
2632                 pid = PyInt_AsLong(entry);
2633
2634                 entry = PyTuple_GET_ITEM(tuple, 2);
2635                 if (!PyInt_Check(entry))
2636                         goto error_out;
2637                 page = PyInt_AsLong(entry);
2638
2639                 entry = PyTuple_GET_ITEM(tuple, 3);
2640                 if (!PyInt_Check(entry))
2641                         goto error_out;
2642                 magazine = PyInt_AsLong(entry);
2643
2644                 m_subtitle_widget = new eSubtitleWidget(parent);
2645                 m_subtitle_widget->resize(parent->size()); /* full size */
2646                 m_teletext_parser->setPageAndMagazine(page, magazine);
2647                 if (m_dvb_service)
2648                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE,((pid&0xFFFF)<<16)|((page&0xFF)<<8)|(magazine&0xFF));
2649         }
2650         else if (type == 0)
2651         {
2652                 int pid = 0, composition_page_id = 0, ancillary_page_id = 0;
2653                 if (!m_subtitle_parser)
2654                 {
2655                         eDebug("enable dvb subtitles.. no parser !!!");
2656                         return -1;
2657                 }
2658                 if (tuplesize < 4)
2659                         goto error_out;
2660
2661                 entry = PyTuple_GET_ITEM(tuple, 1);
2662                 if (!PyInt_Check(entry))
2663                         goto error_out;
2664                 pid = PyInt_AsLong(entry);
2665
2666                 entry = PyTuple_GET_ITEM(tuple, 2);
2667                 if (!PyInt_Check(entry))
2668                         goto error_out;
2669                 composition_page_id = PyInt_AsLong(entry);
2670
2671                 entry = PyTuple_GET_ITEM(tuple, 3);
2672                 if (!PyInt_Check(entry))
2673                         goto error_out;
2674                 ancillary_page_id = PyInt_AsLong(entry);
2675
2676                 m_subtitle_widget = new eSubtitleWidget(parent);
2677                 m_subtitle_widget->resize(parent->size()); /* full size */
2678                 m_subtitle_parser->start(pid, composition_page_id, ancillary_page_id);
2679                 if (m_dvb_service)
2680                         m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, ((pid&0xFFFF)<<16)|((composition_page_id&0xFF)<<8)|(ancillary_page_id&0xFF));
2681         }
2682         else
2683                 goto error_out;
2684         return 0;
2685 error_out:
2686         eDebug("enableSubtitles needs a tuple as 2nd argument!\n"
2687                 "for teletext subtitles (0, pid, teletext_page, teletext_magazine)\n"
2688                 "for dvb subtitles (1, pid, composition_page_id, ancillary_page_id)");
2689         return -1;
2690 }
2691
2692 RESULT eDVBServicePlay::disableSubtitles(eWidget *parent)
2693 {
2694         delete m_subtitle_widget;
2695         m_subtitle_widget = 0;
2696         if (m_subtitle_parser)
2697         {
2698                 m_subtitle_parser->stop();
2699                 m_dvb_subtitle_pages.clear();
2700         }
2701         if (m_teletext_parser)
2702         {
2703                 m_teletext_parser->setPageAndMagazine(-1, -1);
2704                 m_subtitle_pages.clear();
2705         }
2706         if (m_dvb_service)
2707                 m_dvb_service->setCacheEntry(eDVBService::cSUBTITLE, -1);
2708         return 0;
2709 }
2710
2711 PyObject *eDVBServicePlay::getCachedSubtitle()
2712 {
2713         if (m_dvb_service)
2714         {
2715                 int tmp = m_dvb_service->getCacheEntry(eDVBService::cSUBTITLE);
2716                 if (tmp != -1)
2717                 {
2718                         unsigned int data = (unsigned int)tmp;
2719                         int pid = (data&0xFFFF0000)>>16;
2720                         ePyObject tuple = PyTuple_New(4);
2721                         eDVBServicePMTHandler::program program;
2722                         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2723                         if (!h.getProgramInfo(program))
2724                         {
2725                                 if (program.textPid==pid) // teletext
2726                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1)); // type teletext
2727                                 else
2728                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0)); // type dvb
2729                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(pid)); // pid
2730                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong((data&0xFF00)>>8)); // composition_page / page
2731                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(data&0xFF)); // ancillary_page / magazine
2732                                 return tuple;
2733                         }
2734                 }
2735         }
2736         Py_RETURN_NONE;
2737 }
2738
2739 PyObject *eDVBServicePlay::getSubtitleList()
2740 {
2741         if (!m_teletext_parser)
2742                 Py_RETURN_NONE;
2743         
2744         ePyObject l = PyList_New(0);
2745         std::set<int> added_ttx_pages;
2746
2747         std::set<eDVBServicePMTHandler::subtitleStream> &subs =
2748                 m_teletext_parser->m_found_subtitle_pages;
2749
2750         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
2751         eDVBServicePMTHandler::program program;
2752         if (h.getProgramInfo(program))
2753                 eDebug("getting program info failed.");
2754         else
2755         {
2756                 for (std::vector<eDVBServicePMTHandler::subtitleStream>::iterator it(program.subtitleStreams.begin());
2757                         it != program.subtitleStreams.end(); ++it)
2758                 {
2759                         switch(it->subtitling_type)
2760                         {
2761                                 case 0x01: // ebu teletext subtitles
2762                                 {
2763                                         int page_number = it->teletext_page_number & 0xFF;
2764                                         int magazine_number = it->teletext_magazine_number & 7;
2765                                         int hash = magazine_number << 8 | page_number;
2766                                         if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2767                                         {
2768                                                 ePyObject tuple = PyTuple_New(5);
2769                                                 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2770                                                 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2771                                                 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2772                                                 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2773                                                 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2774                                                 PyList_Append(l, tuple);
2775                                                 Py_DECREF(tuple);
2776                                                 added_ttx_pages.insert(hash);
2777                                         }
2778                                         break;
2779                                 }
2780                                 case 0x10 ... 0x13:
2781                                 case 0x20 ... 0x23: // dvb subtitles
2782                                 {
2783                                         ePyObject tuple = PyTuple_New(5);
2784                                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
2785                                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2786                                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->composition_page_id));
2787                                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->ancillary_page_id));
2788                                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->language_code.c_str()));
2789                                         PyList_Insert(l, 0, tuple);
2790                                         Py_DECREF(tuple);
2791                                         break;
2792                                 }
2793                         }
2794                 }
2795         }
2796
2797         for (std::set<eDVBServicePMTHandler::subtitleStream>::iterator it(subs.begin());
2798                 it != subs.end(); ++it)
2799         {
2800                 int page_number = it->teletext_page_number & 0xFF;
2801                 int magazine_number = it->teletext_magazine_number & 7;
2802                 int hash = magazine_number << 8 | page_number;
2803                 if (added_ttx_pages.find(hash) == added_ttx_pages.end())
2804                 {
2805                         ePyObject tuple = PyTuple_New(5);
2806                         PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
2807                         PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->pid));
2808                         PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(page_number));
2809                         PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(magazine_number));
2810                         PyTuple_SET_ITEM(tuple, 4, PyString_FromString("und"));  // undetermined
2811                         PyList_Append(l, tuple);
2812                         Py_DECREF(tuple);
2813                 }
2814         }
2815
2816         return l;
2817 }
2818
2819 void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page)
2820 {
2821         if (m_subtitle_widget)
2822         {
2823                 pts_t pos = 0;
2824                 if (m_decoder)
2825                         m_decoder->getPTS(0, pos);
2826                 eDebug("got new subtitle page %lld %lld %d", pos, page.m_pts, page.m_have_pts);
2827                 m_subtitle_pages.push_back(page);
2828                 checkSubtitleTiming();
2829         }
2830 }
2831
2832 void eDVBServicePlay::checkSubtitleTiming()
2833 {
2834         eDebug("checkSubtitleTiming");
2835         if (!m_subtitle_widget)
2836                 return;
2837         while (1)
2838         {
2839                 enum { TELETEXT, DVB } type;
2840                 eDVBTeletextSubtitlePage page;
2841                 eDVBSubtitlePage dvb_page;
2842                 pts_t show_time;
2843                 if (!m_subtitle_pages.empty())
2844                 {
2845                         page = m_subtitle_pages.front();
2846                         type = TELETEXT;
2847                         show_time = page.m_pts;
2848                 }
2849                 else if (!m_dvb_subtitle_pages.empty())
2850                 {
2851                         dvb_page = m_dvb_subtitle_pages.front();
2852                         type = DVB;
2853                         show_time = dvb_page.m_show_time;
2854                 }
2855                 else
2856                         return;
2857         
2858                 pts_t pos = 0;
2859         
2860                 if (m_decoder)
2861                         m_decoder->getPTS(0, pos);
2862
2863                 eDebug("%lld %lld", pos, show_time);
2864                 int diff = show_time - pos;
2865                 if (type == TELETEXT && !page.m_have_pts)
2866                 {
2867                         eDebug("ttx subtitle page without pts... immediate show");
2868                         diff = 0;
2869                 }
2870                 if (diff < 0)
2871                 {
2872                         eDebug("[late (%d ms)]", -diff / 90);
2873                         diff = 0;
2874                 }
2875                 if (abs(diff) > 1800000)
2876                 {
2877                         eDebug("[invalid]... immediate show!");
2878                         diff = 0;
2879                 }
2880                 if ((diff/90)<20)
2881                 {
2882                         if (type == TELETEXT)
2883                         {
2884                                 eDebug("display teletext subtitle page %lld", show_time);
2885                                 m_subtitle_widget->setPage(page);
2886                                 m_subtitle_pages.pop_front();
2887                         }
2888                         else
2889                         {
2890                                 eDebug("display dvb subtitle Page %lld", show_time);
2891                                 m_subtitle_widget->setPage(dvb_page);
2892                                 m_dvb_subtitle_pages.pop_front();
2893                         }
2894                 } else
2895                 {
2896                         eDebug("start subtitle delay %d", diff / 90);
2897                         m_subtitle_sync_timer->start(diff / 90, 1);
2898                         break;
2899                 }
2900         }
2901 }
2902
2903 void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p)
2904 {
2905         if (m_subtitle_widget)
2906         {
2907                 pts_t pos = 0;
2908                 if (m_decoder)
2909                         m_decoder->getPTS(0, pos);
2910                 eDebug("got new subtitle page %lld %lld", pos, p.m_show_time);
2911                 m_dvb_subtitle_pages.push_back(p);
2912                 checkSubtitleTiming();
2913         }
2914 }
2915
2916 int eDVBServicePlay::getAC3Delay()
2917 {
2918         if (m_dvb_service)
2919                 return m_dvb_service->getCacheEntry(eDVBService::cAC3DELAY);
2920         else if (m_decoder)
2921                 return m_decoder->getAC3Delay();
2922         else
2923                 return 0;
2924 }
2925
2926 int eDVBServicePlay::getPCMDelay()
2927 {
2928         if (m_dvb_service)
2929                 return m_dvb_service->getCacheEntry(eDVBService::cPCMDELAY);
2930         else if (m_decoder)
2931                 return m_decoder->getPCMDelay();
2932         else
2933                 return 0;
2934 }
2935
2936 void eDVBServicePlay::setAC3Delay(int delay)
2937 {
2938         if (m_dvb_service)
2939                 m_dvb_service->setCacheEntry(eDVBService::cAC3DELAY, delay ? delay : -1);
2940         if (m_decoder) {
2941                 std::string config_delay;
2942                 int config_delay_int = 0;
2943                 if(ePythonConfigQuery::getConfigValue("config.av.generalAC3delay", config_delay) == 0)
2944                         config_delay_int = atoi(config_delay.c_str());
2945                 m_decoder->setAC3Delay(delay + config_delay_int);
2946         }
2947 }
2948
2949 void eDVBServicePlay::setPCMDelay(int delay)
2950 {
2951         if (m_dvb_service)
2952                 m_dvb_service->setCacheEntry(eDVBService::cPCMDELAY, delay ? delay : -1);
2953         if (m_decoder) {
2954                 std::string config_delay;
2955                 int config_delay_int = 0;
2956                 if(ePythonConfigQuery::getConfigValue("config.av.generalPCMdelay", config_delay) == 0)
2957                         config_delay_int = atoi(config_delay.c_str());
2958                 else
2959                         config_delay_int = 0;
2960                 m_decoder->setPCMDelay(delay + config_delay_int);
2961         }
2962 }
2963
2964 void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
2965 {
2966         switch(event.type) {
2967                 case iTSMPEGDecoder::videoEvent::eventSizeChanged:
2968                         m_event((iPlayableService*)this, evVideoSizeChanged);
2969                         break;
2970                 case iTSMPEGDecoder::videoEvent::eventFrameRateChanged:
2971                         m_event((iPlayableService*)this, evVideoFramerateChanged);
2972                         break;
2973                 case iTSMPEGDecoder::videoEvent::eventProgressiveChanged:
2974                         m_event((iPlayableService*)this, evVideoProgressiveChanged);
2975                         break;
2976                 default:
2977                         break;
2978         }
2979 }
2980
2981 RESULT eDVBServicePlay::stream(ePtr<iStreamableService> &ptr)
2982 {
2983         ptr = this;
2984         return 0;
2985 }
2986
2987 PyObject *eDVBServicePlay::getStreamingData()
2988 {
2989         eDVBServicePMTHandler::program program;
2990         if (m_service_handler.getProgramInfo(program))
2991         {
2992                 Py_RETURN_NONE;
2993         }
2994
2995         ePyObject r = program.createPythonObject();
2996         ePtr<iDVBDemux> demux;
2997         if (!m_service_handler.getDataDemux(demux))
2998         {
2999                 uint8_t demux_id;
3000                 if (!demux->getCADemuxID(demux_id))
3001                         PutToDict(r, "demux", demux_id);
3002         }
3003
3004         return r;
3005 }
3006
3007
3008 DEFINE_REF(eDVBServicePlay)
3009
3010 PyObject *eDVBService::getInfoObject(const eServiceReference &ref, int w)
3011 {
3012         switch (w)
3013         {
3014         case iServiceInformation::sTransponderData:
3015                 return eStaticServiceDVBInformation().getInfoObject(ref, w);
3016         default:
3017                 break;
3018         }
3019         return iStaticServiceInformation::getInfoObject(ref, w);
3020 }
3021
3022 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");