Merge branch 'tizen_3.0' into tizen
[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 #define RADIO_VOLUME_NUM_MAX        100
44
45 uint32_t g_master_volume_level = 100;
46
47 static const char *g_volume_vconf[AUDIO_VOLUME_TYPE_MAX] = {
48     "file/private/sound/volume/system",         /* AUDIO_VOLUME_TYPE_SYSTEM */
49     "file/private/sound/volume/notification",   /* AUDIO_VOLUME_TYPE_NOTIFICATION */
50     "file/private/sound/volume/alarm",          /* AUDIO_VOLUME_TYPE_ALARM */
51     "file/private/sound/volume/ringtone",       /* AUDIO_VOLUME_TYPE_RINGTONE */
52     "file/private/sound/volume/media",          /* AUDIO_VOLUME_TYPE_MEDIA */
53     "file/private/sound/volume/call",           /* AUDIO_VOLUME_TYPE_CALL */
54     "file/private/sound/volume/voip",           /* AUDIO_VOLUME_TYPE_VOIP */
55     "file/private/sound/volume/voice",          /* AUDIO_VOLUME_TYPE_VOICE */
56 };
57
58 static const char *__get_volume_type_string_by_idx(uint32_t vol_type_idx)
59 {
60     switch (vol_type_idx) {
61     case AUDIO_VOLUME_TYPE_SYSTEM:          return "system";
62     case AUDIO_VOLUME_TYPE_NOTIFICATION:    return "notification";
63     case AUDIO_VOLUME_TYPE_ALARM:           return "alarm";
64     case AUDIO_VOLUME_TYPE_RINGTONE:        return "ringtone";
65     case AUDIO_VOLUME_TYPE_MEDIA:           return "media";
66     case AUDIO_VOLUME_TYPE_CALL:            return "call";
67     case AUDIO_VOLUME_TYPE_VOIP:            return "voip";
68     case AUDIO_VOLUME_TYPE_VOICE:           return "voice";
69     default:                                return "invalid";
70     }
71 }
72
73 static uint32_t __get_volume_idx_by_string_type(const char *vol_type)
74 {
75     if (!strncmp(vol_type, "system", strlen(vol_type)) || !strncmp(vol_type, "0", strlen(vol_type)))
76         return AUDIO_VOLUME_TYPE_SYSTEM;
77     else if (!strncmp(vol_type, "notification", strlen(vol_type)) || !strncmp(vol_type, "1", strlen(vol_type)))
78         return AUDIO_VOLUME_TYPE_NOTIFICATION;
79     else if (!strncmp(vol_type, "alarm", strlen(vol_type)) || !strncmp(vol_type, "2", strlen(vol_type)))
80         return AUDIO_VOLUME_TYPE_ALARM;
81     else if (!strncmp(vol_type, "ringtone", strlen(vol_type)) || !strncmp(vol_type, "3", strlen(vol_type)))
82         return AUDIO_VOLUME_TYPE_RINGTONE;
83     else if (!strncmp(vol_type, "media", strlen(vol_type)) || !strncmp(vol_type, "4", strlen(vol_type)))
84         return AUDIO_VOLUME_TYPE_MEDIA;
85     else if (!strncmp(vol_type, "call", strlen(vol_type)) || !strncmp(vol_type, "5", strlen(vol_type)))
86         return AUDIO_VOLUME_TYPE_CALL;
87     else if (!strncmp(vol_type, "voip", strlen(vol_type)) || !strncmp(vol_type, "6", strlen(vol_type)))
88         return AUDIO_VOLUME_TYPE_VOIP;
89     else if (!strncmp(vol_type, "voice", strlen(vol_type)) || !strncmp(vol_type, "7", strlen(vol_type)))
90         return AUDIO_VOLUME_TYPE_VOICE;
91     else
92         return AUDIO_VOLUME_TYPE_MEDIA;
93 }
94
95 static const char *__get_gain_type_string_by_idx(uint32_t gain_type_idx)
96 {
97     switch (gain_type_idx) {
98     case AUDIO_GAIN_TYPE_DEFAULT:           return "default";
99     case AUDIO_GAIN_TYPE_DIALER:            return "dialer";
100     case AUDIO_GAIN_TYPE_TOUCH:             return "touch";
101     case AUDIO_GAIN_TYPE_AF:                return "af";
102     case AUDIO_GAIN_TYPE_SHUTTER1:          return "shutter1";
103     case AUDIO_GAIN_TYPE_SHUTTER2:          return "shutter2";
104     case AUDIO_GAIN_TYPE_CAMCODING:         return "camcording";
105     case AUDIO_GAIN_TYPE_MIDI:              return "midi";
106     case AUDIO_GAIN_TYPE_BOOTING:           return "booting";
107     case AUDIO_GAIN_TYPE_VIDEO:             return "video";
108     case AUDIO_GAIN_TYPE_TTS:               return "tts";
109     default:                                return "invalid";
110     }
111 }
112
113 static void __dump_tb(audio_hal_t *ah)
114 {
115     audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table;
116     uint32_t vol_type_idx, vol_level_idx, gain_type_idx;
117     const char *gain_type_str[] = {
118         "def",          /* AUDIO_GAIN_TYPE_DEFAULT */
119         "dial",         /* AUDIO_GAIN_TYPE_DIALER */
120         "touch",        /* AUDIO_GAIN_TYPE_TOUCH */
121         "af",           /* AUDIO_GAIN_TYPE_AF */
122         "shut1",        /* AUDIO_GAIN_TYPE_SHUTTER1 */
123         "shut2",        /* AUDIO_GAIN_TYPE_SHUTTER2 */
124         "cam",          /* AUDIO_GAIN_TYPE_CAMCODING */
125         "midi",         /* AUDIO_GAIN_TYPE_MIDI */
126         "boot",         /* AUDIO_GAIN_TYPE_BOOTING */
127         "video",        /* AUDIO_GAIN_TYPE_VIDEO */
128         "tts",          /* AUDIO_GAIN_TYPE_TTS */
129     };
130     char dump_str[AUDIO_DUMP_STR_LEN], *dump_str_ptr;
131
132     /* Dump volume table */
133     AUDIO_LOG_INFO("<<<<< volume table >>>>>");
134
135     const char *table_str = "volumes";
136
137     AUDIO_LOG_INFO("<< %s >>", table_str);
138
139     for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_MAX; vol_type_idx++) {
140         const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
141
142         dump_str_ptr = &dump_str[0];
143         memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
144         snprintf(dump_str_ptr, 8, "%6s:", vol_type_str);
145         dump_str_ptr += strlen(dump_str_ptr);
146
147         for (vol_level_idx = 0; vol_level_idx < ah->volume.volume_level_max[vol_type_idx]; vol_level_idx++) {
148             snprintf(dump_str_ptr, 6, "%01.2f ", volume_value_table->volume[vol_type_idx][vol_level_idx]);
149             dump_str_ptr += strlen(dump_str_ptr);
150         }
151         AUDIO_LOG_INFO("%s", dump_str);
152     }
153
154     volume_value_table = ah->volume.volume_value_table;
155
156     /* Dump gain table */
157     AUDIO_LOG_INFO("<<<<< gain table >>>>>");
158
159     dump_str_ptr = &dump_str[0];
160     memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
161
162     snprintf(dump_str_ptr, 11, "%10s", " ");
163     dump_str_ptr += strlen(dump_str_ptr);
164
165     for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
166         snprintf(dump_str_ptr, 7, "%5s ", gain_type_str[gain_type_idx]);
167         dump_str_ptr += strlen(dump_str_ptr);
168     }
169     AUDIO_LOG_INFO("%s", dump_str);
170
171     dump_str_ptr = &dump_str[0];
172     memset(dump_str, 0x00, sizeof(char) * sizeof(dump_str));
173
174     snprintf(dump_str_ptr, 11, "%9s:", table_str);
175     dump_str_ptr += strlen(dump_str_ptr);
176
177     for (gain_type_idx = 0; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
178         snprintf(dump_str_ptr, 7, "%01.3f ", volume_value_table->gain[gain_type_idx]);
179         dump_str_ptr += strlen(dump_str_ptr);
180     }
181     AUDIO_LOG_INFO("%s", dump_str);
182
183 }
184
185 static audio_return_t __load_volume_value_table_from_ini(audio_hal_t *ah)
186 {
187     dictionary * dict = NULL;
188     uint32_t vol_type_idx, vol_level_idx, gain_type_idx;
189     audio_volume_value_table_t *volume_value_table = ah->volume.volume_value_table;
190     int size = 0;
191
192     dict = iniparser_load(VOLUME_INI_TEMP_PATH);
193     if (!dict) {
194         AUDIO_LOG_DEBUG("Use default volume&gain ini file");
195         dict = iniparser_load(VOLUME_INI_DEFAULT_PATH);
196         if (!dict) {
197             AUDIO_LOG_WARN("Loading volume&gain table from ini file failed");
198             return AUDIO_ERR_UNDEFINED;
199         }
200     }
201
202     const char delimiter[] = ", ";
203     char *key, *list_str, *token, *ptr = NULL;
204     const char *table_str = "volumes";
205
206     /* Load volume table */
207     for (vol_type_idx = 0; vol_type_idx < AUDIO_VOLUME_TYPE_MAX; vol_type_idx++) {
208         const char *vol_type_str = __get_volume_type_string_by_idx(vol_type_idx);
209
210         ah->volume.volume_level_max[vol_type_idx] = 0;
211         size = strlen(table_str) + strlen(vol_type_str) + 2;
212         key = malloc(size);
213         if (key) {
214             snprintf(key, size, "%s:%s", table_str, vol_type_str);
215             list_str = iniparser_getstring(dict, key, NULL);
216             if (list_str) {
217                 token = strtok_r(list_str, delimiter, &ptr);
218                 while (token) {
219                     /* convert dB volume to linear volume */
220                     double vol_value = 0.0f;
221                     if (strncmp(token, "0", strlen(token)))
222                         vol_value = pow(10.0, (atof(token) - 100) / 20.0);
223                     volume_value_table->volume[vol_type_idx][ah->volume.volume_level_max[vol_type_idx]++] = vol_value;
224                     token = strtok_r(NULL, delimiter, &ptr);
225                 }
226             } else {
227                 ah->volume.volume_level_max[vol_type_idx] = 1;
228                 for (vol_level_idx = 0; vol_level_idx < AUDIO_VOLUME_LEVEL_MAX; vol_level_idx++) {
229                     volume_value_table->volume[vol_type_idx][vol_level_idx] = VOLUME_VALUE_MAX;
230                 }
231             }
232             free(key);
233         }
234     }
235
236     /* Load gain table */
237     volume_value_table->gain[AUDIO_GAIN_TYPE_DEFAULT] = GAIN_VALUE_MAX;
238     for (gain_type_idx = AUDIO_GAIN_TYPE_DEFAULT + 1; gain_type_idx < AUDIO_GAIN_TYPE_MAX; gain_type_idx++) {
239         const char *gain_type_str = __get_gain_type_string_by_idx(gain_type_idx);
240
241         size = strlen(table_str) + strlen("gain") + strlen(gain_type_str) + 3;
242         key = malloc(size);
243         if (key) {
244             snprintf(key, size, "%s:gain_%s", table_str, gain_type_str);
245             token = iniparser_getstring(dict, key, NULL);
246             if (token) {
247                 volume_value_table->gain[gain_type_idx] = atof(token);
248             } else {
249                 volume_value_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
250             }
251             free(key);
252         } else {
253             volume_value_table->gain[gain_type_idx] = GAIN_VALUE_MAX;
254         }
255     }
256
257     iniparser_freedict(dict);
258
259     __dump_tb(ah);
260
261     return AUDIO_RET_OK;
262 }
263
264 static audio_return_t __load_radio_volume_table(int** volume_table, int *number_of_elements)
265 {
266     dictionary * dict = NULL;
267     const char delimiter[] = ", ";
268     char* ptr = NULL;
269     char* token = NULL;
270     char* list_str = NULL;
271     int* temp_table = NULL;
272     int index = 0;
273     int ret = 0;
274
275     bool tuning_enable = 0;
276     int not_found = -1;
277     int value = 0;
278
279     dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
280     if (dict == NULL) {
281         AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
282         return AUDIO_ERR_UNDEFINED;
283     } else {
284         /*tuning enable */
285         value = iniparser_getboolean(dict, RADIO_TUNING_ENABLE, not_found);
286         if (value == not_found) {
287             AUDIO_LOG_ERROR("Can't get Tuning Enable value");
288         } else {
289             tuning_enable = value;
290             AUDIO_LOG_INFO("Tuning enabled.");
291         }
292         iniparser_freedict(dict); /*Cleanup*/
293     }
294
295     if (tuning_enable) {
296         AUDIO_LOG_INFO("Tuning enabled. load temp tuning file.");
297         dict = iniparser_load(RADIO_TUNING_TEMP_FILE);
298         if (!dict) {
299             AUDIO_LOG_WARN("%s load failed. Tuning enabled but there is not tuning temp file.  Use temporary file", RADIO_TUNING_TEMP_FILE);
300             dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
301             if (!dict) {
302                 AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
303                 return AUDIO_ERR_UNDEFINED;
304             }
305         }
306     } else {
307         AUDIO_LOG_INFO("Tuning diabled. load default tuning file.");
308         dict = iniparser_load(RADIO_TUNING_DEFUALT_FILE);
309         if (!dict) {
310             AUDIO_LOG_ERROR("%s load failed", RADIO_TUNING_DEFUALT_FILE);
311             return AUDIO_ERR_UNDEFINED;
312         }
313     }
314
315     *number_of_elements = iniparser_getint(dict, RADIO_TUNING_VOLUME_LEVELS, -1);
316     if (*number_of_elements <= 0 || *number_of_elements > RADIO_VOLUME_NUM_MAX) {
317         AUDIO_LOG_ERROR("invalid number of elements, %d", *number_of_elements);
318         ret = AUDIO_ERR_INTERNAL;
319         goto error;
320     }
321     temp_table = (int *)malloc((*number_of_elements) * sizeof(int));
322     if (!temp_table)
323         goto error;
324
325     *volume_table = temp_table;
326
327     list_str = iniparser_getstring(dict, RADIO_TUNING_VOLUME_TABLE, NULL);
328     if (list_str) {
329         token = strtok_r(list_str, delimiter, &ptr);
330         while (token) {
331             temp_table[index] = atoi(token);
332             AUDIO_LOG_INFO("fm volume index %d is %d", index, temp_table[index]);
333             index++;
334             token = strtok_r(NULL, delimiter, &ptr);
335         }
336     }
337 error:
338     iniparser_freedict(dict);
339     return ret;
340 }
341
342 audio_return_t _audio_volume_set_level_radio(audio_hal_t *ah, uint32_t level)
343 {
344     audio_return_t audio_ret = AUDIO_RET_OK;
345     int volume = 0;
346     int mute = -1;
347
348     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
349
350     /* Applying mute at volume zero */
351     if (level == 0) {
352         if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_MUTE, 0)))
353             AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_MUTE);
354
355     } else {
356         if ((audio_ret = _mixer_control_get_value(ah, MIXER_FMRADIO_MUTE, &mute))) {
357             AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_MUTE);
358             return audio_ret;
359         }
360         if (mute == 0) {
361             if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_MUTE, 1))) {
362                 AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_MUTE);
363                 return audio_ret;
364             }
365         }
366     }
367
368     if ((_mixer_control_get_value(ah, MIXER_FMRADIO_L_VOLUME, &volume)))
369         AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_L_VOLUME);
370     else {
371         if (volume != ah->volume.radio_volume_value_table[level]) {
372             if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_L_VOLUME, ah->volume.radio_volume_value_table[level]))) {
373                 AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_L_VOLUME);
374                 return audio_ret;
375             }
376         }
377     }
378
379     if ((_mixer_control_get_value(ah, MIXER_FMRADIO_R_VOLUME, &volume)))
380         AUDIO_LOG_ERROR("get mixer(%s) failed", MIXER_FMRADIO_R_VOLUME);
381     else {
382         if (volume != ah->volume.radio_volume_value_table[level]) {
383             if ((audio_ret = _mixer_control_set_value(ah, MIXER_FMRADIO_R_VOLUME, ah->volume.radio_volume_value_table[level])))
384                 AUDIO_LOG_ERROR("set mixer(%s) failed", MIXER_FMRADIO_R_VOLUME);
385         }
386     }
387
388     return audio_ret;
389 }
390
391 audio_return_t _audio_volume_init(audio_hal_t *ah)
392 {
393     int i;
394     int val = 0;
395     audio_return_t audio_ret = AUDIO_RET_OK;
396     int init_value[AUDIO_VOLUME_TYPE_MAX] = { 9, 11, 7, 11, 7, 4, 4, 7 };
397     int* fm_table = NULL;
398     int number_of_steps = 0;
399
400     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
401
402     for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
403         ah->volume.volume_level[i] = init_value[i];
404     }
405
406     for (i = 0; i < AUDIO_VOLUME_TYPE_MAX; i++) {
407         /* Get volume value string from VCONF */
408         if (vconf_get_int(g_volume_vconf[i], &val) < 0) {
409             AUDIO_LOG_ERROR("vconf_get_int(%s) failed", g_volume_vconf[i]);
410             continue;
411         }
412
413         AUDIO_LOG_INFO("read vconf. %s = %d", g_volume_vconf[i], val);
414         ah->volume.volume_level[i] = val;
415     }
416
417     if (!(ah->volume.volume_value_table = malloc(AUDIO_VOLUME_DEVICE_MAX * sizeof(audio_volume_value_table_t)))) {
418         AUDIO_LOG_ERROR("volume_value_table malloc failed");
419         return AUDIO_ERR_RESOURCE;
420     }
421
422     audio_ret = __load_volume_value_table_from_ini(ah);
423     if (audio_ret != AUDIO_RET_OK) {
424         AUDIO_LOG_ERROR("gain table load error");
425         return AUDIO_ERR_UNDEFINED;
426     }
427
428     /* radio volume table */
429     __load_radio_volume_table(&fm_table, &number_of_steps);
430     if (fm_table) {
431         AUDIO_LOG_DEBUG("number of steps -> %d", number_of_steps);
432         /*copy from temp structure to main strcture*/
433         for (i = 0; i < number_of_steps; i++) {
434             ah->volume.radio_volume_value_table[i] = fm_table[i];
435         }
436         free(fm_table);
437         fm_table = NULL;
438     }
439
440     return audio_ret;
441 }
442
443 audio_return_t _audio_volume_deinit(audio_hal_t *ah)
444 {
445     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
446
447     if (ah->volume.volume_value_table) {
448         free(ah->volume.volume_value_table);
449         ah->volume.volume_value_table = NULL;
450     }
451
452     return AUDIO_RET_OK;
453 }
454
455 audio_return_t audio_get_volume_level_max(void *audio_handle, audio_volume_info_t *info, uint32_t *level)
456 {
457     audio_hal_t *ah = (audio_hal_t *)audio_handle;
458
459     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
460     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
461     AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER);
462
463     /* Get max volume level by device & type */
464     *level = ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)];
465
466     AUDIO_LOG_DEBUG("get_[%s] volume_level_max: %d", info->type, *level);
467
468     return AUDIO_RET_OK;
469 }
470
471 audio_return_t audio_get_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t *level)
472 {
473     audio_hal_t *ah = (audio_hal_t *)audio_handle;
474
475     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
476     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
477     AUDIO_RETURN_VAL_IF_FAIL(level, AUDIO_ERR_PARAMETER);
478
479     if (!strncmp(info->type, "master", strlen("master"))) {
480         *level = g_master_volume_level;
481         return AUDIO_RET_OK;
482     }
483
484     *level = ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)];
485
486     AUDIO_LOG_INFO("get [%s] volume_level: %d, direction(%d)", info->type, *level, info->direction);
487
488     return AUDIO_RET_OK;
489 }
490
491 audio_return_t audio_get_volume_value(void *audio_handle, audio_volume_info_t *info, uint32_t level, double *value)
492 {
493     audio_hal_t *ah = (audio_hal_t *)audio_handle;
494     audio_volume_value_table_t *volume_value_table;
495     char dump_str[AUDIO_DUMP_STR_LEN] = {0,};
496
497     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
498     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
499     AUDIO_RETURN_VAL_IF_FAIL(value, AUDIO_ERR_PARAMETER);
500     AUDIO_RETURN_VAL_IF_FAIL(ah->volume.volume_value_table, AUDIO_ERR_PARAMETER);
501
502     /* Get basic volume by device & type & level */
503     volume_value_table = ah->volume.volume_value_table;
504     if (ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] < level)
505         *value = VOLUME_VALUE_MAX;
506     else
507         *value = volume_value_table->volume[__get_volume_idx_by_string_type(info->type)][level];
508     *value *= volume_value_table->gain[AUDIO_GAIN_TYPE_DEFAULT]; /* need to fix getting gain via audio_info_t */
509
510     AUDIO_LOG_DEBUG("get_volume_value:%d(%s)=>%f %s", level, info->type, *value, &dump_str[0]);
511
512     return AUDIO_RET_OK;
513 }
514
515 audio_return_t audio_set_volume_level(void *audio_handle, audio_volume_info_t *info, uint32_t level)
516 {
517     audio_return_t audio_ret = AUDIO_RET_OK;
518     audio_hal_t *ah = (audio_hal_t *)audio_handle;
519
520     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
521     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
522     if (!strncmp(info->type, "master", strlen("master"))) {
523         g_master_volume_level = level;
524         return AUDIO_RET_OK;
525     }
526     AUDIO_RETURN_VAL_IF_FAIL((ah->volume.volume_level_max[__get_volume_idx_by_string_type(info->type)] >= level), AUDIO_ERR_PARAMETER);
527
528     /* Update volume level */
529     ah->volume.volume_level[__get_volume_idx_by_string_type(info->type)] = level;
530     AUDIO_LOG_INFO("set [%s] volume_level: %d, direction(%d)", info->type, level, info->direction);
531
532     /* set mixer related to H/W volume if needed */
533     if ((__get_volume_idx_by_string_type(info->type) == AUDIO_VOLUME_TYPE_MEDIA) && ah->device.is_radio_on)
534         audio_ret = _audio_volume_set_level_radio(ah, level);
535
536     return audio_ret;
537 }
538
539 audio_return_t audio_get_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t *mute)
540 {
541     audio_return_t audio_ret = AUDIO_RET_OK;
542     audio_hal_t *ah = (audio_hal_t *)audio_handle;
543
544     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
545     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
546     AUDIO_RETURN_VAL_IF_FAIL(mute, AUDIO_ERR_PARAMETER);
547
548     /* TODO. Not implemented */
549
550     return audio_ret;
551 }
552
553 audio_return_t audio_set_volume_mute(void *audio_handle, audio_volume_info_t *info, uint32_t mute)
554 {
555     audio_return_t audio_ret = AUDIO_RET_OK;
556     audio_hal_t *ah = (audio_hal_t *)audio_handle;
557
558     AUDIO_RETURN_VAL_IF_FAIL(ah, AUDIO_ERR_PARAMETER);
559     AUDIO_RETURN_VAL_IF_FAIL(info, AUDIO_ERR_PARAMETER);
560
561     /* TODO. Not implemented */
562
563     return audio_ret;
564 }