summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioEffect.h462
-rw-r--r--media/libmedia/Android.mk3
-rw-r--r--media/libmedia/AudioEffect.cpp462
3 files changed, 926 insertions, 1 deletions
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
new file mode 100644
index 0000000..2bdba2d
--- /dev/null
+++ b/include/media/AudioEffect.h
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIOEFFECT_H
+#define ANDROID_AUDIOEFFECT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <media/IAudioFlinger.h>
+#include <media/IEffect.h>
+#include <media/IEffectClient.h>
+#include <media/EffectApi.h>
+#include <media/AudioSystem.h>
+
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+#include <binder/IInterface.h>
+
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class effect_param_cblk_t;
+
+// ----------------------------------------------------------------------------
+
+class AudioEffect : public RefBase
+{
+public:
+
+ /*
+ * Static methods for effect libraries management.
+ */
+
+ /*
+ * Loads the effect library which path is given as first argument.
+ * This must be the full path of a dynamic library (.so) implementing one or
+ * more effect engines and exposing the effect library interface described in
+ * EffectApi.h. The function returns a handle on the library for use by
+ * further call to unloadEffectLibrary() to unload the library.
+ *
+ * Parameters:
+ * libPath: full path of the dynamic library file in the file system.
+ * handle: address where to return the library handle
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface or
+ * application does not have permission to configure audio
+ * NO_INIT effect factory not initialized or
+ * library could not be loaded or
+ * library does not implement required functions
+ * BAD_VALUE invalid libPath string or handle
+ *
+ * Returned value:
+ * *handle updated with library handle
+ */
+ static status_t loadEffectLibrary(const char *libPath, int *handle);
+
+ /*
+ * Unloads the effect library which handle is given as argument.
+ *
+ * Parameters:
+ * handle: library handle
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface or
+ * application does not have permission to configure audio
+ * NO_INIT effect factory not initialized
+ * BAD_VALUE invalid handle
+ */
+ static status_t unloadEffectLibrary(int handle);
+
+ /*
+ * Static methods for effects enumeration.
+ */
+
+ /*
+ * Returns the number of effects available. This method together
+ * with EffectQueryNext() is used to enumerate all effects:
+ * The enumeration sequence is:
+ * QueryNumberEffects(&num_effects);
+ * while (num_effects--)
+ * QueryNextEffect();
+ *
+ * Parameters:
+ * pNumEffects: address where the number of effects should be returned.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid numEffects pointer
+ *
+ * Returned value
+ * *numEffects: updated with number of effects available
+ */
+ static status_t queryNumberEffects(uint32_t *numEffects);
+
+ /*
+ * Returns number effect descriptor during effect
+ * enumeration.
+ *
+ * Parameters:
+ * pDescriptor: address where the effect descriptor should be returned.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * NAME_NOT_FOUND no more effect available
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid descriptor pointer
+ * INVALID_OPERATION effect list has changed since last execution of queryNumberEffects()
+ *
+ * Returned value
+ * *descriptor: updated with effect descriptor
+ */
+ static status_t queryNextEffect(effect_descriptor_t *descriptor);
+
+
+ /*
+ * Returns the descriptor for the specified effect uuid.
+ *
+ * Parameters:
+ * uuid: pointer to effect uuid.
+ * descriptor: address where the effect descriptor should be returned.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid uuid or descriptor pointers
+ * NAME_NOT_FOUND no effect with this uuid found
+ *
+ * Returned value
+ * *descriptor updated with effect descriptor
+ */
+ static status_t getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor);
+
+
+ /*
+ * Events used by callback function (effect_callback_t).
+ */
+ enum event_type {
+ EVENT_CONTROL_STATUS_CHANGED = 0,
+ EVENT_ENABLE_STATUS_CHANGED = 1,
+ EVENT_PARAMETER_CHANGED = 2,
+ EVENT_ERROR = 3
+ };
+
+ /* Callback function notifying client application of a change in effect engine state or
+ * configuration.
+ * An effect engine can be shared by several applications but only one has the control
+ * of the engine activity and configuration at a time.
+ * The EVENT_CONTROL_STATUS_CHANGED event is received when an application loses or
+ * retrieves the control of the effect engine. Loss of control happens
+ * if another application requests the use of the engine by creating an AudioEffect for
+ * the same effect type but with a higher priority. Control is returned when the
+ * application having the control deletes its AudioEffect object.
+ * The EVENT_ENABLE_STATUS_CHANGED event is received by all applications not having the
+ * control of the effect engine when the effect is enabled or disabled.
+ * The EVENT_PARAMETER_CHANGED event is received by all applications not having the
+ * control of the effect engine when an effect parameter is changed.
+ * The EVENT_ERROR event is received when the media server process dies.
+ *
+ * Parameters:
+ *
+ * event: type of event notified (see enum AudioEffect::event_type).
+ * user: Pointer to context for use by the callback receiver.
+ * info: Pointer to optional parameter according to event type:
+ * - EVENT_CONTROL_STATUS_CHANGED: boolean indicating if control is granted (true)
+ * or stolen (false).
+ * - EVENT_ENABLE_STATUS_CHANGED: boolean indicating if effect is now enabled (true)
+ * or disabled (false).
+ * - EVENT_PARAMETER_CHANGED: pointer to a effect_param_t structure.
+ * - EVENT_ERROR: status_t indicating the error (DEAD_OBJECT when media server dies).
+ */
+
+ typedef void (*effect_callback_t)(int32_t event, void* user, void *info);
+
+
+ /* Constructor.
+ * AudioEffect is the base class for creating and controlling an effect engine from
+ * the application process. Creating an AudioEffect object will create the effect engine
+ * in the AudioFlinger if no engine of the specified type exists. If one exists, this engine
+ * will be used. The application creating the AudioEffect object (or a derived class like
+ * Reverb for instance) will either receive control of the effect engine or not, depending
+ * on the priority parameter. If priority is higher than the priority used by the current
+ * effect engine owner, the control will be transfered to the new application. Otherwise
+ * control will remain to the previous application. In this case, the new application will be
+ * notified of changes in effect engine state or control ownership by the effect callback.
+ * After creating the AudioEffect, the application must call the initCheck() method and
+ * check the creation status before trying to control the effect engine (see initCheck()).
+ * If the effect is to be applied to an AudioTrack or MediaPlayer only the application
+ * must specify the audio session ID corresponding to this player.
+ */
+
+ /* Simple Constructor.
+ */
+ AudioEffect();
+
+
+ /* Constructor.
+ *
+ * Parameters:
+ *
+ * type: type of effect created: can be null if uuid is specified. This corresponds to
+ * the OpenSL ES interface implemented by this effect.
+ * uuid: Uuid of effect created: can be null if type is specified. This uuid corresponds to
+ * a particular implementation of an effect type.
+ * priority: requested priority for effect control: the priority level corresponds to the
+ * value of priority parameter: negative values indicate lower priorities, positive values
+ * higher priorities, 0 being the normal priority.
+ * cbf: optional callback function (see effect_callback_t)
+ * user: pointer to context for use by the callback receiver.
+ * sessionID: audio session this effect is associated to. If 0, the effect will be global to
+ * the output mix. If not 0, the effect will be applied to all players
+ * (AudioTrack or MediaPLayer) within the same audio session.
+ * output: HAL audio output stream to which this effect must be attached. Leave at 0 for
+ * automatic output selection by AudioFlinger.
+ */
+
+ AudioEffect(const effect_uuid_t *type,
+ const effect_uuid_t *uuid = NULL,
+ int32_t priority = 0,
+ effect_callback_t cbf = 0,
+ void* user = 0,
+ int sessionId = 0,
+ audio_io_handle_t output = 0
+ );
+
+ /* Constructor.
+ * Same as above but with type and uuid specified by character strings
+ */
+ AudioEffect(const char *typeStr,
+ const char *uuidStr = NULL,
+ int32_t priority = 0,
+ effect_callback_t cbf = 0,
+ void* user = 0,
+ int sessionId = 0,
+ audio_io_handle_t output = 0
+ );
+
+ /* Terminates the AudioEffect and unregisters it from AudioFlinger.
+ * The effect engine is also destroyed if this AudioEffect was the last controlling
+ * the engine.
+ */
+ ~AudioEffect();
+
+ /* Initialize an uninitialized AudioEffect.
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR or ALREADY_EXISTS: successful initialization
+ * - INVALID_OPERATION: AudioEffect is already initialized
+ * - BAD_VALUE: invalid parameter
+ * - NO_INIT: audio flinger or audio hardware not initialized
+ * */
+ status_t set(const effect_uuid_t *type,
+ const effect_uuid_t *uuid = NULL,
+ int32_t priority = 0,
+ effect_callback_t cbf = 0,
+ void* user = 0,
+ int sessionId = 0,
+ audio_io_handle_t output = 0
+ );
+
+ /* Result of constructing the AudioEffect. This must be checked
+ * before using any AudioEffect API.
+ * initCheck() can return:
+ * - NO_ERROR: the effect engine is successfully created and the application has control.
+ * - ALREADY_EXISTS: the effect engine is successfully created but the application does not
+ * have control.
+ * - NO_INIT: the effect creation failed.
+ *
+ */
+ status_t initCheck() const;
+
+
+ /* Returns the unique effect Id for the controlled effect engine. This ID is unique
+ * system wide and is used for instance in the case of auxiliary effects to attach
+ * the effect to an AudioTrack or MediaPlayer.
+ *
+ */
+ int32_t id() const { return mId; }
+
+ /* Returns a descriptor for the effect (see effect_descriptor_t in EffectApi.h).
+ */
+ effect_descriptor_t descriptor() const;
+
+ /* Returns effect control priority of this AudioEffect object.
+ */
+ int32_t priority() const { return mPriority; }
+
+
+ /* Enables the effect engine.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the application does not have control of the effect engine
+ */
+ status_t enable();
+
+ /* Disables the effect engine.
+ *
+ * Parameters:
+ * None.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation
+ * - INVALID_OPERATION: the application does not have control of the effect engine
+ */
+ status_t disable();
+
+ bool isEnabled() const;
+
+ /* Sets a parameter value.
+ *
+ * Parameters:
+ * param: pointer to effect_param_t structure containing the parameter
+ * and its value (See EffectApi.h).
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the application does not have control of the effect engine.
+ * - BAD_VALUE: invalid parameter identifier or value.
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ status_t setParameter(effect_param_t *param);
+
+ /* Prepare a new parameter value that will be set by next call to
+ * setParameterCommit(). This method can be used to set multiple parameters
+ * in a synchronous manner or to avoid multiple binder calls for each
+ * parameter.
+ *
+ * Parameters:
+ * param: pointer to effect_param_t structure containing the parameter
+ * and its value (See EffectApi.h).
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the application does not have control of the effect engine.
+ * - NO_MEMORY: no more space available in shared memory used for deferred parameter
+ * setting.
+ */
+ status_t setParameterDeferred(effect_param_t *param);
+
+ /* Commit all parameter values previously prepared by setParameterDeferred().
+ *
+ * Parameters:
+ * none
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: No new parameter values ready for commit.
+ * - BAD_VALUE: invalid parameter identifier or value: there is no indication
+ * as to which of the parameters caused this error.
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ status_t setParameterCommit();
+
+ /* Gets a parameter value.
+ *
+ * Parameters:
+ * param: pointer to effect_param_t structure containing the parameter
+ * and the returned value (See EffectApi.h).
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * - NO_ERROR: successful operation.
+ * - INVALID_OPERATION: the AudioEffect was not successfully initialized.
+ * - BAD_VALUE: invalid parameter identifier.
+ * - DEAD_OBJECT: the effect engine has been deleted.
+ */
+ status_t getParameter(effect_param_t *param);
+
+ /* Sends a command and receives a response to/from effect engine.
+ * See EffectApi.h for details on effect command() function, valid command codes
+ * and formats.
+ */
+ status_t command(int32_t cmdCode, int32_t cmdSize, void *cmdData, int32_t *replySize, void *replyData);
+
+
+ /*
+ * Utility functions.
+ */
+
+ /* Converts the string passed as first argument to the effect_uuid_t
+ * pointed to by second argument
+ */
+ static status_t stringToGuid(const char *str, effect_uuid_t *guid);
+ /* Converts the effect_uuid_t pointed to by first argument to the
+ * string passed as second argument
+ */
+ static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen);
+
+private:
+
+ // Implements the IEffectClient interface
+ class EffectClient : public android::BnEffectClient, public android::IBinder::DeathRecipient
+ {
+ public:
+
+ EffectClient(AudioEffect *effect) : mEffect(effect){}
+
+ // IEffectClient
+ virtual void controlStatusChanged(bool controlGranted) {mEffect->controlStatusChanged(controlGranted);}
+ virtual void enableStatusChanged(bool enabled) {mEffect->enableStatusChanged(enabled);}
+ virtual void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData) {
+ mEffect->commandExecuted(cmdCode, cmdSize, pCmdData, replySize, pReplyData);
+ }
+
+ // IBinder::DeathRecipient
+ virtual void binderDied(const wp<IBinder>& who) {mEffect->binderDied();}
+
+ private:
+ AudioEffect *mEffect;
+ };
+
+
+ friend class EffectClient;
+
+ // IEffectClient
+ void controlStatusChanged(bool controlGranted);
+ void enableStatusChanged(bool enabled);
+ void commandExecuted(int cmdCode, int cmdSize, void *pCmdData, int replySize, void *pReplyData);
+ void binderDied();
+
+
+ sp<IEffect> mIEffect; // IEffect binder interface
+ sp<EffectClient> mIEffectClient; // IEffectClient implementation
+ sp<IMemory> mCblkMemory; // shared memory for deferred parameter setting
+ effect_param_cblk_t* mCblk; // control block for deferred parameter setting
+ int32_t mPriority; // priority for effect control
+ status_t mStatus; // effect status
+ volatile int32_t mEnabled; // enable state
+ effect_callback_t mCbf; // callback function for status, control, parameter changes notifications
+ void* mUserData; // client context for callback function
+ effect_descriptor_t mDescriptor; // effect descriptor
+ int32_t mId; // system wide unique effect engine instance identifier
+ int32_t mSessionId; // audio session ID
+};
+
+
+}; // namespace android
+
+#endif // ANDROID_AUDIOEFFECT_H
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 29cd2ee..7908f5d 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -28,7 +28,8 @@ LOCAL_SRC_FILES:= \
IMediaDeathNotifier.cpp \
MediaProfiles.cpp \
IEffect.cpp \
- IEffectClient.cpp
+ IEffectClient.cpp \
+ AudioEffect.cpp
LOCAL_SHARED_LIBRARIES := \
libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
new file mode 100644
index 0000000..8648211
--- /dev/null
+++ b/media/libmedia/AudioEffect.cpp
@@ -0,0 +1,462 @@
+/*
+**
+** Copyright 2010, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "AudioEffect"
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <limits.h>
+
+#include <private/media/AudioEffectShared.h>
+#include <media/AudioEffect.h>
+
+#include <utils/Log.h>
+#include <cutils/atomic.h>
+#include <binder/IPCThreadState.h>
+
+
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+AudioEffect::AudioEffect()
+ : mStatus(NO_INIT)
+{
+}
+
+
+AudioEffect::AudioEffect(const effect_uuid_t *type,
+ const effect_uuid_t *uuid,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t output
+ )
+ : mStatus(NO_INIT)
+{
+ mStatus = set(type, uuid, priority, cbf, user, output, sessionId);
+}
+
+AudioEffect::AudioEffect(const char *typeStr,
+ const char *uuidStr,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t output
+ )
+ : mStatus(NO_INIT)
+{
+ effect_uuid_t type;
+ effect_uuid_t *pType = NULL;
+ effect_uuid_t uuid;
+ effect_uuid_t *pUuid = NULL;
+
+ LOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
+
+ if (typeStr != NULL) {
+ if (stringToGuid(typeStr, &type) == NO_ERROR) {
+ pType = &type;
+ }
+ }
+
+ if (uuidStr != NULL) {
+ if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
+ pUuid = &uuid;
+ }
+ }
+
+ mStatus = set(pType, pUuid, priority, cbf, user, output, sessionId);
+}
+
+status_t AudioEffect::set(const effect_uuid_t *type,
+ const effect_uuid_t *uuid,
+ int32_t priority,
+ effect_callback_t cbf,
+ void* user,
+ int sessionId,
+ audio_io_handle_t output)
+{
+ sp<IEffect> iEffect;
+ sp<IMemory> cblk;
+ int enabled;
+
+ LOGV("set %p mUserData: %p", this, user);
+
+ if (mIEffect != 0) {
+ LOGW("Effect already in use");
+ return INVALID_OPERATION;
+ }
+
+ const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
+ if (audioFlinger == 0) {
+ LOGE("set(): Could not get audioflinger");
+ return NO_INIT;
+ }
+
+ if (type == NULL && uuid == NULL) {
+ LOGW("Must specify at least type or uuid");
+ return BAD_VALUE;
+ }
+
+ mPriority = priority;
+ mCbf = cbf;
+ mUserData = user;
+ mSessionId = sessionId;
+
+ memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
+ memcpy(&mDescriptor.type, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+ memcpy(&mDescriptor.uuid, EFFECT_UUID_NULL, sizeof(effect_uuid_t));
+
+ if (type != NULL) {
+ memcpy(&mDescriptor.type, type, sizeof(effect_uuid_t));
+ }
+ if (uuid != NULL) {
+ memcpy(&mDescriptor.uuid, uuid, sizeof(effect_uuid_t));
+ }
+
+ mIEffectClient = new EffectClient(this);
+
+ iEffect = audioFlinger->createEffect(getpid(), (effect_descriptor_t *)&mDescriptor,
+ mIEffectClient, priority, output, mSessionId, &mStatus, &mId, &enabled);
+
+ if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
+ LOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
+ return mStatus;
+ }
+
+ mEnabled = (volatile int32_t)enabled;
+
+ mIEffect = iEffect;
+ cblk = iEffect->getCblk();
+ if (cblk == 0) {
+ mStatus = NO_INIT;
+ LOGE("Could not get control block");
+ return mStatus;
+ }
+
+ mIEffect = iEffect;
+ mCblkMemory = cblk;
+ mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
+ int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
+ mCblk->buffer = (uint8_t *)mCblk + bufOffset;
+
+ iEffect->asBinder()->linkToDeath(mIEffectClient);
+ LOGV("set() %p OK effect: %s id: %d status %d enabled %d, ", this, mDescriptor.name, mId, mStatus, mEnabled);
+
+ return mStatus;
+}
+
+
+AudioEffect::~AudioEffect()
+{
+ LOGV("Destructor %p", this);
+
+ if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
+ disable();
+ if (mIEffect != NULL) {
+ mIEffect->disconnect();
+ mIEffect->asBinder()->unlinkToDeath(mIEffectClient);
+ }
+ IPCThreadState::self()->flushCommands();
+ }
+ mIEffect.clear();
+ mIEffectClient.clear();
+ mCblkMemory.clear();
+}
+
+
+status_t AudioEffect::initCheck() const
+{
+ return mStatus;
+}
+
+// -------------------------------------------------------------------------
+
+effect_descriptor_t AudioEffect::descriptor() const
+{
+ return mDescriptor;
+}
+
+bool AudioEffect::isEnabled() const
+{
+ return (mEnabled != 0);
+}
+
+status_t AudioEffect::enable()
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ LOGV("enable %p", this);
+
+ if (android_atomic_or(1, &mEnabled) == 0) {
+ return mIEffect->enable();
+ }
+
+ return INVALID_OPERATION;
+}
+
+status_t AudioEffect::disable()
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+ LOGV("disable %p", this);
+
+ if (android_atomic_and(~1, &mEnabled) == 1) {
+ return mIEffect->disable();
+ }
+
+ return INVALID_OPERATION;
+}
+
+status_t AudioEffect::command(int32_t cmdCode, int32_t cmdSize, void *cmdData, int32_t *replySize, void *replyData)
+{
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ return INVALID_OPERATION;
+ }
+
+ return mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
+}
+
+
+status_t AudioEffect::setParameter(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ int size = sizeof(int);
+ int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+ LOGV("setParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+ return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size, &param->status);
+}
+
+status_t AudioEffect::setParameterDeferred(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock _l(mCblk->lock);
+
+ int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+ int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
+
+ if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
+ return NO_MEMORY;
+ }
+ int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
+ *p++ = size;
+ memcpy(p, param, sizeof(effect_param_t) + psize);
+ mCblk->clientIndex += size;
+
+ return NO_ERROR;
+}
+
+status_t AudioEffect::setParameterCommit()
+{
+ if (mStatus != NO_ERROR) {
+ return INVALID_OPERATION;
+ }
+
+ Mutex::Autolock _l(mCblk->lock);
+ if (mCblk->clientIndex == 0) {
+ return INVALID_OPERATION;
+ }
+ int size = 0;
+ return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
+}
+
+status_t AudioEffect::getParameter(effect_param_t *param)
+{
+ if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
+ return INVALID_OPERATION;
+ }
+
+ if (param == NULL || param->psize == 0 || param->vsize == 0) {
+ return BAD_VALUE;
+ }
+
+ LOGV("getParameter: param: %d, param2: %d", *(int *)param->data, (param->psize == 8) ? *((int *)param->data + 1): -1);
+
+ int psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
+
+ return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param, &psize, param);
+}
+
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::binderDied()
+{
+ LOGW("IEffect died");
+ mStatus = NO_INIT;
+ if (mCbf) {
+ status_t status = DEAD_OBJECT;
+ mCbf(EVENT_ERROR, mUserData, &status);
+ }
+ mIEffect.clear();
+}
+
+// -------------------------------------------------------------------------
+
+void AudioEffect::controlStatusChanged(bool controlGranted)
+{
+ LOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf, mUserData);
+ if (controlGranted) {
+ if (mStatus == ALREADY_EXISTS) {
+ mStatus = NO_ERROR;
+ }
+ } else {
+ if (mStatus == NO_ERROR) {
+ mStatus = ALREADY_EXISTS;
+ }
+ }
+ if (mCbf) {
+ mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
+ }
+}
+
+void AudioEffect::enableStatusChanged(bool enabled)
+{
+ LOGV("enableStatusChanged %p enabled %d", this, enabled);
+ if (mStatus == ALREADY_EXISTS) {
+ mEnabled = enabled;
+ if (mCbf) {
+ mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
+ }
+ }
+}
+
+void AudioEffect::commandExecuted(int cmdCode, int cmdSize, void *cmdData, int replySize, void *replyData)
+{
+ if (cmdData == NULL || replyData == NULL) {
+ return;
+ }
+
+ if (mCbf && cmdCode == EFFECT_CMD_SET_PARAM) {
+ effect_param_t *cmd = (effect_param_t *)cmdData;
+ cmd->status = *(int32_t *)replyData;
+ mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
+ }
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::loadEffectLibrary(const char *libPath, int *handle)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->loadEffectLibrary(libPath, handle);
+}
+
+status_t AudioEffect::unloadEffectLibrary(int handle)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->unloadEffectLibrary(handle);
+}
+
+status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->queryNumberEffects(numEffects);
+}
+
+status_t AudioEffect::queryNextEffect(effect_descriptor_t *descriptor)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->queryNextEffect(descriptor);
+}
+
+status_t AudioEffect::getEffectDescriptor(effect_uuid_t *uuid, effect_descriptor_t *descriptor)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ return af->getEffectDescriptor(uuid, descriptor);
+}
+
+// -------------------------------------------------------------------------
+
+status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
+{
+ if (str == NULL || guid == NULL) {
+ return BAD_VALUE;
+ }
+
+ int tmp[10];
+
+ if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
+ return BAD_VALUE;
+ }
+ guid->timeLow = (uint32_t)tmp[0];
+ guid->timeMid = (uint16_t)tmp[1];
+ guid->timeHiAndVersion = (uint16_t)tmp[2];
+ guid->clockSeq = (uint16_t)tmp[3];
+ guid->node[0] = (uint8_t)tmp[4];
+ guid->node[1] = (uint8_t)tmp[5];
+ guid->node[2] = (uint8_t)tmp[6];
+ guid->node[3] = (uint8_t)tmp[7];
+ guid->node[4] = (uint8_t)tmp[8];
+ guid->node[5] = (uint8_t)tmp[9];
+
+ return NO_ERROR;
+}
+
+status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
+{
+ if (guid == NULL || str == NULL) {
+ return BAD_VALUE;
+ }
+
+ snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+ guid->timeLow,
+ guid->timeMid,
+ guid->timeHiAndVersion,
+ guid->clockSeq,
+ guid->node[0],
+ guid->node[1],
+ guid->node[2],
+ guid->node[3],
+ guid->node[4],
+ guid->node[5]);
+
+ return NO_ERROR;
+}
+
+
+}; // namespace android
+