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