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