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