From 4e8cae716ad3fdf29a7b2a45e5eec0a530f93277 Mon Sep 17 00:00:00 2001 From: Andreas Monzner Date: Tue, 16 May 2006 14:58:11 +0000 Subject: [PATCH] add ability to selecte the audio channel (mono left, stereo, mono right) from python store the current selected audio channel then per service in servicelist TODO: extend the audio track selection screen to make audio channel selection usable :) --- lib/dvb/db.cpp | 4 +- lib/dvb/decoder.cpp | 25 ++++++++++++ lib/dvb/decoder.h | 3 ++ lib/dvb/idvb.h | 12 ++++-- lib/dvb/pmt.cpp | 21 +++++----- lib/dvb/pmt.h | 1 + lib/python/Components/ChoiceList.py | 2 +- lib/python/Screens/InfoBarGenerics.py | 17 +++++++-- lib/service/iservice.h | 15 ++++++++ lib/service/servicedvb.cpp | 55 ++++++++++++++++++++------- lib/service/servicedvb.h | 8 +++- lib/service/servicemp3.h | 1 + 12 files changed, 129 insertions(+), 35 deletions(-) diff --git a/lib/dvb/db.cpp b/lib/dvb/db.cpp index 64ef6ed7..9b2324a6 100644 --- a/lib/dvb/db.cpp +++ b/lib/dvb/db.cpp @@ -232,14 +232,14 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ return res; } -int eDVBService::getCachePID(cacheID id) +int eDVBService::getCacheEntry(cacheID id) { if (id >= cacheMax) return -1; return m_cache[id]; } -void eDVBService::setCachePID(cacheID id, int pid) +void eDVBService::setCacheEntry(cacheID id, int pid) { if (id < cacheMax) m_cache[id] = pid; diff --git a/lib/dvb/decoder.cpp b/lib/dvb/decoder.cpp index 1bec997d..76d0f504 100644 --- a/lib/dvb/decoder.cpp +++ b/lib/dvb/decoder.cpp @@ -137,6 +137,22 @@ void eDVBAudio::unfreeze() eDebug("video: AUDIO_CONTINUE: %m"); } +void eDVBAudio::setChannel(int channel) +{ + int val = AUDIO_STEREO; + switch (channel) + { + case aMonoLeft: val = AUDIO_MONO_LEFT; break; + case aMonoRight: val = AUDIO_MONO_RIGHT; break; + default: + break; + } + if (::ioctl(m_fd, AUDIO_CHANNEL_SELECT, val) < 0) + eDebug("video: AUDIO_CHANNEL_SELECT: %m"); + else + eDebug("AUDIO_CHANNEL_SELECT ok"); +} + int eDVBAudio::getPTS(pts_t &now) { return ::ioctl(m_fd, AUDIO_GET_PTS, &now); @@ -552,6 +568,15 @@ RESULT eTSMPEGDecoder::setAudioPID(int apid, int type) return 0; } +RESULT eTSMPEGDecoder::setAudioChannel(int channel) +{ + if (m_audio) + m_audio->setChannel(channel); + else + eDebug("eTSMPEGDecoder::setAudioChannel but no audio decoder exist"); + return 0; +} + RESULT eTSMPEGDecoder::setSyncPCR(int pcrpid) { if (m_pcrpid != pcrpid) diff --git a/lib/dvb/decoder.h b/lib/dvb/decoder.h index 834499b0..f8719869 100644 --- a/lib/dvb/decoder.h +++ b/lib/dvb/decoder.h @@ -14,6 +14,8 @@ public: enum { aMPEG, aAC3, aDTS, aAAC }; eDVBAudio(eDVBDemux *demux, int dev); int startPid(int pid, int type); + enum { aMonoLeft, aStereo, aMonoRight }; + void setChannel(int channel); void stop(); #if HAVE_DVB_API_VERSION < 3 void start(); @@ -107,6 +109,7 @@ public: virtual ~eTSMPEGDecoder(); RESULT setVideoPID(int vpid, int type); RESULT setAudioPID(int apid, int type); + RESULT setAudioChannel(int channel); RESULT setSyncPCR(int pcrpid); RESULT setTextPID(int textpid); RESULT setSyncMaster(int who); diff --git a/lib/dvb/idvb.h b/lib/dvb/idvb.h index ecf8bb92..dff543ca 100644 --- a/lib/dvb/idvb.h +++ b/lib/dvb/idvb.h @@ -223,11 +223,11 @@ class eDVBService: public iStaticServiceInformation public: enum cacheID { - cVPID, cAPID, cTPID, cPCRPID, cAC3PID, cVTYPE, cacheMax + cVPID, cAPID, cTPID, cPCRPID, cAC3PID, cVTYPE, cACHANNEL, cacheMax }; - int getCachePID(cacheID); - void setCachePID(cacheID, int); + int getCacheEntry(cacheID); + void setCacheEntry(cacheID, int); bool cacheEmpty(); @@ -577,10 +577,14 @@ public: /** Set Displayed Video PID and type */ virtual RESULT setVideoPID(int vpid, int type)=0; - enum { af_MPEG, af_AC3, af_DTS }; + enum { af_MPEG, af_AC3, af_DTS, af_AAC }; /** Set Displayed Audio PID and type */ virtual RESULT setAudioPID(int apid, int type)=0; + enum { ac_left, ac_stereo, ac_right }; + /** Set Displayed Audio Channel */ + virtual RESULT setAudioChannel(int channel)=0; + /** Set Displayed Videotext PID */ virtual RESULT setTextPID(int vpid)=0; diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 11cda125..1032267d 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -216,6 +216,7 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) program.isCrypted = false; program.pmtPid = -1; program.textPid = -1; + program.audioChannel = m_service ? m_service->getCacheEntry(eDVBService::cACHANNEL) : -1; if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr)) { @@ -225,10 +226,10 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) int cached_tpid = -1; if ( m_service && !m_service->cacheEmpty() ) { - cached_vpid = m_service->getCachePID(eDVBService::cVPID); - cached_apid_mpeg = m_service->getCachePID(eDVBService::cAC3PID); - cached_apid_ac3 = m_service->getCachePID(eDVBService::cAPID); - cached_tpid = m_service->getCachePID(eDVBService::cTPID); + cached_vpid = m_service->getCacheEntry(eDVBService::cVPID); + cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cAC3PID); + cached_apid_ac3 = m_service->getCacheEntry(eDVBService::cAPID); + cached_tpid = m_service->getCacheEntry(eDVBService::cTPID); } eDVBTableSpec table_spec; ptr->getSpec(table_spec); @@ -359,12 +360,12 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) return 0; } else if ( m_service && !m_service->cacheEmpty() ) { - int vpid = m_service->getCachePID(eDVBService::cVPID), - apid_ac3 = m_service->getCachePID(eDVBService::cAC3PID), - apid_mpeg = m_service->getCachePID(eDVBService::cAPID), - pcrpid = m_service->getCachePID(eDVBService::cPCRPID), - tpid = m_service->getCachePID(eDVBService::cTPID), - vpidtype = m_service->getCachePID(eDVBService::cVTYPE), + int vpid = m_service->getCacheEntry(eDVBService::cVPID), + apid_ac3 = m_service->getCacheEntry(eDVBService::cAC3PID), + apid_mpeg = m_service->getCacheEntry(eDVBService::cAPID), + pcrpid = m_service->getCacheEntry(eDVBService::cPCRPID), + tpid = m_service->getCacheEntry(eDVBService::cTPID), + vpidtype = m_service->getCacheEntry(eDVBService::cVTYPE), cnt=0; if ( vpidtype == -1 ) vpidtype = videoStream::vtMPEG2; diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index b6a3743f..f4e99a57 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -122,6 +122,7 @@ public: int pmtPid; int textPid; bool isCrypted; + int audioChannel; }; int getProgramInfo(struct program &program); diff --git a/lib/python/Components/ChoiceList.py b/lib/python/Components/ChoiceList.py index ca58ecd6..fe3e6008 100644 --- a/lib/python/Components/ChoiceList.py +++ b/lib/python/Components/ChoiceList.py @@ -18,7 +18,7 @@ RT_VALIGN_BOTTOM = 16 def ChoiceEntryComponent(key, text): res = [ text ] - res.append((eListboxPythonMultiContent.TYPE_TEXT, 32, 00, 800,25, 0, RT_HALIGN_LEFT, text[0])) + res.append((eListboxPythonMultiContent.TYPE_TEXT, 32, 00, 800, 25, 0, RT_HALIGN_LEFT, text[0])) png = loadPNG(resolveFilename(SCOPE_SKIN_IMAGE, "key_" + key + "-fs8.png")) if png is not None: diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index c3c6e21a..67212656 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -13,7 +13,7 @@ from Components.PluginComponent import plugins from Components.ProgressBar import * from Components.ServiceEventTracker import ServiceEventTracker from Components.ServiceName import ServiceName -from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean +from Components.config import config, configElement, ConfigSubsection, configSequence, configElementBoolean, configSelection, configElement_nonSave, getConfigListEntry from Components.config import configfile, configsequencearg from Components.TimerList import TimerEntryComponent from Components.TunerInfo import TunerInfo @@ -1192,9 +1192,11 @@ class InfoBarAudioSelection: def audioSelection(self): service = self.session.nav.getCurrentService() audio = service.audioTracks() - self.audio = audio + self.audioTracks = audio n = audio.getNumberOfTracks() if n > 0: +# self.audioChannel = service.audioChannel() +# config.audio.audiochannel = configElement_nonSave("config.audio.audiochannel", configSelection, self.audioChannel.getCurrentChannel(), (("left", _("Left >")), ("stereo", _("< Stereo >")), ("right", _("< Right")))) tlist = [] for x in range(n): i = audio.getTrackInfo(x) @@ -1214,6 +1216,9 @@ class InfoBarAudioSelection: selectedAudio = tlist[0][1] tlist.sort(lambda x,y : cmp(x[0], y[0])) + +# tlist.insert(0, getConfigListEntry(_("Audio Channel"), config.audio.audiochannel)) + selection = 0 for x in tlist: if x[1] != selectedAudio: @@ -1222,11 +1227,15 @@ class InfoBarAudioSelection: break self.session.openWithCallback(self.audioSelected, ChoiceBox, title=_("Select audio track"), list = tlist, selection = selection) + else: + del self.audioTracks def audioSelected(self, audio): if audio is not None: - self.audio.selectTrack(audio[1]) - del self.audio + self.audioTracks.selectTrack(audio[1]) + del self.audioTracks +# del self.audioChannel +# del config.audio.audiochannel class InfoBarSubserviceSelection: def __init__(self): diff --git a/lib/service/iservice.h b/lib/service/iservice.h index c93c84a5..a24b8b21 100644 --- a/lib/service/iservice.h +++ b/lib/service/iservice.h @@ -374,6 +374,20 @@ public: TEMPLATE_TYPEDEF(ePtr, iAudioTrackSelectionPtr); +class iAudioChannelSelection: public iObject +{ +#ifdef SWIG + iAudioChannelSelection(); + ~iAudioChannelSelection(); +#endif +public: + enum { LEFT, STEREO, RIGHT }; + virtual int getCurrentChannel()=0; + virtual RESULT selectChannel(int i)=0; +}; + +TEMPLATE_TYPEDEF(ePtr, iAudioChannelSelectionPtr); + class iSubserviceList: public iObject { #ifdef SWIG @@ -459,6 +473,7 @@ public: virtual SWIG_VOID(RESULT) pause(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) info(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) audioTracks(ePtr &SWIG_OUTPUT)=0; + virtual SWIG_VOID(RESULT) audioChannel(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) subServices(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) frontendStatusInfo(ePtr &SWIG_OUTPUT)=0; virtual SWIG_VOID(RESULT) timeshift(ePtr &SWIG_OUTPUT)=0; diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index e9aeb8a9..0ec488fe 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -997,6 +997,12 @@ RESULT eDVBServicePlay::info(ePtr &ptr) return 0; } +RESULT eDVBServicePlay::audioChannel(ePtr &ptr) +{ + ptr = this; + return 0; +} + RESULT eDVBServicePlay::audioTracks(ePtr &ptr) { ptr = this; @@ -1239,12 +1245,12 @@ int eDVBServicePlay::selectAudioStream(int i) { if (program.audioStreams[i].type == eDVBAudio::aMPEG) { - m_dvb_service->setCachePID(eDVBService::cAPID, program.audioStreams[i].pid); - m_dvb_service->setCachePID(eDVBService::cAC3PID, -1); + m_dvb_service->setCacheEntry(eDVBService::cAPID, program.audioStreams[i].pid); + m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1); } else { - m_dvb_service->setCachePID(eDVBService::cAPID, -1); - m_dvb_service->setCachePID(eDVBService::cAC3PID, program.audioStreams[i].pid); + m_dvb_service->setCacheEntry(eDVBService::cAPID, -1); + m_dvb_service->setCacheEntry(eDVBService::cAC3PID, program.audioStreams[i].pid); } } @@ -1253,6 +1259,24 @@ int eDVBServicePlay::selectAudioStream(int i) return 0; } +int eDVBServicePlay::getCurrentChannel() +{ + int curChannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL); + return curChannel == -1 ? STEREO : curChannel; +} + +RESULT eDVBServicePlay::selectChannel(int i) +{ + if (i < iAudioChannelSelection::LEFT || i > iAudioChannelSelection::RIGHT) + i = -1; // Stereo + if (m_dvb_service->getCacheEntry(eDVBService::cACHANNEL) != i) + { + m_dvb_service->setCacheEntry(eDVBService::cACHANNEL, i); + if (m_decoder) + m_decoder->setAudioChannel(i); + } +} + int eDVBServicePlay::getFrontendInfo(int w) { if (m_is_pvr) @@ -1560,7 +1584,7 @@ void eDVBServicePlay::switchToTimeshift() void eDVBServicePlay::updateDecoder() { - int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1; + int vpid = -1, vpidtype = -1, apid = -1, apidtype = -1, pcrpid = -1, tpid = -1, achannel = -1; eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; bool defaultac3=false; @@ -1619,6 +1643,7 @@ void eDVBServicePlay::updateDecoder() pcrpid = program.pcrPid; eDebug(", and the text pid is %04x", program.textPid); tpid = program.textPid; + achannel = program.audioChannel; } if (!m_decoder) @@ -1651,7 +1676,11 @@ void eDVBServicePlay::updateDecoder() if (!m_is_primary) m_decoder->setTrickmode(1); + m_decoder->start(); + + m_decoder->setAudioChannel(achannel); + // how we can do this better? // update cache pid when the user changed the audio track or video track // TODO handling of difference audio types.. default audio types.. @@ -1661,18 +1690,18 @@ void eDVBServicePlay::updateDecoder() { if (apidtype == eDVBAudio::aMPEG) { - m_dvb_service->setCachePID(eDVBService::cAPID, apid); - m_dvb_service->setCachePID(eDVBService::cAC3PID, -1); + m_dvb_service->setCacheEntry(eDVBService::cAPID, apid); + m_dvb_service->setCacheEntry(eDVBService::cAC3PID, -1); } else { - m_dvb_service->setCachePID(eDVBService::cAPID, -1); - m_dvb_service->setCachePID(eDVBService::cAC3PID, apid); + m_dvb_service->setCacheEntry(eDVBService::cAPID, -1); + m_dvb_service->setCacheEntry(eDVBService::cAC3PID, apid); } - m_dvb_service->setCachePID(eDVBService::cVPID, vpid); - m_dvb_service->setCachePID(eDVBService::cVTYPE, vpidtype); - m_dvb_service->setCachePID(eDVBService::cPCRPID, pcrpid); - m_dvb_service->setCachePID(eDVBService::cTPID, tpid); + m_dvb_service->setCacheEntry(eDVBService::cVPID, vpid); + m_dvb_service->setCacheEntry(eDVBService::cVTYPE, vpidtype); + m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid); + m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid); } } } diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index 01eb0497..79e8d540 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -58,7 +58,8 @@ private: class eDVBServicePlay: public iPlayableService, public iPauseableService, public iSeekableService, public Object, public iServiceInformation, - public iAudioTrackSelection, public iFrontendStatusInformation, + public iAudioTrackSelection, public iAudioChannelSelection, + public iFrontendStatusInformation, public iSubserviceList, public iTimeshiftService, public iCueSheet { @@ -75,6 +76,7 @@ public: RESULT seek(ePtr &ptr); RESULT pause(ePtr &ptr); RESULT info(ePtr &ptr); + RESULT audioChannel(ePtr &ptr); RESULT audioTracks(ePtr &ptr); RESULT frontendStatusInfo(ePtr &ptr); RESULT subServices(ePtr &ptr); @@ -107,6 +109,10 @@ public: RESULT selectTrack(unsigned int i); RESULT getTrackInfo(struct iAudioTrackInfo &, unsigned int n); + // iAudioChannelSelection + int getCurrentChannel(); + RESULT selectChannel(int i); + // iFrontendStatusInformation int getFrontendInfo(int w); PyObject *getFrontendData(bool); diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index cb400cc6..c6a0df06 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -58,6 +58,7 @@ public: RESULT seek(ePtr &ptr); // not implemented (yet) + RESULT audioChannel(ePtr &ptr) { ptr = 0; return -1; } RESULT audioTracks(ePtr &ptr) { ptr = 0; return -1; } RESULT frontendStatusInfo(ePtr &ptr) { ptr = 0; return -1; } RESULT subServices(ePtr &ptr) { ptr = 0; return -1; } -- 2.30.2