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