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