format, ac3 and crypted indicators now working
[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                 m_event((iPlayableService*)this, evUpdatedInfo);
623                 break;
624         }
625         }
626 }
627
628 RESULT eDVBServicePlay::start()
629 {
630         int r;
631         eDebug("starting DVB service");
632         r = m_service_handler.tune((eServiceReferenceDVB&)m_reference);
633         eDebug("tune result: %d", r);
634         m_event(this, evStart);
635         return 0;
636 }
637
638 RESULT eDVBServicePlay::stop()
639 {
640         eDebug("stopping..");
641         return 0;
642 }
643
644 RESULT eDVBServicePlay::connectEvent(const Slot2<void,iPlayableService*,int> &event, ePtr<eConnection> &connection)
645 {
646         connection = new eConnection((iPlayableService*)this, m_event.connect(event));
647         return 0;
648 }
649
650 RESULT eDVBServicePlay::pause(ePtr<iPauseableService> &ptr)
651 {
652         if (!m_is_pvr)
653         {
654                 ptr = 0;
655                 return -1;
656         }
657
658         ptr = this;
659         return 0;
660 }
661
662 RESULT eDVBServicePlay::setSlowMotion(int ratio)
663 {
664         if (m_decoder)
665                 return m_decoder->setSlowMotion(ratio);
666         else
667                 return -1;
668 }
669
670 RESULT eDVBServicePlay::setFastForward(int ratio)
671 {
672         if (m_decoder)
673                 return m_decoder->setFastForward(ratio);
674         else
675                 return -1;
676 }
677     
678 RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
679 {
680         if (m_is_pvr)
681         {
682                 ptr = this;
683                 return 0;
684         }
685         
686         ptr = 0;
687         return -1;
688 }
689
690 RESULT eDVBServicePlay::getLength(pts_t &len)
691 {
692         ePtr<iDVBPVRChannel> pvr_channel;
693         
694         if (m_service_handler.getPVRChannel(pvr_channel))
695         {
696                 eDebug("getPVRChannel failed!");
697                 return -1;
698         }
699         
700         return pvr_channel->getLength(len);
701 }
702
703 RESULT eDVBServicePlay::pause()
704 {
705         if (!m_is_paused && m_decoder)
706         {
707                 m_is_paused = 1;
708                 return m_decoder->freeze(0);
709         } else
710                 return -1;
711 }
712
713 RESULT eDVBServicePlay::unpause()
714 {
715         if (m_is_paused && m_decoder)
716         {
717                 m_is_paused = 0;
718                 return m_decoder->unfreeze();
719         } else
720                 return -1;
721 }
722
723 RESULT eDVBServicePlay::seekTo(pts_t to)
724 {
725         eDebug("eDVBServicePlay::seekTo: jump %lld", to);
726
727         ePtr<iDVBPVRChannel> pvr_channel;
728         
729         if (m_service_handler.getPVRChannel(pvr_channel))
730                 return -1;
731         
732         ePtr<iDVBDemux> demux;
733         m_service_handler.getDemux(demux);
734         if (!demux)
735                 return -1;
736         
737         return pvr_channel->seekTo(demux, 0, to);
738 }
739
740 RESULT eDVBServicePlay::seekRelative(int direction, pts_t to)
741 {
742         eDebug("eDVBServicePlay::seekRelative: jump %d, %lld", direction, to);
743
744         ePtr<iDVBPVRChannel> pvr_channel;
745         
746         if (m_service_handler.getPVRChannel(pvr_channel))
747                 return -1;
748         
749         to *= direction;
750         
751         ePtr<iDVBDemux> demux;
752         m_service_handler.getDemux(demux);
753         if (!demux)
754                 return -1;
755         
756         return pvr_channel->seekTo(demux, 1, to);
757 }
758
759 RESULT eDVBServicePlay::getPlayPosition(pts_t &pos)
760 {
761         ePtr<iDVBPVRChannel> pvr_channel;
762         
763         if (m_service_handler.getPVRChannel(pvr_channel))
764                 return -1;
765         
766         ePtr<iDVBDemux> demux;
767         m_service_handler.getDemux(demux);
768         if (!demux)
769                 return -1;
770         
771         return pvr_channel->getCurrentPosition(demux, pos, 1);
772 }
773
774 RESULT eDVBServicePlay::setTrickmode(int trick)
775 {
776         if (m_decoder)
777                 m_decoder->setTrickmode(trick);
778         return 0;
779 }
780
781 RESULT eDVBServicePlay::frontendStatusInfo(ePtr<iFrontendStatusInformation> &ptr)
782 {
783         ptr = this;
784         return 0;
785 }
786
787 RESULT eDVBServicePlay::info(ePtr<iServiceInformation> &ptr)
788 {
789         ptr = this;
790         return 0;
791 }
792
793 RESULT eDVBServicePlay::audioTracks(ePtr<iAudioTrackSelection> &ptr)
794 {
795         ptr = this;
796         return 0;
797 }
798
799 RESULT eDVBServicePlay::subServices(ePtr<iSubserviceList> &ptr)
800 {
801         ptr = this;
802         return 0;
803 }
804
805 RESULT eDVBServicePlay::timeshift(ePtr<iTimeshiftService> &ptr)
806 {
807         if (m_timeshift_enabled || !m_is_pvr)
808         {
809                 ptr = this;
810                 return 0;
811         }
812         ptr = 0;
813         return -1;
814 }
815
816 RESULT eDVBServicePlay::getName(std::string &name)
817 {
818         if (m_dvb_service)
819         {
820                 m_dvb_service->getName(m_reference, name);
821                 if (name.empty())
822                         name = "(...)";
823         }
824         else if (!m_reference.name.empty())
825                 eStaticServiceDVBInformation().getName(m_reference, name);
826         else
827                 name = "DVB service";
828         return 0;
829 }
830
831 RESULT eDVBServicePlay::getEvent(ePtr<eServiceEvent> &evt, int nownext)
832 {
833         return m_event_handler.getEvent(evt, nownext);
834 }
835
836 int eDVBServicePlay::getInfo(int w)
837 {
838         eDVBServicePMTHandler::program program;
839
840         if (m_service_handler.getProgramInfo(program))
841                 return -1;
842         
843         switch (w)
844         {
845         case sAspect:
846                 if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
847                 {
848                         ePtr<eServiceEvent> evt;
849                         if (!m_event_handler.getEvent(evt, 0))
850                         {
851                                 ePtr<eComponentData> data;
852                                 if (!evt->getComponentData(data, program.videoStreams[0].component_tag))
853                                 {
854                                         if ( data->getStreamContent() == 1 )
855                                         {
856                                                 switch(data->getComponentType())
857                                                 {
858                                                         // SD
859                                                         case 1: // 4:3 SD PAL
860                                                         case 2:
861                                                         case 3: // 16:9 SD PAL
862                                                         case 4: // > 16:9 PAL
863                                                         case 5: // 4:3 SD NTSC
864                                                         case 6: 
865                                                         case 7: // 16:9 SD NTSC
866                                                         case 8: // > 16:9 NTSC
867
868                                                         // HD
869                                                         case 9: // 4:3 HD PAL
870                                                         case 0xA:
871                                                         case 0xB: // 16:9 HD PAL
872                                                         case 0xC: // > 16:9 HD PAL
873                                                         case 0xD: // 4:3 HD NTSC
874                                                         case 0xE:
875                                                         case 0xF: // 16:9 HD NTSC
876                                                         case 0x10: // > 16:9 HD PAL
877                                                                 return data->getComponentType();
878                                                 }
879                                         }
880                                 }
881                         }
882                 }
883                 return -1;
884         case sIsCrypted: return program.isCrypted;
885         case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
886         case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;
887         case sPCRPID: return program.pcrPid;
888         case sPMTPID: return program.pmtPid;
889         case sTXTPID: return -1;
890         case sSID: return ((const eServiceReferenceDVB&)m_reference).getServiceID().get();
891         case sONID: return ((const eServiceReferenceDVB&)m_reference).getOriginalNetworkID().get();
892         case sTSID: return ((const eServiceReferenceDVB&)m_reference).getTransportStreamID().get();
893         case sNamespace: return ((const eServiceReferenceDVB&)m_reference).getDVBNamespace().get();
894         case sProvider: if (!m_dvb_service) return -1; return -2;
895         default:
896                 return -1;
897         }
898 }
899
900 std::string eDVBServicePlay::getInfoString(int w)
901 {       
902         switch (w)
903         {
904         case sProvider:
905                 if (!m_dvb_service) return "";
906                 return m_dvb_service->m_provider_name;
907         default:
908                 return "";
909         }
910 }
911
912 int eDVBServicePlay::getNumberOfTracks()
913 {
914         eDVBServicePMTHandler::program program;
915         if (m_service_handler.getProgramInfo(program))
916                 return 0;
917         return program.audioStreams.size();
918 }
919
920 RESULT eDVBServicePlay::selectTrack(unsigned int i)
921 {
922         int ret = selectAudioStream(i);
923
924         if (m_decoder->start())
925                 return -5;
926
927         return ret;
928 }
929
930 RESULT eDVBServicePlay::getTrackInfo(struct iAudioTrackInfo &info, unsigned int i)
931 {
932         eDVBServicePMTHandler::program program;
933
934         if (m_service_handler.getProgramInfo(program))
935                 return -1;
936         
937         if (i >= program.audioStreams.size())
938                 return -2;
939         
940         if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atMPEG)
941                 info.m_description = "MPEG";
942         else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAC3)
943                 info.m_description = "AC3";
944         else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
945                 info.m_description = "DTS";
946         else
947                 info.m_description = "???";
948
949         if (program.audioStreams[i].component_tag != -1)
950         {
951                 ePtr<eServiceEvent> evt;
952                 if (!m_event_handler.getEvent(evt, 0))
953                 {
954                         ePtr<eComponentData> data;
955                         if (!evt->getComponentData(data, program.audioStreams[i].component_tag))
956                                 info.m_language = data->getText();
957                 }
958         }
959
960         if (info.m_language.empty())
961                 info.m_language = program.audioStreams[i].language_code;
962         
963         return 0;
964 }
965
966 int eDVBServicePlay::selectAudioStream(int i)
967 {
968         eDVBServicePMTHandler::program program;
969
970         if (m_service_handler.getProgramInfo(program))
971                 return -1;
972         
973         if ((unsigned int)i >= program.audioStreams.size())
974                 return -2;
975         
976         if (!m_decoder)
977                 return -3;
978         
979         if (m_decoder->setAudioPID(program.audioStreams[i].pid, program.audioStreams[i].type))
980                 return -4;
981
982         m_current_audio_stream = i;
983
984         return 0;
985 }
986
987 int eDVBServicePlay::getFrontendInfo(int w)
988 {
989         if (m_is_pvr)
990                 return 0;
991         eUsePtr<iDVBChannel> channel;
992         if(m_service_handler.getChannel(channel))
993                 return 0;
994         ePtr<iDVBFrontend> fe;
995         if(channel->getFrontend(fe))
996                 return 0;
997         return fe->readFrontendData(w);
998 }
999
1000 int eDVBServicePlay::getNumberOfSubservices()
1001 {
1002         ePtr<eServiceEvent> evt;
1003         if (!m_event_handler.getEvent(evt, 0))
1004                 return evt->getNumOfLinkageServices();
1005         return 0;
1006 }
1007
1008 RESULT eDVBServicePlay::getSubservice(eServiceReference &sub, unsigned int n)
1009 {
1010         ePtr<eServiceEvent> evt;
1011         if (!m_event_handler.getEvent(evt, 0))
1012         {
1013                 if (!evt->getLinkageService(sub, n))
1014                 {
1015                         eServiceReferenceDVB &subservice = (eServiceReferenceDVB&) sub;
1016                         eServiceReferenceDVB &current = (eServiceReferenceDVB&) m_reference;
1017                         subservice.setDVBNamespace(current.getDVBNamespace());
1018                         if ( current.getParentTransportStreamID().get() )
1019                         {
1020                                 subservice.setParentTransportStreamID( current.getParentTransportStreamID() );
1021                                 subservice.setParentServiceID( current.getParentServiceID() );
1022                         }
1023                         else
1024                         {
1025                                 subservice.setParentTransportStreamID( current.getTransportStreamID() );
1026                                 subservice.setParentServiceID( current.getServiceID() );
1027                         }
1028                         if ( subservice.getParentTransportStreamID() == subservice.getTransportStreamID() &&
1029                                 subservice.getParentServiceID() == subservice.getServiceID() )
1030                         {
1031                                 subservice.setParentTransportStreamID( eTransportStreamID(0) );
1032                                 subservice.setParentServiceID( eServiceID(0) );
1033                         }
1034                         return 0;
1035                 }
1036         }
1037         sub.type=eServiceReference::idInvalid;
1038         return -1;
1039 }
1040
1041 RESULT eDVBServicePlay::startTimeshift()
1042 {
1043         if (m_timeshift_enabled)
1044                 return -1;
1045         eDebug("TIMESHIFT - start!");
1046         return 0;
1047 }
1048
1049 RESULT eDVBServicePlay::stopTimeshift()
1050 {
1051         if (!m_timeshift_enabled)
1052                 return -1;
1053         m_timeshift_enabled = 0;
1054         eDebug("timeshift disabled");
1055         return 0;
1056 }
1057
1058 DEFINE_REF(eDVBServicePlay)
1059
1060 eAutoInitPtr<eServiceFactoryDVB> init_eServiceFactoryDVB(eAutoInitNumbers::service+1, "eServiceFactoryDVB");