add needed functions
[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                 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         return -1;
725 }
726
727 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
728 {
729         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
730
731         ePtr<iDVBPVRChannel> pvr_channel;
732         
733         if (m_service_handler.getPVRChannel(pvr_channel))
734                 return -1;
735         
736         to *= direction;
737         
738         ePtr<iDVBDemux> demux;
739         m_service_handler.getDemux(demux);
740         if (!demux)
741                 return -1;
742         
743         return pvr_channel->seekTo(demux, 1, to);
744 }
745
746 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
747 {
748         ePtr<iDVBPVRChannel> pvr_channel;
749         
750         if (m_service_handler.getPVRChannel(pvr_channel))
751                 return -1;
752         
753         ePtr<iDVBDemux> demux;
754         m_service_handler.getDemux(demux);
755         if (!demux)
756                 return -1;
757         
758         return pvr_channel->getCurrentPosition(demux, pos);
759 }
760
761 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
762 {
763         ptr = this;
764         return 0;
765 }
766
767 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
768 {
769         ptr = this;
770         return 0;
771 }
772
773 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
774 {
775         ptr = this;
776         return 0;
777 }
778
779 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
780 {
781         ptr = this;
782         return 0;
783 }
784
785 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
786 {
787         if (m_timeshift_enabled || !m_is_pvr)
788         {
789                 ptr = this;
790                 return 0;
791         }
792         ptr = 0;
793         return -1;
794 }
795
796 RESULT eDVBServicePlay::getName(std::string &name)
797 {
798         if (m_dvb_service)
799         {
800                 m_dvb_service->getName(m_reference, name);
801                 if (name.empty())
802                         name = "(...)";
803         }
804         else if (!m_reference.name.empty())
805                 eStaticServiceDVBInformation().getName(m_reference, name);
806         else
807                 name = "DVB service";
808         return 0;
809 }
810
811 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
812 {
813         return m_event_handler.getEvent(evt, nownext);
814 }
815
816 int eDVBServicePlay::getInfo(int w)
817 {
818         eDVBServicePMTHandler::program program;
819
820         if (m_service_handler.getProgramInfo(program))
821                 return -1;
822         
823         switch (w)
824         {
825         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
826         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
827         case sPCRPID: return program.pcrPid;
828         case sPMTPID: return program.pmtPid;
829         case sTXTPID: return -1;
830                 
831         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
832         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
833         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
834         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
835         case sProvider: if (!m_dvb_service) return -1; return -2;
836         default:
837                 return -1;
838         }
839 }
840
841 std::string eDVBServicePlay::getInfoString(int w)
842 {       
843         switch (w)
844         {
845         case sProvider:
846                 if (!m_dvb_service) return "";
847                 return m_dvb_service->m_provider_name;
848         default:
849                 return "";
850         }
851 }
852
853 int eDVBServicePlay::getNumberOfTracks()
854 {
855         eDVBServicePMTHandler::program program;
856         if (m_service_handler.getProgramInfo(program))
857                 return 0;
858         return program.audioStreams.size();
859 }
860
861 RESULT eDVBServicePlay::selectTrack(unsigned int i)
862 {
863         int ret = selectAudioStream(i);
864
865         if (m_decoder->start())
866                 return -5;
867
868         return ret;
869 }
870
871 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
872 {
873         eDVBServicePMTHandler::program program;
874
875         if (m_service_handler.getProgramInfo(program))
876                 return -1;
877         
878         if (i >= program.audioStreams.size())
879                 return -2;
880         
881         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
882                 info.m_description = "MPEG";
883         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
884                 info.m_description = "AC3";
885         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
886                 info.m_description = "DTS";
887         else
888                 info.m_description = "???";
889
890         if (program.audioStreams[i].component_tag != -1)
891         {
892                 ePtr<eServiceEvent> evt;
893                 if (!m_event_handler.getEvent(evt, 0))
894                 {
895                         ePtr<eComponentData> data;
896                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
897                                 info.m_language = data->getText();
898                 }
899         }
900
901         if (info.m_language.empty())
902                 info.m_language = program.audioStreams[i].language_code;
903         
904         return 0;
905 }
906
907 int eDVBServicePlay::selectAudioStream(int i)
908 {
909         eDVBServicePMTHandler::program program;
910
911         if (m_service_handler.getProgramInfo(program))
912                 return -1;
913         
914         if ((unsigned int)i >= program.audioStreams.size())
915                 return -2;
916         
917         if (!m_decoder)
918                 return -3;
919         
920         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
921                 return -4;
922
923         m_current_audio_stream = i;
924
925         return 0;
926 }
927
928 int eDVBServicePlay::getFrontendInfo(int w)
929 {
930         if (m_is_pvr)
931                 return 0;
932         eUsePtr<iDVBChannel> channel;
933         if(m_service_handler.getChannel(channel))
934                 return 0;
935         ePtr<iDVBFrontend> fe;
936         if(channel->getFrontend(fe))
937                 return 0;
938         return fe->readFrontendData(w);
939 }
940
941 int eDVBServicePlay::getNumberOfSubservices()
942 {
943         ePtr<eServiceEvent> evt;
944         if (!m_event_handler.getEvent(evt, 0))
945                 return evt->getNumOfLinkageServices();
946         return 0;
947 }
948
949 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
950 {
951         ePtr<eServiceEvent> evt;
952         if (!m_event_handler.getEvent(evt, 0))
953         {
954                 if (!evt->getLinkageService(sub, n))
955                 {
956                         eServiceReferenceDVB &subservice = (eServiceReferenceDVB&) sub;
957                         eServiceReferenceDVB &current = (eServiceReferenceDVB&) m_reference;
958                         subservice.setDVBNamespace(current.getDVBNamespace());
959                         if ( current.getParentTransportStreamID().get() )
960                         {
961                                 subservice.setParentTransportStreamID( current.getParentTransportStreamID() );
962                                 subservice.setParentServiceID( current.getParentServiceID() );
963                         }
964                         else
965                         {
966                                 subservice.setParentTransportStreamID( current.getTransportStreamID() );
967                                 subservice.setParentServiceID( current.getServiceID() );
968                         }
969                         if ( subservice.getParentTransportStreamID() == subservice.getTransportStreamID() &&
970                                 subservice.getParentServiceID() == subservice.getServiceID() )
971                         {
972                                 subservice.setParentTransportStreamID( eTransportStreamID(0) );
973                                 subservice.setParentServiceID( eServiceID(0) );
974                         }
975                         return 0;
976                 }
977         }
978         sub.type=eServiceReference::idInvalid;
979         return -1;
980 }
981
982 RESULT eDVBServicePlay::startTimeshift()
983 {
984         if (m_timeshift_enabled)
985                 return -1;
986         eDebug("TIMESHIFT - start!");
987         return 0;
988 }
989
990 RESULT eDVBServicePlay::stopTimeshift()
991 {
992         if (!m_timeshift_enabled)
993                 return -1;
994         m_timeshift_enabled = 0;
995         eDebug("timeshift disabled");
996         return 0;
997 }
998
999 DEFINE_REF(eDVBServicePlay)
1000
1001 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");