e9aeb8a9545758998eff1e0fadca0e5f52c4db34
[enigma2.git] / lib / service / servicedvb.cpp
1 #include <lib/base/eerror.h>
2 #include <lib/base/object.h>
3 #include <string>
4 #include <lib/service/servicedvb.h>
5 #include <lib/service/service.h>
6 #include <lib/base/init_num.h>
7 #include <lib/base/init.h>
8 #include <lib/base/nconfig.h> // access to python config
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
20 #include <sys/vfs.h>
21
22 #include <byteswap.h>
23 #include <netinet/in.h>
24
25 #include <dvbsi++/event_information_section.h>
26
27 #ifndef BYTE_ORDER
28 #error no byte order defined!
29 #endif
30
31 #define TSPATH "/media/hdd"
32
33 class eStaticServiceDVBInformation: public iStaticServiceInformation
34 {
35         DECLARE_REF(eStaticServiceDVBInformation);
36 public:
37         RESULT getName(const eServiceReference &ref, std::string &name);
38         int getLength(const eServiceReference &ref);
39 };
40
41 DEFINE_REF(eStaticServiceDVBInformation);
42
43 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
44 {
45         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
46         if ( !ref.name.empty() )
47         {
48                 if (service.getParentTransportStreamID().get()) // linkage subservice
49                 {
50                         ePtr<iServiceHandler> service_center;
51                         if (!eServiceCenter::getInstance(service_center))
52                         {
53                                 eServiceReferenceDVB parent = service;
54                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
55                                 parent.setServiceID( service.getParentServiceID() );
56                                 parent.setParentTransportStreamID(eTransportStreamID(0));
57                                 parent.setParentServiceID(eServiceID(0));
58                                 parent.name="";
59                                 ePtr<iStaticServiceInformation> service_info;
60                                 if (!service_center->info(parent, service_info))
61                                 {
62                                         if (!service_info->getName(parent, name))
63                                         {
64                                                 // just show short name
65                                                 unsigned int pos = name.find("\xc2\x86");
66                                                 if ( pos != std::string::npos )
67                                                         name.erase(0, pos+2);
68                                                 pos = name.find("\xc2\x87");
69                                                 if ( pos != std::string::npos )
70                                                         name.erase(pos);
71                                                 name+=" - ";
72                                         }
73                                 }
74                         }
75                 }
76                 else
77                         name="";
78                 name += ref.name;
79                 return 0;
80         }
81         else
82                 return -1;
83 }
84
85 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
86 {
87         return -1;
88 }
89
90 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
91 {
92         DECLARE_REF(eStaticServiceDVBBouquetInformation);
93 public:
94         RESULT getName(const eServiceReference &ref, std::string &name);
95         int getLength(const eServiceReference &ref);
96 };
97
98 DEFINE_REF(eStaticServiceDVBBouquetInformation);
99
100 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
101 {
102         ePtr<iDVBChannelList> db;
103         ePtr<eDVBResourceManager> res;
104
105         int err;
106         if ((err = eDVBResourceManager::getInstance(res)) != 0)
107         {
108                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
109                 return err;
110         }
111         if ((err = res->getChannelList(db)) != 0)
112         {
113                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
114                 return err;
115         }
116
117         eBouquet *bouquet=0;
118         if ((err = db->getBouquet(ref, bouquet)) != 0)
119         {
120                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
121                 return -1;
122         }
123
124         if ( bouquet && bouquet->m_bouquet_name.length() )
125         {
126                 name = bouquet->m_bouquet_name;
127                 return 0;
128         }
129         else
130                 return -1;
131 }
132
133 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
134 {
135         return -1;
136 }
137
138 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
139 {
140         DECLARE_REF(eStaticServiceDVBPVRInformation);
141         eServiceReference m_ref;
142         eDVBMetaParser m_parser;
143 public:
144         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
145         RESULT getName(const eServiceReference &ref, std::string &name);
146         int getLength(const eServiceReference &ref);
147         
148         int getInfo(const eServiceReference &ref, int w);
149         std::string getInfoString(const eServiceReference &ref,int w);
150 };
151
152 DEFINE_REF(eStaticServiceDVBPVRInformation);
153
154 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
155 {
156         m_ref = ref;
157         m_parser.parseFile(ref.path);
158 }
159
160 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
161 {
162         ASSERT(ref == m_ref);
163         name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
164         return 0;
165 }
166
167 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
168 {
169         ASSERT(ref == m_ref);
170         
171         eDVBTSTools tstools;
172         
173         if (tstools.openFile(ref.path.c_str()))
174                 return 0;
175
176         pts_t len;
177         if (tstools.calcLen(len))
178                 return 0;
179
180         return len / 90000;
181 }
182
183 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
184 {
185         switch (w)
186         {
187         case iServiceInformation::sDescription:
188                 return iServiceInformation::resIsString;
189         case iServiceInformation::sServiceref:
190                 return iServiceInformation::resIsString;
191         case iServiceInformation::sTimeCreate:
192                 if (m_parser.m_time_create)
193                         return m_parser.m_time_create;
194                 else
195                         return iServiceInformation::resNA;
196         default:
197                 return iServiceInformation::resNA;
198         }
199 }
200
201 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
202 {
203         switch (w)
204         {
205         case iServiceInformation::sDescription:
206                 return m_parser.m_description;
207         case iServiceInformation::sServiceref:
208                 return m_parser.m_ref.toString();
209         default:
210                 return "";
211         }
212 }
213
214 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
215 {
216         DECLARE_REF(eDVBPVRServiceOfflineOperations);
217         eServiceReferenceDVB m_ref;
218 public:
219         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
220         
221         RESULT deleteFromDisk(int simulate);
222         RESULT getListOfFilenames(std::list<std::string> &);
223 };
224
225 DEFINE_REF(eDVBPVRServiceOfflineOperations);
226
227 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
228 {
229 }
230
231 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
232 {
233         if (simulate)
234                 return 0;
235         else
236         {
237                 std::list<std::string> res;
238                 if (getListOfFilenames(res))
239                         return -1;
240                 
241                 eBackgroundFileEraser *eraser = eBackgroundFileEraser::getInstance();
242                 if (!eraser)
243                         eDebug("FATAL !! can't get background file eraser");
244                 
245                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
246                 {
247                         eDebug("Removing %s...", i->c_str());
248                         if (eraser)
249                                 eraser->erase(i->c_str());
250                         else
251                                 ::unlink(i->c_str());
252                 }
253                 
254                 return 0;
255         }
256 }
257
258 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
259 {
260         res.clear();
261         res.push_back(m_ref.path);
262
263 // handling for old splitted recordings (enigma 1)
264         char buf[255];
265         int slice=1;
266         while(true)
267         {
268                 snprintf(buf, 255, "%s.%03d", m_ref.path.c_str(), slice++);
269                 struct stat s;
270                 if (stat(buf, &s) < 0)
271                         break;
272                 res.push_back(buf);
273         }       
274
275         res.push_back(m_ref.path + ".meta");
276         res.push_back(m_ref.path + ".ap");
277         res.push_back(m_ref.path + ".cuts");
278         std::string tmp = m_ref.path;
279         tmp.erase(m_ref.path.length()-3);
280         res.push_back(tmp + ".eit");
281         return 0;
282 }
283
284 DEFINE_REF(eServiceFactoryDVB)
285
286 eServiceFactoryDVB::eServiceFactoryDVB()
287 {
288         ePtr<eServiceCenter> sc;
289         
290         eServiceCenter::getPrivInstance(sc);
291         if (sc)
292                 sc->addServiceFactory(eServiceFactoryDVB::id, this);
293 }
294
295 eServiceFactoryDVB::~eServiceFactoryDVB()
296 {
297         ePtr<eServiceCenter> sc;
298         
299         eServiceCenter::getPrivInstance(sc);
300         if (sc)
301                 sc->removeServiceFactory(eServiceFactoryDVB::id);
302 }
303
304 DEFINE_REF(eDVBServiceList);
305
306 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
307 {
308 }
309
310 eDVBServiceList::~eDVBServiceList()
311 {
312 }
313
314 RESULT eDVBServiceList::startQuery()
315 {
316         ePtr<iDVBChannelList> db;
317         ePtr<eDVBResourceManager> res;
318         
319         int err;
320         if ((err = eDVBResourceManager::getInstance(res)) != 0)
321         {
322                 eDebug("no resource manager");
323                 return err;
324         }
325         if ((err = res->getChannelList(db)) != 0)
326         {
327                 eDebug("no channel list");
328                 return err;
329         }
330         
331         ePtr<eDVBChannelQuery> q;
332         
333         if (!m_parent.path.empty())
334         {
335                 eDVBChannelQuery::compile(q, m_parent.path);
336                 if (!q)
337                 {
338                         eDebug("compile query failed");
339                         return err;
340                 }
341         }
342         
343         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
344         {
345                 eDebug("startQuery failed");
346                 return err;
347         }
348
349         return 0;
350 }
351
352 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list, bool sorted)
353 {
354         eServiceReferenceDVB ref;
355         
356         if (!m_query)
357                 return -1;
358         
359         while (!m_query->getNextResult(ref))
360                 list.push_back(ref);
361
362         if (sorted)
363                 list.sort(iListableServiceCompare(this));
364
365         return 0;
366 }
367
368 //   The first argument of this function is a format string to specify the order and
369 //   the content of the returned list
370 //   useable format options are
371 //   R = Service Reference (as swig object .. this is very slow)
372 //   S = Service Reference (as python string object .. same as ref.toString())
373 //   N = Service Name (as python string object)
374 //   when exactly one return value per service is selected in the format string,
375 //   then each value is directly a list entry
376 //   when more than one value is returned per service, then the list is a list of
377 //   python tuples
378 //   unknown format string chars are returned as python None values !
379 PyObject *eDVBServiceList::getContent(const char* format, bool sorted)
380 {
381         PyObject *ret=0;
382         std::list<eServiceReference> tmplist;
383         int retcount=1;
384
385         if (!format || !(retcount=strlen(format)))
386                 format = "R"; // just return service reference swig object ...
387
388         if (!getContent(tmplist, sorted))
389         {
390                 int services=tmplist.size();
391                 ePtr<iStaticServiceInformation> sptr;
392                 eServiceCenterPtr service_center;
393
394                 if (strchr(format, 'N'))
395                         eServiceCenter::getPrivInstance(service_center);
396
397                 ret = PyList_New(services);
398                 std::list<eServiceReference>::iterator it(tmplist.begin());
399
400                 for (int cnt=0; cnt < services; ++cnt)
401                 {
402                         eServiceReference &ref=*it++;
403                         PyObject *tuple = retcount > 1 ? PyTuple_New(retcount) : 0;
404                         for (int i=0; i < retcount; ++i)
405                         {
406                                 PyObject *tmp=0;
407                                 switch(format[i])
408                                 {
409                                 case 'R':  // service reference (swig)object
410                                         tmp = New_eServiceReference(ref);
411                                         break;
412                                 case 'S':  // service reference string
413                                         tmp = PyString_FromString(ref.toString().c_str());
414                                         break;
415                                 case 'N':  // service name
416                                         if (service_center)
417                                         {
418                                                 service_center->info(ref, sptr);
419                                                 if (sptr)
420                                                 {
421                                                         std::string name;
422                                                         sptr->getName(ref, name);
423                                                         if (name.length())
424                                                                 tmp = PyString_FromString(name.c_str());
425                                                 }
426                                         }
427                                         if (!tmp)
428                                                 tmp = PyString_FromString("<n/a>");
429                                         break;
430                                 default:
431                                         if (tuple)
432                                         {
433                                                 tmp = Py_None;
434                                                 Py_INCREF(Py_None);
435                                         }
436                                         break;
437                                 }
438                                 if (tmp)
439                                 {
440                                         if (tuple)
441                                                 PyTuple_SET_ITEM(tuple, i, tmp);
442                                         else
443                                                 PyList_SET_ITEM(ret, cnt, tmp);
444                                 }
445                         }
446                         if (tuple)
447                                 PyList_SET_ITEM(ret, cnt, tuple);
448                 }
449         }
450         return ret ? ret : PyList_New(0);
451 }
452
453 RESULT eDVBServiceList::getNext(eServiceReference &ref)
454 {
455         if (!m_query)
456                 return -1;
457         
458         return m_query->getNextResult((eServiceReferenceDVB&)ref);
459 }
460
461 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
462 {
463         return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
464 }
465
466 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
467 {
468         if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
469         {
470                 ePtr<iDVBChannelList> db;
471                 ePtr<eDVBResourceManager> resm;
472
473                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
474                         return -1;
475
476                 if (db->getBouquet(m_parent, m_bouquet) != 0)
477                         return -1;
478
479                 res = this;
480                 
481                 return 0;
482         }
483         res = 0;
484         return -1;
485 }
486
487 RESULT eDVBServiceList::addService(eServiceReference &ref)
488 {
489         if (!m_bouquet)
490                 return -1;
491         return m_bouquet->addService(ref);
492 }
493
494 RESULT eDVBServiceList::removeService(eServiceReference &ref)
495 {
496         if (!m_bouquet)
497                 return -1;
498         return m_bouquet->removeService(ref);
499 }
500
501 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
502 {
503         if (!m_bouquet)
504                 return -1;
505         return m_bouquet->moveService(ref, pos);
506 }
507
508 RESULT eDVBServiceList::flushChanges()
509 {
510         if (!m_bouquet)
511                 return -1;
512         return m_bouquet->flushChanges();
513 }
514
515 RESULT eDVBServiceList::setListName(const std::string &name)
516 {
517         if (!m_bouquet)
518                 return -1;
519         return m_bouquet->setListName(name);
520 }
521
522 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
523 {
524         ePtr<eDVBService> service;
525         int r = lookupService(service, ref);
526         if (r)
527                 service = 0;
528                 // check resources...
529         ptr = new eDVBServicePlay(ref, service);
530         return 0;
531 }
532
533 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
534 {
535         if (ref.path.empty())
536         {
537                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
538                 return 0;
539         } else
540         {
541                 ptr = 0;
542                 return -1;
543         }
544 }
545
546 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
547 {
548         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
549         if (list->startQuery())
550         {
551                 ptr = 0;
552                 return -1;
553         }
554         
555         ptr = list;
556         return 0;
557 }
558
559 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
560 {
561         /* is a listable service? */
562         if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
563         {
564                 if ( !ref.name.empty() )  // satellites or providers list
565                         ptr = new eStaticServiceDVBInformation;
566                 else // a dvb bouquet
567                         ptr = new eStaticServiceDVBBouquetInformation;
568         }
569         else if (!ref.path.empty()) /* do we have a PVR service? */
570                 ptr = new eStaticServiceDVBPVRInformation(ref);
571         else // normal dvb service
572         {
573                 ePtr<eDVBService> service;
574                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
575                         ptr = new eStaticServiceDVBInformation;
576                 else
577                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
578                         ptr = service;
579         }
580         return 0;
581 }
582
583 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
584 {
585         if (ref.path.empty())
586         {
587                 ptr = 0;
588                 return -1;
589         } else
590         {
591                 ptr = new eDVBPVRServiceOfflineOperations(ref);
592                 return 0;
593         }
594 }
595
596 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
597 {
598                         // TODO: handle the listing itself
599         // if (ref.... == -1) .. return "... bouquets ...";
600         // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
601                         // TODO: cache
602         ePtr<iDVBChannelList> db;
603         ePtr<eDVBResourceManager> res;
604         
605         int err;
606         if ((err = eDVBResourceManager::getInstance(res)) != 0)
607         {
608                 eDebug("no resource manager");
609                 return err;
610         }
611         if ((err = res->getChannelList(db)) != 0)
612         {
613                 eDebug("no channel list");
614                 return err;
615         }
616         
617                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
618         if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
619         {
620                 eDebug("getService failed!");
621                 return err;
622         }
623
624         return 0;
625 }
626
627 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
628         m_reference(ref), m_dvb_service(service), m_is_paused(0)
629 {
630         m_is_primary = 1;
631         m_is_pvr = !m_reference.path.empty();
632         
633         m_timeshift_enabled = m_timeshift_active = 0;
634         m_skipmode = 0;
635         
636         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
637         CONNECT(m_service_handler_timeshift.serviceEvent, eDVBServicePlay::serviceEventTimeshift);
638         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
639
640         m_cuesheet_changed = 0;
641         m_cutlist_enabled = 1;
642 }
643
644 eDVBServicePlay::~eDVBServicePlay()
645 {
646 }
647
648 void eDVBServicePlay::gotNewEvent()
649 {
650 #if 0
651                 // debug only
652         ePtr<eServiceEvent> m_event_now, m_event_next;
653         getEvent(m_event_now, 0);
654         getEvent(m_event_next, 1);
655
656         if (m_event_now)
657                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
658         if (m_event_next)
659                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
660 #endif
661         m_event((iPlayableService*)this, evUpdatedEventInfo);
662 }
663
664 void eDVBServicePlay::serviceEvent(int event)
665 {
666         switch (event)
667         {
668         case eDVBServicePMTHandler::eventTuned:
669         {
670                 ePtr<iDVBDemux> m_demux;
671                 if (!m_service_handler.getDataDemux(m_demux))
672                 {
673                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
674                         int sid = ref.getParentServiceID().get();
675                         if (!sid)
676                                 sid = ref.getServiceID().get();
677                         if ( ref.getParentTransportStreamID().get() &&
678                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
679                                 m_event_handler.startOther(m_demux, sid);
680                         else
681                                 m_event_handler.start(m_demux, sid);
682                 }
683                 break;
684         }
685         case eDVBServicePMTHandler::eventTuneFailed:
686         {
687                 eDebug("DVB service failed to tune");
688                 m_event((iPlayableService*)this, evTuneFailed);
689                 break;
690         }
691         case eDVBServicePMTHandler::eventNewProgramInfo:
692         {
693                 eDebug("eventNewProgramInfo %d %d", m_timeshift_enabled, m_timeshift_active);
694                 if (m_timeshift_enabled)
695                         updateTimeshiftPids();
696                 if (!m_timeshift_active)
697                         updateDecoder();
698                 if (m_first_program_info && m_is_pvr)
699                 {
700                         m_first_program_info = 0;
701                         seekTo(0);
702                 }
703                 m_event((iPlayableService*)this, evUpdatedInfo);
704                 break;
705         }
706         case eDVBServicePMTHandler::eventEOF:
707                 m_event((iPlayableService*)this, evEOF);
708                 break;
709         case eDVBServicePMTHandler::eventSOF:
710                 m_event((iPlayableService*)this, evSOF);
711                 break;
712         }
713 }
714
715 void eDVBServicePlay::serviceEventTimeshift(int event)
716 {
717         switch (event)
718         {
719         case eDVBServicePMTHandler::eventNewProgramInfo:
720                 if (m_timeshift_active)
721                         updateDecoder();
722                 break;
723         case eDVBServicePMTHandler::eventSOF:
724                 m_event((iPlayableService*)this, evSOF);
725                 break;
726         case eDVBServicePMTHandler::eventEOF:
727                 switchToLive();
728                 break;
729         }
730 }
731
732 RESULT eDVBServicePlay::start()
733 {
734         int r;
735                 /* in pvr mode, we only want to use one demux. in tv mode, we're using 
736                    two (one for decoding, one for data source), as we must be prepared
737                    to start recording from the data demux. */
738         if (m_is_pvr)
739                 m_cue = new eCueSheet();
740
741         m_first_program_info = 1;
742         eServiceReferenceDVB &service = (eServiceReferenceDVB&)m_reference;
743         r = m_service_handler.tune(service, m_is_pvr, m_cue);
744         
745                 /* inject EIT if there is a stored one */
746         if (m_is_pvr)
747         {
748                 std::string filename = service.path;
749                 filename.erase(filename.length()-2, 2);
750                 filename+="eit";
751                 int fd = ::open( filename.c_str(), O_RDONLY );
752                 if ( fd > -1 )
753                 {
754                         __u8 buf[4096];
755                         int rd = ::read(fd, buf, 4096);
756                         ::close(fd);
757                         if ( rd > 12 /*EIT_LOOP_SIZE*/ )
758                         {
759                                 Event ev(buf);
760                                 ePtr<eServiceEvent> event = new eServiceEvent;
761                                 ePtr<eServiceEvent> empty;
762                                 event->parseFrom(&ev, (service.getTransportStreamID().get()<<16)|service.getOriginalNetworkID().get());
763                                 m_event_handler.inject(event, 0);
764                                 m_event_handler.inject(empty, 1);
765                                 eDebug("injected");
766                         }
767                 }
768         }
769         
770         if (m_is_pvr)
771                 loadCuesheet();
772
773         m_event(this, evStart);
774         m_event((iPlayableService*)this, evSeekableStatusChanged);
775         return 0;
776 }
777
778 RESULT eDVBServicePlay::stop()
779 {
780         stopTimeshift(); /* in case timeshift was enabled, remove buffer etc. */
781
782         m_service_handler_timeshift.free();
783         m_service_handler.free();
784         
785         if (m_is_pvr && m_cuesheet_changed)
786                 saveCuesheet();
787         
788         return 0;
789 }
790
791 RESULT eDVBServicePlay::setTarget(int target)
792 {
793         m_is_primary = !target;
794         return 0;
795 }
796
797 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
798 {
799         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
800         return 0;
801 }
802
803 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
804 {
805                 /* note: we check for timeshift to be enabled,
806                    not neccessary active. if you pause when timeshift
807                    is not active, you should activate it when unpausing */
808         if ((!m_is_pvr) && (!m_timeshift_enabled))
809         {
810                 ptr = 0;
811                 return -1;
812         }
813
814         ptr = this;
815         return 0;
816 }
817
818 RESULT eDVBServicePlay::setSlowMotion(int ratio)
819 {
820         if (m_decoder)
821                 return m_decoder->setSlowMotion(ratio);
822         else
823                 return -1;
824 }
825
826 RESULT eDVBServicePlay::setFastForward(int ratio)
827 {
828         int skipmode, ffratio;
829         
830         if (ratio > 8)
831         {
832                 skipmode = ratio;
833                 ffratio = 1;
834         } else if (ratio > 0)
835         {
836                 skipmode = 0;
837                 ffratio = ratio;
838         } else if (!ratio)
839         {
840                 skipmode = 0;
841                 ffratio = 0;
842         } else // if (ratio < 0)
843         {
844                 skipmode = ratio;
845                 ffratio = 1;
846         }
847
848         if (m_skipmode != skipmode)
849         {
850                 eDebug("setting cue skipmode to %d", skipmode);
851                 if (m_cue)
852                         m_cue->setSkipmode(skipmode * 90000); /* convert to 90000 per second */
853         }
854         
855         m_skipmode = skipmode;
856         
857         if (!m_decoder)
858                 return -1;
859
860         return m_decoder->setFastForward(ffratio);
861 }
862     
863 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
864 {
865         if (m_is_pvr || m_timeshift_enabled)
866         {
867                 ptr = this;
868                 return 0;
869         }
870         
871         ptr = 0;
872         return -1;
873 }
874
875         /* TODO: when timeshift is enabled but not active, this doesn't work. */
876 RESULT eDVBServicePlay::getLength(pts_t &len)
877 {
878         ePtr<iDVBPVRChannel> pvr_channel;
879         
880         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
881                 return -1;
882         
883         return pvr_channel->getLength(len);
884 }
885
886 RESULT eDVBServicePlay::pause()
887 {
888         if (!m_is_paused && m_decoder)
889         {
890                 m_is_paused = 1;
891                 return m_decoder->freeze(0);
892         } else
893                 return -1;
894 }
895
896 RESULT eDVBServicePlay::unpause()
897 {
898         if (m_is_paused && m_decoder)
899         {
900                 m_is_paused = 0;
901                 return m_decoder->unfreeze();
902         } else
903                 return -1;
904 }
905
906 RESULT eDVBServicePlay::seekTo(pts_t to)
907 {
908         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
909         
910         if (!m_decode_demux)
911                 return -1;
912
913         ePtr<iDVBPVRChannel> pvr_channel;
914         
915         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
916                 return -1;
917         
918         if (!m_cue)
919                 return -1;
920         
921         m_cue->seekTo(0, to);
922         return 0;
923 }
924
925 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
926 {
927         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
928         
929         if (!m_decode_demux)
930                 return -1;
931
932         ePtr<iDVBPVRChannel> pvr_channel;
933         
934         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
935                 return -1;
936         
937         int mode = 1;
938         
939                         /* HACK until we have skip-AP api */
940         if ((to > 0) && (to < 100))
941                 mode = 2;
942         
943         to *= direction;
944         
945         if (!m_cue)
946                 return 0;
947         
948         m_cue->seekTo(mode, to);
949         return 0;
950 }
951
952 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
953 {
954         ePtr<iDVBPVRChannel> pvr_channel;
955         
956         if (!m_decode_demux)
957                 return -1;
958         
959         if ((m_timeshift_enabled ? m_service_handler_timeshift : m_service_handler).getPVRChannel(pvr_channel))
960                 return -1;
961         
962         int r = 0;
963
964                 /* if there is a decoder, use audio or video PTS */
965         if (m_decoder)
966         {
967                 r = m_decoder->getPTS(0, pos);
968                 if (r)
969                         return r;
970         }
971         
972                 /* fixup */
973         return pvr_channel->getCurrentPosition(m_decode_demux, pos, m_decoder ? 1 : 0);
974 }
975
976 RESULT eDVBServicePlay::setTrickmode(int trick)
977 {
978         if (m_decoder)
979                 m_decoder->setTrickmode(trick);
980         return 0;
981 }
982
983 RESULT eDVBServicePlay::isCurrentlySeekable()
984 {
985         return m_is_pvr || m_timeshift_active;
986 }
987
988 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
989 {
990         ptr = this;
991         return 0;
992 }
993
994 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
995 {
996         ptr = this;
997         return 0;
998 }
999
1000 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
1001 {
1002         ptr = this;
1003         return 0;
1004 }
1005
1006 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
1007 {
1008         ptr = this;
1009         return 0;
1010 }
1011
1012 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
1013 {
1014         ptr = 0;
1015         if (m_timeshift_enabled || !m_is_pvr)
1016         {
1017                 if (!m_timeshift_enabled)
1018                 {
1019                                 /* we need enough diskspace */
1020                         struct statfs fs;
1021                         if (statfs(TSPATH "/.", &fs) < 0)
1022                         {
1023                                 eDebug("statfs failed!");
1024                                 return -2;
1025                         }
1026                 
1027                         if (((off_t)fs.f_bavail) * ((off_t)fs.f_bsize) < 1024*1024*1024LL)
1028                         {
1029                                 eDebug("not enough diskspace for timeshift! (less than 1GB)");
1030                                 return -3;
1031                         }
1032                 }
1033                 ptr = this;
1034                 return 0;
1035         }
1036         return -1;
1037 }
1038
1039 RESULT eDVBServicePlay::cueSheet(ePtr<iCueSheet> &ptr)
1040 {
1041         if (m_is_pvr)
1042         {
1043                 ptr = this;
1044                 return 0;
1045         }
1046         ptr = 0;
1047         return -1;
1048 }
1049
1050 RESULT eDVBServicePlay::getName(std::string &name)
1051 {
1052         if (m_is_pvr)
1053         {
1054                 ePtr<iStaticServiceInformation> i = new eStaticServiceDVBPVRInformation(m_reference);
1055                 return i->getName(m_reference, name);
1056         }
1057         if (m_dvb_service)
1058         {
1059                 m_dvb_service->getName(m_reference, name);
1060                 if (name.empty())
1061                         name = "(...)";
1062         }
1063         else if (!m_reference.name.empty())
1064                 eStaticServiceDVBInformation().getName(m_reference, name);
1065         else
1066                 name = "DVB service";
1067         return 0;
1068 }
1069
1070 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
1071 {
1072         return m_event_handler.getEvent(evt, nownext);
1073 }
1074
1075 int eDVBServicePlay::getInfo(int w)
1076 {
1077         eDVBServicePMTHandler::program program;
1078
1079         if (w == sCAIDs)
1080                 return resIsPyObject;
1081
1082         if (m_service_handler.getProgramInfo(program))
1083                 return -1;
1084         
1085         switch (w)
1086         {
1087         case sAspect:
1088                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
1089                 {
1090                         ePtr<eServiceEvent> evt;
1091                         if (!m_event_handler.getEvent(evt, 0))
1092                         {
1093                                 ePtr<eComponentData> data;
1094                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
1095                                 {
1096                                         if ( data->getStreamContent() == 1 )
1097                                         {
1098                                                 switch(data->getComponentType())
1099                                                 {
1100                                                         // SD
1101                                                         case 1: // 4:3 SD PAL
1102                                                         case 2:
1103                                                         case 3: // 16:9 SD PAL
1104                                                         case 4: // > 16:9 PAL
1105                                                         case 5: // 4:3 SD NTSC
1106                                                         case 6: 
1107                                                         case 7: // 16:9 SD NTSC
1108                                                         case 8: // > 16:9 NTSC
1109
1110                                                         // HD
1111                                                         case 9: // 4:3 HD PAL
1112                                                         case 0xA:
1113                                                         case 0xB: // 16:9 HD PAL
1114                                                         case 0xC: // > 16:9 HD PAL
1115                                                         case 0xD: // 4:3 HD NTSC
1116                                                         case 0xE:
1117                                                         case 0xF: // 16:9 HD NTSC
1118                                                         case 0x10: // > 16:9 HD PAL
1119                                                                 return data->getComponentType();
1120                                                 }
1121                                         }
1122                                 }
1123                         }
1124                 }
1125                 return -1;
1126         case sIsCrypted: return program.isCrypted;
1127         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
1128         case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
1129         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
1130         case sPCRPID: return program.pcrPid;
1131         case sPMTPID: return program.pmtPid;
1132         case sTXTPID: return program.textPid;
1133         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
1134         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
1135         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
1136         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
1137         case sProvider: if (!m_dvb_service) return -1; return -2;
1138         default:
1139                 return -1;
1140         }
1141 }
1142
1143 std::string eDVBServicePlay::getInfoString(int w)
1144 {
1145         switch (w)
1146         {
1147         case sProvider:
1148                 if (!m_dvb_service) return "";
1149                 return m_dvb_service->m_provider_name;
1150         default:
1151                 break;
1152         }
1153         return iServiceInformation::getInfoString(w);
1154 }
1155
1156 PyObject *eDVBServicePlay::getInfoObject(int w)
1157 {
1158         switch (w)
1159         {
1160         case sCAIDs:
1161                 return m_service_handler.getCaIds();
1162         default:
1163                 break;
1164         }
1165         return iServiceInformation::getInfoObject(w);
1166 }
1167
1168 int eDVBServicePlay::getNumberOfTracks()
1169 {
1170         eDVBServicePMTHandler::program program;
1171         if (m_service_handler.getProgramInfo(program))
1172                 return 0;
1173         return program.audioStreams.size();
1174 }
1175
1176 RESULT eDVBServicePlay::selectTrack(unsigned int i)
1177 {
1178         int ret = selectAudioStream(i);
1179
1180         if (m_decoder->start())
1181                 return -5;
1182
1183         return ret;
1184 }
1185
1186 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
1187 {
1188         eDVBServicePMTHandler::program program;
1189
1190         if (m_service_handler.getProgramInfo(program))
1191                 return -1;
1192         
1193         if (i >= program.audioStreams.size())
1194                 return -2;
1195         
1196         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
1197                 info.m_description = "MPEG";
1198         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
1199                 info.m_description = "AC3";
1200         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
1201                 info.m_description = "DTS";
1202         else
1203                 info.m_description = "???";
1204
1205         if (program.audioStreams[i].component_tag != -1)
1206         {
1207                 ePtr<eServiceEvent> evt;
1208                 if (!m_event_handler.getEvent(evt, 0))
1209                 {
1210                         ePtr<eComponentData> data;
1211                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
1212                                 info.m_language = data->getText();
1213                 }
1214         }
1215
1216         if (info.m_language.empty())
1217                 info.m_language = program.audioStreams[i].language_code;
1218         
1219         return 0;
1220 }
1221
1222 int eDVBServicePlay::selectAudioStream(int i)
1223 {
1224         eDVBServicePMTHandler::program program;
1225
1226         if (m_service_handler.getProgramInfo(program))
1227                 return -1;
1228         
1229         if ((unsigned int)i >= program.audioStreams.size())
1230                 return -2;
1231         
1232         if (!m_decoder)
1233                 return -3;
1234         
1235         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
1236                 return -4;
1237
1238         if (m_dvb_service && !m_is_pvr)
1239         {
1240                 if (program.audioStreams[i].type == eDVBAudio::aMPEG)
1241                 {
1242                         m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid);
1243                         m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1244                 }       else
1245                 {
1246                         m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1247                         m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid);
1248                 }
1249         }
1250
1251         m_current_audio_stream = i;
1252
1253         return 0;
1254 }
1255
1256 int eDVBServicePlay::getFrontendInfo(int w)
1257 {
1258         if (m_is_pvr)
1259                 return 0;
1260         eUsePtr<iDVBChannel> channel;
1261         if(m_service_handler.getChannel(channel))
1262                 return 0;
1263         ePtr<iDVBFrontend> fe;
1264         if(channel->getFrontend(fe))
1265                 return 0;
1266         return fe->readFrontendData(w);
1267 }
1268
1269 PyObject *eDVBServicePlay::getFrontendData(bool original)
1270 {
1271         PyObject *ret=0;
1272
1273         eUsePtr<iDVBChannel> channel;
1274         if(!m_service_handler.getChannel(channel))
1275         {
1276                 ePtr<iDVBFrontend> fe;
1277                 if(!channel->getFrontend(fe))
1278                 {
1279                         ret = fe->readTransponderData(original);
1280                         if (ret)
1281                         {
1282                                 ePtr<iDVBFrontendParameters> feparm;
1283                                 channel->getCurrentFrontendParameters(feparm);
1284                                 if (feparm)
1285                                 {
1286                                         eDVBFrontendParametersSatellite osat;
1287                                         if (!feparm->getDVBS(osat))
1288                                         {
1289                                                 void PutToDict(PyObject *, const char*, long);
1290                                                 void PutToDict(PyObject *, const char*, const char*);
1291                                                 PutToDict(ret, "orbital_position", osat.orbital_position);
1292                                                 const char *tmp = "UNKNOWN";
1293                                                 switch(osat.polarisation)
1294                                                 {
1295                                                         case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
1296                                                         case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
1297                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
1298                                                         case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
1299                                                         default:break;
1300                                                 }
1301                                                 PutToDict(ret, "polarization", tmp);
1302                                         }
1303                                 }
1304                         }
1305                 }
1306         }
1307         if (!ret)
1308         {
1309                 ret = Py_None;
1310                 Py_INCREF(ret);
1311         }
1312         return ret;
1313 }
1314
1315 int eDVBServicePlay::getNumberOfSubservices()
1316 {
1317         ePtr<eServiceEvent> evt;
1318         if (!m_event_handler.getEvent(evt, 0))
1319                 return evt->getNumOfLinkageServices();
1320         return 0;
1321 }
1322
1323 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1324 {
1325         ePtr<eServiceEvent> evt;
1326         if (!m_event_handler.getEvent(evt, 0))
1327         {
1328                 if (!evt->getLinkageService(sub, m_reference, n))
1329                         return 0;
1330         }
1331         sub.type=eServiceReference::idInvalid;
1332         return -1;
1333 }
1334
1335 RESULT eDVBServicePlay::startTimeshift()
1336 {
1337         ePtr<iDVBDemux> demux;
1338         
1339         eDebug("Start timeshift!");
1340         
1341         if (m_timeshift_enabled)
1342                 return -1;
1343         
1344                 /* start recording with the data demux. */
1345         if (m_service_handler.getDataDemux(demux))
1346                 return -2;
1347
1348         demux->createTSRecorder(m_record);
1349         if (!m_record)
1350                 return -3;
1351
1352         char templ[]=TSPATH "/timeshift.XXXXXX";
1353         m_timeshift_fd = mkstemp(templ);
1354         m_timeshift_file = templ;
1355         
1356         eDebug("recording to %s", templ);
1357         
1358         if (m_timeshift_fd < 0)
1359         {
1360                 m_record = 0;
1361                 return -4;
1362         }
1363                 
1364         m_record->setTargetFD(m_timeshift_fd);
1365
1366         m_timeshift_enabled = 1;
1367         
1368         updateTimeshiftPids();
1369         m_record->start();
1370
1371         return 0;
1372 }
1373
1374 RESULT eDVBServicePlay::stopTimeshift()
1375 {
1376         if (!m_timeshift_enabled)
1377                 return -1;
1378         
1379         switchToLive();
1380         
1381         m_timeshift_enabled = 0;
1382         
1383         m_record->stop();
1384         m_record = 0;
1385         
1386         close(m_timeshift_fd);
1387         eDebug("remove timeshift file");
1388         remove(m_timeshift_file.c_str());
1389         
1390         return 0;
1391 }
1392
1393 int eDVBServicePlay::isTimeshiftActive()
1394 {
1395         return m_timeshift_enabled && m_timeshift_active;
1396 }
1397
1398 RESULT eDVBServicePlay::activateTimeshift()
1399 {
1400         if (!m_timeshift_enabled)
1401                 return -1;
1402         
1403         if (!m_timeshift_active)
1404         {
1405                 switchToTimeshift();
1406                 return 0;
1407         }
1408         
1409         return -2;
1410 }
1411
1412 PyObject *eDVBServicePlay::getCutList()
1413 {
1414         PyObject *list = PyList_New(0);
1415         
1416         for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1417         {
1418                 PyObject *tuple = PyTuple_New(2);
1419                 PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
1420                 PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
1421                 PyList_Append(list, tuple);
1422                 Py_DECREF(tuple);
1423         }
1424         
1425         return list;
1426 }
1427
1428 void eDVBServicePlay::setCutList(PyObject *list)
1429 {
1430         if (!PyList_Check(list))
1431                 return;
1432         int size = PyList_Size(list);
1433         int i;
1434         
1435         m_cue_entries.clear();
1436         
1437         for (i=0; i<size; ++i)
1438         {
1439                 PyObject *tuple = PyList_GetItem(list, i);
1440                 if (!PyTuple_Check(tuple))
1441                 {
1442                         eDebug("non-tuple in cutlist");
1443                         continue;
1444                 }
1445                 if (PyTuple_Size(tuple) != 2)
1446                 {
1447                         eDebug("cutlist entries need to be a 2-tuple");
1448                         continue;
1449                 }
1450                 PyObject *ppts = PyTuple_GetItem(tuple, 0), *ptype = PyTuple_GetItem(tuple, 1);
1451                 if (!(PyLong_Check(ppts) && PyInt_Check(ptype)))
1452                 {
1453                         eDebug("cutlist entries need to be (pts, type)-tuples (%d %d)", PyLong_Check(ppts), PyInt_Check(ptype));
1454                         continue;
1455                 }
1456                 pts_t pts = PyLong_AsLongLong(ppts);
1457                 int type = PyInt_AsLong(ptype);
1458                 m_cue_entries.insert(cueEntry(pts, type));
1459                 eDebug("adding %08llx, %d", pts, type);
1460         }
1461         m_cuesheet_changed = 1;
1462         
1463         cutlistToCuesheet();
1464         m_event((iPlayableService*)this, evCuesheetChanged);
1465 }
1466
1467 void eDVBServicePlay::setCutListEnable(int enable)
1468 {
1469         m_cutlist_enabled = enable;
1470         cutlistToCuesheet();
1471 }
1472
1473 void eDVBServicePlay::updateTimeshiftPids()
1474 {
1475         if (!m_record)
1476                 return;
1477         
1478         eDVBServicePMTHandler::program program;
1479         if (m_service_handler.getProgramInfo(program))
1480                 return;
1481         else
1482         {
1483                 std::set<int> pids_to_record;
1484                 pids_to_record.insert(0); // PAT
1485                 if (program.pmtPid != -1)
1486                         pids_to_record.insert(program.pmtPid); // PMT
1487
1488                 if (program.textPid != -1)
1489                         pids_to_record.insert(program.textPid); // Videotext
1490
1491                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1492                         i(program.videoStreams.begin()); 
1493                         i != program.videoStreams.end(); ++i)
1494                         pids_to_record.insert(i->pid);
1495
1496                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1497                         i(program.audioStreams.begin()); 
1498                         i != program.audioStreams.end(); ++i)
1499                                 pids_to_record.insert(i->pid);
1500
1501                 std::set<int> new_pids, obsolete_pids;
1502                 
1503                 std::set_difference(pids_to_record.begin(), pids_to_record.end(), 
1504                                 m_pids_active.begin(), m_pids_active.end(),
1505                                 std::inserter(new_pids, new_pids.begin()));
1506                 
1507                 std::set_difference(
1508                                 m_pids_active.begin(), m_pids_active.end(),
1509                                 pids_to_record.begin(), pids_to_record.end(), 
1510                                 std::inserter(new_pids, new_pids.begin())
1511                                 );
1512
1513                 for (std::set<int>::iterator i(new_pids.begin()); i != new_pids.end(); ++i)
1514                         m_record->addPID(*i);
1515
1516                 for (std::set<int>::iterator i(obsolete_pids.begin()); i != obsolete_pids.end(); ++i)
1517                         m_record->removePID(*i);
1518         }
1519 }
1520
1521 void eDVBServicePlay::switchToLive()
1522 {
1523         if (!m_timeshift_active)
1524                 return;
1525         
1526         m_cue = 0;
1527         m_decoder = 0;
1528         m_decode_demux = 0;
1529         m_teletext_parser = 0;
1530         
1531                 /* free the timeshift service handler, we need the resources */
1532         m_service_handler_timeshift.free();
1533         m_timeshift_active = 0;
1534         
1535         m_event((iPlayableService*)this, evSeekableStatusChanged);
1536         
1537         updateDecoder();
1538 }
1539
1540 void eDVBServicePlay::switchToTimeshift()
1541 {
1542         if (m_timeshift_active)
1543                 return;
1544         
1545         m_decode_demux = 0;
1546         m_decoder = 0;
1547         m_teletext_parser = 0;
1548         
1549         m_timeshift_active = 1;
1550
1551         m_event((iPlayableService*)this, evSeekableStatusChanged);
1552         
1553         eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference;
1554         r.path = m_timeshift_file;
1555         
1556         m_cue = new eCueSheet();
1557         m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */
1558         updateDecoder(); /* mainly to switch off PCR */
1559 }
1560
1561 void eDVBServicePlay::updateDecoder()
1562 {
1563         int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1;
1564         eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler;
1565
1566         bool defaultac3=false;
1567         std::string default_ac3;
1568
1569         if (!ePythonConfigQuery::getConfigValue("config.av.defaultac3", default_ac3))
1570                 defaultac3 = default_ac3 == "enable";
1571
1572         eDVBServicePMTHandler::program program;
1573         if (h.getProgramInfo(program))
1574                 eDebug("getting program info failed.");
1575         else
1576         {
1577                 eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
1578                 if (!program.videoStreams.empty())
1579                 {
1580                         eDebugNoNewLine(" (");
1581                         for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
1582                                 i(program.videoStreams.begin()); 
1583                                 i != program.videoStreams.end(); ++i)
1584                         {
1585                                 if (vpid == -1)
1586                                 {
1587                                         vpid = i->pid;
1588                                         vpidtype = i->type;
1589                                 }
1590                                 if (i != program.videoStreams.begin())
1591                                         eDebugNoNewLine(", ");
1592                                 eDebugNoNewLine("%04x", i->pid);
1593                         }
1594                         eDebugNoNewLine(")");
1595                 }
1596                 eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
1597                 if (!program.audioStreams.empty())
1598                 {
1599                         eDebugNoNewLine(" (");
1600                         for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
1601                                 i(program.audioStreams.begin()); 
1602                                 i != program.audioStreams.end(); ++i)
1603                         {
1604                                 if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3))
1605                                 {
1606                                         if ( apid == -1 || (i->type != eDVBAudio::aMPEG) )
1607                                         {
1608                                                 apid = i->pid;
1609                                                 apidtype = i->type;
1610                                         }
1611                                 }
1612                                 if (i != program.audioStreams.begin())
1613                                         eDebugNoNewLine(", ");
1614                                 eDebugNoNewLine("%04x", i->pid);
1615                         }
1616                         eDebugNoNewLine(")");
1617                 }
1618                 eDebugNoNewLine(", and the pcr pid is %04x", program.pcrPid);
1619                 pcrpid = program.pcrPid;
1620                 eDebug(", and the text pid is %04x", program.textPid);
1621                 tpid = program.textPid;
1622         }
1623
1624         if (!m_decoder)
1625         {
1626                 h.getDecodeDemux(m_decode_demux);
1627                 if (m_decode_demux)
1628                         m_decode_demux->getMPEGDecoder(m_decoder, m_is_primary);
1629                 if (m_cue)
1630                         m_cue->setDecodingDemux(m_decode_demux, m_decoder);
1631 #ifdef INTERNAL_TELETEXT
1632                 m_teletext_parser = new eDVBTeletextParser(m_decode_demux);
1633 #endif
1634         }
1635
1636         if (m_decoder)
1637         {
1638                 m_decoder->setVideoPID(vpid, vpidtype);
1639                 m_current_audio_stream = 0;
1640                 m_decoder->setAudioPID(apid, apidtype);
1641                 if (!(m_is_pvr || m_timeshift_active || !m_is_primary))
1642                         m_decoder->setSyncPCR(pcrpid);
1643                 else
1644                         m_decoder->setSyncPCR(-1);
1645 #ifndef INTERNAL_TELETEXT
1646                 m_decoder->setTextPID(tpid);
1647 #else
1648                 if (m_teletext_parser)
1649                         m_teletext_parser->start(tpid);
1650 #endif
1651
1652                 if (!m_is_primary)
1653                         m_decoder->setTrickmode(1);
1654                 m_decoder->start();
1655 // how we can do this better?
1656 // update cache pid when the user changed the audio track or video track
1657 // TODO handling of difference audio types.. default audio types..
1658                                 
1659                 /* don't worry about non-existing services, nor pvr services */
1660                 if (m_dvb_service && !m_is_pvr)
1661                 {
1662                         if (apidtype == eDVBAudio::aMPEG)
1663                         {
1664                                 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
1665                                 m_dvb_service->setCachePID(eDVBService::cAC3PID, -1);
1666                         }
1667                         else
1668                         {
1669                                 m_dvb_service->setCachePID(eDVBService::cAPID, -1);
1670                                 m_dvb_service->setCachePID(eDVBService::cAC3PID, apid);
1671                         }
1672                         m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
1673                         m_dvb_service->setCachePID(eDVBService::cVTYPE, vpidtype);
1674                         m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
1675                         m_dvb_service->setCachePID(eDVBService::cTPID, tpid);
1676                 }
1677         }
1678 }
1679
1680 void eDVBServicePlay::loadCuesheet()
1681 {
1682         std::string filename = m_reference.path + ".cuts";
1683         
1684         m_cue_entries.clear();
1685
1686         FILE *f = fopen(filename.c_str(), "rb");
1687
1688         if (f)
1689         {
1690                 eDebug("loading cuts..");
1691                 while (1)
1692                 {
1693                         unsigned long long where;
1694                         unsigned int what;
1695                         
1696                         if (!fread(&where, sizeof(where), 1, f))
1697                                 break;
1698                         if (!fread(&what, sizeof(what), 1, f))
1699                                 break;
1700                         
1701 #if BYTE_ORDER == LITTLE_ENDIAN
1702                         where = bswap_64(where);
1703 #endif
1704                         what = ntohl(what);
1705                         
1706                         if (what > 2)
1707                                 break;
1708                         
1709                         m_cue_entries.insert(cueEntry(where, what));
1710                 }
1711                 fclose(f);
1712                 eDebug("%d entries", m_cue_entries.size());
1713         } else
1714                 eDebug("cutfile not found!");
1715         
1716         m_cuesheet_changed = 0;
1717         cutlistToCuesheet();
1718         m_event((iPlayableService*)this, evCuesheetChanged);
1719 }
1720
1721 void eDVBServicePlay::saveCuesheet()
1722 {
1723         std::string filename = m_reference.path + ".cuts";
1724         
1725         FILE *f = fopen(filename.c_str(), "wb");
1726
1727         if (f)
1728         {
1729                 unsigned long long where;
1730                 int what;
1731
1732                 for (std::multiset<cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
1733                 {
1734 #if BYTE_ORDER == BIG_ENDIAN
1735                         where = i->where;
1736 #else
1737                         where = bswap_64(i->where);
1738 #endif
1739                         what = htonl(i->what);
1740                         fwrite(&where, sizeof(where), 1, f);
1741                         fwrite(&what, sizeof(what), 1, f);
1742                         
1743                 }
1744                 fclose(f);
1745         }
1746         
1747         m_cuesheet_changed = 0;
1748 }
1749
1750 void eDVBServicePlay::cutlistToCuesheet()
1751 {
1752         if (!m_cue)
1753         {
1754                 eDebug("no cue sheet");
1755                 return;
1756         }       
1757         m_cue->clear();
1758         
1759         if (!m_cutlist_enabled)
1760         {
1761                 m_cue->commitSpans();
1762                 eDebug("cutlists where disabled");
1763                 return;
1764         }
1765
1766         pts_t in = 0, out = 0, length = 0;
1767         
1768         getLength(length);
1769                 
1770         std::multiset<cueEntry>::iterator i(m_cue_entries.begin());
1771         
1772         while (1)
1773         {
1774                 if (i == m_cue_entries.end())
1775                         out = length;
1776                 else {
1777                         if (i->what == 0) /* in */
1778                         {
1779                                 in = i++->where;
1780                                 continue;
1781                         } else if (i->what == 1) /* out */
1782                                 out = i++->where;
1783                         else /* mark */
1784                         {
1785                                 i++;
1786                                 continue;
1787                         }
1788                 }
1789                 
1790                 if (in != out)
1791                         m_cue->addSourceSpan(in, out);
1792                 
1793                 in = length;
1794                 
1795                 if (i == m_cue_entries.end())
1796                         break;
1797         }
1798         m_cue->commitSpans();
1799 }
1800
1801 DEFINE_REF(eDVBServicePlay)
1802
1803 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");