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