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