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