Fix build warnings
[platform/adaptation/spreadtrum/audio-hal-sc7727.git] / tizen-audio-volume.c
1 /*
2  * audio-hal
3  *
4  * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <math.h>
28 #include <vconf.h>
29 #include <iniparser.h>
30
31 #include "tizen-audio-internal.h"
32 #include "tizen-audio-impl.h"
33
34 #define VOLUME_INI_DEFAULT_PATH     SYSCONFDIR"/multimedia/mmfw_audio_volume.ini" /* SYSCONFDIR is defined at .spec */
35 #define VOLUME_INI_TEMP_PATH        "/opt/system/mmfw_audio_volume.ini"
36 #define VOLUME_VALUE_MAX            (1.0f)
37 #define GAIN_VALUE_MAX              (1.0f)
38 #define RADIO_TUNING_DEFUALT_FILE   SYSCONFDIR"/multimedia/mmfw_fmradio.ini"
39 #define RADIO_TUNING_TEMP_FILE      "/opt/system/.mmfw_fmradio.ini"
40 #define RADIO_TUNING_ENABLE         "tuning:enable"
41 #define RADIO_TUNING_VOLUME_LEVELS  "fmradio:volume_levels"
42 #define RADIO_TUNING_VOLUME_TABLE   "fmradio:volume_table"
43
44 uint32_t g_master_volume_level = 100;
45
46 static const char *g_volume_vconf[AUDIO_VOLUME_TYPE_MAX] = {
47     "file/private/sound/volume/system",         /* AUDIO_VOLUME_TYPE_SYSTEM */
48     "file/private/sound/volume/notification",   /* AUDIO_VOLUME_TYPE_NOTIFICATION */
49     "file/private/sound/volume/alarm",          /* AUDIO_VOLUME_TYPE_ALARM */
50     "file/private/sound/volume/ringtone",       /* AUDIO_VOLUME_TYPE_RINGTONE */
51     "file/private/sound/volume/media",          /* AUDIO_VOLUME_TYPE_MEDIA */
52     "file/private/sound/volume/call",           /* AUDIO_VOLUME_TYPE_CALL */
53     "file/private/sound/volume/voip",           /* AUDIO_VOLUME_TYPE_VOIP */
54     "file/private/sound/volume/voice",          /* AUDIO_VOLUME_TYPE_VOICE */
55 };
56
57 static const char *__get_volume_type_string_by_idx(uint32_t vol_type_idx)
58 {
59     switch (vol_type_idx) {
60     case AUDIO_VOLUME_TYPE_SYSTEM:          return "system";
61     case AUDIO_VOLUME_TYPE_NOTIFICATION:    return "notification";
62     case AUDIO_VOLUME_TYPE_ALARM:           return "alarm";
63     case AUDIO_VOLUME_TYPE_RINGTONE:        return "ringtone";
64     case AUDIO_VOLUME_TYPE_MEDIA:           return "media";
65     case AUDIO_VOLUME_TYPE_CALL:            return "call";
66     case AUDIO_VOLUME_TYPE_VOIP:            return "voip";
67     case AUDIO_VOLUME_TYPE_VOICE:           return "voice";
68     default:                                return "invalid";
69     }
70 }
71
72 static uint32_t __get_volume_idx_by_string_type(const char *vol_type)
73 {
74     if (!strncmp(vol_type, "system", strlen(vol_type)) || !strncmp(vol_type, "0", strlen(vol_type)))
75         return AUDIO_VOLUME_TYPE_SYSTEM;
76     else if (!strncmp(vol_type, "notification", strlen(vol_type)) || !strncmp(vol_type, "1", strlen(vol_type)))
77         return AUDIO_VOLUME_TYPE_NOTIFICATION;
78     else if (!strncmp(vol_type, "alarm", strlen(vol_type)) || !strncmp(vol_type, "2", strlen(vol_type)))
79         return AUDIO_VOLUME_TYPE_ALARM;
80     else if (!strncmp(vol_type, "ringtone", strlen(vol_type)) || !strncmp(vol_type, "3", strlen(vol_type)))
81         return AUDIO_VOLUME_TYPE_RINGTONE;
82     else if (!strncmp(vol_type, "media", strlen(vol_type)) || !strncmp(vol_type, "4", strlen(vol_type)))
83         return AUDIO_VOLUME_TYPE_MEDIA;
84     else if (!strncmp(vol_type, "call", strlen(vol_type)) || !strncmp(vol_type, "5", strlen(vol_type)))
85         return AUDIO_VOLUME_TYPE_CALL;
86     else if (!strncmp(vol_type, "voip", strlen(vol_type)) || !strncmp(vol_type, "6", strlen(vol_type)))
87         return AUDIO_VOLUME_TYPE_VOIP;
88     else if (!strncmp(vol_type, "voice", strlen(vol_type)) || !strncmp(vol_type, "7", strlen(vol_type)))
89         return AUDIO_VOLUME_TYPE_VOICE;
90     else
91         return AUDIO_VOLUME_TYPE_MEDIA;
92 }
93
94 static const char *__get_gain_type_string_by_idx(uint32_t gain_type_idx)
95 {
96     switch (gain_type_idx) {
97     case AUDIO_GAIN_TYPE_DEFAULT:           return "default";
98     case AUDIO_GAIN_TYPE_DIALER:            return "dialer";
99     case AUDIO_GAIN_TYPE_TOUCH:             return "touch";
100     case AUDIO_GAIN_TYPE_AF:                return "af";
101     case AUDIO_GAIN_TYPE_SHUTTER1:          return "shutter1";
102     case AUDIO_GAIN_TYPE_SHUTTER2:          return "shutter2";
103     case AUDIO_GAIN_TYPE_CAMCODING:         return "camcording";
104     case AUDIO_GAIN_TYPE_MIDI:              return "midi";
105     case AUDIO_GAIN_TYPE_BOOTING:           return "booting";
106     case AUDIO_GAIN_TYPE_VIDEO:             return "video";
107     case AUDIO_GAIN_TYPE_TTS:               return "tts";
108     default:                                return "invalid";
109     }
110 }
111
112 static void __dump_tb(audio_hal_t *ah)
113 {
114     audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table;
115     uint32_t vol_type_idx, vol_level_idx, gain_type_idx;
116     const char *gain_type_str[] = {
117         "def",          /* AUDIO_GAIN_TYPE_DEFAULT */
118         "dial",         /* AUDIO_GAIN_TYPE_DIALER */
119         "touch",        /* AUDIO_GAIN_TYPE_TOUCH */
120         "af",           /* AUDIO_GAIN_TYPE_AF */
121         "shut1",        /* AUDIO_GAIN_TYPE_SHUTTER1 */
122         "shut2",        /* AUDIO_GAIN_TYPE_SHUTTER2 */
123         "cam",          /* AUDIO_GAIN_TYPE_CAMCODING */
124         "midi",         /* AUDIO_GAIN_TYPE_MIDI */
125         "boot",         /* AUDIO_GAIN_TYPE_BOOTING */
126         "video",        /* AUDIO_GAIN_TYPE_VIDEO */
127         "tts",          /* AUDIO_GAIN_TYPE_TTS */
128     };
129     char dump_str[AUDIO_DUMP_STR_LEN], *dump_str_ptr;
130
131     /* Dump volume table */
132     AUDIO_LOG_INFO("<<<<< volume table >>>>>");
133
134     const char *table_str = "volumes";
135
136     AUDIO_LOG_INFO("<< %s >>", table_str);
137
138     for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_MAX; vol_type_idx++) {
139         const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
140
141         dump_str_ptr = &dump_str[0];
142         memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
143         snprintf(dump_str_ptr, 8, "%6s:", vol_type_str);
144         dump_str_ptr += strlen(dump_str_ptr);
145
146         for (vol_level_idx = 0; vol_level_idx < ah->volume.volume_level_max[vol_type_idx]; vol_level_idx++) {
147             snprintf(dump_str_ptr, 6, "%01.2f ", volume_value_table->volume[vol_type_idx][vol_level_idx]);
148             dump_str_ptr += strlen(dump_str_ptr);
149         }
150         AUDIO_LOG_INFO("%s", dump_str);
151     }
152
153     volume_value_table = ah->volume.volume_value_table;
154
155     /* Dump gain table */
156     AUDIO_LOG_INFO("<<<<< gain table >>>>>");
157
158     dump_str_ptr = &dump_str[0];
159     memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
160
161     snprintf(dump_str_ptr, 11, "%10s", " ");
162     dump_str_ptr += strlen(dump_str_ptr);
163
164     for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
165         snprintf(dump_str_ptr, 7, "%5s ", gain_type_str[gain_type_idx]);
166         dump_str_ptr += strlen(dump_str_ptr);
167     }
168     AUDIO_LOG_INFO("%s", dump_str);
169
170     dump_str_ptr = &dump_str[0];
171     memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
172
173     snprintf(dump_str_ptr, 11, "%9s:", table_str);
174     dump_str_ptr += strlen(dump_str_ptr);
175
176     for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
177         snprintf(dump_str_ptr, 7, "%01.3f ", volume_value_table->gain[gain_type_idx]);
178         dump_str_ptr += strlen(dump_str_ptr);
179     }
180     AUDIO_LOG_INFO("%s", dump_str);
181
182 }
183
184 static audio_return_e __load_volume_value_table_from_ini(audio_hal_t *ah)
185 {
186     dictionary * dict = NULL;
187     uint32_t vol_type_idx, vol_level_idx, gain_type_idx;
188     audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table;
189     int size = 0;
190     const char delimiter[] = ", ";
191     const char *table_str = "volumes";
192     const char *tmp_str = NULL;
193     const char *gain_str = NULL;
194     char *list_str = NULL, *ptr = NULL;
195     char *key, *token;
196
197     if (access(VOLUME_INI_TEMP_PATH, F_OK) == 0)
198         dict = iniparser_load(VOLUME_INI_TEMP_PATH);
199     if (!dict) {
200         AUDIO_LOG_DEBUG("Use default volume&gain ini file");
201         dict = iniparser_load(VOLUME_INI_DEFAULT_PATH);
202         if (!dict) {
203             AUDIO_LOG_WARN("Loading volume&gain table from ini file failed");
204             return AUDIO_ERR_UNDEFINED;
205         }
206     }
207
208     /* Load volume table */
209     for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_MAX; vol_type_idx++) {
210         const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
211
212         ah->volume.volume_level_max[vol_type_idx] = 0;
213         size = strlen(table_str) + strlen(vol_type_str) + 2;
214         key = malloc(size);
215         if (key) {
216             snprintf(key, size, "%s:%s", table_str, vol_type_str);
217             if ((tmp_str = iniparser_getstring(dict, key, NULL)))
218                 list_str = strdup(tmp_str);
219
220             if (list_str) {
221                 token = strtok_r(list_str, delimiter, &ptr);
222                 while (token) {
223                     /* convert dB volume to linear volume */
224                     double vol_value = 0.0f;
225                     if (strncmp(token, "0", strlen(token)))
226                         vol_value = pow(10.0, (atof(token) - 100) / 20.0);
227                     volume_value_table->volume[vol_type_idx][ah->volume.volume_level_max[vol_type_idx]++] = vol_value;
228                     token = strtok_r(NULL, delimiter, &ptr);
229                 }
230                 free(list_str);
231                 list_str = NULL;
232             } else {
233                 ah->volume.volume_level_max[vol_type_idx] = 1;
234                 for (vol_level_idx = 0; vol_level_idx < AUDIO_VOLUME_LEVEL_MAX; vol_level_idx++) {
235                     volume_value_table->volume[vol_type_idx][vol_level_idx] = VOLUME_VALUE_MAX;
236                 }
237             }
238             free(key);
239         }
240     }
241
242     /* Load gain table */
243     volume_value_table->gain[AUDIO_GAIN_TYPE_DEFAULT] = GAIN_VALUE_MAX;
244     for (gain_type_idx = AUDIO_GAIN_TYPE_DEFAULT + 1; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
245         const char *gain_type_str = __get_gain_type_string_by_idx(gain_type_idx);
246
247         size = strlen(table_str) + strlen("gain") + strlen(gain_type_str) + 3;
248         key = malloc(size);
249         if (key) {
250             snprintf(key, size, "%s:gain_%s", table_str, gain_type_str);
251             gain_str = iniparser_getstring(dict, key, NULL);
252             if (gain_str) {
253                 volume_value_table->gain[gain_type_idx] = atof(gain_str);
254             } else {
255                 volume_value_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
256             }
257             free(key);
258         } else {
259             volume_value_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
260         }
261     }
262
263     iniparser_freedict(dict);
264
265     __dump_tb(ah);
266
267     return AUDIO_RET_OK;
268 }
269
270 static audio_return_e __load_radio_volume_table(int** volume_table, int *number_of_elements)
271 {
272     dictionary * dict = NULL;
273     const char delimiter[] = ", ";
274     const char *tmp_str = NULL;
275     char* ptr = NULL;
276     char* token = NULL;
277     char* list_str = NULL;
278     int* temp_table = NULL;
279     int index = 0;
280     int ret = 0;
281
282     bool tuning_enable = 0;
283     int not_found = -1;
284     int value = 0;
285
286     dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
287     if (dict == NULL) {
288         AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
289         return AUDIO_ERR_UNDEFINED;
290     } else {
291         /*tuning enable */
292         value = iniparser_getboolean(dict, RADIO_TUNING_ENABLE, not_found);
293         if (value == not_found) {
294             AUDIO_LOG_ERROR("Can't get Tuning Enable value");
295         } else {
296             tuning_enable = value;
297             AUDIO_LOG_INFO("Tuning enabled.");
298         }
299         iniparser_freedict(dict); /*Cleanup*/
300     }
301
302     if (tuning_enable) {
303         AUDIO_LOG_INFO("Tuning enabled. load temp tuning file.");
304         dict = iniparser_load(RADIO_TUNING_TEMP_FILE);
305         if (!dict) {
306             AUDIO_LOG_WARN("%s load failed. Tuning enabled but there is not tuning temp file.  Use temporary file", RADIO_TUNING_TEMP_FILE);
307             dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
308             if (!dict) {
309                 AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
310                 return AUDIO_ERR_UNDEFINED;
311             }
312         }
313     } else {
314         AUDIO_LOG_INFO("Tuning diabled. load default tuning file.");
315         dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
316         if (!dict) {
317             AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
318             return AUDIO_ERR_UNDEFINED;
319         }
320     }
321
322     *number_of_elements = iniparser_getint(dict, RADIO_TUNING_VOLUME_LEVELS, -1);
323     if (*number_of_elements <= 0 || *number_of_elements > RADIO_VOLUME_LEVEL_MAX) {
324         AUDIO_LOG_ERROR("invalid number of elements, %d", *number_of_elements);
325         ret = AUDIO_ERR_INTERNAL;
326         goto error;
327     }
328     temp_table = (int *)malloc((*number_of_elements) * sizeof(int));
329     if (!temp_table)
330         goto error;
331
332     *volume_table = temp_table;
333
334     if ((tmp_str = iniparser_getstring(dict, RADIO_TUNING_VOLUME_TABLE, NULL)))
335         list_str = strdup(tmp_str);
336
337     if (list_str) {
338         token = strtok_r(list_str, delimiter, &ptr);
339         while (token) {
340             temp_table[index] = atoi(token);
341             AUDIO_LOG_INFO("fm volume index %d is %d", index, temp_table[index]);
342             index++;
343             token = strtok_r(NULL, delimiter, &ptr);
344         }
345         free(list_str);
346         list_str = NULL;
347     }
348 error:
349     iniparser_freedict(dict);
350     return ret;
351 }
352
353 static audio_return_e _audio_volume_set_ratio_radio(audio_hal_t *ah, double ratio)
354 {
355     audio_return_e audio_ret = AUDIO_RET_OK;
356     int new_value = 0;
357     int prev_value = -1;
358     int mute = -1;
359     int max_value;
360     int min_value;
361
362     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
363
364     /* Applying mute at volume zero */
365     if (ratio == 0) {
366         if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_MUTE, FMRADIO_MUTE_ON))) {
367             AUDIO_LOG_ERROR("[mute on] set mixer(%s) failed", MIXER_FMRADIO_MUTE);
368             return AUDIO_ERR_INTERNAL;
369         }
370         new_value = 0;
371         goto set_volume;
372     }
373
374     max_value = ah->volume.radio_volume_value_table[ah->volume.radio_volume_num_of_levels - 1];
375     min_value = ah->volume.radio_volume_value_table[0];
376     new_value = (int) (ratio * (max_value - min_value) + min_value);
377
378 set_volume:
379     /* Left volume */
380     if ((_mixer_control_get_value(ah, MIXER_FMRADIO_L_VOLUME, &prev_value)))
381         AUDIO_LOG_ERROR("[volume get] get mixer(%s) failed", MIXER_FMRADIO_L_VOLUME);
382     if (new_value != prev_value) {
383         AUDIO_LOG_INFO("[volume set] set mixer(%s), %d", MIXER_FMRADIO_L_VOLUME, new_value);
384         if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_L_VOLUME, new_value))) {
385             AUDIO_LOG_ERROR("[volume set] set mixer(%s) failed", MIXER_FMRADIO_L_VOLUME);
386             return audio_ret;
387         }
388     }
389
390     /* Right volume */
391     if ((_mixer_control_get_value(ah, MIXER_FMRADIO_R_VOLUME, &prev_value)))
392         AUDIO_LOG_ERROR("[volume get] get mixer(%s) failed", MIXER_FMRADIO_R_VOLUME);
393     if (new_value != prev_value) {
394         AUDIO_LOG_INFO("[volume set] set mixer(%s), %d", MIXER_FMRADIO_R_VOLUME, new_value);
395         if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_R_VOLUME, new_value))) {
396             AUDIO_LOG_ERROR("[volume set] set mixer(%s) failed", MIXER_FMRADIO_R_VOLUME);
397             return audio_ret;
398         }
399     }
400
401     if (ratio == 0)
402         return audio_ret;
403
404     /* Unmute if muted */
405     if ((audio_ret = _mixer_control_get_value(ah, MIXER_FMRADIO_MUTE, &mute))) {
406         AUDIO_LOG_ERROR("[mute get] get mixer(%s) failed", MIXER_FMRADIO_MUTE);
407         return audio_ret;
408     }
409     if (mute == FMRADIO_MUTE_ON) {
410         if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_MUTE, FMRADIO_MUTE_OFF))) {
411             AUDIO_LOG_ERROR("[mute off] set mixer(%s) failed", MIXER_FMRADIO_MUTE);
412             return audio_ret;
413         }
414     }
415
416     return audio_ret;
417 }
418
419 audio_return_e _audio_volume_init(audio_hal_t *ah)
420 {
421     int i;
422     int val = 0;
423     audio_return_e audio_ret = AUDIO_RET_OK;
424     int init_value[AUDIO_VOLUME_TYPE_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7 };
425     int* fm_table = NULL;
426
427     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
428
429     for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
430         ah->volume.volume_level[i] = init_value[i];
431     }
432
433     for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
434         /* Get volume value string from VCONF */
435         if (vconf_get_int(g_volume_vconf[i], &val) < 0) {
436             AUDIO_LOG_ERROR("vconf_get_int(%s) failed", g_volume_vconf[i]);
437             continue;
438         }
439
440         AUDIO_LOG_INFO("read vconf. %s = %d", g_volume_vconf[i], val);
441         ah->volume.volume_level[i] = val;
442     }
443
444     if (!(ah->volume.volume_value_table = malloc(AUDIO_VOLUME_DEVICE_MAX * sizeof(audio_volume_value_table_t)))) {
445         AUDIO_LOG_ERROR("volume_value_table malloc failed");
446         return AUDIO_ERR_RESOURCE;
447     }
448
449     audio_ret = __load_volume_value_table_from_ini(ah);
450     if (audio_ret != AUDIO_RET_OK) {
451         AUDIO_LOG_ERROR("gain table load error");
452         return AUDIO_ERR_UNDEFINED;
453     }
454
455     /* radio volume table */
456     __load_radio_volume_table(&fm_table, &ah->volume.radio_volume_num_of_levels);
457     if (fm_table) {
458         AUDIO_LOG_DEBUG("number of levels -> %d", ah->volume.radio_volume_num_of_levels);
459         /*copy from temp structure to main strcture*/
460         for (i = 0; i < ah->volume.radio_volume_num_of_levels; i++)
461             ah->volume.radio_volume_value_table[i] = fm_table[i];
462
463         free(fm_table);
464         fm_table = NULL;
465     }
466
467     return audio_ret;
468 }
469
470 audio_return_e _audio_volume_deinit(audio_hal_t *ah)
471 {
472     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
473
474     if (ah->volume.volume_value_table) {
475         free(ah->volume.volume_value_table);
476         ah->volume.volume_value_table = NULL;
477     }
478
479     return AUDIO_RET_OK;
480 }
481
482 audio_return_e audio_get_volume_level_max(void *audio_handle, audio_volume_info_s *info, uint32_t *level)
483 {
484     audio_hal_t *ah = (audio_hal_t *)audio_handle;
485
486     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
487     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
488     AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER);
489
490     /* Get max volume level by device & type */
491     *level = ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)];
492
493     AUDIO_LOG_DEBUG("get_[%s] volume_level_max: %d", info->type, *level);
494
495     return AUDIO_RET_OK;
496 }
497
498 audio_return_e audio_get_volume_level(void *audio_handle, audio_volume_info_s *info, uint32_t *level)
499 {
500     audio_hal_t *ah = (audio_hal_t *)audio_handle;
501
502     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
503     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
504     AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER);
505
506     if (!strncmp(info->type, "master", strlen("master"))) {
507         *level = g_master_volume_level;
508         return AUDIO_RET_OK;
509     }
510
511     *level = ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)];
512
513     AUDIO_LOG_INFO("get [%s] volume_level: %d, direction(%d)", info->type, *level, info->direction);
514
515     return AUDIO_RET_OK;
516 }
517
518 audio_return_e audio_get_volume_value(void *audio_handle, audio_volume_info_s *info, uint32_t level, double *value)
519 {
520     audio_hal_t *ah = (audio_hal_t *)audio_handle;
521     audio_volume_value_table_t *volume_value_table;
522     char dump_str[AUDIO_DUMP_STR_LEN] = {0,};
523
524     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
525     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
526     AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER);
527     AUDIO_RETURN_VAL_IF_FAIL(ah->volume.volume_value_table, AUDIO_ERR_PARAMETER);
528
529     /* Get basic volume by device & type & level */
530     volume_value_table = ah->volume.volume_value_table;
531     if (ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] < level)
532         *value = VOLUME_VALUE_MAX;
533     else
534         *value = volume_value_table->volume[__get_volume_idx_by_string_type(info->type)][level];
535     *value *= volume_value_table->gain[AUDIO_GAIN_TYPE_DEFAULT]; /* need to fix getting gain via audio_info_t */
536
537     AUDIO_LOG_DEBUG("get_volume_value:%d(%s)=>%f %s", level, info->type, *value, &dump_str[0]);
538
539     return AUDIO_RET_OK;
540 }
541
542 audio_return_e audio_set_volume_level(void *audio_handle, audio_volume_info_s *info, uint32_t level)
543 {
544     audio_return_e audio_ret = AUDIO_RET_OK;
545     audio_hal_t *ah = (audio_hal_t *)audio_handle;
546
547     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
548     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
549     if (!strncmp(info->type, "master", strlen("master"))) {
550         g_master_volume_level = level;
551         return AUDIO_RET_OK;
552     }
553     AUDIO_RETURN_VAL_IF_FAIL((ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] >= level), AUDIO_ERR_PARAMETER);
554
555     /* Update volume level */
556     ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)] = level;
557     AUDIO_LOG_INFO("set [%s] volume_level: %d, direction(%d)", info->type, level, info->direction);
558
559     return audio_ret;
560 }
561
562 audio_return_e audio_get_volume_mute(void *audio_handle, audio_volume_info_s *info, uint32_t *mute)
563 {
564     audio_return_e audio_ret = AUDIO_RET_OK;
565     audio_hal_t *ah = (audio_hal_t *)audio_handle;
566
567     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
568     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
569     AUDIO_RETURN_VAL_IF_FAIL(mute, AUDIO_ERR_PARAMETER);
570
571     /* TODO. Not implemented */
572
573     return audio_ret;
574 }
575
576 audio_return_e audio_set_volume_mute(void *audio_handle, audio_volume_info_s *info, uint32_t mute)
577 {
578     audio_return_e audio_ret = AUDIO_RET_OK;
579     audio_hal_t *ah = (audio_hal_t *)audio_handle;
580
581     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
582     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
583
584     /* TODO. Not implemented */
585
586     return audio_ret;
587 }
588
589 audio_return_e audio_set_volume_ratio(void *audio_handle, audio_stream_info_s *info, double ratio)
590 {
591     audio_return_e audio_ret = AUDIO_RET_OK;
592     audio_hal_t *ah = (audio_hal_t *)audio_handle;
593
594     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
595     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
596
597     AUDIO_LOG_INFO("set [%s] volume_ratio: %f, direction(%u), index(%u)", info->role, ratio, info->direction, info->idx);
598
599     if (!strncmp(info->role, "radio",  strlen(info->role))) {
600         AUDIO_LOG_INFO("set radio volume according to the ratio[%f]", ratio);
601         audio_ret = _audio_volume_set_ratio_radio(ah, ratio);
602     }
603
604     return audio_ret;
605 }