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