summaryrefslogtreecommitdiff
path: root/tizen-audio-stream.c
diff options
context:
space:
mode:
Diffstat (limited to 'tizen-audio-stream.c')
-rw-r--r--tizen-audio-stream.c638
1 files changed, 638 insertions, 0 deletions
diff --git a/tizen-audio-stream.c b/tizen-audio-stream.c
new file mode 100644
index 0000000..8ddbbad
--- /dev/null
+++ b/tizen-audio-stream.c
@@ -0,0 +1,638 @@
+/*
+ * audio-hal
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <math.h>
+#include <vconf.h>
+#include <iniparser.h>
+
+#include "tizen-audio-internal.h"
+
+#define VOLUME_INI_DEFAULT_PATH "/usr/etc/mmfw_audio_volume.ini"
+#define VOLUME_INI_TEMP_PATH "/opt/system/mmfw_audio_volume.ini"
+#define VOLUME_VALUE_MAX (1.0f)
+#define GAIN_VALUE_MAX (1.0f)
+
+#ifdef USE_FMRADIO_V4L2_SPRD
+#define RADIO_TUNING_DEFUALT_FILE "/usr/etc/mmfw_fmradio.ini"
+#define RADIO_TUNING_TEMP_FILE "/opt/usr/media/.mmfw_fmradio.ini"
+#define RADIO_TUNING_ENABLE "tuning:enable"
+#define RADIO_TUNING_VOLUME_LEVELS "fmradio:volume_levels"
+#define RADIO_TUNING_VOLUME_TABLE "fmradio:volume_table"
+#endif
+
+enum {
+ STREAM_DEVICE_SPEAKER,
+ STREAM_DEVICE_HEADSET,
+ STREAM_DEVICE_BLUETOOTH,
+ STREAM_DEVICE_HDMI,
+ STREAM_DEVICE_DOCK,
+ STREAM_DEVICE_MAX,
+};
+
+static const char *g_volume_vconf[AUDIO_VOLUME_TYPE_VCONF_MAX] = {
+ "file/private/sound/volume/system", /* AUDIO_VOLUME_TYPE_SYSTEM */
+ "file/private/sound/volume/notification", /* AUDIO_VOLUME_TYPE_NOTIFICATION */
+ "file/private/sound/volume/alarm", /* AUDIO_VOLUME_TYPE_ALARM */
+ "file/private/sound/volume/ringtone", /* AUDIO_VOLUME_TYPE_RINGTONE */
+ "file/private/sound/volume/media", /* AUDIO_VOLUME_TYPE_MEDIA */
+ "file/private/sound/volume/call", /* AUDIO_VOLUME_TYPE_CALL */
+ "file/private/sound/volume/voip", /* AUDIO_VOLUME_TYPE_VOIP */
+ "file/private/sound/volume/voice", /* AUDIO_VOLUME_TYPE_VOICE */
+};
+
+static inline uint8_t __get_volume_dev_index(audio_mgr_t *am, uint32_t volume_type)
+{
+
+ switch (am->device.active_out) {
+ case AUDIO_DEVICE_OUT_SPEAKER: return AUDIO_VOLUME_DEVICE_SPEAKER;
+ case AUDIO_DEVICE_OUT_RECEIVER: return AUDIO_VOLUME_DEVICE_RECEIVER;
+ case AUDIO_DEVICE_OUT_WIRED_ACCESSORY: return AUDIO_VOLUME_DEVICE_EARJACK;
+ case AUDIO_DEVICE_OUT_BT_SCO: return AUDIO_VOLUME_DEVICE_BT_SCO;
+ case AUDIO_DEVICE_OUT_BT_A2DP: return AUDIO_VOLUME_DEVICE_BT_A2DP;
+ case AUDIO_DEVICE_OUT_DOCK: return AUDIO_VOLUME_DEVICE_DOCK;
+ case AUDIO_DEVICE_OUT_HDMI: return AUDIO_VOLUME_DEVICE_HDMI;
+ case AUDIO_DEVICE_OUT_MIRRORING: return AUDIO_VOLUME_DEVICE_MIRRORING;
+ case AUDIO_DEVICE_OUT_USB_AUDIO: return AUDIO_VOLUME_DEVICE_USB;
+ case AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK: return AUDIO_VOLUME_DEVICE_MULTIMEDIA_DOCK;
+ default: return AUDIO_VOLUME_DEVICE_SPEAKER;
+ }
+}
+
+static const uint8_t __get_stream_dev_index (uint32_t device_out)
+{
+ switch (device_out) {
+ case AUDIO_DEVICE_OUT_SPEAKER: return STREAM_DEVICE_SPEAKER;
+ case AUDIO_DEVICE_OUT_RECEIVER: return STREAM_DEVICE_SPEAKER;
+ case AUDIO_DEVICE_OUT_WIRED_ACCESSORY: return STREAM_DEVICE_HEADSET;
+ case AUDIO_DEVICE_OUT_BT_SCO: return STREAM_DEVICE_BLUETOOTH;
+ case AUDIO_DEVICE_OUT_BT_A2DP: return STREAM_DEVICE_BLUETOOTH;
+ case AUDIO_DEVICE_OUT_DOCK: return STREAM_DEVICE_DOCK;
+ case AUDIO_DEVICE_OUT_HDMI: return STREAM_DEVICE_HDMI;
+ case AUDIO_DEVICE_OUT_MIRRORING: return STREAM_DEVICE_SPEAKER;
+ case AUDIO_DEVICE_OUT_USB_AUDIO: return STREAM_DEVICE_SPEAKER;
+ case AUDIO_DEVICE_OUT_MULTIMEDIA_DOCK: return STREAM_DEVICE_DOCK;
+ default:
+ AUDIO_LOG_DEBUG("invalid device_out:%d", device_out);
+ break;
+ }
+
+ return STREAM_DEVICE_SPEAKER;
+}
+
+static const char *__get_device_string_by_idx (uint32_t dev_idx)
+{
+ switch (dev_idx) {
+ case STREAM_DEVICE_SPEAKER: return "speaker";
+ case STREAM_DEVICE_HEADSET: return "headset";
+ case STREAM_DEVICE_BLUETOOTH: return "btheadset";
+ case STREAM_DEVICE_HDMI: return "hdmi";
+ case STREAM_DEVICE_DOCK: return "dock";
+ default: return "invalid";
+ }
+}
+
+static const char *__get_volume_type_string_by_idx (uint32_t vol_type_idx)
+{
+ switch (vol_type_idx) {
+ case AUDIO_VOLUME_TYPE_SYSTEM: return "system";
+ case AUDIO_VOLUME_TYPE_NOTIFICATION: return "notification";
+ case AUDIO_VOLUME_TYPE_ALARM: return "alarm";
+ case AUDIO_VOLUME_TYPE_RINGTONE: return "ringtone";
+ case AUDIO_VOLUME_TYPE_MEDIA: return "media";
+ case AUDIO_VOLUME_TYPE_CALL: return "call";
+ case AUDIO_VOLUME_TYPE_VOIP: return "voip";
+ case AUDIO_VOLUME_TYPE_VOICE: return "voice";
+ case AUDIO_VOLUME_TYPE_FIXED: return "fixed";
+ default: return "invalid";
+ }
+}
+
+static const char *__get_gain_type_string_by_idx (uint32_t gain_type_idx)
+{
+ switch (gain_type_idx) {
+ case AUDIO_GAIN_TYPE_DEFAULT: return "default";
+ case AUDIO_GAIN_TYPE_DIALER: return "dialer";
+ case AUDIO_GAIN_TYPE_TOUCH: return "touch";
+ case AUDIO_GAIN_TYPE_AF: return "af";
+ case AUDIO_GAIN_TYPE_SHUTTER1: return "shutter1";
+ case AUDIO_GAIN_TYPE_SHUTTER2: return "shutter2";
+ case AUDIO_GAIN_TYPE_CAMCODING: return "camcording";
+ case AUDIO_GAIN_TYPE_MIDI: return "midi";
+ case AUDIO_GAIN_TYPE_BOOTING: return "booting";
+ case AUDIO_GAIN_TYPE_VIDEO: return "video";
+ case AUDIO_GAIN_TYPE_TTS: return "tts";
+ default: return "invalid";
+ }
+}
+#ifdef USE_FMRADIO_V4L2_SPRD
+audio_return_t _set_volume_level_fmradio(audio_mgr_t *am, uint32_t level)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+
+ int volume = 0;
+ int mute = -1;
+
+ /* Applying mute at volume zero */
+ if (level == 0) {
+ audio_ret = _audio_mixer_control_set_value(am, MIXER_FMRADIO_MUTE, 0);
+ if (AUDIO_IS_ERROR(audio_ret)) {
+ AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_MUTE);
+ }
+ } else {
+ audio_ret = _audio_mixer_control_get_value(am, MIXER_FMRADIO_MUTE, &mute);
+ if (AUDIO_IS_ERROR(audio_ret)) {
+ AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_MUTE);
+ return audio_ret;
+ }
+ if (mute == 0) {
+ audio_ret = _audio_mixer_control_set_value(am, MIXER_FMRADIO_MUTE, 1);
+ if (AUDIO_IS_ERROR(audio_ret)) {
+ AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_MUTE);
+ return audio_ret;
+ }
+ }
+ }
+
+ if (AUDIO_IS_ERROR(_audio_mixer_control_get_value(am, MIXER_FMRADIO_L_VOLUME, &volume))) {
+ AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_L_VOLUME);
+ } else {
+ if (volume != am->stream.fmradio_volume_table[level]) {
+ audio_ret = _audio_mixer_control_set_value(am, MIXER_FMRADIO_L_VOLUME, am->stream.fmradio_volume_table[level]);
+ if (AUDIO_IS_ERROR(audio_ret)) {
+ AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_L_VOLUME);
+ return audio_ret;
+ }
+ }
+ }
+
+ if (AUDIO_IS_ERROR(_audio_mixer_control_get_value(am, MIXER_FMRADIO_R_VOLUME, &volume))) {
+ AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_R_VOLUME);
+ } else {
+ if (volume != am->stream.fmradio_volume_table[level]) {
+ audio_ret = _audio_mixer_control_set_value(am, MIXER_FMRADIO_R_VOLUME, am->stream.fmradio_volume_table[level]);
+ if (AUDIO_IS_ERROR(audio_ret)) {
+ AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_R_VOLUME);
+ }
+ }
+ }
+ return audio_ret;
+}
+#endif
+static void __dump_info(char *dump, audio_info_t *info)
+{
+ int len;
+ char name[64] = { '\0', };
+
+ if (info->device.api == AUDIO_DEVICE_API_ALSA) {
+ len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:alsa(%d.%d)", info->device.alsa.card_idx, info->device.alsa.device_idx);
+ } else if (info->device.api == AUDIO_DEVICE_API_ALSA) {
+ len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:bluez(%s,nrec:%d)", info->device.bluez.protocol, info->device.bluez.nrec);
+ } else {
+ len = snprintf(dump, AUDIO_DUMP_STR_LEN, "device:unknown");
+ }
+
+ if (len > 0)
+ dump += len;
+
+ strncpy(name, info->stream.name ? info->stream.name : "null", sizeof(name)-1);
+ len = snprintf(dump, AUDIO_DUMP_STR_LEN, "stream:%s(%dhz,%dch,vol:%s,gain:%s)",
+ name, info->stream.samplerate, info->stream.channels,
+ __get_volume_type_string_by_idx(info->stream.volume_type), __get_gain_type_string_by_idx(info->stream.gain_type));
+
+ if (len > 0)
+ dump += len;
+
+ *dump = '\0';
+}
+
+static void __dump_tb (audio_mgr_t *am)
+{
+ audio_volume_gain_table_t *volume_gain_table = am->stream.volume_gain_table;
+ uint32_t dev_idx, vol_type_idx, vol_level_idx, gain_type_idx;
+ const char *gain_type_str[] = {
+ "def", /* AUDIO_GAIN_TYPE_DEFAULT */
+ "dial", /* AUDIO_GAIN_TYPE_DIALER */
+ "touch", /* AUDIO_GAIN_TYPE_TOUCH */
+ "af", /* AUDIO_GAIN_TYPE_AF */
+ "shut1", /* AUDIO_GAIN_TYPE_SHUTTER1 */
+ "shut2", /* AUDIO_GAIN_TYPE_SHUTTER2 */
+ "cam", /* AUDIO_GAIN_TYPE_CAMCODING */
+ "midi", /* AUDIO_GAIN_TYPE_MIDI */
+ "boot", /* AUDIO_GAIN_TYPE_BOOTING */
+ "video", /* AUDIO_GAIN_TYPE_VIDEO */
+ "tts", /* AUDIO_GAIN_TYPE_TTS */
+ };
+ char dump_str[AUDIO_DUMP_STR_LEN], *dump_str_ptr;
+
+ /* Dump volume table */
+ AUDIO_LOG_INFO("<<<<< volume table >>>>>");
+
+
+ for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_VCONF_MAX; vol_type_idx++) {
+ const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
+
+ dump_str_ptr = &dump_str[0];
+ memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
+ snprintf(dump_str_ptr, 8, "%6s:", vol_type_str);
+ dump_str_ptr += strlen(dump_str_ptr);
+
+ for (vol_level_idx = 0; vol_level_idx < volume_gain_table->volume_level_max[vol_type_idx]; vol_level_idx++) {
+ snprintf(dump_str_ptr, 6, "%01.2f ", volume_gain_table->volume[vol_type_idx][vol_level_idx]);
+ dump_str_ptr += strlen(dump_str_ptr);
+ }
+ AUDIO_LOG_INFO("%s", dump_str);
+ }
+
+
+ /* Dump gain table */
+ AUDIO_LOG_INFO("<<<<< gain table >>>>>");
+
+ dump_str_ptr = &dump_str[0];
+ memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
+
+ snprintf(dump_str_ptr, 11, "%10s", " ");
+ dump_str_ptr += strlen(dump_str_ptr);
+
+ for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
+ snprintf(dump_str_ptr, 7, "%5s ", gain_type_str[gain_type_idx]);
+ dump_str_ptr += strlen(dump_str_ptr);
+ }
+ AUDIO_LOG_INFO("%s", dump_str);
+
+
+ dump_str_ptr = &dump_str[0];
+ memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
+
+ dump_str_ptr += strlen(dump_str_ptr);
+
+ for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
+ snprintf(dump_str_ptr, 7, "%01.3f ", volume_gain_table->gain[gain_type_idx]);
+ dump_str_ptr += strlen(dump_str_ptr);
+ }
+ AUDIO_LOG_INFO("%s", dump_str);
+
+}
+
+static audio_return_t __load_volume_gain_table_from_ini (audio_mgr_t *am)
+{
+ dictionary * dict = NULL;
+ uint32_t vol_type_idx, vol_level_idx, gain_type_idx;
+ audio_volume_gain_table_t *volume_gain_table = am->stream.volume_gain_table;
+ int size = 0;
+ const char delimiter[] = ", ";
+ char *key, *list_str, *token, *ptr = NULL;
+ const char *section = "volumes";
+
+ dict = iniparser_load(VOLUME_INI_TEMP_PATH);
+ if (!dict) {
+ AUDIO_LOG_DEBUG("Use default volume&gain ini file");
+ dict = iniparser_load(VOLUME_INI_DEFAULT_PATH);
+ if (!dict) {
+ AUDIO_LOG_WARN("Loading volume&gain table from ini file failed");
+ return AUDIO_ERR_UNDEFINED;
+ }
+ }
+
+ /* Load volume table */
+ for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_VCONF_MAX; vol_type_idx++) {
+ const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
+
+ volume_gain_table->volume_level_max[vol_type_idx] = 0;
+ size = strlen(section) + strlen(vol_type_str) + 2;
+ key = malloc(size);
+ if (key) {
+ snprintf(key, size, "%s:%s", section, vol_type_str);
+ list_str = iniparser_getstr(dict, key);
+ if (list_str) {
+ token = strtok_r(list_str, delimiter, &ptr);
+ while (token) {
+ /* convert dB volume to linear volume */
+ double vol_value = 0.0f;
+ if(strncmp(token, "0", strlen(token)))
+ vol_value = pow(10.0, (atof(token) - 100) / 20.0);
+ volume_gain_table->volume[vol_type_idx][volume_gain_table->volume_level_max[vol_type_idx]++] = vol_value;
+ token = strtok_r(NULL, delimiter, &ptr);
+ }
+ } else {
+ volume_gain_table->volume_level_max[vol_type_idx] = 1;
+ for (vol_level_idx = 0; vol_level_idx < AUDIO_VOLUME_LEVEL_MAX; vol_level_idx++) {
+ volume_gain_table->volume[vol_type_idx][vol_level_idx] = VOLUME_VALUE_MAX;
+ }
+ }
+ free(key);
+ }
+ }
+
+ /* Load gain table */
+ volume_gain_table->gain[AUDIO_GAIN_TYPE_DEFAULT] = GAIN_VALUE_MAX;
+ for (gain_type_idx = AUDIO_GAIN_TYPE_DEFAULT + 1; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
+ const char *gain_type_str = __get_gain_type_string_by_idx(gain_type_idx);
+
+ size = strlen(section) + strlen("gain") + strlen(gain_type_str) + 3;
+ key = malloc(size);
+ if (key) {
+ snprintf(key, size, "%s:gain_%s", section, gain_type_str);
+ token = iniparser_getstr(dict, key);
+ if (token) {
+ volume_gain_table->gain[gain_type_idx] = atof(token);
+ } else {
+ volume_gain_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
+ }
+ free(key);
+ } else {
+ volume_gain_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
+ }
+ }
+
+ iniparser_freedict(dict);
+
+ __dump_tb(am);
+
+ return AUDIO_RET_OK;
+}
+
+#ifdef USE_FMRADIO_V4L2_SPRD
+int _radio_load_volume_table(int** volume_table, int *number_of_elements)
+{
+ dictionary * dict = NULL;
+ const char delimiter[] = ", ";
+ char* ptr = NULL;
+ char* token = NULL;
+ char* list_str = NULL;
+ int* temp_table = NULL;
+ int index = 0;
+ int ret = 0;
+
+ bool tuning_enable = 0;
+ int not_found = -1;
+ int value = 0;
+
+ dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
+ if (dict == NULL) {
+ AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
+ return AUDIO_ERR_UNDEFINED;
+ } else {
+ /*tuning enable */
+ value = iniparser_getboolean(dict, RADIO_TUNING_ENABLE, not_found);
+ if (value == not_found) {
+ AUDIO_LOG_ERROR("Can't get Tuning Enable value");
+ } else {
+ tuning_enable = value;
+ AUDIO_LOG_INFO("Tuning enabled.");
+ }
+ iniparser_freedict(dict); /*Cleanup*/
+ }
+
+ if (tuning_enable) {
+ AUDIO_LOG_INFO("Tuning enabled. load temp tuning file.");
+ dict = iniparser_load(RADIO_TUNING_TEMP_FILE);
+ if (!dict) {
+ AUDIO_LOG_WARN("%s load failed. Tuning enabled but there is not tuning temp file. Use temporary file", RADIO_TUNING_TEMP_FILE);
+ dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
+ if (!dict) {
+ AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
+ return AUDIO_ERR_UNDEFINED;
+ }
+ }
+ } else {
+ AUDIO_LOG_INFO("Tuning diabled. load default tuning file.");
+ dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
+ if (!dict) {
+ AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
+ return AUDIO_ERR_UNDEFINED;
+ }
+ }
+
+ *number_of_elements = iniparser_getint (dict, RADIO_TUNING_VOLUME_LEVELS, -1);
+ if (*number_of_elements == -1) {
+ ret = AUDIO_ERR_UNDEFINED;
+ goto error;
+ }
+ temp_table = (int *)malloc ((*number_of_elements) * sizeof(int));
+ if (!temp_table) {
+ goto error;
+ }
+ *volume_table = temp_table;
+
+ list_str = iniparser_getstr(dict, RADIO_TUNING_VOLUME_TABLE);
+ if (list_str) {
+ token = strtok_r(list_str, delimiter, &ptr);
+ while (token) {
+ temp_table[index] = atoi(token);
+ AUDIO_LOG_INFO("fm volume index %d is %d", index, temp_table[index]);
+ index++;
+ token = strtok_r(NULL, delimiter, &ptr);
+ }
+ }
+error:
+ iniparser_freedict(dict);
+ return ret;
+}
+#endif
+
+audio_return_t _audio_stream_init (audio_mgr_t *am)
+{
+ int i, val;
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ int init_value[AUDIO_VOLUME_TYPE_VCONF_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7 };
+#ifdef USE_FMRADIO_V4L2_SPRD
+ int number_of_steps = 0;
+ int index =0;
+ int* fm_table = NULL;
+#endif
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ for (i = 0; i < AUDIO_VOLUME_TYPE_VCONF_MAX; i++) {
+ am->stream.volume_level[i] = init_value[i];
+ }
+
+ for (i = 0; i < AUDIO_VOLUME_TYPE_VCONF_MAX; i++) {
+ /* Get volume value string from VCONF */
+ if(vconf_get_int(g_volume_vconf[i], &val) < 0) {
+ AUDIO_LOG_ERROR("vconf_get_int(%s) failed", g_volume_vconf[i]);
+ continue;
+ }
+
+ AUDIO_LOG_INFO("read vconf. %s = %d", g_volume_vconf[i], val);
+
+ am->stream.volume_level[i] = val;
+ }
+
+ if (!(am->stream.volume_gain_table = malloc(sizeof(audio_volume_gain_table_t)))) {
+ AUDIO_LOG_ERROR("volume_gain_table malloc failed");
+ return AUDIO_ERR_RESOURCE;
+ }
+
+ audio_ret = __load_volume_gain_table_from_ini(am);
+ if(audio_ret != AUDIO_RET_OK) {
+ AUDIO_LOG_ERROR("gain table load error");
+ return AUDIO_ERR_UNDEFINED;
+ }
+#ifdef USE_FMRADIO_V4L2_SPRD
+ _radio_load_volume_table(&fm_table, &number_of_steps);
+ if (fm_table) {
+ AUDIO_LOG_DEBUG("number of steps -> %d", number_of_steps);
+ /*copy from temp structure to main strcture*/
+ for (index = 0; index < number_of_steps; index++) {
+ am->stream.fmradio_volume_table[index] = fm_table[index];
+ }
+ free(fm_table);
+ fm_table = NULL;
+ }
+
+#endif
+ return audio_ret;
+}
+
+audio_return_t _audio_stream_deinit (audio_mgr_t *am)
+{
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ if (am->stream.volume_gain_table) {
+ free(am->stream.volume_gain_table);
+ am->stream.volume_gain_table = NULL;
+ }
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_get_volume_level_max (void *userdata, uint32_t volume_type, uint32_t *level)
+{
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+ audio_volume_gain_table_t *volume_gain_table;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
+
+ /* Get max volume level by device & type */
+ volume_gain_table = am->stream.volume_gain_table;
+
+ if (volume_type < AUDIO_VOLUME_TYPE_VCONF_MAX) {
+ *level = volume_gain_table->volume_level_max[volume_type];
+ AUDIO_LOG_DEBUG("get_volume_level_max:%s=>%d", __get_volume_type_string_by_idx(volume_type), *level);
+ }
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_get_volume_level (void *userdata, uint32_t volume_type, uint32_t *level)
+{
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ if (volume_type < AUDIO_VOLUME_TYPE_VCONF_MAX)
+ *level = am->stream.volume_level[volume_type];
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_get_volume_value (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level, double *value)
+{
+ if (info) {
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+ audio_volume_gain_table_t *volume_gain_table;
+ char dump_str[AUDIO_DUMP_STR_LEN];
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
+ __dump_info(&dump_str[0], info);
+ /* Get basic volume by device & type & level */
+ volume_gain_table = am->stream.volume_gain_table;
+ if (volume_type < AUDIO_VOLUME_TYPE_VCONF_MAX) {
+ if (volume_gain_table->volume_level_max[volume_type] < level)
+ *value = VOLUME_VALUE_MAX;
+ else
+ *value = volume_gain_table->volume[volume_type][level];
+ *value *= volume_gain_table->gain[info->stream.gain_type];
+ } else if (volume_type == AUDIO_VOLUME_TYPE_FIXED)
+ *value = 1.0 * volume_gain_table->gain[info->stream.gain_type];
+
+ AUDIO_LOG_DEBUG("get_volume_value:%d(%s)=>%f %s", level, __get_volume_type_string_by_idx(volume_type), *value, &dump_str[0]);
+ }
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_set_volume_level (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t level)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ if (info == NULL && volume_type < AUDIO_VOLUME_TYPE_VCONF_MAX) {
+
+ /* Update volume level */
+ am->stream.volume_level[volume_type] = level;
+ AUDIO_LOG_INFO("set_volume_level:session(%d), %d(%s)", am->session.session, level, __get_volume_type_string_by_idx(volume_type));
+ }
+#ifdef USE_FMRADIO_V4L2_SPRD
+ if (volume_type == AUDIO_VOLUME_TYPE_MEDIA && am->session.is_radio_on == 1) {
+ audio_ret = _set_volume_level_fmradio(am, level);
+ }
+#endif
+ return audio_ret;
+}
+
+audio_return_t audio_get_gain_value (void *userdata, audio_info_t *info, uint32_t volume_type, double *value)
+{
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+ audio_volume_gain_table_t *volume_gain_table;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+ AUDIO_RETURN_VAL_IF_FAIL(am->stream.volume_gain_table, AUDIO_ERR_PARAMETER);
+
+ if (info != NULL) {
+ volume_gain_table = am->stream.volume_gain_table;
+ *value = volume_gain_table->gain[info->stream.gain_type];
+ }
+
+ return AUDIO_RET_OK;
+}
+
+audio_return_t audio_get_mute (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t *mute)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+
+ /* TODO. Not implemented */
+
+ return audio_ret;
+}
+
+audio_return_t audio_set_mute (void *userdata, audio_info_t *info, uint32_t volume_type, uint32_t direction, uint32_t mute)
+{
+ audio_return_t audio_ret = AUDIO_RET_OK;
+ audio_mgr_t *am = (audio_mgr_t *)userdata;
+
+ AUDIO_RETURN_VAL_IF_FAIL(am, AUDIO_ERR_PARAMETER);
+ /* TODO. Not implemented */
+
+ return audio_ret;
+}