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