| /* |
| * Copyright (c) 2017, The Linux Foundation. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* effect test to be applied on HAL layer */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <string.h> |
| #include <errno.h> |
| |
| #include "qahw_api.h" |
| #include "qahw_defs.h" |
| #include "qahw_effect_api.h" |
| #include "qahw_effect_audiosphere.h" |
| #include "qahw_effect_bassboost.h" |
| #include "qahw_effect_environmentalreverb.h" |
| #include "qahw_effect_equalizer.h" |
| #include "qahw_effect_presetreverb.h" |
| #include "qahw_effect_virtualizer.h" |
| #include "qahw_effect_visualizer.h" |
| |
| #include "qahw_effect_test.h" |
| |
| // lookup table of allowed effect commands |
| #define MAX_CMD_STR_SIZE 20 |
| cmd_def_t cmds_lookup_table[EFFECT_MAX][TTY_CMD_MAX] = { |
| { /* EFFECT_BASSBOOST */ |
| {"enable", TTY_ENABLE, NULL}, |
| {"disable", TTY_DISABLE, NULL}, |
| {"strength", TTY_BB_SET_STRENGTH, "input bassboost strength value(0-1000):\n"}, |
| {"invalid", TTY_INVALID, NULL}, |
| }, |
| { /* EFFECT_VIRTUALIZER */ |
| {"enable", TTY_ENABLE, NULL}, |
| {"disable", TTY_DISABLE, NULL}, |
| {"strength", TTY_VT_SET_STRENGTH, "input virtualizer strength value(0-1000):\n"}, |
| {"invalid", TTY_INVALID, NULL}, |
| }, |
| { /* EFFECT_EQUALIZER */ |
| {"enable", TTY_ENABLE, NULL}, |
| {"disable", TTY_DISABLE, NULL}, |
| {"preset", TTY_EQ_SET_PRESET, "select equalizer presets:\n(0-normal, 1-classical, 2-dance, 3-flat, 4-folk, 5-heavy metal, 6-hiphop, 7-jazz, 8-pop, 9-rock, 10-fx booster)\n"}, |
| {"custom", TTY_EQ_SET_CUSTOM, "customize equalizer settings:\n"}, |
| }, |
| { /* EFFECT_VISUALIZER */ |
| {"invalid", TTY_INVALID, NULL}, |
| {"invalid", TTY_INVALID, NULL}, |
| {"invalid", TTY_INVALID, NULL}, |
| {"invalid", TTY_INVALID, NULL}, |
| }, |
| { /* EFFECT_REVERB */ |
| {"enable", TTY_ENABLE, NULL}, |
| {"disable", TTY_DISABLE, NULL}, |
| {"preset", TTY_RB_SET_PRESET, "select reverb presets:\n(0-none, 1-small room, 2-medium room, 3-large room, 4-medium hall, 5-large hall, 6-plate)\n"}, |
| {"invalid", TTY_INVALID, NULL}, |
| }, |
| { /* EFFECT_AUDIOSPHERE */ |
| {"enable", TTY_ENABLE, NULL}, |
| {"disable", TTY_DISABLE, NULL}, |
| {"strength", TTY_ASPHERE_SET_STRENGTH, "input audiosphere strength value(0-1000):\n"}, |
| {"invalid", TTY_INVALID, NULL}, |
| }, |
| }; |
| |
| thread_func_t effect_thread_funcs[EFFECT_MAX] = { |
| &bassboost_thread_func, |
| &virtualizer_thread_func, |
| &equalizer_thread_func, |
| &visualizer_thread_func, |
| &reverb_thread_func, |
| &asphere_thread_func, |
| }; |
| |
| const char * effect_str[EFFECT_MAX] = { |
| "bassboost", |
| "virtualizer", |
| "equalizer", |
| "visualizer", |
| "reverb", |
| "audiosphere", |
| }; |
| |
| // placing non-standard EQ stuff here rather than in header file |
| #define NUM_EQ_BANDS 5 |
| const uint16_t qahw_equalizer_band_freqs[NUM_EQ_BANDS] = {60, 230, 910, 3600, 14000}; /* frequencies in HZ */ |
| |
| /* THREAD BODY OF BASSBOOST */ |
| void *bassboost_thread_func(void* data) { |
| thread_data_t *thr_ctxt = (thread_data_t *)data; |
| qahw_effect_lib_handle_t lib_handle; |
| qahw_effect_handle_t effect_handle; |
| qahw_effect_descriptor_t effect_desc; |
| int32_t rc; |
| int reply_data; |
| uint32_t reply_size = sizeof(int); |
| |
| pthread_mutex_lock(&thr_ctxt->mutex); |
| while(!thr_ctxt->exit) { |
| // suspend thread till signaled |
| fprintf(stdout, "suspend effect thread\n"); |
| pthread_cond_wait(&thr_ctxt->loop_cond, &thr_ctxt->mutex); |
| fprintf(stdout, "awake effect thread\n"); |
| |
| switch(thr_ctxt->cmd) { |
| case(EFFECT_LOAD_LIB): |
| lib_handle = qahw_effect_load_library(QAHW_EFFECT_BASSBOOST_LIBRARY); |
| break; |
| case(EFFECT_GET_DESC): |
| rc = qahw_effect_get_descriptor(lib_handle, SL_IID_BASSBOOST_UUID, &effect_desc); |
| if (rc != 0) { |
| fprintf(stderr, "effect_get_descriptor() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CREATE): |
| rc = qahw_effect_create(lib_handle, SL_IID_BASSBOOST_UUID, |
| thr_ctxt->io_handle, &effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_create() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CMD): |
| thr_ctxt->reply_size = (uint32_t *)&reply_size; |
| thr_ctxt->reply_data = (void *)&reply_data; |
| rc = qahw_effect_command(effect_handle, thr_ctxt->cmd_code, |
| thr_ctxt->cmd_size, thr_ctxt->cmd_data, |
| thr_ctxt->reply_size, thr_ctxt->reply_data); |
| if (rc != 0) { |
| fprintf(stderr, "effect_command() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_PROC): |
| //qahw_effect_process(); |
| break; |
| case(EFFECT_RELEASE): |
| rc = qahw_effect_release(lib_handle, effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_release() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_UNLOAD_LIB): |
| rc = qahw_effect_unload_library(lib_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_unload_library() returns %d\n", rc); |
| } |
| break; |
| default: |
| fprintf(stderr, "unrecognized command %d\n", thr_ctxt->cmd); |
| } |
| } |
| pthread_mutex_unlock(&thr_ctxt->mutex); |
| |
| return NULL; |
| } |
| |
| /* THREAD BODY OF VIRTUALIZER */ |
| void *virtualizer_thread_func(void* data) { |
| thread_data_t *thr_ctxt = (thread_data_t *)data; |
| qahw_effect_lib_handle_t lib_handle; |
| qahw_effect_handle_t effect_handle; |
| qahw_effect_descriptor_t effect_desc; |
| int32_t rc; |
| int reply_data; |
| uint32_t reply_size = sizeof(int); |
| |
| pthread_mutex_lock(&thr_ctxt->mutex); |
| while(!thr_ctxt->exit) { |
| // suspend thread till signaled |
| fprintf(stdout, "suspend effect thread\n"); |
| pthread_cond_wait(&thr_ctxt->loop_cond, &thr_ctxt->mutex); |
| fprintf(stdout, "awake effect thread\n"); |
| |
| switch(thr_ctxt->cmd) { |
| case(EFFECT_LOAD_LIB): |
| lib_handle = qahw_effect_load_library(QAHW_EFFECT_VIRTUALIZER_LIBRARY); |
| break; |
| case(EFFECT_GET_DESC): |
| rc = qahw_effect_get_descriptor(lib_handle, SL_IID_VIRTUALIZER_UUID, &effect_desc); |
| if (rc != 0) { |
| fprintf(stderr, "effect_get_descriptor() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CREATE): |
| rc = qahw_effect_create(lib_handle, SL_IID_VIRTUALIZER_UUID, |
| thr_ctxt->io_handle, &effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_create() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CMD): |
| thr_ctxt->reply_size = (uint32_t *)&reply_size; |
| thr_ctxt->reply_data = (void *)&reply_data; |
| rc = qahw_effect_command(effect_handle, thr_ctxt->cmd_code, |
| thr_ctxt->cmd_size, thr_ctxt->cmd_data, |
| thr_ctxt->reply_size, thr_ctxt->reply_data); |
| if (rc != 0) { |
| fprintf(stderr, "effect_command() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_PROC): |
| //qahw_effect_process(); |
| break; |
| case(EFFECT_RELEASE): |
| rc = qahw_effect_release(lib_handle, effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_release() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_UNLOAD_LIB): |
| rc = qahw_effect_unload_library(lib_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_unload_library() returns %d\n", rc); |
| } |
| break; |
| default: |
| fprintf(stderr, "unrecognized command %d\n", thr_ctxt->cmd); |
| } |
| } |
| pthread_mutex_unlock(&thr_ctxt->mutex); |
| |
| return NULL; |
| } |
| |
| /* THREAD BODY OF EQUALIZER */ |
| void *equalizer_thread_func(void* data) { |
| thread_data_t *thr_ctxt = (thread_data_t *)data; |
| qahw_effect_lib_handle_t lib_handle; |
| qahw_effect_handle_t effect_handle; |
| qahw_effect_descriptor_t effect_desc; |
| int32_t rc; |
| int reply_data; |
| uint32_t reply_size = sizeof(int); |
| |
| pthread_mutex_lock(&thr_ctxt->mutex); |
| while(!thr_ctxt->exit) { |
| // suspend thread till signaled |
| fprintf(stdout, "suspend effect thread\n"); |
| pthread_cond_wait(&thr_ctxt->loop_cond, &thr_ctxt->mutex); |
| fprintf(stdout, "awake effect thread\n"); |
| |
| switch(thr_ctxt->cmd) { |
| case(EFFECT_LOAD_LIB): |
| lib_handle = qahw_effect_load_library(QAHW_EFFECT_EQUALIZER_LIBRARY); |
| break; |
| case(EFFECT_GET_DESC): |
| rc = qahw_effect_get_descriptor(lib_handle, SL_IID_EQUALIZER_UUID, &effect_desc); |
| if (rc != 0) { |
| fprintf(stderr, "effect_get_descriptor() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CREATE): |
| rc = qahw_effect_create(lib_handle, SL_IID_EQUALIZER_UUID, |
| thr_ctxt->io_handle, &effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_create() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CMD): |
| thr_ctxt->reply_size = (uint32_t *)&reply_size; |
| thr_ctxt->reply_data = (void *)&reply_data; |
| rc = qahw_effect_command(effect_handle, thr_ctxt->cmd_code, |
| thr_ctxt->cmd_size, thr_ctxt->cmd_data, |
| thr_ctxt->reply_size, thr_ctxt->reply_data); |
| if (rc != 0) { |
| fprintf(stderr, "effect_command() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_PROC): |
| //qahw_effect_process(); |
| break; |
| case(EFFECT_RELEASE): |
| rc = qahw_effect_release(lib_handle, effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_release() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_UNLOAD_LIB): |
| rc = qahw_effect_unload_library(lib_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_unload_library() returns %d\n", rc); |
| } |
| break; |
| default: |
| fprintf(stderr, "unrecognized command %d\n", thr_ctxt->cmd); |
| } |
| } |
| pthread_mutex_unlock(&thr_ctxt->mutex); |
| |
| return NULL; |
| } |
| |
| /* THREAD BODY OF VISUALIZER */ |
| void *visualizer_thread_func(void* data __unused) { |
| /* TODO */ |
| return NULL; |
| } |
| |
| /* THREAD BODY OF REVERB */ |
| void *reverb_thread_func(void* data) { |
| thread_data_t *thr_ctxt = (thread_data_t *)data; |
| qahw_effect_lib_handle_t lib_handle; |
| qahw_effect_handle_t effect_handle; |
| qahw_effect_descriptor_t effect_desc; |
| int32_t rc; |
| int reply_data; |
| uint32_t reply_size = sizeof(int); |
| |
| pthread_mutex_lock(&thr_ctxt->mutex); |
| while(!thr_ctxt->exit) { |
| // suspend thread till signaled |
| fprintf(stdout, "suspend effect thread\n"); |
| pthread_cond_wait(&thr_ctxt->loop_cond, &thr_ctxt->mutex); |
| fprintf(stdout, "awake effect thread\n"); |
| |
| switch(thr_ctxt->cmd) { |
| case(EFFECT_LOAD_LIB): |
| lib_handle = qahw_effect_load_library(QAHW_EFFECT_PRESET_REVERB_LIBRARY); |
| break; |
| case(EFFECT_GET_DESC): |
| rc = qahw_effect_get_descriptor(lib_handle, SL_IID_INS_PRESETREVERB_UUID, &effect_desc); |
| if (rc != 0) { |
| fprintf(stderr, "effect_get_descriptor() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CREATE): |
| rc = qahw_effect_create(lib_handle, SL_IID_INS_PRESETREVERB_UUID, |
| thr_ctxt->io_handle, &effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_create() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CMD): |
| thr_ctxt->reply_size = (uint32_t *)&reply_size; |
| thr_ctxt->reply_data = (void *)&reply_data; |
| rc = qahw_effect_command(effect_handle, thr_ctxt->cmd_code, |
| thr_ctxt->cmd_size, thr_ctxt->cmd_data, |
| thr_ctxt->reply_size, thr_ctxt->reply_data); |
| if (rc != 0) { |
| fprintf(stderr, "effect_command() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_PROC): |
| //qahw_effect_process(); |
| break; |
| case(EFFECT_RELEASE): |
| rc = qahw_effect_release(lib_handle, effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_release() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_UNLOAD_LIB): |
| rc = qahw_effect_unload_library(lib_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_unload_library() returns %d\n", rc); |
| } |
| break; |
| default: |
| fprintf(stderr, "unrecognized command %d\n", thr_ctxt->cmd); |
| } |
| } |
| pthread_mutex_unlock(&thr_ctxt->mutex); |
| |
| return NULL; |
| } |
| |
| void *command_thread_func(void* data) { |
| cmd_data_t *thr_ctxt = (cmd_data_t *)data; |
| thread_data_t *fx_ctxt = *(thr_ctxt->fx_data_ptr); |
| char cmd_str[MAX_CMD_STR_SIZE]; |
| int cmd_key; |
| uint32_t size = sizeof(qahw_effect_param_t) + 2 * sizeof(int32_t); |
| uint32_t size_2 = sizeof(qahw_effect_param_t) + 3 * sizeof(int32_t); |
| uint32_t buf32[size]; |
| uint32_t buf32_2[size_2]; |
| int strength; |
| uint32_t preset; |
| int level; |
| uint16_t band_idx; |
| int enable; |
| qahw_effect_param_t *param = (qahw_effect_param_t *)buf32; |
| qahw_effect_param_t *param_2 = (qahw_effect_param_t *)buf32_2; |
| |
| while(!thr_ctxt->exit) { |
| if (fgets(cmd_str, sizeof(cmd_str), stdin) == NULL) { |
| fprintf(stderr, "read error\n"); |
| break; |
| } |
| strtok(cmd_str, "\n"); |
| |
| // no ops if there's no effect thread running |
| // or input string is invalid |
| if (!is_valid_input(cmd_str) || !fx_ctxt) |
| continue; |
| |
| cmd_key = get_key_from_name(fx_ctxt->who_am_i, cmd_str); |
| switch (cmd_key) { |
| case TTY_ENABLE: |
| enable = 1; |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_ENABLE, 0, NULL); |
| if (fx_ctxt->who_am_i == EFFECT_AUDIOSPHERE) { |
| param->psize = 2 * sizeof(int32_t); |
| *(int32_t *)param->data = ASPHERE_PARAM_ENABLE; |
| param->vsize = sizeof(int32_t); |
| memcpy((param->data + param->psize), &enable, param->vsize); |
| |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, size, param); |
| } |
| break; |
| case TTY_DISABLE: |
| enable = 0; |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_DISABLE, 0, NULL); |
| if (fx_ctxt->who_am_i == EFFECT_AUDIOSPHERE) { |
| param->psize = 2 * sizeof(int32_t); |
| *(int32_t *)param->data = ASPHERE_PARAM_ENABLE; |
| param->vsize = sizeof(int32_t); |
| memcpy((param->data + param->psize), &enable, param->vsize); |
| |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, size, param); |
| } |
| break; |
| case TTY_BB_SET_STRENGTH: |
| case TTY_VT_SET_STRENGTH: |
| case TTY_ASPHERE_SET_STRENGTH: |
| { |
| fprintf(stdout, "%s", get_prompt_from_name(fx_ctxt->who_am_i, cmd_str)); |
| if (fgets(cmd_str, sizeof(cmd_str), stdin) == NULL) { |
| fprintf(stderr, "unrecognized strength number!\n"); |
| break; |
| } |
| |
| strtok(cmd_str, "\n"); |
| strength = atoi(cmd_str); |
| if ((strength < 0) || (strength > 1000)) { |
| fprintf(stderr, "invalid strength number!\n"); |
| break; |
| } |
| |
| param->psize = sizeof(int32_t); |
| *(int32_t *)param->data = ((cmd_key == TTY_BB_SET_STRENGTH) ? BASSBOOST_PARAM_STRENGTH : |
| ((cmd_key == TTY_VT_SET_STRENGTH) ? VIRTUALIZER_PARAM_STRENGTH: |
| ASPHERE_PARAM_STRENGTH)); |
| param->vsize = sizeof(int32_t); |
| memcpy((param->data + param->psize), &strength, param->vsize); |
| |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, size, param); |
| break; |
| } |
| case TTY_EQ_SET_PRESET: |
| { |
| fprintf(stdout, "%s", get_prompt_from_name(fx_ctxt->who_am_i, cmd_str)); |
| if (fgets(cmd_str, sizeof(cmd_str), stdin) == NULL) { |
| fprintf(stderr, "unrecognized preset!\n"); |
| break; |
| } |
| |
| strtok(cmd_str, "\n"); |
| preset = atoi(cmd_str); |
| if ((preset < EQ_PRESET_NORMAL) || (preset > EQ_PRESET_LAST)) { |
| fprintf(stderr, "invalid preset!\n"); |
| break; |
| } |
| |
| param->psize = sizeof(int32_t); |
| *(int32_t *)param->data = EQ_PARAM_CUR_PRESET; |
| param->vsize = sizeof(int32_t); |
| memcpy((param->data + param->psize), &preset, param->vsize); |
| |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, size, param); |
| break; |
| } |
| case TTY_EQ_SET_CUSTOM: |
| { |
| fprintf(stdout, "%s", get_prompt_from_name(fx_ctxt->who_am_i, cmd_str)); |
| for (band_idx = 0; band_idx < NUM_EQ_BANDS; ++band_idx) { |
| fprintf(stdout, "input level for band (%d - %dHz) (range from -15 to +15):\n", |
| band_idx, qahw_equalizer_band_freqs[band_idx]); |
| if (fgets(cmd_str, sizeof(cmd_str), stdin) == NULL) { |
| fprintf(stderr, "unrecognized band level!\n"); |
| break; |
| } |
| |
| strtok(cmd_str, "\n"); |
| level = atoi(cmd_str) * 100; |
| if ((level < -1500) || (level > 1500)) { |
| fprintf(stderr, "equalizer band level out of range!\n"); |
| break; |
| } |
| |
| param_2->psize = 2 * sizeof(int32_t); |
| *(int32_t *)param_2->data = EQ_PARAM_BAND_LEVEL; |
| *((int32_t *)param_2->data + 1) = band_idx; |
| param_2->vsize = sizeof(int32_t); |
| memcpy((param_2->data + param_2->psize), &level, param_2->vsize); |
| |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, size, param_2); |
| } |
| break; |
| } |
| break; |
| case TTY_RB_SET_PRESET: |
| { |
| fprintf(stdout, "%s", get_prompt_from_name(fx_ctxt->who_am_i, cmd_str)); |
| if (fgets(cmd_str, sizeof(cmd_str), stdin) == NULL) { |
| fprintf(stderr, "unrecognized preset!\n"); |
| break; |
| } |
| |
| strtok(cmd_str, "\n"); |
| preset = atoi(cmd_str); |
| if ((preset < REVERB_PRESET_NONE) || (preset > REVERB_PRESET_LAST)) { |
| fprintf(stderr, "invalid preset!\n"); |
| break; |
| } |
| |
| param->psize = sizeof(int32_t); |
| *(int32_t *)param->data = REVERB_PARAM_PRESET; |
| param->vsize = sizeof(int32_t); |
| memcpy((param->data + param->psize), &preset, param->vsize); |
| |
| notify_effect_command(fx_ctxt, EFFECT_CMD, QAHW_EFFECT_CMD_SET_PARAM, size, param); |
| break; |
| } |
| default: |
| fprintf(stderr, "unknown command %d\n", cmd_key); |
| break; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| thread_data_t *create_effect_thread(int effect_idx, thread_func_t func_ptr) { |
| int result; |
| |
| thread_data_t *ethread_data = (thread_data_t *)calloc(1, sizeof(thread_data_t)); |
| ethread_data->exit = false; |
| ethread_data->who_am_i = effect_idx; |
| |
| pthread_attr_init(ðread_data->attr); |
| pthread_attr_setdetachstate(ðread_data->attr, PTHREAD_CREATE_JOINABLE); |
| pthread_mutex_init(ðread_data->mutex, NULL); |
| if (pthread_cond_init(ðread_data->loop_cond, NULL) != 0) { |
| fprintf(stderr, "pthread_cond_init fails\n"); |
| return NULL; |
| } |
| // create effect thread |
| result = pthread_create(ðread_data->effect_thread, ðread_data->attr, |
| func_ptr, ethread_data); |
| |
| if (result < 0) { |
| fprintf(stderr, "Could not create effect thread!\n"); |
| return NULL; |
| } |
| |
| return ethread_data; |
| } |
| |
| void notify_effect_command(thread_data_t *ethread_data, |
| int cmd, uint32_t cmd_code, |
| uint32_t cmd_size, void *cmd_data) { |
| if (ethread_data == NULL) { |
| fprintf(stderr, "invalid thread data\n"); |
| return; |
| } |
| |
| // leave interval to let thread consume the previous cond signal |
| usleep(500000); |
| |
| pthread_mutex_lock(ðread_data->mutex); |
| ethread_data->cmd = cmd; |
| ethread_data->cmd_code = cmd_code; |
| ethread_data->cmd_size = cmd_size; |
| ethread_data->cmd_data = cmd_data; |
| pthread_mutex_unlock(ðread_data->mutex); |
| pthread_cond_signal(ðread_data->loop_cond); |
| |
| return; |
| } |
| |
| void destroy_effect_thread(thread_data_t *ethread_data) { |
| int result; |
| |
| if (ethread_data == NULL) { |
| fprintf(stderr, "invalid thread data\n"); |
| return; |
| } |
| |
| pthread_mutex_lock(ðread_data->mutex); |
| ethread_data->exit = true; |
| pthread_mutex_unlock(ðread_data->mutex); |
| pthread_cond_signal(ðread_data->loop_cond); |
| |
| result = pthread_join(ethread_data->effect_thread, NULL); |
| if (result < 0) { |
| fprintf(stderr, "Fail to join effect thread!\n"); |
| return; |
| } |
| pthread_mutex_destroy(ðread_data->mutex); |
| pthread_cond_destroy(ðread_data->loop_cond); |
| |
| return; |
| } |
| |
| int get_key_from_name(int fx_id, const char *name) { |
| cmd_def_t *tmp = cmds_lookup_table[fx_id]; |
| int rc = -EINVAL; |
| int i; |
| |
| if (name == NULL) |
| goto done; |
| |
| for(i = 0; i < TTY_CMD_MAX; i++) { |
| if (strcmp(tmp[i].cmd_str, name) == 0) { |
| rc = tmp[i].cmd_id; |
| break; |
| } |
| } |
| |
| done: |
| return rc; |
| } |
| |
| char *get_prompt_from_name(int fx_id, const char *name) { |
| cmd_def_t *tmp = cmds_lookup_table[fx_id]; |
| char *rc = NULL; |
| int i; |
| |
| if (name == NULL) |
| goto done; |
| |
| for(i = 0; i < TTY_CMD_MAX; i++) { |
| if (strcmp(tmp[i].cmd_str, name) == 0) { |
| rc = tmp[i].cmd_prompt; |
| break; |
| } |
| } |
| |
| done: |
| return rc; |
| } |
| |
| bool is_valid_input(char *inputs) { |
| char *input_ptr = inputs; |
| |
| if (input_ptr == NULL) |
| return false; |
| |
| while (*input_ptr == ' ') |
| input_ptr++; |
| |
| if ((*input_ptr != '\0') && (*input_ptr != '\n')) |
| return true; |
| |
| return false; |
| } |
| |
| /* THREAD BODY OF AUDIOSPHERE */ |
| void *asphere_thread_func(void* data) { |
| thread_data_t *thr_ctxt = (thread_data_t *)data; |
| qahw_effect_lib_handle_t lib_handle; |
| qahw_effect_handle_t effect_handle; |
| qahw_effect_descriptor_t effect_desc; |
| int32_t rc; |
| int reply_data; |
| uint32_t reply_size = sizeof(int); |
| |
| pthread_mutex_lock(&thr_ctxt->mutex); |
| while(!thr_ctxt->exit) { |
| // suspend thread till signaled |
| fprintf(stdout, "suspend effect thread\n"); |
| pthread_cond_wait(&thr_ctxt->loop_cond, &thr_ctxt->mutex); |
| fprintf(stdout, "awake effect thread\n"); |
| |
| switch(thr_ctxt->cmd) { |
| case(EFFECT_LOAD_LIB): |
| lib_handle = qahw_effect_load_library(QAHW_EFFECT_AUDIOSPHERE_LIBRARY); |
| break; |
| case(EFFECT_GET_DESC): |
| rc = qahw_effect_get_descriptor(lib_handle, SL_IID_AUDIOSPHERE_UUID, &effect_desc); |
| if (rc != 0) { |
| fprintf(stderr, "effect_get_descriptor() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CREATE): |
| rc = qahw_effect_create(lib_handle, SL_IID_AUDIOSPHERE_UUID, |
| thr_ctxt->io_handle, &effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_create() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_CMD): |
| thr_ctxt->reply_size = (uint32_t *)&reply_size; |
| thr_ctxt->reply_data = (void *)&reply_data; |
| rc = qahw_effect_command(effect_handle, thr_ctxt->cmd_code, |
| thr_ctxt->cmd_size, thr_ctxt->cmd_data, |
| thr_ctxt->reply_size, thr_ctxt->reply_data); |
| if (rc != 0) { |
| fprintf(stderr, "effect_command() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_PROC): |
| //qahw_effect_process(); |
| break; |
| case(EFFECT_RELEASE): |
| rc = qahw_effect_release(lib_handle, effect_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_release() returns %d\n", rc); |
| } |
| break; |
| case(EFFECT_UNLOAD_LIB): |
| rc = qahw_effect_unload_library(lib_handle); |
| if (rc != 0) { |
| fprintf(stderr, "effect_unload_library() returns %d\n", rc); |
| } |
| break; |
| default: |
| fprintf(stderr, "unrecognized command %d\n", thr_ctxt->cmd); |
| } |
| } |
| pthread_mutex_unlock(&thr_ctxt->mutex); |
| |
| return NULL; |
| } |