use video stc for display. make skipping look a bit better.
[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
12 #include <lib/service/servicedvbrecord.h>
13 #include <lib/dvb/metaparser.h>
14 #include <lib/dvb/tstools.h>
15
16 class eStaticServiceDVBInformation: public iStaticServiceInformation
17 {
18         DECLARE_REF(eStaticServiceDVBInformation);
19 public:
20         RESULT getName(const eServiceReference &ref, std::string &name);
21         int getLength(const eServiceReference &ref);
22 };
23
24 DEFINE_REF(eStaticServiceDVBInformation);
25
26 RESULT eStaticServiceDVBInformation::getName(const eServiceReference &ref, std::string &name)
27 {
28         eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
29         if ( !ref.name.empty() )
30         {
31                 if (service.getParentTransportStreamID().get()) // linkage subservice
32                 {
33                         ePtr<iServiceHandler> service_center;
34                         if (!eServiceCenter::getInstance(service_center))
35                         {
36                                 eServiceReferenceDVB parent = service;
37                                 parent.setTransportStreamID( service.getParentTransportStreamID() );
38                                 parent.setServiceID( service.getParentServiceID() );
39                                 parent.setParentTransportStreamID(eTransportStreamID(0));
40                                 parent.setParentServiceID(eServiceID(0));
41                                 parent.name="";
42                                 ePtr<iStaticServiceInformation> service_info;
43                                 if (!service_center->info(parent, service_info))
44                                 {
45                                         if (!service_info->getName(parent, name))
46                                         {
47                                                 // just show short name
48                                                 unsigned int pos = name.find("\xc2\x86");
49                                                 if ( pos != std::string::npos )
50                                                         name.erase(0, pos+2);
51                                                 pos = name.find("\xc2\x87");
52                                                 if ( pos != std::string::npos )
53                                                         name.erase(pos);
54                                                 name+=" - ";
55                                         }
56                                 }
57                         }
58                 }
59                 else
60                         name="";
61                 name += ref.name;
62                 return 0;
63         }
64         else
65                 return -1;
66 }
67
68 int eStaticServiceDVBInformation::getLength(const eServiceReference &ref)
69 {
70         return -1;
71 }
72
73 class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation
74 {
75         DECLARE_REF(eStaticServiceDVBBouquetInformation);
76 public:
77         RESULT getName(const eServiceReference &ref, std::string &name);
78         int getLength(const eServiceReference &ref);
79 };
80
81 DEFINE_REF(eStaticServiceDVBBouquetInformation);
82
83 RESULT eStaticServiceDVBBouquetInformation::getName(const eServiceReference &ref, std::string &name)
84 {
85         ePtr<iDVBChannelList> db;
86         ePtr<eDVBResourceManager> res;
87
88         int err;
89         if ((err = eDVBResourceManager::getInstance(res)) != 0)
90         {
91                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no resource manager!");
92                 return err;
93         }
94         if ((err = res->getChannelList(db)) != 0)
95         {
96                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. no channel list!");
97                 return err;
98         }
99
100         eBouquet *bouquet=0;
101         if ((err = db->getBouquet(ref, bouquet)) != 0)
102         {
103                 eDebug("eStaticServiceDVBBouquetInformation::getName failed.. getBouquet failed!");
104                 return -1;
105         }
106
107         if ( bouquet && bouquet->m_bouquet_name.length() )
108         {
109                 name = bouquet->m_bouquet_name;
110                 return 0;
111         }
112         else
113                 return -1;
114 }
115
116 int eStaticServiceDVBBouquetInformation::getLength(const eServiceReference &ref)
117 {
118         return -1;
119 }
120
121 class eStaticServiceDVBPVRInformation: public iStaticServiceInformation
122 {
123         DECLARE_REF(eStaticServiceDVBPVRInformation);
124         eServiceReference m_ref;
125         eDVBMetaParser m_parser;
126 public:
127         eStaticServiceDVBPVRInformation(const eServiceReference &ref);
128         RESULT getName(const eServiceReference &ref, std::string &name);
129         int getLength(const eServiceReference &ref);
130         
131         int getInfo(const eServiceReference &ref, int w);
132         std::string getInfoString(const eServiceReference &ref,int w);
133 };
134
135 DEFINE_REF(eStaticServiceDVBPVRInformation);
136
137 eStaticServiceDVBPVRInformation::eStaticServiceDVBPVRInformation(const eServiceReference &ref)
138 {
139         m_ref = ref;
140         m_parser.parseFile(ref.path);
141 }
142
143 RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name)
144 {
145         ASSERT(ref == m_ref);
146         name = m_parser.m_name.size() ? m_parser.m_name : ref.path;
147         return 0;
148 }
149
150 int eStaticServiceDVBPVRInformation::getLength(const eServiceReference &ref)
151 {
152         ASSERT(ref == m_ref);
153         
154         eDVBTSTools tstools;
155         
156         if (tstools.openFile(ref.path.c_str()))
157                 return 0;
158
159         pts_t len;
160         if (tstools.calcLen(len))
161                 return 0;
162
163         return len / 90000;
164 }
165
166 int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
167 {
168         switch (w)
169         {
170         case iServiceInformation::sDescription:
171                 return iServiceInformation::resIsString;
172         case iServiceInformation::sTimeCreate:
173                 if (m_parser.m_time_create)
174                         return m_parser.m_time_create;
175                 else
176                         return iServiceInformation::resNA;
177         default:
178                 return iServiceInformation::resNA;
179         }
180 }
181
182 std::string eStaticServiceDVBPVRInformation::getInfoString(const eServiceReference &ref,int w)
183 {
184         switch (w)
185         {
186         case iServiceInformation::sDescription:
187                 return m_parser.m_description;
188         default:
189                 return "";
190         }
191 }
192
193 class eDVBPVRServiceOfflineOperations: public iServiceOfflineOperations
194 {
195         DECLARE_REF(eDVBPVRServiceOfflineOperations);
196         eServiceReferenceDVB m_ref;
197 public:
198         eDVBPVRServiceOfflineOperations(const eServiceReference &ref);
199         
200         RESULT deleteFromDisk(int simulate);
201         RESULT getListOfFilenames(std::list<std::string> &);
202 };
203
204 DEFINE_REF(eDVBPVRServiceOfflineOperations);
205
206 eDVBPVRServiceOfflineOperations::eDVBPVRServiceOfflineOperations(const eServiceReference &ref): m_ref((const eServiceReferenceDVB&)ref)
207 {
208 }
209
210 RESULT eDVBPVRServiceOfflineOperations::deleteFromDisk(int simulate)
211 {
212         if (simulate)
213                 return 0;
214         else
215         {
216                 std::list<std::string> res;
217                 if (getListOfFilenames(res))
218                         return -1;
219                 
220                                 /* TODO: deferred removing.. */
221                 for (std::list<std::string>::iterator i(res.begin()); i != res.end(); ++i)
222                 {
223                         eDebug("Removing %s...", i->c_str());
224                         ::unlink(i->c_str());
225                 }
226                 
227                 return 0;
228         }
229 }
230
231 RESULT eDVBPVRServiceOfflineOperations::getListOfFilenames(std::list<std::string> &res)
232 {
233         res.clear();
234         res.push_back(m_ref.path);
235         res.push_back(m_ref.path + ".meta");
236         return 0;
237 }
238
239 DEFINE_REF(eServiceFactoryDVB)
240
241 eServiceFactoryDVB::eServiceFactoryDVB()
242 {
243         ePtr<eServiceCenter> sc;
244         
245         eServiceCenter::getPrivInstance(sc);
246         if (sc)
247                 sc->addServiceFactory(eServiceFactoryDVB::id, this);
248 }
249
250 eServiceFactoryDVB::~eServiceFactoryDVB()
251 {
252         ePtr<eServiceCenter> sc;
253         
254         eServiceCenter::getPrivInstance(sc);
255         if (sc)
256                 sc->removeServiceFactory(eServiceFactoryDVB::id);
257 }
258
259 DEFINE_REF(eDVBServiceList);
260
261 eDVBServiceList::eDVBServiceList(const eServiceReference &parent): m_parent(parent)
262 {
263 }
264
265 eDVBServiceList::~eDVBServiceList()
266 {
267 }
268
269 RESULT eDVBServiceList::startQuery()
270 {
271         ePtr<iDVBChannelList> db;
272         ePtr<eDVBResourceManager> res;
273         
274         int err;
275         if ((err = eDVBResourceManager::getInstance(res)) != 0)
276         {
277                 eDebug("no resource manager");
278                 return err;
279         }
280         if ((err = res->getChannelList(db)) != 0)
281         {
282                 eDebug("no channel list");
283                 return err;
284         }
285         
286         ePtr<eDVBChannelQuery> q;
287         
288         if (!m_parent.path.empty())
289         {
290                 eDVBChannelQuery::compile(q, m_parent.path);
291                 if (!q)
292                 {
293                         eDebug("compile query failed");
294                         return err;
295                 }
296         }
297         
298         if ((err = db->startQuery(m_query, q, m_parent)) != 0)
299         {
300                 eDebug("startQuery failed");
301                 return err;
302         }
303
304         return 0;
305 }
306
307 RESULT eDVBServiceList::getContent(std::list<eServiceReference> &list)
308 {
309         eServiceReferenceDVB ref;
310         
311         if (!m_query)
312                 return -1;
313         
314         while (!m_query->getNextResult(ref))
315                 list.push_back(ref);
316         return 0;
317 }
318
319 RESULT eDVBServiceList::getNext(eServiceReference &ref)
320 {
321         if (!m_query)
322                 return -1;
323         
324         return m_query->getNextResult((eServiceReferenceDVB&)ref);
325 }
326
327 int eDVBServiceList::compareLessEqual(const eServiceReference &a, const eServiceReference &b)
328 {
329         return m_query->compareLessEqual((const eServiceReferenceDVB&)a, (const eServiceReferenceDVB&)b);
330 }
331
332 RESULT eDVBServiceList::startEdit(ePtr<iMutableServiceList> &res)
333 {
334         if (m_parent.flags & eServiceReference::flagDirectory) // bouquet
335         {
336                 ePtr<iDVBChannelList> db;
337                 ePtr<eDVBResourceManager> resm;
338
339                 if (eDVBResourceManager::getInstance(resm) || resm->getChannelList(db))
340                         return -1;
341
342                 if (db->getBouquet(m_parent, m_bouquet) != 0)
343                         return -1;
344
345                 res = this;
346                 
347                 return 0;
348         }
349         res = 0;
350         return -1;
351 }
352
353 RESULT eDVBServiceList::addService(eServiceReference &ref)
354 {
355         if (!m_bouquet)
356                 return -1;
357         return m_bouquet->addService(ref);
358 }
359
360 RESULT eDVBServiceList::removeService(eServiceReference &ref)
361 {
362         if (!m_bouquet)
363                 return -1;
364         return m_bouquet->removeService(ref);
365 }
366
367 RESULT eDVBServiceList::moveService(eServiceReference &ref, int pos)
368 {
369         if (!m_bouquet)
370                 return -1;
371         return m_bouquet->moveService(ref, pos);
372 }
373
374 RESULT eDVBServiceList::flushChanges()
375 {
376         if (!m_bouquet)
377                 return -1;
378         return m_bouquet->flushChanges();
379 }
380
381 RESULT eServiceFactoryDVB::play(const eServiceReference &ref, ePtr<iPlayableService> &ptr)
382 {
383         ePtr<eDVBService> service;
384         int r = lookupService(service, ref);
385         if (r)
386                 service = 0;
387                 // check resources...
388         ptr = new eDVBServicePlay(ref, service);
389         return 0;
390 }
391
392 RESULT eServiceFactoryDVB::record(const eServiceReference &ref, ePtr<iRecordableService> &ptr)
393 {
394         if (ref.path.empty())
395         {
396                 ptr = new eDVBServiceRecord((eServiceReferenceDVB&)ref);
397                 return 0;
398         } else
399         {
400                 ptr = 0;
401                 return -1;
402         }
403 }
404
405 RESULT eServiceFactoryDVB::list(const eServiceReference &ref, ePtr<iListableService> &ptr)
406 {
407         ePtr<eDVBServiceList> list = new eDVBServiceList(ref);
408         if (list->startQuery())
409         {
410                 ptr = 0;
411                 return -1;
412         }
413         
414         ptr = list;
415         return 0;
416 }
417
418 RESULT eServiceFactoryDVB::info(const eServiceReference &ref, ePtr<iStaticServiceInformation> &ptr)
419 {
420         /* is a listable service? */
421         if ((ref.flags & eServiceReference::flagDirectory) == eServiceReference::flagDirectory) // bouquet
422         {
423                 if ( !ref.name.empty() )  // satellites or providers list
424                         ptr = new eStaticServiceDVBInformation;
425                 else // a dvb bouquet
426                         ptr = new eStaticServiceDVBBouquetInformation;
427         }
428         else if (!ref.path.empty()) /* do we have a PVR service? */
429                 ptr = new eStaticServiceDVBPVRInformation(ref);
430         else // normal dvb service
431         {
432                 ePtr<eDVBService> service;
433                 if (lookupService(service, ref)) // no eDVBService avail for this reference ( Linkage Services... )
434                         ptr = new eStaticServiceDVBInformation;
435                 else
436                         /* eDVBService has the iStaticServiceInformation interface, so we pass it here. */
437                         ptr = service;
438         }
439         return 0;
440 }
441
442 RESULT eServiceFactoryDVB::offlineOperations(const eServiceReference &ref, ePtr<iServiceOfflineOperations> &ptr)
443 {
444         if (ref.path.empty())
445         {
446                 ptr = 0;
447                 return -1;
448         } else
449         {
450                 ptr = new eDVBPVRServiceOfflineOperations(ref);
451                 return 0;
452         }
453 }
454
455 RESULT eServiceFactoryDVB::lookupService(ePtr<eDVBService> &service, const eServiceReference &ref)
456 {
457                         // TODO: handle the listing itself
458         // if (ref.... == -1) .. return "... bouquets ...";
459         // could be also done in another serviceFactory (with seperate ID) to seperate actual services and lists
460                         // TODO: cache
461         ePtr<iDVBChannelList> db;
462         ePtr<eDVBResourceManager> res;
463         
464         int err;
465         if ((err = eDVBResourceManager::getInstance(res)) != 0)
466         {
467                 eDebug("no resource manager");
468                 return err;
469         }
470         if ((err = res->getChannelList(db)) != 0)
471         {
472                 eDebug("no channel list");
473                 return err;
474         }
475         
476                 /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */
477         if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0)
478         {
479                 eDebug("getService failed!");
480                 return err;
481         }
482
483         return 0;
484 }
485
486 eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
487         m_reference(ref), m_dvb_service(service), m_service_handler(0), m_is_paused(0)
488 {
489         m_is_pvr = !ref.path.empty();
490         m_timeshift_enabled = 0;
491         
492         CONNECT(m_service_handler.serviceEvent, eDVBServicePlay::serviceEvent);
493         CONNECT(m_event_handler.m_eit_changed, eDVBServicePlay::gotNewEvent);
494 }
495
496 eDVBServicePlay::~eDVBServicePlay()
497 {
498 }
499
500 void eDVBServicePlay::gotNewEvent()
501 {
502 #if 0
503                 // debug only
504         ePtr<eServiceEvent> m_event_now, m_event_next;
505         getEvent(m_event_now, 0);
506         getEvent(m_event_next, 1);
507
508         if (m_event_now)
509                 eDebug("now running: %s (%d seconds :)", m_event_now->m_event_name.c_str(), m_event_now->m_duration);
510         if (m_event_next)
511                 eDebug("next running: %s (%d seconds :)", m_event_next->m_event_name.c_str(), m_event_next->m_duration);
512 #endif
513         m_event((iPlayableService*)this, evUpdatedEventInfo);
514 }
515
516 void eDVBServicePlay::serviceEvent(int event)
517 {
518         switch (event)
519         {
520         case eDVBServicePMTHandler::eventTuned:
521         {
522                 ePtr<iDVBDemux> m_demux;
523                 if (!m_service_handler.getDemux(m_demux))
524                 {
525                         eServiceReferenceDVB &ref = (eServiceReferenceDVB&) m_reference;
526                         int sid = ref.getParentServiceID().get();
527                         if (!sid)
528                                 sid = ref.getServiceID().get();
529                         if ( ref.getParentTransportStreamID().get() &&
530                                 ref.getParentTransportStreamID() != ref.getTransportStreamID() )
531                                 m_event_handler.startOther(m_demux, sid);
532                         else
533                                 m_event_handler.start(m_demux, sid);
534                 }
535                 break;
536         }
537         case eDVBServicePMTHandler::eventTuneFailed:
538         {
539                 eDebug("DVB service failed to tune");
540                 m_event((iPlayableService*)this, evTuneFailed);
541                 break;
542         }
543         case eDVBServicePMTHandler::eventNewProgramInfo:
544         {
545                 int vpid = -1, apid = -1, apidtype = -1, pcrpid = -1;
546                 eDVBServicePMTHandler::program program;
547                 if (m_service_handler.getProgramInfo(program))
548                         eDebug("getting program info failed.");
549                 else
550                 {
551                         eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size());
552                         if (!program.videoStreams.empty())
553                         {
554                                 eDebugNoNewLine(" (");
555                                 for (std::vector<eDVBServicePMTHandler::videoStream>::const_iterator
556                                         i(program.videoStreams.begin()); 
557                                         i != program.videoStreams.end(); ++i)
558                                 {
559                                         if (vpid == -1)
560                                                 vpid = i->pid;
561                                         if (i != program.videoStreams.begin())
562                                                 eDebugNoNewLine(", ");
563                                         eDebugNoNewLine("%04x", i->pid);
564                                 }
565                                 eDebugNoNewLine(")");
566                         }
567                         eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size());
568                         if (!program.audioStreams.empty())
569                         {
570                                 eDebugNoNewLine(" (");
571                                 for (std::vector<eDVBServicePMTHandler::audioStream>::const_iterator
572                                         i(program.audioStreams.begin()); 
573                                         i != program.audioStreams.end(); ++i)
574                                 {
575                                         if (apid == -1)
576                                         {
577                                                 apid = i->pid;
578                                                 apidtype = i->type;
579                                         }
580                                         if (i != program.audioStreams.begin())
581                                                 eDebugNoNewLine(", ");
582                                         eDebugNoNewLine("%04x", i->pid);
583                                 }
584                                 eDebugNoNewLine(")");
585                         }
586                         eDebug(", and the pcr pid is %04x", program.pcrPid);
587                         if (program.pcrPid != 0x1fff)
588                                 pcrpid = program.pcrPid;
589                 }
590                 
591                 if (!m_decoder)
592                 {
593                         ePtr<iDVBDemux> demux;
594                         m_service_handler.getDemux(demux);
595                         if (demux)
596                                 demux->getMPEGDecoder(m_decoder);
597                 }
598
599                 if (m_decoder)
600                 {
601                         m_decoder->setVideoPID(vpid);
602                         m_current_audio_stream = 0;
603                         m_decoder->setAudioPID(apid, apidtype);
604                         if (!m_is_pvr)
605                                 m_decoder->setSyncPCR(pcrpid);
606                         else
607                                 m_decoder->setSyncPCR(-1);
608                         m_decoder->start();
609 // how we can do this better?
610 // update cache pid when the user changed the audio track or video track
611 // TODO handling of difference audio types.. default audio types..
612                                 
613                                 /* don't worry about non-existing services, nor pvr services */
614                         if (m_dvb_service && !m_is_pvr)
615                         {
616                                 m_dvb_service->setCachePID(eDVBService::cVPID, vpid);
617                                 m_dvb_service->setCachePID(eDVBService::cAPID, apid);
618                                 m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid);
619                         }
620                 }
621                 
622                 break;
623         }
624         }
625 }
626
627 RESULT eDVBServicePlay::start()
628 {
629         int r;
630         eDebug("starting DVB service");
631         r = m_service_handler.tune((eServiceReferenceDVB&)m_reference);
632         eDebug("tune result: %d", r);
633         m_event(this, evStart);
634         return 0;
635 }
636
637 RESULT eDVBServicePlay::stop()
638 {
639         eDebug("stopping..");
640         return 0;
641 }
642
643 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
644 {
645         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
646         return 0;
647 }
648
649 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
650 {
651         if (!m_is_pvr)
652         {
653                 ptr = 0;
654                 return -1;
655         }
656
657         ptr = this;
658         return 0;
659 }
660
661 RESULT eDVBServicePlay::setSlowMotion(int ratio)
662 {
663         if (m_decoder)
664                 return m_decoder->setSlowMotion(ratio);
665         else
666                 return -1;
667 }
668
669 RESULT eDVBServicePlay::setFastForward(int ratio)
670 {
671         if (m_decoder)
672                 return m_decoder->setFastForward(ratio);
673         else
674                 return -1;
675 }
676     
677 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
678 {
679         if (m_is_pvr)
680         {
681                 ptr = this;
682                 return 0;
683         }
684         
685         ptr = 0;
686         return -1;
687 }
688
689 RESULT eDVBServicePlay::getLength(pts_t &len)
690 {
691         ePtr<iDVBPVRChannel> pvr_channel;
692         
693         if (m_service_handler.getPVRChannel(pvr_channel))
694         {
695                 eDebug("getPVRChannel failed!");
696                 return -1;
697         }
698         
699         return pvr_channel->getLength(len);
700 }
701
702 RESULT eDVBServicePlay::pause()
703 {
704         if (!m_is_paused && m_decoder)
705         {
706                 m_is_paused = 1;
707                 return m_decoder->freeze(0);
708         } else
709                 return -1;
710 }
711
712 RESULT eDVBServicePlay::unpause()
713 {
714         if (m_is_paused && m_decoder)
715         {
716                 m_is_paused = 0;
717                 return m_decoder->unfreeze();
718         } else
719                 return -1;
720 }
721
722 RESULT eDVBServicePlay::seekTo(pts_t to)
723 {
724         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
725
726         ePtr<iDVBPVRChannel> pvr_channel;
727         
728         if (m_service_handler.getPVRChannel(pvr_channel))
729                 return -1;
730         
731         ePtr<iDVBDemux> demux;
732         m_service_handler.getDemux(demux);
733         if (!demux)
734                 return -1;
735         
736         return pvr_channel->seekTo(demux, 0, to);
737 }
738
739 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
740 {
741         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
742
743         ePtr<iDVBPVRChannel> pvr_channel;
744         
745         if (m_service_handler.getPVRChannel(pvr_channel))
746                 return -1;
747         
748         to *= direction;
749         
750         ePtr<iDVBDemux> demux;
751         m_service_handler.getDemux(demux);
752         if (!demux)
753                 return -1;
754         
755         return pvr_channel->seekTo(demux, 1, to);
756 }
757
758 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
759 {
760         ePtr<iDVBPVRChannel> pvr_channel;
761         
762         if (m_service_handler.getPVRChannel(pvr_channel))
763                 return -1;
764         
765         ePtr<iDVBDemux> demux;
766         m_service_handler.getDemux(demux);
767         if (!demux)
768                 return -1;
769         
770         return pvr_channel->getCurrentPosition(demux, pos, 1);
771 }
772
773 RESULT eDVBServicePlay::setTrickmode(int trick)
774 {
775         if (m_decoder)
776                 m_decoder->setTrickmode(trick);
777         return 0;
778 }
779
780 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
781 {
782         ptr = this;
783         return 0;
784 }
785
786 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
787 {
788         ptr = this;
789         return 0;
790 }
791
792 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
793 {
794         ptr = this;
795         return 0;
796 }
797
798 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
799 {
800         ptr = this;
801         return 0;
802 }
803
804 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
805 {
806         if (m_timeshift_enabled || !m_is_pvr)
807         {
808                 ptr = this;
809                 return 0;
810         }
811         ptr = 0;
812         return -1;
813 }
814
815 RESULT eDVBServicePlay::getName(std::string &name)
816 {
817         if (m_dvb_service)
818         {
819                 m_dvb_service->getName(m_reference, name);
820                 if (name.empty())
821                         name = "(...)";
822         }
823         else if (!m_reference.name.empty())
824                 eStaticServiceDVBInformation().getName(m_reference, name);
825         else
826                 name = "DVB service";
827         return 0;
828 }
829
830 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
831 {
832         return m_event_handler.getEvent(evt, nownext);
833 }
834
835 int eDVBServicePlay::getInfo(int w)
836 {
837         eDVBServicePMTHandler::program program;
838
839         if (m_service_handler.getProgramInfo(program))
840                 return -1;
841         
842         switch (w)
843         {
844         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
845         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
846         case sPCRPID: return program.pcrPid;
847         case sPMTPID: return program.pmtPid;
848         case sTXTPID: return -1;
849                 
850         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
851         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
852         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
853         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
854         case sProvider: if (!m_dvb_service) return -1; return -2;
855         default:
856                 return -1;
857         }
858 }
859
860 std::string eDVBServicePlay::getInfoString(int w)
861 {       
862         switch (w)
863         {
864         case sProvider:
865                 if (!m_dvb_service) return "";
866                 return m_dvb_service->m_provider_name;
867         default:
868                 return "";
869         }
870 }
871
872 int eDVBServicePlay::getNumberOfTracks()
873 {
874         eDVBServicePMTHandler::program program;
875         if (m_service_handler.getProgramInfo(program))
876                 return 0;
877         return program.audioStreams.size();
878 }
879
880 RESULT eDVBServicePlay::selectTrack(unsigned int i)
881 {
882         int ret = selectAudioStream(i);
883
884         if (m_decoder->start())
885                 return -5;
886
887         return ret;
888 }
889
890 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
891 {
892         eDVBServicePMTHandler::program program;
893
894         if (m_service_handler.getProgramInfo(program))
895                 return -1;
896         
897         if (i >= program.audioStreams.size())
898                 return -2;
899         
900         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
901                 info.m_description = "MPEG";
902         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
903                 info.m_description = "AC3";
904         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
905                 info.m_description = "DTS";
906         else
907                 info.m_description = "???";
908
909         if (program.audioStreams[i].component_tag != -1)
910         {
911                 ePtr<eServiceEvent> evt;
912                 if (!m_event_handler.getEvent(evt, 0))
913                 {
914                         ePtr<eComponentData> data;
915                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
916                                 info.m_language = data->getText();
917                 }
918         }
919
920         if (info.m_language.empty())
921                 info.m_language = program.audioStreams[i].language_code;
922         
923         return 0;
924 }
925
926 int eDVBServicePlay::selectAudioStream(int i)
927 {
928         eDVBServicePMTHandler::program program;
929
930         if (m_service_handler.getProgramInfo(program))
931                 return -1;
932         
933         if ((unsigned int)i >= program.audioStreams.size())
934                 return -2;
935         
936         if (!m_decoder)
937                 return -3;
938         
939         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
940                 return -4;
941
942         m_current_audio_stream = i;
943
944         return 0;
945 }
946
947 int eDVBServicePlay::getFrontendInfo(int w)
948 {
949         if (m_is_pvr)
950                 return 0;
951         eUsePtr<iDVBChannel> channel;
952         if(m_service_handler.getChannel(channel))
953                 return 0;
954         ePtr<iDVBFrontend> fe;
955         if(channel->getFrontend(fe))
956                 return 0;
957         return fe->readFrontendData(w);
958 }
959
960 int eDVBServicePlay::getNumberOfSubservices()
961 {
962         ePtr<eServiceEvent> evt;
963         if (!m_event_handler.getEvent(evt, 0))
964                 return evt->getNumOfLinkageServices();
965         return 0;
966 }
967
968 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
969 {
970         ePtr<eServiceEvent> evt;
971         if (!m_event_handler.getEvent(evt, 0))
972         {
973                 if (!evt->getLinkageService(sub, n))
974                 {
975                         eServiceReferenceDVB &subservice = (eServiceReferenceDVB&) sub;
976                         eServiceReferenceDVB &current = (eServiceReferenceDVB&) m_reference;
977                         subservice.setDVBNamespace(current.getDVBNamespace());
978                         if ( current.getParentTransportStreamID().get() )
979                         {
980                                 subservice.setParentTransportStreamID( current.getParentTransportStreamID() );
981                                 subservice.setParentServiceID( current.getParentServiceID() );
982                         }
983                         else
984                         {
985                                 subservice.setParentTransportStreamID( current.getTransportStreamID() );
986                                 subservice.setParentServiceID( current.getServiceID() );
987                         }
988                         if ( subservice.getParentTransportStreamID() == subservice.getTransportStreamID() &&
989                                 subservice.getParentServiceID() == subservice.getServiceID() )
990                         {
991                                 subservice.setParentTransportStreamID( eTransportStreamID(0) );
992                                 subservice.setParentServiceID( eServiceID(0) );
993                         }
994                         return 0;
995                 }
996         }
997         sub.type=eServiceReference::idInvalid;
998         return -1;
999 }
1000
1001 RESULT eDVBServicePlay::startTimeshift()
1002 {
1003         if (m_timeshift_enabled)
1004                 return -1;
1005         eDebug("TIMESHIFT - start!");
1006         return 0;
1007 }
1008
1009 RESULT eDVBServicePlay::stopTimeshift()
1010 {
1011         if (!m_timeshift_enabled)
1012                 return -1;
1013         m_timeshift_enabled = 0;
1014         eDebug("timeshift disabled");
1015         return 0;
1016 }
1017
1018 DEFINE_REF(eDVBServicePlay)
1019
1020 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");