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