141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Copyright (C) 2014 The Android Open Source Project
341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George *
441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Licensed under the Apache License, Version 2.0 (the "License");
541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * you may not use this file except in compliance with the License.
641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * You may obtain a copy of the License at
741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George *
841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George *      http://www.apache.org/licenses/LICENSE-2.0
941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George *
1041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Unless required by applicable law or agreed to in writing, software
1141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * distributed under the License is distributed on an "AS IS" BASIS,
1241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * See the License for the specific language governing permissions and
1441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * limitations under the License.
1541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
1641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
1741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#define LOG_TAG "offload_effect_bundle"
1841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George//#define LOG_NDEBUG 0
1941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
2037a7699e96b3a4433e80b3899230809976d5e14bGlenn Kasten#include <stdlib.h>
2141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include <cutils/list.h>
2241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include <cutils/log.h>
2341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include <system/thread_defs.h>
2441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include <tinyalsa/asoundlib.h>
2541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include <hardware/audio_effect.h>
2641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
2741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include "bundle.h"
2841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include "equalizer.h"
2941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include "bass_boost.h"
3041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include "virtualizer.h"
3141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George#include "reverb.h"
3241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
3341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeenum {
3441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    EFFECT_STATE_UNINITIALIZED,
3541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    EFFECT_STATE_INITIALIZED,
3641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    EFFECT_STATE_ACTIVE,
3741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George};
3841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
3941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeconst effect_descriptor_t *descriptors[] = {
4041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &equalizer_descriptor,
4141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &bassboost_descriptor,
4241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &virtualizer_descriptor,
4341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &aux_env_reverb_descriptor,
4441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &ins_env_reverb_descriptor,
4541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &aux_preset_reverb_descriptor,
4641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        &ins_preset_reverb_descriptor,
4741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        NULL,
4841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George};
4941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
5041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgepthread_once_t once = PTHREAD_ONCE_INIT;
5141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint init_status;
5241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
5341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * list of created effects.
5441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Updated by offload_effects_bundle_hal_start_output()
5541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * and offload_effects_bundle_hal_stop_output()
5641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
5741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgestruct listnode created_effects_list;
5841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
5941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * list of active output streams.
6041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Updated by offload_effects_bundle_hal_start_output()
6141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * and offload_effects_bundle_hal_stop_output()
6241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
6341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgestruct listnode active_outputs_list;
6441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
6541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * lock must be held when modifying or accessing
6641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * created_effects_list or active_outputs_list
6741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
6841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgepthread_mutex_t lock;
6941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
7041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
7141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
7241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George *  Local functions
7341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
7441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgestatic void init_once() {
7541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_init(&created_effects_list);
7641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_init(&active_outputs_list);
7741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
7841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_init(&lock, NULL);
7941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
8041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    init_status = 0;
8141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
8241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
8341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint lib_init()
8441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
8541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_once(&once, init_once);
8641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return init_status;
8741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
8841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
8941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgebool effect_exists(effect_context_t *context)
9041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
9141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *node;
9241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
9341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(node, &created_effects_list) {
9441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_context_t *fx_ctxt = node_to_item(node,
9541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effect_context_t,
9641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effects_list_node);
9741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (fx_ctxt == context) {
9841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            return true;
9941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
10041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
10141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return false;
10241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
10341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
10441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeoutput_context_t *get_output(audio_io_handle_t output)
10541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
10641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *node;
10741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
10841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(node, &active_outputs_list) {
10941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        output_context_t *out_ctxt = node_to_item(node,
11041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                  output_context_t,
11141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                  outputs_list_node);
11241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (out_ctxt->handle == output)
11341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            return out_ctxt;
11441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
11541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return NULL;
11641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
11741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
11841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgevoid add_effect_to_output(output_context_t * output, effect_context_t *context)
11941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
12041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *fx_node;
12141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
12241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(fx_node, &output->effects_list) {
12341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_context_t *fx_ctxt = node_to_item(fx_node,
12441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effect_context_t,
12541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 output_node);
12641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (fx_ctxt == context)
12741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            return;
12841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
12941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_add_tail(&output->effects_list, &context->output_node);
13041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (context->ops.start)
13141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.start(context, output);
13241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
13341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
13441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
13541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgevoid remove_effect_from_output(output_context_t * output,
13641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                               effect_context_t *context)
13741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
13841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *fx_node;
13941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
14041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(fx_node, &output->effects_list) {
14141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_context_t *fx_ctxt = node_to_item(fx_node,
14241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effect_context_t,
14341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 output_node);
14441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (fx_ctxt == context) {
14541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            if (context->ops.stop)
14641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                context->ops.stop(context, output);
14741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            list_remove(&context->output_node);
14841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            return;
14941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
15041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
15141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
15241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
15341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgebool effects_enabled()
15441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
15541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *out_node;
15641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
15741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(out_node, &active_outputs_list) {
15841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        struct listnode *fx_node;
15941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        output_context_t *out_ctxt = node_to_item(out_node,
16041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                  output_context_t,
16141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                  outputs_list_node);
16241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
16341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        list_for_each(fx_node, &out_ctxt->effects_list) {
16441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            effect_context_t *fx_ctxt = node_to_item(fx_node,
16541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                     effect_context_t,
16641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                     output_node);
16741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            if ((fx_ctxt->state == EFFECT_STATE_ACTIVE) &&
16841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                (fx_ctxt->ops.process != NULL))
16941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                return true;
17041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
17141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
17241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return false;
17341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
17441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
17541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
17641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
17741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Interface from audio HAL
17841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
17941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George__attribute__ ((visibility ("default")))
18041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint offload_effects_bundle_hal_start_output(audio_io_handle_t output, int pcm_id)
18141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
18241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int ret = 0;
18341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *node;
18441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    char mixer_string[128];
18541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    output_context_t * out_ctxt = NULL;
18641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
18741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
18841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
18941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (lib_init() != 0)
19041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return init_status;
19141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
19241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_lock(&lock);
19341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (get_output(output) != NULL) {
19441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGW("%s output already started", __func__);
19541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ret = -ENOSYS;
19641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
19741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
19841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
19941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    out_ctxt = (output_context_t *)
20041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                 malloc(sizeof(output_context_t));
20141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    out_ctxt->handle = output;
20241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    out_ctxt->pcm_device_id = pcm_id;
20341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
20441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    /* populate the mixer control to send offload parameters */
20541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    snprintf(mixer_string, sizeof(mixer_string),
20641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George             "%s %d", "Audio Effects Config", out_ctxt->pcm_device_id);
20741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    out_ctxt->mixer = mixer_open(MIXER_CARD);
20841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (!out_ctxt->mixer) {
20941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGE("Failed to open mixer");
21041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        out_ctxt->ctl = NULL;
21141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ret = -EINVAL;
21241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        free(out_ctxt);
21341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
21441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    } else {
21541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        out_ctxt->ctl = mixer_get_ctl_by_name(out_ctxt->mixer, mixer_string);
21641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (!out_ctxt->ctl) {
21741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ALOGE("mixer_get_ctl_by_name failed");
21841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            mixer_close(out_ctxt->mixer);
21941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            out_ctxt->mixer = NULL;
22041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ret = -EINVAL;
22141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            free(out_ctxt);
22241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
22341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
22441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
22541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
22641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_init(&out_ctxt->effects_list);
22741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
22841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(node, &created_effects_list) {
22941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_context_t *fx_ctxt = node_to_item(node,
23041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effect_context_t,
23141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effects_list_node);
23241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (fx_ctxt->out_handle == output) {
23341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            if (fx_ctxt->ops.start)
23441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                fx_ctxt->ops.start(fx_ctxt, out_ctxt);
23541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            list_add_tail(&out_ctxt->effects_list, &fx_ctxt->output_node);
23641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
23741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
23841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_add_tail(&active_outputs_list, &out_ctxt->outputs_list_node);
23941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeexit:
24041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_unlock(&lock);
24141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return ret;
24241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
24341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
24441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George__attribute__ ((visibility ("default")))
24541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint offload_effects_bundle_hal_stop_output(audio_io_handle_t output, int pcm_id)
24641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
24741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int ret;
24841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *node;
24941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    struct listnode *fx_node;
25041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    output_context_t *out_ctxt;
25141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
25241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
25341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
25441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (lib_init() != 0)
25541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return init_status;
25641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
25741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_lock(&lock);
25841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
25941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    out_ctxt = get_output(output);
26041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (out_ctxt == NULL) {
26141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGW("%s output not started", __func__);
26241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ret = -ENOSYS;
26341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
26441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
26541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
26641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (out_ctxt->mixer)
26741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        mixer_close(out_ctxt->mixer);
26841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
26941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_for_each(fx_node, &out_ctxt->effects_list) {
27041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_context_t *fx_ctxt = node_to_item(fx_node,
27141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 effect_context_t,
27241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                 output_node);
27341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (fx_ctxt->ops.stop)
27441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
27541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
27641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
27741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_remove(&out_ctxt->outputs_list_node);
27841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
27941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    free(out_ctxt);
28041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
28141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeexit:
28241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_unlock(&lock);
28341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return ret;
28441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
28541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
28641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
28741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
28841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Effect operations
28941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
29041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint set_config(effect_context_t *context, effect_config_t *config)
29141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
29241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    context->config = *config;
29341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
29441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (context->ops.reset)
29541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.reset(context);
29641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
29741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return 0;
29841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
29941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
30041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgevoid get_config(effect_context_t *context, effect_config_t *config)
30141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
30241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    *config = context->config;
30341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
30441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
30541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
30641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
30741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Effect Library Interface Implementation
30841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
30941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint effect_lib_create(const effect_uuid_t *uuid,
31041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                         int32_t sessionId,
31141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                         int32_t ioId,
31241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                         effect_handle_t *pHandle) {
31341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int ret;
31441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int i;
31541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
31641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ALOGV("%s: sessionId: %d, ioId: %d", __func__, sessionId, ioId);
31741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (lib_init() != 0)
31841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return init_status;
31941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
32041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (pHandle == NULL || uuid == NULL)
32141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return -EINVAL;
32241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
32341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    for (i = 0; descriptors[i] != NULL; i++) {
32441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0)
32541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            break;
32641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
32741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
32841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (descriptors[i] == NULL)
32941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return -EINVAL;
33041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
33141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_context_t *context;
33241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (memcmp(uuid, &equalizer_descriptor.uuid,
33341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        sizeof(effect_uuid_t)) == 0) {
33441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        equalizer_context_t *eq_ctxt = (equalizer_context_t *)
33541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                       calloc(1, sizeof(equalizer_context_t));
33641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context = (effect_context_t *)eq_ctxt;
33741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.init = equalizer_init;
33841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.reset = equalizer_reset;
33941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_parameter = equalizer_set_parameter;
34041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.get_parameter = equalizer_get_parameter;
34141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_device = equalizer_set_device;
34241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.enable = equalizer_enable;
34341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.disable = equalizer_disable;
34441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.start = equalizer_start;
34541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.stop = equalizer_stop;
34641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
34741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->desc = &equalizer_descriptor;
34841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        eq_ctxt->ctl = NULL;
34941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    } else if (memcmp(uuid, &bassboost_descriptor.uuid,
35041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George               sizeof(effect_uuid_t)) == 0) {
35141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        bassboost_context_t *bass_ctxt = (bassboost_context_t *)
35241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                         calloc(1, sizeof(bassboost_context_t));
35341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context = (effect_context_t *)bass_ctxt;
35441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.init = bassboost_init;
35541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.reset = bassboost_reset;
35641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_parameter = bassboost_set_parameter;
35741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.get_parameter = bassboost_get_parameter;
35841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_device = bassboost_set_device;
35941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.enable = bassboost_enable;
36041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.disable = bassboost_disable;
36141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.start = bassboost_start;
36241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.stop = bassboost_stop;
36341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
36441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->desc = &bassboost_descriptor;
36541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        bass_ctxt->ctl = NULL;
36641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    } else if (memcmp(uuid, &virtualizer_descriptor.uuid,
36741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George               sizeof(effect_uuid_t)) == 0) {
36841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        virtualizer_context_t *virt_ctxt = (virtualizer_context_t *)
36941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                           calloc(1, sizeof(virtualizer_context_t));
37041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context = (effect_context_t *)virt_ctxt;
37141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.init = virtualizer_init;
37241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.reset = virtualizer_reset;
37341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_parameter = virtualizer_set_parameter;
37441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.get_parameter = virtualizer_get_parameter;
37541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_device = virtualizer_set_device;
37641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.enable = virtualizer_enable;
37741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.disable = virtualizer_disable;
37841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.start = virtualizer_start;
37941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.stop = virtualizer_stop;
38041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
38141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->desc = &virtualizer_descriptor;
38241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        virt_ctxt->ctl = NULL;
38341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    } else if ((memcmp(uuid, &aux_env_reverb_descriptor.uuid,
38441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                sizeof(effect_uuid_t)) == 0) ||
38541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George               (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
38641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                sizeof(effect_uuid_t)) == 0) ||
38741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George               (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
38841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                sizeof(effect_uuid_t)) == 0) ||
38941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George               (memcmp(uuid, &ins_preset_reverb_descriptor.uuid,
39041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                sizeof(effect_uuid_t)) == 0)) {
39141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        reverb_context_t *reverb_ctxt = (reverb_context_t *)
39241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                        calloc(1, sizeof(reverb_context_t));
39341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context = (effect_context_t *)reverb_ctxt;
39441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.init = reverb_init;
39541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.reset = reverb_reset;
39641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_parameter = reverb_set_parameter;
39741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.get_parameter = reverb_get_parameter;
39841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.set_device = reverb_set_device;
39941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.enable = reverb_enable;
40041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.disable = reverb_disable;
40141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.start = reverb_start;
40241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->ops.stop = reverb_stop;
40341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
40441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (memcmp(uuid, &aux_env_reverb_descriptor.uuid,
40541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                   sizeof(effect_uuid_t)) == 0) {
40641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->desc = &aux_env_reverb_descriptor;
40741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            reverb_auxiliary_init(reverb_ctxt);
40841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } else if (memcmp(uuid, &ins_env_reverb_descriptor.uuid,
40941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                   sizeof(effect_uuid_t)) == 0) {
41041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->desc = &ins_env_reverb_descriptor;
41141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            reverb_insert_init(reverb_ctxt);
41241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } else if (memcmp(uuid, &aux_preset_reverb_descriptor.uuid,
41341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                   sizeof(effect_uuid_t)) == 0) {
41441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->desc = &aux_preset_reverb_descriptor;
41541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            reverb_auxiliary_init(reverb_ctxt);
41641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } else if (memcmp(uuid, &ins_preset_reverb_descriptor.uuid,
41741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                   sizeof(effect_uuid_t)) == 0) {
41841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->desc = &ins_preset_reverb_descriptor;
41941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            reverb_preset_init(reverb_ctxt);
42041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
42141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        reverb_ctxt->ctl = NULL;
42241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    } else {
42341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return -EINVAL;
42441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
42541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
42641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    context->itfe = &effect_interface;
42741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    context->state = EFFECT_STATE_UNINITIALIZED;
42841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    context->out_handle = (audio_io_handle_t)ioId;
42941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
43041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ret = context->ops.init(context);
43141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (ret < 0) {
43241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGW("%s init failed", __func__);
43341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        free(context);
43441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return ret;
43541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
43641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
43741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    context->state = EFFECT_STATE_INITIALIZED;
43841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
43941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_lock(&lock);
44041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    list_add_tail(&created_effects_list, &context->effects_list_node);
44141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    output_context_t *out_ctxt = get_output(ioId);
44241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (out_ctxt != NULL)
44341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        add_effect_to_output(out_ctxt, context);
44441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_unlock(&lock);
44541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
44641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    *pHandle = (effect_handle_t)context;
44741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
44841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ALOGV("%s created context %p", __func__, context);
44941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
45041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return 0;
45141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
45241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
45341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
45441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint effect_lib_release(effect_handle_t handle)
45541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
45641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_context_t *context = (effect_context_t *)handle;
45741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int status;
45841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
45941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (lib_init() != 0)
46041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return init_status;
46141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
46241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ALOGV("%s context %p", __func__, handle);
46341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_lock(&lock);
46441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    status = -EINVAL;
46541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (effect_exists(context)) {
46641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        output_context_t *out_ctxt = get_output(context->out_handle);
46741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (out_ctxt != NULL)
46841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            remove_effect_from_output(out_ctxt, context);
46941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        list_remove(&context->effects_list_node);
47041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.release)
47141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->ops.release(context);
47241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        free(context);
47341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        status = 0;
47441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
47541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_unlock(&lock);
47641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
47741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return status;
47841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
47941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
48041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint effect_lib_get_descriptor(const effect_uuid_t *uuid,
48141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                              effect_descriptor_t *descriptor)
48241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
48341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int i;
48441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
48541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (lib_init() != 0)
48641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return init_status;
48741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
48841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (descriptor == NULL || uuid == NULL) {
48941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGV("%s called with NULL pointer", __func__);
49041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return -EINVAL;
49141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
49241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
49341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    for (i = 0; descriptors[i] != NULL; i++) {
49441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
49541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            *descriptor = *descriptors[i];
49641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            return 0;
49741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
49841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
49941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
50041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return  -EINVAL;
50141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
50241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
50341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
50441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/*
50541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George * Effect Control Interface Implementation
50641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George */
50741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
50841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/* Stub function for effect interface: never called for offloaded effects */
50941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint effect_process(effect_handle_t self,
51097a1059da4d3aa8bfb0883d5f932f86b95876512Haynes Mathew George                       audio_buffer_t *inBuffer __unused,
51197a1059da4d3aa8bfb0883d5f932f86b95876512Haynes Mathew George                       audio_buffer_t *outBuffer __unused)
51241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
51341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_context_t * context = (effect_context_t *)self;
51441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int status = 0;
51541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
51641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    ALOGW("%s Called ?????", __func__);
51741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
51841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_lock(&lock);
51941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (!effect_exists(context)) {
52041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        status = -ENOSYS;
52141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
52241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
52341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
52441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (context->state != EFFECT_STATE_ACTIVE) {
52541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        status = -ENODATA;
52641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
52741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
52841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
52941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeexit:
53041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_unlock(&lock);
53141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return status;
53241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
53341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
53441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint effect_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
53541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                   void *pCmdData, uint32_t *replySize, void *pReplyData)
53641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
53741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
53841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_context_t * context = (effect_context_t *)self;
53941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int retsize;
54041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    int status = 0;
54141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
54241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_lock(&lock);
54341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
54441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (!effect_exists(context)) {
54541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        status = -ENOSYS;
54641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
54741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
54841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
54941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (context == NULL || context->state == EFFECT_STATE_UNINITIALIZED) {
55041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        status = -ENOSYS;
55141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        goto exit;
55241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
55341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
55441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    switch (cmdCode) {
55541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_INIT:
55641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pReplyData == NULL || *replySize != sizeof(int)) {
55741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
55841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
55941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
56041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.init)
56141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            *(int *) pReplyData = context->ops.init(context);
56241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        else
56341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            *(int *) pReplyData = 0;
56441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
56541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_SET_CONFIG:
56641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
56741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                || pReplyData == NULL || *replySize != sizeof(int)) {
56841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
56941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
57041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
57141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        *(int *) pReplyData = set_config(context, (effect_config_t *) pCmdData);
57241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
57341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_GET_CONFIG:
57441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pReplyData == NULL ||
57541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            *replySize != sizeof(effect_config_t)) {
57641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
57741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
57841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
57941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (!context->offload_enabled) {
58041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
58141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
58241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
58341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
58441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        get_config(context, (effect_config_t *)pReplyData);
58541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
58641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_RESET:
58741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.reset)
58841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->ops.reset(context);
58941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
59041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_ENABLE:
59141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pReplyData == NULL || *replySize != sizeof(int)) {
59241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
59341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
59441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
59541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->state != EFFECT_STATE_INITIALIZED) {
59641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -ENOSYS;
59741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
59841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
59941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->state = EFFECT_STATE_ACTIVE;
60041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.enable)
60141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->ops.enable(context);
60241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGV("%s EFFECT_CMD_ENABLE", __func__);
60341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        *(int *)pReplyData = 0;
60441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
60541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_DISABLE:
60641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pReplyData == NULL || *replySize != sizeof(int)) {
60741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
60841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
60941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
61041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->state != EFFECT_STATE_ACTIVE) {
61141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -ENOSYS;
61241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
61341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
61441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->state = EFFECT_STATE_INITIALIZED;
61541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.disable)
61641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->ops.disable(context);
61741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGV("%s EFFECT_CMD_DISABLE", __func__);
61841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        *(int *)pReplyData = 0;
61941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
62041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_GET_PARAM: {
62141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pCmdData == NULL ||
62241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
62341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            pReplyData == NULL ||
6241015d94fb02b3213c22c9ac4a16b20c4ed9498b6Andy Hung            *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint16_t)) ||
6251015d94fb02b3213c22c9ac4a16b20c4ed9498b6Andy Hung            // constrain memcpy below
6261015d94fb02b3213c22c9ac4a16b20c4ed9498b6Andy Hung            ((effect_param_t *)pCmdData)->psize > *replySize - sizeof(effect_param_t)) {
62741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
62841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ALOGV("EFFECT_CMD_GET_PARAM invalid command cmdSize %d *replySize %d",
62941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                  cmdSize, *replySize);
63041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
63141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
63241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (!context->offload_enabled) {
63341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
63441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
63541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
63641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_param_t *q = (effect_param_t *)pCmdData;
63741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + q->psize);
63841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_param_t *p = (effect_param_t *)pReplyData;
63941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.get_parameter)
64041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->ops.get_parameter(context, p, replySize);
64141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } break;
64241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_SET_PARAM: {
64341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pCmdData == NULL ||
64441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            cmdSize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) +
64541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                            sizeof(uint16_t)) ||
64641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            pReplyData == NULL || *replySize != sizeof(int32_t)) {
64741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
64841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ALOGV("EFFECT_CMD_SET_PARAM invalid command cmdSize %d *replySize %d",
64941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                  cmdSize, *replySize);
65041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
65141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
65241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        *(int32_t *)pReplyData = 0;
65341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_param_t *p = (effect_param_t *)pCmdData;
65441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.set_parameter)
65541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            *(int32_t *)pReplyData = context->ops.set_parameter(context, p,
65641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                                                *replySize);
65741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
65841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } break;
65941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_SET_DEVICE: {
66041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        uint32_t device;
66141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGV("\t EFFECT_CMD_SET_DEVICE start");
66241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (pCmdData == NULL || cmdSize < sizeof(uint32_t)) {
66341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
66441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ALOGV("EFFECT_CMD_SET_DEVICE invalid command cmdSize %d", cmdSize);
66541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            goto exit;
66641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
66741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        device = *(uint32_t *)pCmdData;
66841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->ops.set_device)
66941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            context->ops.set_device(context, device);
67041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } break;
67141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_SET_VOLUME:
67241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_SET_AUDIO_MODE:
67341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
67441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
67541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    case EFFECT_CMD_OFFLOAD: {
67641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        output_context_t *out_ctxt;
67741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
67841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (cmdSize != sizeof(effect_offload_param_t) || pCmdData == NULL
67941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                || pReplyData == NULL || *replySize != sizeof(int)) {
68041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ALOGV("%s EFFECT_CMD_OFFLOAD bad format", __func__);
68141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
68241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            break;
68341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
68441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
68541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        effect_offload_param_t* offload_param = (effect_offload_param_t*)pCmdData;
68641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
68741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        ALOGV("%s EFFECT_CMD_OFFLOAD offload %d output %d", __func__,
68841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George              offload_param->isOffload, offload_param->ioHandle);
68941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
69041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        *(int *)pReplyData = 0;
69141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
69241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->offload_enabled = offload_param->isOffload;
69341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (context->out_handle == offload_param->ioHandle)
69441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            break;
69541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
69641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        out_ctxt = get_output(context->out_handle);
69741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (out_ctxt != NULL)
69841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            remove_effect_from_output(out_ctxt, context);
69941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
70041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        context->out_handle = offload_param->ioHandle;
70141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        out_ctxt = get_output(context->out_handle);
70241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (out_ctxt != NULL)
70341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            add_effect_to_output(out_ctxt, context);
70441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
70541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        } break;
70641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
70741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
70841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    default:
70941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
71041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = context->ops.command(context, cmdCode, cmdSize,
71141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                                          pCmdData, replySize, pReplyData);
71241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        else {
71341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            ALOGW("%s invalid command %d", __func__, cmdCode);
71441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George            status = -EINVAL;
71541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        }
71641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        break;
71741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    }
71841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
71941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeexit:
72041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    pthread_mutex_unlock(&lock);
72141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
72241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return status;
72341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
72441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
72541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/* Effect Control Interface Implementation: get_descriptor */
72641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeint effect_get_descriptor(effect_handle_t   self,
72741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George                          effect_descriptor_t *descriptor)
72841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George{
72941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_context_t *context = (effect_context_t *)self;
73041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
73141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    if (!effect_exists(context) || (descriptor == NULL))
73241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George        return -EINVAL;
73341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
73441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    *descriptor = *context->desc;
73541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
73641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return 0;
73741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
73841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
73941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgebool effect_is_active(effect_context_t * ctxt) {
74041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    return ctxt->state == EFFECT_STATE_ACTIVE;
74141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George}
74241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
74341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George/* effect_handle_t interface implementation for offload effects */
74441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeconst struct effect_interface_s effect_interface = {
74541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_process,
74641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_command,
74741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    effect_get_descriptor,
74841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    NULL,
74941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George};
75041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George
75141f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George__attribute__ ((visibility ("default")))
75241f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew Georgeaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
75341f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    tag : AUDIO_EFFECT_LIBRARY_TAG,
75441f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    version : EFFECT_LIBRARY_API_VERSION,
75541f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    name : "Offload Effects Bundle Library",
75641f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    implementor : "The Android Open Source Project",
75741f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    create_effect : effect_lib_create,
75841f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    release_effect : effect_lib_release,
75941f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George    get_descriptor : effect_lib_get_descriptor,
76041f86651e362abc62d9d03f5c612c986bf15298fHaynes Mathew George};
761