161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Copyright (C) 2013 The Android Open Source Project
361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti *
461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Licensed under the Apache License, Version 2.0 (the "License");
561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * you may not use this file except in compliance with the License.
661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * You may obtain a copy of the License at
761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti *
861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti *      http://www.apache.org/licenses/LICENSE-2.0
961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti *
1061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Unless required by applicable law or agreed to in writing, software
1161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * distributed under the License is distributed on an "AS IS" BASIS,
1261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * See the License for the specific language governing permissions and
1461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * limitations under the License.
1561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
1661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
1761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define LOG_TAG "offload_visualizer"
1861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*#define LOG_NDEBUG 0*/
1961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <assert.h>
2061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <math.h>
2161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <stdlib.h>
2261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <string.h>
2361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <time.h>
2461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <sys/prctl.h>
2561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
2661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <cutils/list.h>
2761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <cutils/log.h>
2861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <system/thread_defs.h>
2961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <tinyalsa/asoundlib.h>
3061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#include <audio_effects/effect_visualizer.h>
3161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
3261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
3361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletienum {
3461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    EFFECT_STATE_UNINITIALIZED,
3561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    EFFECT_STATE_INITIALIZED,
3661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    EFFECT_STATE_ACTIVE,
3761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
3861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
3961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletitypedef struct effect_context_s effect_context_t;
4061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletitypedef struct output_context_s output_context_t;
4161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
4261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* effect specific operations. Only the init() and process() operations must be defined.
4361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Others are optional.
4461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
4561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletitypedef struct effect_ops_s {
4661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*init)(effect_context_t *context);
4761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*release)(effect_context_t *context);
4861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*reset)(effect_context_t *context);
4961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*enable)(effect_context_t *context);
5061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*disable)(effect_context_t *context);
5161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*start)(effect_context_t *context, output_context_t *output);
5261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*stop)(effect_context_t *context, output_context_t *output);
5361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*process)(effect_context_t *context, audio_buffer_t *in, audio_buffer_t *out);
5461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*set_parameter)(effect_context_t *context, effect_param_t *param, uint32_t size);
5561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*get_parameter)(effect_context_t *context, effect_param_t *param, uint32_t *size);
5661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int (*command)(effect_context_t *context, uint32_t cmdCode, uint32_t cmdSize,
5761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            void *pCmdData, uint32_t *replySize, void *pReplyData);
5861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti} effect_ops_t;
5961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
6061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletistruct effect_context_s {
6161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    const struct effect_interface_s *itfe;
6261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode effects_list_node;  /* node in created_effects_list */
6361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode output_node;  /* node in output_context_t.effects_list */
6461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_config_t config;
6561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    const effect_descriptor_t *desc;
6661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    audio_io_handle_t out_handle;  /* io handle of the output the effect is attached to */
6761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t state;
6861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    bool offload_enabled;  /* when offload is enabled we process VISUALIZER_CMD_CAPTURE command.
6961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                              Otherwise non offloaded visualizer has already processed the command
7061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                              and we must not overwrite the reply. */
7161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_ops_t ops;
7261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
7361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
7461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletitypedef struct output_context_s {
7561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode outputs_list_node;  /* node in active_outputs_list */
7661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    audio_io_handle_t handle; /* io handle */
7761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode effects_list; /* list of effects attached to this output */
7861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti} output_context_t;
7961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
8061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
8161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* maximum time since last capture buffer update before resetting capture buffer. This means
8261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti  that the framework has stopped playing audio and we must start returning silence */
8361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define MAX_STALL_TIME_MS 1000
8461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
8561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define CAPTURE_BUF_SIZE 65536 /* "64k should be enough for everyone" */
8661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
8761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define DISCARD_MEASUREMENTS_TIME_MS 2000 /* discard measurements older than this number of ms */
8861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
8961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* maximum number of buffers for which we keep track of the measurements */
9061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS 25 /* note: buffer index is stored in uint8_t */
9161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
9261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletitypedef struct buffer_stats_s {
9361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    bool is_valid;
9461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint16_t peak_u16; /* the positive peak of the absolute value of the samples in a buffer */
9561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    float rms_squared; /* the average square of the samples in a buffer */
9661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti} buffer_stats_t;
9761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
9861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletitypedef struct visualizer_context_s {
9961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_context_t common;
10061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
10161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t capture_idx;
10261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t capture_size;
10361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t scaling_mode;
10461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t last_capture_idx;
10561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t latency;
10661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct timespec buffer_update_time;
10761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint8_t capture_buf[CAPTURE_BUF_SIZE];
10861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    /* for measurements */
10961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint8_t channel_count; /* to avoid recomputing it every time a buffer is processed */
11061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t meas_mode;
11161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint8_t meas_wndw_size_in_buffers;
11261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint8_t meas_buffer_idx;
11361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    buffer_stats_t past_meas[MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS];
11461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti} visualizer_context_t;
11561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
11661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
11761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiextern const struct effect_interface_s effect_interface;
11861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
11961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* Offload visualizer UUID: 7a8044a0-1a71-11e3-a184-0002a5d5c51b */
12061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleticonst effect_descriptor_t visualizer_descriptor = {
12161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        {0xe46b26a0, 0xdddd, 0x11db, 0x8afd, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
12261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        {0x7a8044a0, 0x1a71, 0x11e3, 0xa184, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}},
12361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        EFFECT_CONTROL_API_VERSION,
12461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        (EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_HW_ACC_TUNNEL ),
12561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        0, /* TODO */
12661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        1,
12761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        "QCOM MSM offload visualizer",
12861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        "The Android Open Source Project",
12961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
13061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
13161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleticonst effect_descriptor_t *descriptors[] = {
13261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        &visualizer_descriptor,
13361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        NULL,
13461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
13561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
13661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
13761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletipthread_once_t once = PTHREAD_ONCE_INIT;
13861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint init_status;
13961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
14061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* list of created effects. Updated by visualizer_hal_start_output()
14161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * and visualizer_hal_stop_output() */
14261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletistruct listnode created_effects_list;
14361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* list of active output streams. Updated by visualizer_hal_start_output()
14461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * and visualizer_hal_stop_output() */
14561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletistruct listnode active_outputs_list;
14661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
14761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* thread capturing PCM from Proxy port and calling the process function on each enabled effect
14861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * attached to an active output stream */
14961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletipthread_t capture_thread;
15061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* lock must be held when modifying or accessing created_effects_list or active_outputs_list */
15161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletipthread_mutex_t lock;
15261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* thread_lock must be held when starting or stopping the capture thread.
15361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Locking order: thread_lock -> lock */
15461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletipthread_mutex_t thread_lock;
15561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* cond is signaled when an output is started or stopped or an effect is enabled or disable: the
15661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * capture thread will reevaluate the capture and effect rocess conditions. */
15761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletipthread_cond_t cond;
15861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* true when requesting the capture thread to exit */
15961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletibool exit_thread;
16061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* 0 if the capture thread was created successfully */
16161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint thread_status;
16261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
16361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
16461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define DSP_OUTPUT_LATENCY_MS 0 /* Fudge factor for latency after capture point in audio DSP */
16561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
16661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* Retry for delay for mixer open */
16761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define RETRY_NUMBER 10
16861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define RETRY_US 500000
16961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
17061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define MIXER_CARD 0
17161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define SOUND_CARD 0
17261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define CAPTURE_DEVICE 8
17361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
17461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* Proxy port supports only MMAP read and those fixed parameters*/
17561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define AUDIO_CAPTURE_CHANNEL_COUNT 2
17661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define AUDIO_CAPTURE_SMP_RATE 48000
17761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define AUDIO_CAPTURE_PERIOD_SIZE (768)
17861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti#define AUDIO_CAPTURE_PERIOD_COUNT 32
17961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
18061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletistruct pcm_config pcm_config_capture = {
18161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .channels = AUDIO_CAPTURE_CHANNEL_COUNT,
18261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .rate = AUDIO_CAPTURE_SMP_RATE,
18361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .period_size = AUDIO_CAPTURE_PERIOD_SIZE,
18461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
18561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .format = PCM_FORMAT_S16_LE,
18661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .start_threshold = AUDIO_CAPTURE_PERIOD_SIZE / 4,
18761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .stop_threshold = INT_MAX,
18861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    .avail_min = AUDIO_CAPTURE_PERIOD_SIZE / 4,
18961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
19061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
19161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
19261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
19361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti *  Local functions
19461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
19561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
19661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletistatic void init_once() {
19761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_init(&created_effects_list);
19861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_init(&active_outputs_list);
19961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
20061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_init(&lock, NULL);
20161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_init(&thread_lock, NULL);
20261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_cond_init(&cond, NULL);
20361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    exit_thread = false;
20461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    thread_status = -1;
20561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
20661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    init_status = 0;
20761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
20861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
20961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint lib_init() {
21061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_once(&once, init_once);
21161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return init_status;
21261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
21361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
21461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletibool effect_exists(effect_context_t *context) {
21561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *node;
21661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
21761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(node, &created_effects_list) {
21861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_context_t *fx_ctxt = node_to_item(node,
21961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     effect_context_t,
22061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     effects_list_node);
22161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (fx_ctxt == context) {
22261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return true;
22361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
22461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
22561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return false;
22661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
22761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
22861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletioutput_context_t *get_output(audio_io_handle_t output) {
22961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *node;
23061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
23161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(node, &active_outputs_list) {
23261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        output_context_t *out_ctxt = node_to_item(node,
23361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                  output_context_t,
23461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                  outputs_list_node);
23561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (out_ctxt->handle == output) {
23661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return out_ctxt;
23761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
23861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
23961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return NULL;
24061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
24161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
24261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletivoid add_effect_to_output(output_context_t * output, effect_context_t *context) {
24361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *fx_node;
24461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
24561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(fx_node, &output->effects_list) {
24661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_context_t *fx_ctxt = node_to_item(fx_node,
24761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     effect_context_t,
24861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     output_node);
24961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (fx_ctxt == context)
25061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return;
25161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
25261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_add_tail(&output->effects_list, &context->output_node);
25361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (context->ops.start)
25461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.start(context, output);
25561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
25661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
25761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletivoid remove_effect_from_output(output_context_t * output, effect_context_t *context) {
25861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *fx_node;
25961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
26061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(fx_node, &output->effects_list) {
26161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_context_t *fx_ctxt = node_to_item(fx_node,
26261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     effect_context_t,
26361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     output_node);
26461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (fx_ctxt == context) {
26561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (context->ops.stop)
26661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                context->ops.stop(context, output);
26761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            list_remove(&context->output_node);
26861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return;
26961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
27061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
27161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
27261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
27361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletibool effects_enabled() {
27461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *out_node;
27561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
27661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(out_node, &active_outputs_list) {
27761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        struct listnode *fx_node;
27861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        output_context_t *out_ctxt = node_to_item(out_node,
27961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                  output_context_t,
28061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                  outputs_list_node);
28161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
28261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        list_for_each(fx_node, &out_ctxt->effects_list) {
28361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            effect_context_t *fx_ctxt = node_to_item(fx_node,
28461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                         effect_context_t,
28561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                         output_node);
28661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (fx_ctxt->state == EFFECT_STATE_ACTIVE && fx_ctxt->ops.process != NULL)
28761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                return true;
28861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
28961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
29061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return false;
29161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
29261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
29361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint configure_proxy_capture(struct mixer *mixer, int value) {
29461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    const char *proxy_ctl_name = "AFE_PCM_RX Audio Mixer MultiMedia4";
29561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct mixer_ctl *ctl;
29661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
29761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ctl = mixer_get_ctl_by_name(mixer, proxy_ctl_name);
29861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (ctl == NULL) {
29961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGW("%s: could not get %s ctl", __func__, proxy_ctl_name);
30061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
30161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
30261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (mixer_ctl_set_value(ctl, 0, value) != 0)
30361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGW("%s: error setting value %d on %s ", __func__, value, proxy_ctl_name);
30461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
30561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
30661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
30761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
30861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
30961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletivoid *capture_thread_loop(void *arg)
31061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
31161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int16_t data[AUDIO_CAPTURE_PERIOD_SIZE * AUDIO_CAPTURE_CHANNEL_COUNT * sizeof(int16_t)];
31261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    audio_buffer_t buf;
31361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    buf.frameCount = AUDIO_CAPTURE_PERIOD_SIZE;
31461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    buf.s16 = data;
31561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    bool capture_enabled = false;
31661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct mixer *mixer;
31761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct pcm *pcm = NULL;
31861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int ret;
31961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int retry_num = 0;
32061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
32161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGD("thread enter");
32261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
32361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    prctl(PR_SET_NAME, (unsigned long)"visualizer capture", 0, 0, 0);
32461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
32561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
32661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
32761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    mixer = mixer_open(MIXER_CARD);
32861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    while (mixer == NULL && retry_num < RETRY_NUMBER) {
32961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        usleep(RETRY_US);
33061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        mixer = mixer_open(MIXER_CARD);
33161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        retry_num++;
33261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
33361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (mixer == NULL) {
33461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        pthread_mutex_unlock(&lock);
33561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return NULL;
33661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
33761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
33861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    for (;;) {
33961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (exit_thread) {
34061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            break;
34161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
34261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (effects_enabled()) {
34361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (!capture_enabled) {
34461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                ret = configure_proxy_capture(mixer, 1);
34561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                if (ret == 0) {
34661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    pcm = pcm_open(SOUND_CARD, CAPTURE_DEVICE,
34761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                   PCM_IN|PCM_MMAP|PCM_NOIRQ, &pcm_config_capture);
34861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    if (pcm && !pcm_is_ready(pcm)) {
34961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        ALOGW("%s: %s", __func__, pcm_get_error(pcm));
35061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        pcm_close(pcm);
35161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        pcm = NULL;
35261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        configure_proxy_capture(mixer, 0);
35361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    } else {
35461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        capture_enabled = true;
35561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        ALOGD("%s: capture ENABLED", __func__);
35661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    }
35761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                }
35861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
35961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } else {
36061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (capture_enabled) {
36161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                if (pcm != NULL)
36261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    pcm_close(pcm);
36361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                configure_proxy_capture(mixer, 0);
36461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                ALOGD("%s: capture DISABLED", __func__);
36561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                capture_enabled = false;
36661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
36761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pthread_cond_wait(&cond, &lock);
36861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
36961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (!capture_enabled)
37061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            continue;
37161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
37261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        pthread_mutex_unlock(&lock);
37361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ret = pcm_mmap_read(pcm, data, sizeof(data));
37461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        pthread_mutex_lock(&lock);
37561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
37661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (ret == 0) {
37761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            struct listnode *out_node;
37861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
37961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            list_for_each(out_node, &active_outputs_list) {
38061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                output_context_t *out_ctxt = node_to_item(out_node,
38161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                          output_context_t,
38261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                          outputs_list_node);
38361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                struct listnode *fx_node;
38461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
38561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                list_for_each(fx_node, &out_ctxt->effects_list) {
38661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    effect_context_t *fx_ctxt = node_to_item(fx_node,
38761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                                effect_context_t,
38861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                                output_node);
38961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    if (fx_ctxt->ops.process != NULL)
39061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        fx_ctxt->ops.process(fx_ctxt, &buf, &buf);
39161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                }
39261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
39361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } else {
39461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            ALOGW("%s: read status %d %s", __func__, ret, pcm_get_error(pcm));
39561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
39661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
39761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
39861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (capture_enabled) {
39961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pcm != NULL)
40061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pcm_close(pcm);
40161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        configure_proxy_capture(mixer, 0);
40261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
40361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    mixer_close(mixer);
40461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
40561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
40661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGD("thread exit");
40761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
40861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return NULL;
40961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
41061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
41161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
41261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Interface from audio HAL
41361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
41461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
41561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti__attribute__ ((visibility ("default")))
41661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_hal_start_output(audio_io_handle_t output, int pcm_id) {
41761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int ret;
41861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *node;
41961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
42061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
42161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
42261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (lib_init() != 0)
42361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return init_status;
42461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
42561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&thread_lock);
42661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
42761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (get_output(output) != NULL) {
42861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGW("%s output already started", __func__);
42961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ret = -ENOSYS;
43061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
43161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
43261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
43361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    output_context_t *out_ctxt = (output_context_t *)malloc(sizeof(output_context_t));
43461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (out_ctxt == NULL) {
43561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGE("%s fail to allocate memory", __func__);
43661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ret = -ENOMEM;
43761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
43861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
43961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    out_ctxt->handle = output;
44061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_init(&out_ctxt->effects_list);
44161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
44261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(node, &created_effects_list) {
44361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_context_t *fx_ctxt = node_to_item(node,
44461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     effect_context_t,
44561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                     effects_list_node);
44661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (fx_ctxt->out_handle == output) {
44761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (fx_ctxt->ops.start)
44861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                fx_ctxt->ops.start(fx_ctxt, out_ctxt);
44961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            list_add_tail(&out_ctxt->effects_list, &fx_ctxt->output_node);
45061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
45161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
45261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (list_empty(&active_outputs_list)) {
45361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        exit_thread = false;
45461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        thread_status = pthread_create(&capture_thread, (const pthread_attr_t *) NULL,
45561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        capture_thread_loop, NULL);
45661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
45761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_add_tail(&active_outputs_list, &out_ctxt->outputs_list_node);
45861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_cond_signal(&cond);
45961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
46061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiexit:
46161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
46261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&thread_lock);
46361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return ret;
46461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
46561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
46661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti__attribute__ ((visibility ("default")))
46761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_hal_stop_output(audio_io_handle_t output, int pcm_id) {
46861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int ret;
46961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *node;
47061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    struct listnode *fx_node;
47161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    output_context_t *out_ctxt;
47261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
47361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGV("%s output %d pcm_id %d", __func__, output, pcm_id);
47461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
47561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (lib_init() != 0)
47661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return init_status;
47761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
47861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&thread_lock);
47961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
48061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
48161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    out_ctxt = get_output(output);
48261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (out_ctxt == NULL) {
48361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGW("%s output not started", __func__);
48461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ret = -ENOSYS;
48561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
48661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
48761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_for_each(fx_node, &out_ctxt->effects_list) {
48861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_context_t *fx_ctxt = node_to_item(fx_node,
48961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                 effect_context_t,
49061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                 output_node);
49161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (fx_ctxt->ops.stop)
49261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
49361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
49461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_remove(&out_ctxt->outputs_list_node);
49561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_cond_signal(&cond);
49661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
49761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (list_empty(&active_outputs_list)) {
49861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (thread_status == 0) {
49961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            exit_thread = true;
50061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pthread_cond_signal(&cond);
50161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pthread_mutex_unlock(&lock);
50261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pthread_join(capture_thread, (void **) NULL);
50361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pthread_mutex_lock(&lock);
50461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            thread_status = -1;
50561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
50661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
50761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
50861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    free(out_ctxt);
50961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
51061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiexit:
51161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
51261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&thread_lock);
51361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return ret;
51461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
51561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
51661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
51761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
51861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Effect operations
51961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
52061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
52161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint set_config(effect_context_t *context, effect_config_t *config)
52261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
52361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (config->inputCfg.samplingRate != config->outputCfg.samplingRate) return -EINVAL;
52461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (config->inputCfg.channels != config->outputCfg.channels) return -EINVAL;
52561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (config->inputCfg.format != config->outputCfg.format) return -EINVAL;
52661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (config->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL;
52761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (config->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
52861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            config->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
52961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (config->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT) return -EINVAL;
53061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
53161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config = *config;
53261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
53361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (context->ops.reset)
53461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.reset(context);
53561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
53661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
53761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
53861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
53961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletivoid get_config(effect_context_t *context, effect_config_t *config)
54061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
54161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    *config = context->config;
54261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
54361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
54461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
54561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
54661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Visualizer operations
54761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
54861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
54961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiuint32_t visualizer_get_delta_time_ms_from_updated_time(visualizer_context_t* visu_ctxt) {
55061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t delta_ms = 0;
55161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (visu_ctxt->buffer_update_time.tv_sec != 0) {
55261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        struct timespec ts;
55361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
55461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            time_t secs = ts.tv_sec - visu_ctxt->buffer_update_time.tv_sec;
55561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            long nsec = ts.tv_nsec - visu_ctxt->buffer_update_time.tv_nsec;
55661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (nsec < 0) {
55761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                --secs;
55861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                nsec += 1000000000;
55961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
56061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            delta_ms = secs * 1000 + nsec / 1000000;
56161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
56261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
56361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return delta_ms;
56461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
56561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
56661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_reset(effect_context_t *context)
56761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
56861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visualizer_context_t * visu_ctxt = (visualizer_context_t *)context;
56961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
57061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->capture_idx = 0;
57161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->last_capture_idx = 0;
57261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->buffer_update_time.tv_sec = 0;
57361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->latency = DSP_OUTPUT_LATENCY_MS;
57461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    memset(visu_ctxt->capture_buf, 0x80, CAPTURE_BUF_SIZE);
57561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
57661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
57761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
57861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_init(effect_context_t *context)
57961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
58061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int32_t i;
58161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
58261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visualizer_context_t * visu_ctxt = (visualizer_context_t *)context;
58361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
58461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
58561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
58661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
58761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.samplingRate = 44100;
58861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.bufferProvider.getBuffer = NULL;
58961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.bufferProvider.releaseBuffer = NULL;
59061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.bufferProvider.cookie = NULL;
59161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.inputCfg.mask = EFFECT_CONFIG_ALL;
59261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
59361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
59461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
59561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.samplingRate = 44100;
59661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.bufferProvider.getBuffer = NULL;
59761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.bufferProvider.releaseBuffer = NULL;
59861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.bufferProvider.cookie = NULL;
59961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->config.outputCfg.mask = EFFECT_CONFIG_ALL;
60061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
60161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->capture_size = VISUALIZER_CAPTURE_SIZE_MAX;
60261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->scaling_mode = VISUALIZER_SCALING_MODE_NORMALIZED;
60361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
60461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    // measurement initialization
60561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->channel_count = popcount(context->config.inputCfg.channels);
60661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->meas_mode = MEASUREMENT_MODE_NONE;
60761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->meas_wndw_size_in_buffers = MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS;
60861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->meas_buffer_idx = 0;
60961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    for (i=0 ; i<visu_ctxt->meas_wndw_size_in_buffers ; i++) {
61061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->past_meas[i].is_valid = false;
61161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->past_meas[i].peak_u16 = 0;
61261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->past_meas[i].rms_squared = 0;
61361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
61461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
61561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    set_config(context, &context->config);
61661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
61761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
61861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
61961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
62061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_get_parameter(effect_context_t *context, effect_param_t *p, uint32_t *size)
62161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
62261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visualizer_context_t *visu_ctxt = (visualizer_context_t *)context;
62361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
62461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    p->status = 0;
62561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    *size = sizeof(effect_param_t) + sizeof(uint32_t);
62661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (p->psize != sizeof(uint32_t)) {
62761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        p->status = -EINVAL;
62861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return 0;
62961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
63061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    switch (*(uint32_t *)p->data) {
63161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_CAPTURE_SIZE:
63261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s get capture_size = %d", __func__, visu_ctxt->capture_size);
63361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *((uint32_t *)p->data + 1) = visu_ctxt->capture_size;
63461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        p->vsize = sizeof(uint32_t);
63561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *size += sizeof(uint32_t);
63661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
63761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_SCALING_MODE:
63861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s get scaling_mode = %d", __func__, visu_ctxt->scaling_mode);
63961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *((uint32_t *)p->data + 1) = visu_ctxt->scaling_mode;
64061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        p->vsize = sizeof(uint32_t);
64161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *size += sizeof(uint32_t);
64261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
64361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_MEASUREMENT_MODE:
64461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s get meas_mode = %d", __func__, visu_ctxt->meas_mode);
64561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *((uint32_t *)p->data + 1) = visu_ctxt->meas_mode;
64661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        p->vsize = sizeof(uint32_t);
64761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *size += sizeof(uint32_t);
64861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
64961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    default:
65061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        p->status = -EINVAL;
65161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
65261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
65361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
65461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
65561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_set_parameter(effect_context_t *context, effect_param_t *p, uint32_t size)
65661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
65761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visualizer_context_t *visu_ctxt = (visualizer_context_t *)context;
65861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
65961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (p->psize != sizeof(uint32_t) || p->vsize != sizeof(uint32_t))
66061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
66161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
66261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    switch (*(uint32_t *)p->data) {
66361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_CAPTURE_SIZE:
66461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->capture_size = *((uint32_t *)p->data + 1);
66561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s set capture_size = %d", __func__, visu_ctxt->capture_size);
66661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
66761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_SCALING_MODE:
66861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->scaling_mode = *((uint32_t *)p->data + 1);
66961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s set scaling_mode = %d", __func__, visu_ctxt->scaling_mode);
67061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
67161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_LATENCY:
67261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* Ignore latency as we capture at DSP output
67361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         * visu_ctxt->latency = *((uint32_t *)p->data + 1); */
67461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s set latency = %d", __func__, visu_ctxt->latency);
67561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
67661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_PARAM_MEASUREMENT_MODE:
67761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->meas_mode = *((uint32_t *)p->data + 1);
67861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s set meas_mode = %d", __func__, visu_ctxt->meas_mode);
67961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
68061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    default:
68161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
68261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
68361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
68461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
68561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
68661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* Real process function called from capture thread. Called with lock held */
68761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_process(effect_context_t *context,
68861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                       audio_buffer_t *inBuffer,
68961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                       audio_buffer_t *outBuffer)
69061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
69161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visualizer_context_t *visu_ctxt = (visualizer_context_t *)context;
69261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
69361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (!effect_exists(context))
69461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
69561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
69661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (inBuffer == NULL || inBuffer->raw == NULL ||
69761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        outBuffer == NULL || outBuffer->raw == NULL ||
69861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        inBuffer->frameCount != outBuffer->frameCount ||
69961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        inBuffer->frameCount == 0) {
70061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
70161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
70261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
70361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    // perform measurements if needed
70461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (visu_ctxt->meas_mode & MEASUREMENT_MODE_PEAK_RMS) {
70561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        // find the peak and RMS squared for the new buffer
70661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        uint32_t inIdx;
70761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        int16_t max_sample = 0;
70861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        float rms_squared_acc = 0;
70961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        for (inIdx = 0 ; inIdx < inBuffer->frameCount * visu_ctxt->channel_count ; inIdx++) {
71061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (inBuffer->s16[inIdx] > max_sample) {
71161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                max_sample = inBuffer->s16[inIdx];
71261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            } else if (-inBuffer->s16[inIdx] > max_sample) {
71361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                max_sample = -inBuffer->s16[inIdx];
71461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
71561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            rms_squared_acc += (inBuffer->s16[inIdx] * inBuffer->s16[inIdx]);
71661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
71761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        // store the measurement
71861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->past_meas[visu_ctxt->meas_buffer_idx].peak_u16 = (uint16_t)max_sample;
71961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->past_meas[visu_ctxt->meas_buffer_idx].rms_squared =
72061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                rms_squared_acc / (inBuffer->frameCount * visu_ctxt->channel_count);
72161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->past_meas[visu_ctxt->meas_buffer_idx].is_valid = true;
72261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (++visu_ctxt->meas_buffer_idx >= visu_ctxt->meas_wndw_size_in_buffers) {
72361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            visu_ctxt->meas_buffer_idx = 0;
72461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
72561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
72661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
72761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    /* all code below assumes stereo 16 bit PCM output and input */
72861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int32_t shift;
72961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
73061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (visu_ctxt->scaling_mode == VISUALIZER_SCALING_MODE_NORMALIZED) {
73161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* derive capture scaling factor from peak value in current buffer
73261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         * this gives more interesting captures for display. */
73361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        shift = 32;
73461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        int len = inBuffer->frameCount * 2;
73561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        int i;
73661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        for (i = 0; i < len; i++) {
73761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            int32_t smp = inBuffer->s16[i];
73861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (smp < 0) smp = -smp - 1; /* take care to keep the max negative in range */
73961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            int32_t clz = __builtin_clz(smp);
74061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (shift > clz) shift = clz;
74161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
74261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* A maximum amplitude signal will have 17 leading zeros, which we want to
74361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         * translate to a shift of 8 (for converting 16 bit to 8 bit) */
74461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        shift = 25 - shift;
74561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* Never scale by less than 8 to avoid returning unaltered PCM signal. */
74661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (shift < 3) {
74761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            shift = 3;
74861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
74961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* add one to combine the division by 2 needed after summing
75061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         * left and right channels below */
75161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        shift++;
75261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    } else {
75361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        assert(visu_ctxt->scaling_mode == VISUALIZER_SCALING_MODE_AS_PLAYED);
75461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        shift = 9;
75561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
75661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
75761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t capt_idx;
75861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint32_t in_idx;
75961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    uint8_t *buf = visu_ctxt->capture_buf;
76061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    for (in_idx = 0, capt_idx = visu_ctxt->capture_idx;
76161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         in_idx < inBuffer->frameCount;
76261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         in_idx++, capt_idx++) {
76361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (capt_idx >= CAPTURE_BUF_SIZE) {
76461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            /* wrap around */
76561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            capt_idx = 0;
76661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
76761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        int32_t smp = inBuffer->s16[2 * in_idx] + inBuffer->s16[2 * in_idx + 1];
76861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        smp = smp >> shift;
76961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        buf[capt_idx] = ((uint8_t)smp)^0x80;
77061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
77161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
77261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    /* XXX the following two should really be atomic, though it probably doesn't
77361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti     * matter much for visualization purposes */
77461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visu_ctxt->capture_idx = capt_idx;
77561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    /* update last buffer update time stamp */
77661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (clock_gettime(CLOCK_MONOTONIC, &visu_ctxt->buffer_update_time) < 0) {
77761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visu_ctxt->buffer_update_time.tv_sec = 0;
77861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
77961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
78061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (context->state != EFFECT_STATE_ACTIVE) {
78161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s DONE inactive", __func__);
78261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -ENODATA;
78361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
78461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
78561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
78661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
78761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
78861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint visualizer_command(effect_context_t * context, uint32_t cmdCode, uint32_t cmdSize,
78961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        void *pCmdData, uint32_t *replySize, void *pReplyData)
79061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
79161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    visualizer_context_t * visu_ctxt = (visualizer_context_t *)context;
79261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
79361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    switch (cmdCode) {
79461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_CMD_CAPTURE:
79561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pReplyData == NULL || *replySize != visu_ctxt->capture_size) {
79661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            ALOGV("%s VISUALIZER_CMD_CAPTURE error *replySize %d context->capture_size %d",
79761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                  __func__, *replySize, visu_ctxt->capture_size);
79861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return -EINVAL;
79961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
80061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
80161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (!context->offload_enabled)
80261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            break;
80361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
80461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->state == EFFECT_STATE_ACTIVE) {
80561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            int32_t latency_ms = visu_ctxt->latency;
80661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            const uint32_t delta_ms = visualizer_get_delta_time_ms_from_updated_time(visu_ctxt);
80761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            latency_ms -= delta_ms;
80861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (latency_ms < 0) {
80961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                latency_ms = 0;
81061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
81161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            const uint32_t delta_smp = context->config.inputCfg.samplingRate * latency_ms / 1000;
81261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
81361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            int32_t capture_point = visu_ctxt->capture_idx - visu_ctxt->capture_size - delta_smp;
81461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            int32_t capture_size = visu_ctxt->capture_size;
81561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if (capture_point < 0) {
81661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                int32_t size = -capture_point;
81761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                if (size > capture_size)
81861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    size = capture_size;
81961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
82061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                memcpy(pReplyData,
82161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                       visu_ctxt->capture_buf + CAPTURE_BUF_SIZE + capture_point,
82261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                       size);
82361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                pReplyData = (void *)((size_t)pReplyData + size);
82461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                capture_size -= size;
82561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                capture_point = 0;
82661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
82761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            memcpy(pReplyData,
82861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                   visu_ctxt->capture_buf + capture_point,
82961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                   capture_size);
83061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
83161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
83261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            /* if audio framework has stopped playing audio although the effect is still
83361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti             * active we must clear the capture buffer to return silence */
83461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            if ((visu_ctxt->last_capture_idx == visu_ctxt->capture_idx) &&
83561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    (visu_ctxt->buffer_update_time.tv_sec != 0)) {
83661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                if (delta_ms > MAX_STALL_TIME_MS) {
83761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    ALOGV("%s capture going to idle", __func__);
83861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    visu_ctxt->buffer_update_time.tv_sec = 0;
83961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    memset(pReplyData, 0x80, visu_ctxt->capture_size);
84061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                }
84161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
84261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            visu_ctxt->last_capture_idx = visu_ctxt->capture_idx;
84361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } else {
84461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            memset(pReplyData, 0x80, visu_ctxt->capture_size);
84561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
84661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
84761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
84861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case VISUALIZER_CMD_MEASURE: {
84961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        uint16_t peak_u16 = 0;
85061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        float sum_rms_squared = 0.0f;
85161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        uint8_t nb_valid_meas = 0;
85261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* reset measurements if last measurement was too long ago (which implies stored
85361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti         * measurements aren't relevant anymore and shouldn't bias the new one) */
85461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        const int32_t delay_ms = visualizer_get_delta_time_ms_from_updated_time(visu_ctxt);
85561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (delay_ms > DISCARD_MEASUREMENTS_TIME_MS) {
85661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            uint32_t i;
85761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            ALOGV("Discarding measurements, last measurement is %dms old", delay_ms);
85861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            for (i=0 ; i<visu_ctxt->meas_wndw_size_in_buffers ; i++) {
85961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                visu_ctxt->past_meas[i].is_valid = false;
86061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                visu_ctxt->past_meas[i].peak_u16 = 0;
86161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                visu_ctxt->past_meas[i].rms_squared = 0;
86261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
86361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            visu_ctxt->meas_buffer_idx = 0;
86461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } else {
86561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            /* only use actual measurements, otherwise the first RMS measure happening before
86661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti             * MEASUREMENT_WINDOW_MAX_SIZE_IN_BUFFERS have been played will always be artificially
86761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti             * low */
86861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            uint32_t i;
86961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            for (i=0 ; i < visu_ctxt->meas_wndw_size_in_buffers ; i++) {
87061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                if (visu_ctxt->past_meas[i].is_valid) {
87161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    if (visu_ctxt->past_meas[i].peak_u16 > peak_u16) {
87261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                        peak_u16 = visu_ctxt->past_meas[i].peak_u16;
87361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    }
87461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    sum_rms_squared += visu_ctxt->past_meas[i].rms_squared;
87561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                    nb_valid_meas++;
87661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                }
87761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            }
87861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
87961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        float rms = nb_valid_meas == 0 ? 0.0f : sqrtf(sum_rms_squared / nb_valid_meas);
88061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        int32_t* p_int_reply_data = (int32_t*)pReplyData;
88161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        /* convert from I16 sample values to mB and write results */
88261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (rms < 0.000016f) {
88361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            p_int_reply_data[MEASUREMENT_IDX_RMS] = -9600; //-96dB
88461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } else {
88561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            p_int_reply_data[MEASUREMENT_IDX_RMS] = (int32_t) (2000 * log10(rms / 32767.0f));
88661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
88761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (peak_u16 == 0) {
88861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            p_int_reply_data[MEASUREMENT_IDX_PEAK] = -9600; //-96dB
88961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } else {
89061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            p_int_reply_data[MEASUREMENT_IDX_PEAK] = (int32_t) (2000 * log10(peak_u16 / 32767.0f));
89161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
89261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("VISUALIZER_CMD_MEASURE peak=%d (%dmB), rms=%.1f (%dmB)",
89361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                peak_u16, p_int_reply_data[MEASUREMENT_IDX_PEAK],
89461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                rms, p_int_reply_data[MEASUREMENT_IDX_RMS]);
89561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
89661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
89761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
89861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    default:
89961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGW("%s invalid command %d", __func__, cmdCode);
90061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
90161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
90261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
90361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
90461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
90561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
90661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
90761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Effect Library Interface Implementation
90861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
90961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
91061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint effect_lib_create(const effect_uuid_t *uuid,
91161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                         int32_t sessionId,
91261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                         int32_t ioId,
91361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                         effect_handle_t *pHandle) {
91461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int ret;
91561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int i;
91661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
91761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (lib_init() != 0)
91861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return init_status;
91961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
92061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (pHandle == NULL || uuid == NULL)
92161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
92261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
92361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    for (i = 0; descriptors[i] != NULL; i++) {
92461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0)
92561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            break;
92661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
92761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
92861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (descriptors[i] == NULL)
92961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
93061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
93161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_context_t *context;
93261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (memcmp(uuid, &visualizer_descriptor.uuid, sizeof(effect_uuid_t)) == 0) {
93361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        visualizer_context_t *visu_ctxt = (visualizer_context_t *)calloc(1,
93461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                                                     sizeof(visualizer_context_t));
93561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (visu_ctxt == NULL) {
93661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            ALOGE("%s fail to allocate memory", __func__);
93761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return -ENOMEM;
93861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
93961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context = (effect_context_t *)visu_ctxt;
94061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.init = visualizer_init;
94161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.reset = visualizer_reset;
94261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.process = visualizer_process;
94361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.set_parameter = visualizer_set_parameter;
94461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.get_parameter = visualizer_get_parameter;
94561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->ops.command = visualizer_command;
94661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->desc = &visualizer_descriptor;
94761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    } else {
94861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
94961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
95061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
95161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->itfe = &effect_interface;
95261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->state = EFFECT_STATE_UNINITIALIZED;
95361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->out_handle = (audio_io_handle_t)ioId;
95461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
95561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ret = context->ops.init(context);
95661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (ret < 0) {
95761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGW("%s init failed", __func__);
95861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        free(context);
95961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return ret;
96061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
96161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
96261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    context->state = EFFECT_STATE_INITIALIZED;
96361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
96461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
96561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    list_add_tail(&created_effects_list, &context->effects_list_node);
96661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    output_context_t *out_ctxt = get_output(ioId);
96761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (out_ctxt != NULL)
96861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        add_effect_to_output(out_ctxt, context);
96961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
97061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
97161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    *pHandle = (effect_handle_t)context;
97261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
97361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGV("%s created context %p", __func__, context);
97461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
97561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
97661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
97761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
97861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
97961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint effect_lib_release(effect_handle_t handle) {
98061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_context_t *context = (effect_context_t *)handle;
98161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int status;
98261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
98361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (lib_init() != 0)
98461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return init_status;
98561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
98661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGV("%s context %p", __func__, handle);
98761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
98861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    status = -EINVAL;
98961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (effect_exists(context)) {
99061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        output_context_t *out_ctxt = get_output(context->out_handle);
99161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (out_ctxt != NULL)
99261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            remove_effect_from_output(out_ctxt, context);
99361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        list_remove(&context->effects_list_node);
99461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.release)
99561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            context->ops.release(context);
99661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        free(context);
99761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        status = 0;
99861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
99961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
100061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
100161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return status;
100261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
100361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
100461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint effect_lib_get_descriptor(const effect_uuid_t *uuid,
100561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                effect_descriptor_t *descriptor) {
100661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int i;
100761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
100861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (lib_init() != 0)
100961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return init_status;
101061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
101161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (descriptor == NULL || uuid == NULL) {
101261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s called with NULL pointer", __func__);
101361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
101461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
101561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
101661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    for (i = 0; descriptors[i] != NULL; i++) {
101761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (memcmp(uuid, &descriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
101861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            *descriptor = *descriptors[i];
101961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            return 0;
102061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
102161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
102261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
102361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return  -EINVAL;
102461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
102561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
102661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/*
102761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti * Effect Control Interface Implementation
102861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti */
102961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
103061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti /* Stub function for effect interface: never called for offloaded effects */
103161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint effect_process(effect_handle_t self,
103261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                       audio_buffer_t *inBuffer,
103361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                       audio_buffer_t *outBuffer)
103461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
103561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_context_t * context = (effect_context_t *)self;
103661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int status = 0;
103761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
103861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    ALOGW("%s Called ?????", __func__);
103961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
104061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
104161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (!effect_exists(context)) {
104261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        status = -EINVAL;
104361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
104461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
104561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
104661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (context->state != EFFECT_STATE_ACTIVE) {
104761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        status = -EINVAL;
104861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
104961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
105061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
105161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiexit:
105261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
105361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return status;
105461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
105561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
105661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint effect_command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
105761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        void *pCmdData, uint32_t *replySize, void *pReplyData)
105861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
105961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
106061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_context_t * context = (effect_context_t *)self;
106161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int retsize;
106261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    int status = 0;
106361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
106461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_lock(&lock);
106561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
106661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (!effect_exists(context)) {
106761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        status = -EINVAL;
106861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
106961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
107061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
107161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (context == NULL || context->state == EFFECT_STATE_UNINITIALIZED) {
107261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        status = -EINVAL;
107361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        goto exit;
107461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
107561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
107661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti//    ALOGV_IF(cmdCode != VISUALIZER_CMD_CAPTURE,
107761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti//             "%s command %d cmdSize %d", __func__, cmdCode, cmdSize);
107861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
107961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    switch (cmdCode) {
108061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_INIT:
108161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pReplyData == NULL || *replySize != sizeof(int)) {
108261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
108361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
108461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
108561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.init)
108661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            *(int *) pReplyData = context->ops.init(context);
108761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        else
108861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            *(int *) pReplyData = 0;
108961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
109061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_SET_CONFIG:
109161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
109261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                || pReplyData == NULL || *replySize != sizeof(int)) {
109361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
109461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
109561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
109661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *(int *) pReplyData = set_config(context, (effect_config_t *) pCmdData);
109761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
109861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_GET_CONFIG:
109961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pReplyData == NULL ||
110061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            *replySize != sizeof(effect_config_t)) {
110161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
110261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
110361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
110461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (!context->offload_enabled) {
110561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
110661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
110761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
110861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
110961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        get_config(context, (effect_config_t *)pReplyData);
111061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
111161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_RESET:
111261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.reset)
111361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            context->ops.reset(context);
111461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
111561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_ENABLE:
111661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pReplyData == NULL || *replySize != sizeof(int)) {
111761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
111861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
111961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
112061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->state != EFFECT_STATE_INITIALIZED) {
112161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -ENOSYS;
112261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
112361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
112461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->state = EFFECT_STATE_ACTIVE;
112561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.enable)
112661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            context->ops.enable(context);
112761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        pthread_cond_signal(&cond);
112861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s EFFECT_CMD_ENABLE", __func__);
112961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *(int *)pReplyData = 0;
113061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
113161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_DISABLE:
113261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pReplyData == NULL || *replySize != sizeof(int)) {
113361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
113461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
113561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
113661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->state != EFFECT_STATE_ACTIVE) {
113761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -ENOSYS;
113861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
113961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
114061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->state = EFFECT_STATE_INITIALIZED;
114161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.disable)
114261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            context->ops.disable(context);
114361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        pthread_cond_signal(&cond);
114461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s EFFECT_CMD_DISABLE", __func__);
114561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *(int *)pReplyData = 0;
114661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
114761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_GET_PARAM: {
114861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pCmdData == NULL ||
114961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t)) ||
115061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pReplyData == NULL ||
115161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            *replySize < (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t))) {
115261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
115361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
115461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
115561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (!context->offload_enabled) {
115661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
115761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
115861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
115961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(uint32_t));
116061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_param_t *p = (effect_param_t *)pReplyData;
116161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.get_parameter)
116261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            context->ops.get_parameter(context, p, replySize);
116361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } break;
116461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_SET_PARAM: {
116561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (pCmdData == NULL ||
116661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            cmdSize != (int)(sizeof(effect_param_t) + sizeof(uint32_t) + sizeof(uint32_t)) ||
116761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            pReplyData == NULL || *replySize != sizeof(int32_t)) {
116861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
116961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            goto exit;
117061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
117161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *(int32_t *)pReplyData = 0;
117261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_param_t *p = (effect_param_t *)pCmdData;
117361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->ops.set_parameter)
117461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            *(int32_t *)pReplyData = context->ops.set_parameter(context, p, *replySize);
117561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
117661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } break;
117761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_SET_DEVICE:
117861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_SET_VOLUME:
117961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_SET_AUDIO_MODE:
118061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
118161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
118261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    case EFFECT_CMD_OFFLOAD: {
118361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        output_context_t *out_ctxt;
118461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
118561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (cmdSize != sizeof(effect_offload_param_t) || pCmdData == NULL
118661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                || pReplyData == NULL || *replySize != sizeof(int)) {
118761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            ALOGV("%s EFFECT_CMD_OFFLOAD bad format", __func__);
118861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
118961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            break;
119061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
119161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
119261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_offload_param_t* offload_param = (effect_offload_param_t*)pCmdData;
119361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
119461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        ALOGV("%s EFFECT_CMD_OFFLOAD offload %d output %d",
119561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti              __func__, offload_param->isOffload, offload_param->ioHandle);
119661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
119761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        *(int *)pReplyData = 0;
119861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
119961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->offload_enabled = offload_param->isOffload;
120061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (context->out_handle == offload_param->ioHandle)
120161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            break;
120261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
120361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        out_ctxt = get_output(context->out_handle);
120461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (out_ctxt != NULL)
120561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            remove_effect_from_output(out_ctxt, context);
120661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
120761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        context->out_handle = offload_param->ioHandle;
120861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        out_ctxt = get_output(offload_param->ioHandle);
120961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (out_ctxt != NULL)
121061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            add_effect_to_output(out_ctxt, context);
121161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
121261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        } break;
121361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
121461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
121561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    default:
121661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        if (cmdCode >= EFFECT_CMD_FIRST_PROPRIETARY && context->ops.command)
121761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = context->ops.command(context, cmdCode, cmdSize,
121861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                          pCmdData, replySize, pReplyData);
121961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        else {
122061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            ALOGW("%s invalid command %d", __func__, cmdCode);
122161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti            status = -EINVAL;
122261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        }
122361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        break;
122461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    }
122561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
122661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiexit:
122761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    pthread_mutex_unlock(&lock);
122861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
122961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti//    ALOGV_IF(cmdCode != VISUALIZER_CMD_CAPTURE,"%s DONE", __func__);
123061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return status;
123161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
123261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
123361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* Effect Control Interface Implementation: get_descriptor */
123461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiint effect_get_descriptor(effect_handle_t   self,
123561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti                                    effect_descriptor_t *descriptor)
123661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti{
123761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    effect_context_t *context = (effect_context_t *)self;
123861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
123961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (!effect_exists(context))
124061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
124161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
124261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    if (descriptor == NULL)
124361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        return -EINVAL;
124461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
124561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    *descriptor = *context->desc;
124661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
124761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    return 0;
124861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti}
124961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
125061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti/* effect_handle_t interface implementation for visualizer effect */
125161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleticonst struct effect_interface_s effect_interface = {
125261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_process,
125361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_command,
125461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        effect_get_descriptor,
125561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti        NULL,
125661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
125761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti
125861e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti__attribute__ ((visibility ("default")))
125961e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuletiaudio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
126061e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    tag : AUDIO_EFFECT_LIBRARY_TAG,
126161e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    version : EFFECT_LIBRARY_API_VERSION,
126261e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    name : "Visualizer Library",
126361e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    implementor : "The Android Open Source Project",
126461e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    create_effect : effect_lib_create,
126561e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    release_effect : effect_lib_release,
126661e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti    get_descriptor : effect_lib_get_descriptor,
126761e21a4fe27118141afc13323807f83b733cf426Uday Kishore Pasupuleti};
1268