diff options
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 61 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 4 |
2 files changed, 65 insertions, 0 deletions
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index b78c6d1..abe0293 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1106,6 +1106,20 @@ void AudioFlinger::removeClient_l(pid_t pid) mClients.removeItem(pid); } +// getEffectThread_l() must be called with AudioFlinger::mLock held +sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(int sessionId, int EffectId) +{ + sp<PlaybackThread> thread; + + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { + if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) { + ALOG_ASSERT(thread == 0); + thread = mPlaybackThreads.valueAt(i); + } + } + + return thread; +} // ---------------------------------------------------------------------------- @@ -4677,6 +4691,47 @@ status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId) sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); + sp<AudioFlinger> af = mClient->audioFlinger(); + + Mutex::Autolock _l(af->mLock); + + sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId); + if (srcThread == 0) { + return INVALID_OPERATION; + } + + if (EffectId != 0 && playbackThread != srcThread.get()) { + Mutex::Autolock _dl(playbackThread->mLock); + Mutex::Autolock _sl(srcThread->mLock); + sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX); + if (chain == 0) { + return INVALID_OPERATION; + } + + sp<EffectModule> effect = chain->getEffectFromId_l(EffectId); + if (effect == 0) { + return INVALID_OPERATION; + } + srcThread->removeEffect_l(effect); + playbackThread->addEffect_l(effect); + // removeEffect_l() has stopped the effect if it was active so it must be restarted + if (effect->state() == EffectModule::ACTIVE || + effect->state() == EffectModule::STOPPING) { + effect->start(); + } + + sp<EffectChain> dstChain = effect->chain().promote(); + if (dstChain == 0) { + srcThread->addEffect_l(effect); + return INVALID_OPERATION; + } + AudioSystem::unregisterEffect(effect->id()); + AudioSystem::registerEffect(&effect->desc(), + srcThread->id(), + dstChain->strategy(), + AUDIO_SESSION_OUTPUT_MIX, + effect->id()); + } status = playbackThread->attachAuxEffect(this, EffectId); } return status; @@ -7645,6 +7700,12 @@ Exit: return handle; } +sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(int sessionId, int effectId) +{ + Mutex::Autolock _l(mLock); + return getEffect_l(sessionId, effectId); +} + sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(int sessionId, int effectId) { sp<EffectChain> chain = getEffectChain_l(sessionId); diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 384306c..cfd718f 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -253,6 +253,7 @@ public: int listenerSession, sync_event_callback_t callBack, void *cookie); + private: audio_mode_t getMode() const { return mMode; } @@ -543,6 +544,7 @@ private: // set audio mode to all effect chains void setMode(audio_mode_t mode); // get effect module with corresponding ID on specified audio session + sp<AudioFlinger::EffectModule> getEffect(int sessionId, int effectId); sp<AudioFlinger::EffectModule> getEffect_l(int sessionId, int effectId); // add and effect module. Also creates the effect chain is none exists for // the effects audio session @@ -1287,6 +1289,8 @@ private: PlaybackThread *primaryPlaybackThread_l() const; uint32_t primaryOutputDevice_l() const; + sp<PlaybackThread> getEffectThread_l(int sessionId, int EffectId); + // server side of the client's IAudioTrack class TrackHandle : public android::BnAudioTrack { public: |