4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
31 #include "include/mm_sound.h"
32 #include "include/mm_sound_client.h"
33 #include "include/mm_sound_proxy.h"
34 #include "include/mm_sound_common.h"
35 #include "include/mm_sound_device.h"
36 #include "include/mm_sound_stream.h"
37 #include "include/mm_sound_focus_private.h"
39 #define CLIENT_HANDLE_MAX 256
40 #define VOLUME_TYPE_LEN 64
42 #define VCONF_KEY_VOLUME_PREFIX "file/private/sound/volume"
43 #define VCONF_KEY_VOLUME_TYPE_SYSTEM VCONF_KEY_VOLUME_PREFIX"/system"
44 #define VCONF_KEY_VOLUME_TYPE_NOTIFICATION VCONF_KEY_VOLUME_PREFIX"/notification"
45 #define VCONF_KEY_VOLUME_TYPE_ALARM VCONF_KEY_VOLUME_PREFIX"/alarm"
46 #define VCONF_KEY_VOLUME_TYPE_RINGTONE VCONF_KEY_VOLUME_PREFIX"/ringtone"
47 #define VCONF_KEY_VOLUME_TYPE_MEDIA VCONF_KEY_VOLUME_PREFIX"/media"
48 #define VCONF_KEY_VOLUME_TYPE_CALL VCONF_KEY_VOLUME_PREFIX"/call"
49 #define VCONF_KEY_VOLUME_TYPE_VOIP VCONF_KEY_VOLUME_PREFIX"/voip"
50 #define VCONF_KEY_VOLUME_TYPE_VOICE VCONF_KEY_VOLUME_PREFIX"/voice"
51 #define VCONF_KEY_VOLUME_TYPE_ANDROID VCONF_KEY_VOLUME_PREFIX"/fixed"
53 #define VCONF_KEY_MUTE_PREFIX "file/private/sound/mute"
54 #define VCONF_KEY_MUTE_TYPE_SYSTEM VCONF_KEY_MUTE_PREFIX"/system"
55 #define VCONF_KEY_MUTE_TYPE_NOTIFICATION VCONF_KEY_MUTE_PREFIX"/notification"
56 #define VCONF_KEY_MUTE_TYPE_ALARM VCONF_KEY_MUTE_PREFIX"/alarm"
57 #define VCONF_KEY_MUTE_TYPE_RINGTONE VCONF_KEY_MUTE_PREFIX"/ringtone"
58 #define VCONF_KEY_MUTE_TYPE_MEDIA VCONF_KEY_MUTE_PREFIX"/media"
59 #define VCONF_KEY_MUTE_TYPE_CALL VCONF_KEY_MUTE_PREFIX"/call"
60 #define VCONF_KEY_MUTE_TYPE_VOIP VCONF_KEY_MUTE_PREFIX"/voip"
61 #define VCONF_KEY_MUTE_TYPE_VOICE VCONF_KEY_MUTE_PREFIX"/voice"
63 /* For internal use */
64 #define VCONF_KEY_VOLUME_TYPE_BIXBY VCONF_KEY_VOLUME_PREFIX"/bixby"
66 static char *g_volume_vconf[VOLUME_TYPE_MAX] = {
67 VCONF_KEY_VOLUME_TYPE_SYSTEM, /* VOLUME_TYPE_SYSTEM */
68 VCONF_KEY_VOLUME_TYPE_NOTIFICATION, /* VOLUME_TYPE_NOTIFICATION */
69 VCONF_KEY_VOLUME_TYPE_ALARM, /* VOLUME_TYPE_ALARM */
70 VCONF_KEY_VOLUME_TYPE_RINGTONE, /* VOLUME_TYPE_RINGTONE */
71 VCONF_KEY_VOLUME_TYPE_MEDIA, /* VOLUME_TYPE_MEDIA */
72 VCONF_KEY_VOLUME_TYPE_CALL, /* VOLUME_TYPE_CALL */
73 VCONF_KEY_VOLUME_TYPE_VOIP, /* VOLUME_TYPE_VOIP */
74 VCONF_KEY_VOLUME_TYPE_VOICE, /* VOLUME_TYPE_VOICE */
75 VCONF_KEY_VOLUME_TYPE_ANDROID /* VOLUME_TYPE_FIXED */
78 static char *g_volume_vconf_internal[] = {
79 VCONF_KEY_VOLUME_TYPE_BIXBY, /* VOLUME_TYPE_BIXBY */
82 static char *g_mute_vconf[] = {
83 VCONF_KEY_MUTE_TYPE_SYSTEM, /* MUTE_TYPE_SYSTEM */
84 VCONF_KEY_MUTE_TYPE_NOTIFICATION, /* MUTE_TYPE_NOTIFICATION */
85 VCONF_KEY_MUTE_TYPE_ALARM, /* MUTE_TYPE_ALARM */
86 VCONF_KEY_MUTE_TYPE_RINGTONE, /* MUTE_TYPE_RINGTONE */
87 VCONF_KEY_MUTE_TYPE_MEDIA, /* MUTE_TYPE_MEDIA */
88 VCONF_KEY_MUTE_TYPE_CALL, /* MUTE_TYPE_CALL */
89 VCONF_KEY_MUTE_TYPE_VOIP, /* MUTE_TYPE_VOIP */
90 VCONF_KEY_MUTE_TYPE_VOICE, /* MUTE_TYPE_VOICE */
93 struct callback_data {
100 #define GET_CB_DATA(_cb_data, _func, _userdata, _extradata) \
102 _cb_data = (struct callback_data*) g_try_malloc0(sizeof(struct callback_data)); \
104 debug_error("failed to allocate callback_data"); \
105 return MM_ERROR_OUT_OF_MEMORY; \
107 _cb_data->user_cb = _func; \
108 _cb_data->user_data = _userdata; \
109 _cb_data->extra_data = _extradata; \
112 static pthread_mutex_t g_index_mutex = PTHREAD_MUTEX_INITIALIZER;
113 static pthread_mutex_t g_event_mutex = PTHREAD_MUTEX_INITIALIZER;
114 static guint g_idle_event_src;
117 /* handle to watch end of playing */
119 /* subscription id to unsubscribe when handle ended */
121 } play_sound_end_callback_data_t;
123 typedef struct _focus_idle_event {
124 focus_idle_event_type_e type;
126 } focus_idle_event_t;
128 int mm_sound_client_initialize(void)
130 int ret = MM_ERROR_NONE;
134 mm_sound_proxy_initialize();
135 g_idle_event_src = 0;
141 int mm_sound_client_finalize(void)
143 int ret = MM_ERROR_NONE;
147 ret = mm_sound_proxy_finalize();
149 if (g_idle_event_src > 0) {
150 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_event_mutex, MM_ERROR_SOUND_INTERNAL);
151 g_source_remove(g_idle_event_src);
152 MMSOUND_LEAVE_CRITICAL_SECTION(&g_event_mutex);
159 void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_type)
161 switch (volume_type) {
162 case VOLUME_TYPE_SYSTEM:
163 MMSOUND_STRNCPY(stream_type, "system", MAX_STREAM_TYPE_LEN);
165 case VOLUME_TYPE_NOTIFICATION:
166 MMSOUND_STRNCPY(stream_type, "notification", MAX_STREAM_TYPE_LEN);
168 case VOLUME_TYPE_ALARM:
169 MMSOUND_STRNCPY(stream_type, "alarm", MAX_STREAM_TYPE_LEN);
171 case VOLUME_TYPE_RINGTONE:
172 MMSOUND_STRNCPY(stream_type, "ringtone-voip", MAX_STREAM_TYPE_LEN);
174 case VOLUME_TYPE_MEDIA:
175 MMSOUND_STRNCPY(stream_type, "media", MAX_STREAM_TYPE_LEN);
177 case VOLUME_TYPE_CALL:
178 MMSOUND_STRNCPY(stream_type, "call-voice", MAX_STREAM_TYPE_LEN);
180 case VOLUME_TYPE_VOIP:
181 MMSOUND_STRNCPY(stream_type, "voip", MAX_STREAM_TYPE_LEN);
183 case VOLUME_TYPE_VOICE:
184 MMSOUND_STRNCPY(stream_type, "voice-information", MAX_STREAM_TYPE_LEN);
187 MMSOUND_STRNCPY(stream_type, "media", MAX_STREAM_TYPE_LEN);
191 debug_msg("volume type (%d) converted to stream type (%s)", volume_type, stream_type);
195 /*****************************************************************************************
196 DBUS SUPPORTED FUNCTIONS
197 ******************************************************************************************/
198 int mm_sound_client_play_tone_with_stream_info(int tone, char *stream_type, int stream_id,
199 double volume, int duration, int *handle)
201 int ret = MM_ERROR_NONE;
205 ret = mm_sound_proxy_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle);
211 static void _mm_sound_stop_callback_wrapper_func(int ended_handle, void *userdata)
213 struct callback_data *cb_data = (struct callback_data*) userdata;
214 play_sound_end_callback_data_t *end_cb_data;
216 debug_log("ended_handle : %d", ended_handle);
218 if (cb_data == NULL) {
219 debug_warning("stop callback data null");
223 end_cb_data = (play_sound_end_callback_data_t*) cb_data->extra_data;
225 if (ended_handle == end_cb_data->watching_handle) {
226 debug_log("Interested playing handle end : %d", ended_handle);
227 ((mm_sound_stop_callback_func)(cb_data->user_cb))(cb_data->user_data, ended_handle);
228 if (mm_sound_proxy_remove_play_sound_end_callback(end_cb_data->subs_id) != MM_ERROR_NONE)
229 debug_error("mm_sound_client_dbus_remove_play_file_end_callback failed");
231 debug_log("Not interested playing handle : %d", ended_handle);
235 static void play_end_callback_data_free_func(void *data)
237 struct callback_data *cb_data = (struct callback_data*) data;
240 g_free(cb_data->extra_data);
245 int mm_sound_client_play_sound_with_stream_info(MMSoundPlayParam *param, int *handle, char* stream_type, int stream_id)
247 int ret = MM_ERROR_NONE;
248 struct callback_data *cb_data = NULL;
249 play_sound_end_callback_data_t *end_cb_data;
251 ret = mm_sound_proxy_play_sound_with_stream_info(param->filename, param->loop, param->volume,
252 getpid(), handle, stream_type, stream_id);
253 if (ret != MM_ERROR_NONE) {
254 debug_error("Play Sound Failed");
257 if (param->callback) {
258 end_cb_data = (play_sound_end_callback_data_t *) g_try_malloc0(sizeof(play_sound_end_callback_data_t));
260 debug_error("Failed to alloc end_cb_data");
261 return MM_ERROR_OUT_OF_MEMORY;
263 end_cb_data->watching_handle = *handle;
264 GET_CB_DATA(cb_data, param->callback, param->data, end_cb_data);
266 ret = mm_sound_proxy_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data,
267 play_end_callback_data_free_func, &end_cb_data->subs_id);
268 if (ret != MM_ERROR_NONE)
269 debug_error("Add callback for play sound(%d) Failed", *handle);
277 int mm_sound_client_stop_sound(int handle)
279 int ret = MM_ERROR_NONE;
282 if (handle < 0 || handle > CLIENT_HANDLE_MAX) {
283 ret = MM_ERROR_INVALID_ARGUMENT;
287 ret = mm_sound_proxy_stop_sound(handle);
293 static int _mm_sound_client_device_list_dump(GList *device_list)
295 int ret = MM_ERROR_NONE;
297 mm_sound_device_t *device_node = NULL;
300 debug_error("Device list NULL, cannot dump list");
301 return MM_ERROR_SOUND_INTERNAL;
304 debug_log("======================== device list : start ==========================");
305 for (list = device_list; list != NULL; list = list->next) {
306 device_node = (mm_sound_device_t *)list->data;
308 debug_log(" list idx[%d]: type[%17s], id[%02d], io_direction[%d], state[%d], name[%s]",
309 count++, device_node->type, device_node->id, device_node->io_direction,
310 device_node->state, device_node->name);
313 debug_log("======================== device list : end ============================");
318 int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t *device_list)
320 int ret = MM_ERROR_NONE;
324 debug_error("Device list NULL");
325 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
329 if ((ret = mm_sound_proxy_get_current_connected_device_list(device_flags, &device_list->list)) != MM_ERROR_NONE) {
330 debug_error("failed to get current connected device list with dbus, ret[0x%x]", ret);
333 if (!device_list->list) {
334 debug_error("Got device list null");
335 ret = MM_ERROR_SOUND_NO_DATA;
338 _mm_sound_client_device_list_dump(device_list->list);
345 int mm_sound_client_get_device_by_id(int device_id, mm_sound_device_t **device)
347 int ret = MM_ERROR_NONE;
351 if ((ret = mm_sound_proxy_get_device_by_id(device_id, device)) != MM_ERROR_NONE)
352 debug_error("failed to get device by id");
359 static bool device_is_match_direction(int direction, int mask)
361 if (mask == DEVICE_IO_DIRECTION_FLAGS || mask == 0)
364 if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_IN_FLAG) && (direction & MM_SOUND_DEVICE_IO_DIRECTION_IN))
366 if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG) && (direction & MM_SOUND_DEVICE_IO_DIRECTION_OUT))
368 if ((mask & MM_SOUND_DEVICE_IO_DIRECTION_BOTH_FLAG) && (direction == MM_SOUND_DEVICE_IO_DIRECTION_BOTH))
374 static bool device_is_match_state(int state, int mask)
376 if (mask == DEVICE_STATE_FLAGS || mask == 0)
379 if ((mask & MM_SOUND_DEVICE_STATE_DEACTIVATED_FLAG) && (state == MM_SOUND_DEVICE_STATE_DEACTIVATED))
381 if ((mask & MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG) && (state == MM_SOUND_DEVICE_STATE_ACTIVATED))
387 static bool device_is_match_type(const char *type, int mask)
390 const char *builtin_prefix = "builtin";
392 if (mask == DEVICE_TYPE_FLAGS || mask == 0)
395 is_builtin = !strncmp(type, builtin_prefix, strlen(builtin_prefix));
397 if ((mask & MM_SOUND_DEVICE_TYPE_INTERNAL_FLAG) && (is_builtin))
399 if ((mask & MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG) && (!is_builtin))
405 static bool device_is_match_with_mask(const char *type, int direction, int state, int mask)
407 if (mask == DEVICE_ALL_FLAG)
410 return (device_is_match_direction(direction, mask & DEVICE_IO_DIRECTION_FLAGS) &&
411 device_is_match_state(state, mask & DEVICE_STATE_FLAGS) &&
412 device_is_match_type(type, mask & DEVICE_TYPE_FLAGS));
415 static int _fill_sound_device(mm_sound_device_t *device_h, int device_id, const char *device_type,
416 int direction, int state, const char *name, int vendor_id, int product_id,
417 int *stream_id, int stream_num, bool is_running)
421 if (stream_num > 0 && stream_id == NULL) {
422 debug_error("stream_num is %d, but stream_id is NULL", stream_num);
426 if (stream_num > MAX_STREAM_ON_DEVICE) {
427 debug_error("too many streams on this device");
431 device_h->id = device_id;
432 device_h->io_direction = direction;
433 device_h->state = state;
434 MMSOUND_STRNCPY(device_h->name, name, MAX_DEVICE_NAME_NUM);
435 MMSOUND_STRNCPY(device_h->type, device_type, MAX_DEVICE_TYPE_STR_LEN);
436 device_h->vendor_id = vendor_id;
437 device_h->product_id = product_id;
438 device_h->is_running = is_running;
440 if (stream_num > 0) {
441 device_h->stream_num = stream_num;
442 debug_log("%d streams on this device", stream_num);
443 for (i = 0; i < stream_num; i++) {
444 debug_log(" stream_id : %d", stream_id[i]);
445 device_h->stream_id[i] = stream_id[i];
448 device_h->stream_num = 0;
449 debug_log("There is no stream on this device");
455 static void _mm_sound_device_connected_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
456 int state, const char *name, int vendor_id, int product_id, bool is_running,
457 int *stream_id, int stream_num, bool is_connected, void *userdata)
459 mm_sound_device_t device_h;
460 struct callback_data *cb_data = (struct callback_data*) userdata;
463 debug_log("[Device %s] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) vendor-id(%04x) product-id(%04x)",
464 is_connected ? "Connected" : "Disconnected", device_id, device_type, io_direction, state, name,
465 is_running, vendor_id, product_id);
467 if (cb_data == NULL) {
468 debug_warning("device connected changed callback data null");
472 device_flags = (int) cb_data->extra_data;
473 if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
476 if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
477 vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
478 debug_error("Failed to fill sound device");
482 ((mm_sound_device_connected_cb)(cb_data->user_cb))(&device_h, is_connected, cb_data->user_data);
485 int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func,
486 void* userdata, unsigned int *subs_id)
488 int ret = MM_ERROR_NONE;
489 struct callback_data *cb_data = NULL;
493 GET_CB_DATA(cb_data, func, userdata, (void*) device_flags);
495 ret = mm_sound_proxy_add_device_connected_callback(_mm_sound_device_connected_callback_wrapper_func,
496 cb_data, g_free, subs_id);
502 int mm_sound_client_remove_device_connected_callback(unsigned int subs_id)
504 int ret = MM_ERROR_NONE;
507 ret = mm_sound_proxy_remove_device_connected_callback(subs_id);
513 static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
514 int state, const char *name, int vendor_id, int product_id, bool is_running,
515 int *stream_id, int stream_num, int changed_device_info_type, void *userdata)
517 mm_sound_device_t device_h;
518 struct callback_data *cb_data = (struct callback_data*) userdata;
521 debug_log("[Device Info Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) "
522 "vendor-id(%04x) product-id(%04x) changed_info_type(%d)",
523 device_id, device_type, io_direction, state, name, is_running, vendor_id, product_id, changed_device_info_type);
525 if (cb_data == NULL) {
526 debug_warning("device info changed callback data null");
530 device_flags = (int) cb_data->extra_data;
531 if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
534 if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
535 vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
536 debug_error("Failed to fill sound device");
540 ((mm_sound_device_info_changed_cb)(cb_data->user_cb))(&device_h, changed_device_info_type, cb_data->user_data);
543 int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func,
544 void *userdata, unsigned int *subs_id)
546 int ret = MM_ERROR_NONE;
547 struct callback_data *cb_data = (struct callback_data*) userdata;
551 GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
553 ret = mm_sound_proxy_add_device_info_changed_callback(_mm_sound_device_info_changed_callback_wrapper_func,
554 cb_data, g_free, subs_id);
560 int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id)
562 int ret = MM_ERROR_NONE;
565 ret = mm_sound_proxy_remove_device_info_changed_callback(subs_id);
572 static void _mm_sound_device_state_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
573 int state, const char *name, int vendor_id, int product_id,
574 bool is_running, int *stream_id, int stream_num, void *userdata)
576 mm_sound_device_t device_h;
577 struct callback_data *cb_data = (struct callback_data*) userdata;
580 debug_log("[Device State Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) vendor-id(%04x) product-id(%04x)",
581 device_id, device_type, io_direction, state, name, is_running, vendor_id, product_id);
583 if (cb_data == NULL) {
584 debug_warning("device state changed callback data null");
588 device_flags = (int) cb_data->extra_data;
590 if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
593 if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
594 vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
595 debug_error("Failed to fill sound device");
599 ((mm_sound_device_state_changed_cb)(cb_data->user_cb))(&device_h, state, cb_data->user_data);
602 int mm_sound_client_add_device_state_changed_callback(int device_flags, mm_sound_device_state_changed_cb func,
603 void *userdata, unsigned int *id)
605 int ret = MM_ERROR_NONE;
606 struct callback_data *cb_data = (struct callback_data*) userdata;
610 GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
612 ret = mm_sound_proxy_add_device_state_changed_callback(_mm_sound_device_state_changed_callback_wrapper_func,
613 cb_data, g_free, id);
619 int mm_sound_client_remove_device_state_changed_callback(unsigned int id)
621 int ret = MM_ERROR_NONE;
624 ret = mm_sound_proxy_remove_device_state_changed_callback(id);
630 static void _mm_sound_device_running_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction,
631 int state, const char *name, int vendor_id, int product_id,
632 bool is_running, int *stream_id, int stream_num, void *userdata)
634 mm_sound_device_t device_h;
635 struct callback_data *cb_data = (struct callback_data*) userdata;
638 debug_log("[Device Running Changed] id(%d) type(%s) direction(%d) state(%d) name(%s) is_running(%d) vendor-id(%04x), product-id(%04x)",
639 device_id, device_type, io_direction, state, name, is_running, vendor_id, product_id);
641 if (cb_data == NULL) {
642 debug_warning("device running changed callback data null");
646 device_flags = (int) cb_data->extra_data;
648 if (!device_is_match_with_mask(device_type, io_direction, state, device_flags))
651 if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name,
652 vendor_id, product_id, stream_id, stream_num, is_running) < 0) {
653 debug_error("Failed to fill sound device");
657 ((mm_sound_device_running_changed_cb)(cb_data->user_cb))(&device_h, is_running, cb_data->user_data);
660 int mm_sound_client_add_device_running_changed_callback(int device_flags, mm_sound_device_running_changed_cb func,
661 void *userdata, unsigned int *id)
663 int ret = MM_ERROR_NONE;
664 struct callback_data *cb_data = (struct callback_data*) userdata;
668 GET_CB_DATA(cb_data, func, userdata, (void *) device_flags);
670 ret = mm_sound_proxy_add_device_running_changed_callback(_mm_sound_device_running_changed_callback_wrapper_func,
671 cb_data, g_free, id);
677 int mm_sound_client_remove_device_running_changed_callback(unsigned int id)
679 int ret = MM_ERROR_NONE;
682 ret = mm_sound_proxy_remove_device_running_changed_callback(id);
688 int mm_sound_client_is_stream_on_device(int stream_id, int device_id, bool *is_on)
690 int ret = MM_ERROR_NONE;
694 debug_error("Invalid Parameter");
695 ret = MM_ERROR_COMMON_INVALID_ARGUMENT;
699 if ((ret = mm_sound_proxy_is_stream_on_device(stream_id, device_id, is_on)) != MM_ERROR_NONE) {
700 debug_error("failed to query is stream on device, ret[0x%x]", ret);
709 int __convert_volume_type_to_str(volume_type_t volume_type, char **volume_type_str)
711 int ret = MM_ERROR_NONE;
713 if (!volume_type_str)
714 return MM_ERROR_COMMON_INVALID_ARGUMENT;
716 switch (volume_type) {
717 case VOLUME_TYPE_SYSTEM:
718 *volume_type_str = "system";
720 case VOLUME_TYPE_NOTIFICATION:
721 *volume_type_str = "notification";
723 case VOLUME_TYPE_ALARM:
724 *volume_type_str = "alarm";
726 case VOLUME_TYPE_RINGTONE:
727 *volume_type_str = "ringtone";
729 case VOLUME_TYPE_MEDIA:
730 *volume_type_str = "media";
732 case VOLUME_TYPE_CALL:
733 *volume_type_str = "call";
735 case VOLUME_TYPE_VOIP:
736 *volume_type_str = "voip";
738 case VOLUME_TYPE_VOICE:
739 *volume_type_str = "voice";
742 debug_error("unexpected volume type [%d]", volume_type);
743 return MM_ERROR_SOUND_INTERNAL;
745 debug_log("volume_type[%s]", *volume_type_str);
749 int __convert_volume_type_internal_to_str(volume_type_internal_t volume_type, char **volume_type_str)
751 int ret = MM_ERROR_NONE;
753 if (!volume_type_str)
754 return MM_ERROR_COMMON_INVALID_ARGUMENT;
756 switch (volume_type) {
757 case VOLUME_TYPE_BIXBY:
758 *volume_type_str = "bixby";
761 debug_error("unexpected volume type [%d]", volume_type);
762 return MM_ERROR_SOUND_INTERNAL;
764 debug_log("volume_type[%s]", *volume_type_str);
768 static int __convert_volume_type_to_int(const char *volume_type_str, int *volume_type, bool *is_for_internal)
770 int ret = MM_ERROR_NONE;
772 if (!volume_type || !volume_type_str || !is_for_internal)
773 return MM_ERROR_COMMON_INVALID_ARGUMENT;
775 if (!strncmp(volume_type_str, "system", VOLUME_TYPE_LEN)) {
776 *volume_type = VOLUME_TYPE_SYSTEM;
777 *is_for_internal = false;
778 } else if (!strncmp(volume_type_str, "notification", VOLUME_TYPE_LEN)) {
779 *volume_type = VOLUME_TYPE_NOTIFICATION;
780 *is_for_internal = false;
781 } else if (!strncmp(volume_type_str, "alarm", VOLUME_TYPE_LEN)) {
782 *volume_type = VOLUME_TYPE_ALARM;
783 *is_for_internal = false;
784 } else if (!strncmp(volume_type_str, "ringtone", VOLUME_TYPE_LEN)) {
785 *volume_type = VOLUME_TYPE_RINGTONE;
786 *is_for_internal = false;
787 } else if (!strncmp(volume_type_str, "media", VOLUME_TYPE_LEN)) {
788 *volume_type = VOLUME_TYPE_MEDIA;
789 *is_for_internal = false;
790 } else if (!strncmp(volume_type_str, "call", VOLUME_TYPE_LEN)) {
791 *volume_type = VOLUME_TYPE_CALL;
792 *is_for_internal = false;
793 } else if (!strncmp(volume_type_str, "voip", VOLUME_TYPE_LEN)) {
794 *volume_type = VOLUME_TYPE_VOIP;
795 *is_for_internal = false;
796 } else if (!strncmp(volume_type_str, "voice", VOLUME_TYPE_LEN)) {
797 *volume_type = VOLUME_TYPE_VOICE;
798 *is_for_internal = false;
799 /* else-if statements below are for internal use */
800 } else if (!strncmp(volume_type_str, "bixby", VOLUME_TYPE_LEN)) {
801 *volume_type = VOLUME_TYPE_BIXBY;
802 *is_for_internal = true;
804 debug_log("Invalid volume type : [%s]", volume_type_str);
805 ret = MM_ERROR_SOUND_INTERNAL;
811 int mm_sound_client_set_volume_by_type(volume_type_t type, const unsigned int level)
813 int ret = MM_ERROR_NONE;
814 char *type_str = NULL;
817 if (type >= VOLUME_TYPE_MAX) {
818 debug_error("invalid volume type %d", type);
819 return MM_ERROR_INVALID_ARGUMENT;
822 if ((ret = __convert_volume_type_to_str(type, &type_str)) != MM_ERROR_NONE) {
823 debug_error("volume type convert failed");
827 ret = mm_sound_proxy_set_volume_by_type(type_str, level);
834 int mm_sound_client_get_volume_by_type(volume_type_t type, unsigned int *level)
836 int ret = MM_ERROR_NONE;
840 debug_error("invalid argument, level is null");
841 return MM_ERROR_INVALID_ARGUMENT;
844 if (type >= VOLUME_TYPE_MAX) {
845 debug_error("invalid volume type %d", type);
846 return MM_ERROR_INVALID_ARGUMENT;
849 /* Get volume value from VCONF */
850 if (vconf_get_int(g_volume_vconf[type], &vconf_value)) {
851 debug_error("vconf_get_int(%s) failed..\n", g_volume_vconf[type]);
852 return MM_ERROR_SOUND_INTERNAL;
855 *level = vconf_value;
860 int mm_sound_client_set_volume_by_internal_type(volume_type_internal_t type, const unsigned int level)
862 int ret = MM_ERROR_NONE;
863 char *type_str = NULL;
867 if ((ret = __convert_volume_type_internal_to_str(type, &type_str)) != MM_ERROR_NONE) {
868 debug_error("volume type convert failed");
872 ret = mm_sound_proxy_set_volume_by_type(type_str, level);
879 int mm_sound_client_get_volume_by_internal_type(volume_type_internal_t type, unsigned int *level)
881 int ret = MM_ERROR_NONE;
885 debug_error("invalid argument, level is null");
886 return MM_ERROR_INVALID_ARGUMENT;
889 /* Get volume value from VCONF */
890 if (vconf_get_int(g_volume_vconf_internal[type], &vconf_value)) {
891 debug_error("vconf_get_int(%s) failed..\n", g_volume_vconf_internal[type]);
892 return MM_ERROR_SOUND_INTERNAL;
895 *level = vconf_value;
900 static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction, const char *volume_type_str,
901 int volume_level, void *userdata)
904 bool is_for_internal = false;
905 struct callback_data *cb_data = (struct callback_data *) userdata;
907 debug_log("direction : %s, volume_type : %s, volume_level : %d",
908 direction, volume_type_str, volume_level);
910 if (cb_data == NULL) {
911 debug_warning("volume changed callback data null");
915 if (__convert_volume_type_to_int(volume_type_str, &volume_type, &is_for_internal) != MM_ERROR_NONE) {
916 debug_error("volume type convert failed");
920 if (!is_for_internal && !cb_data->extra_data) {
921 debug_log("Invoke volume changed cb, direction : %s, vol_type : %s(%d), level : %u",
922 direction, volume_type_str, volume_type, volume_level);
923 ((mm_sound_volume_changed_cb)(cb_data->user_cb))((volume_type_t)volume_type, volume_level, cb_data->user_data);
924 } else if (is_for_internal && (cb_data->extra_data && (bool)(cb_data->extra_data))) {
925 debug_log("Invoke internal volume changed cb, direction : %s, vol_type : %s(%d), level : %u",
926 direction, volume_type_str, volume_type, volume_level);
927 ((mm_sound_volume_changed_cb_internal)(cb_data->user_cb))((volume_type_internal_t)volume_type, volume_level, cb_data->user_data);
931 int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* userdata, unsigned int *subs_id)
933 int ret = MM_ERROR_NONE;
934 struct callback_data *cb_data = NULL;
938 GET_CB_DATA(cb_data, func, userdata, NULL);
940 ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id);
947 int mm_sound_client_add_volume_changed_callback_internal(mm_sound_volume_changed_cb_internal func, void* userdata, unsigned int *subs_id)
949 int ret = MM_ERROR_NONE;
950 struct callback_data *cb_data = NULL;
951 gboolean is_for_internal = true;
955 GET_CB_DATA(cb_data, func, userdata, (void*)is_for_internal);
957 ret = mm_sound_proxy_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, g_free, subs_id);
964 int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id)
966 int ret = MM_ERROR_NONE;
969 ret = mm_sound_proxy_remove_volume_changed_callback(subs_id);
975 int mm_sound_client_set_mute_by_type(volume_type_t type, bool mute)
977 int ret = MM_ERROR_NONE;
978 char *type_str = NULL;
982 if (type > VOLUME_TYPE_VOICE) {
983 debug_error("invalid volume type %d", type);
984 return MM_ERROR_INVALID_ARGUMENT;
987 if ((ret = __convert_volume_type_to_str(type, &type_str)) != MM_ERROR_NONE) {
988 debug_error("volume type convert failed");
992 ret = mm_sound_proxy_set_mute_by_type(type_str, mute);
999 int mm_sound_client_get_mute_by_type(volume_type_t type, bool *muted)
1001 int ret = MM_ERROR_NONE;
1002 int vconf_value = 0;
1006 if (type > VOLUME_TYPE_VOICE) {
1007 debug_error("invalid volume type %d", type);
1008 return MM_ERROR_INVALID_ARGUMENT;
1011 /* Get mute state from VCONF */
1012 if (vconf_get_bool(g_mute_vconf[type], &vconf_value)) {
1013 debug_error("vconf_get_int(%s) failed..\n", g_mute_vconf[type]);
1014 return MM_ERROR_SOUND_INTERNAL;
1017 *muted = (bool)vconf_value;
1023 int mm_sound_client_set_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_parameters, const char *filter_group)
1025 int ret = MM_ERROR_NONE;
1028 ret = mm_sound_proxy_set_filter_by_type(stream_type, filter_name, filter_parameters, filter_group);
1034 int mm_sound_client_unset_filter_by_type(const char *stream_type)
1036 int ret = MM_ERROR_NONE;
1039 ret = mm_sound_proxy_unset_filter_by_type(stream_type);
1045 int mm_sound_client_control_filter_by_type(const char *stream_type, const char *filter_name, const char *filter_controls)
1047 int ret = MM_ERROR_NONE;
1050 ret = mm_sound_proxy_control_filter_by_type(stream_type, filter_name, filter_controls);
1056 int mm_sound_client_is_focus_cb_thread(GThread *mine, bool *result, bool *is_for_watching)
1058 int ret = MM_ERROR_NONE;
1061 if (!mine || !result)
1062 ret = MM_ERROR_INVALID_ARGUMENT;
1065 for (i = 0; i < FOCUS_HANDLE_MAX; i++) {
1066 if (!g_focus_sound_handle[i].is_used)
1068 if (g_focus_sound_handle[i].focus_cb_thread == mine) {
1070 if (is_for_watching)
1071 *is_for_watching = false;
1074 if (g_focus_sound_handle[i].focus_watch_cb_thread == mine) {
1076 if (is_for_watching)
1077 *is_for_watching = true;
1086 int mm_sound_client_register_focus(int pid, const char *stream_type,
1087 mm_sound_focus_changed_cb callback, void* user_data, int *id)
1089 int ret = MM_ERROR_NONE;
1093 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1095 if (focus_find_empty_index(&index)) {
1096 ret = MM_ERROR_SOUND_INTERNAL;
1100 g_focus_sound_handle[index].focus_pid = pid;
1101 g_focus_sound_handle[index].focus_callback = callback;
1102 g_focus_sound_handle[index].user_data = user_data;
1103 g_focus_sound_handle[index].auto_reacquire = true;
1105 ret = mm_sound_proxy_register_focus(index, stream_type, id);
1106 if (ret == MM_ERROR_NONE) {
1107 debug_msg("Success to register focus, client_fd[%d], id[%d]", g_focus_sound_handle[index].client_fd, *id);
1108 if (focus_init_context(index, false)) {
1109 ret = MM_ERROR_SOUND_INTERNAL;
1113 debug_error("Error occurred : 0x%x", ret);
1117 focus_init_callback(index, false);
1120 if (ret != MM_ERROR_NONE && index >= 0)
1121 g_focus_sound_handle[index].is_used = false;
1123 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1129 int mm_sound_client_unregister_focus(int id)
1131 int ret = MM_ERROR_NONE;
1135 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1137 index = focus_find_index_by_handle(id);
1139 debug_error("Could not find index");
1140 ret = MM_ERROR_INVALID_ARGUMENT;
1144 if (!g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) {
1145 debug_warning("maybe focus_callback is being called, try one more time..");
1146 usleep(2500000); /* 2.5 sec */
1147 if (g_mutex_trylock(&g_focus_sound_handle[index].focus_lock))
1148 debug_msg("finally got focus_lock");
1151 ret = mm_sound_proxy_unregister_focus(index);
1152 if (ret == MM_ERROR_NONE)
1153 debug_msg("Success to unregister focus");
1155 debug_error("Error occurred : 0x%x", ret);
1157 g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1159 focus_deinit_callback(index, false);
1160 g_focus_sound_handle[index].focus_fd = 0;
1161 g_focus_sound_handle[index].focus_pid = 0;
1162 g_focus_sound_handle[index].client_fd = 0;
1163 g_focus_sound_handle[index].handle = 0;
1164 g_focus_sound_handle[index].is_used = false;
1165 focus_deinit_context(index, false);
1168 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1173 int mm_sound_client_set_focus_reacquisition(int id, bool reacquisition)
1175 int ret = MM_ERROR_NONE;
1181 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1183 index = focus_find_index_by_handle(id);
1185 debug_error("Could not find index");
1186 ret = MM_ERROR_INVALID_ARGUMENT;
1190 ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), &result, NULL);
1192 debug_error("mm_sound_client_is_focus_cb_thread failed");
1194 } else if (!result) {
1195 ret = mm_sound_proxy_set_focus_reacquisition(index, reacquisition);
1196 if (ret == MM_ERROR_NONE) {
1197 debug_msg("Success to set focus reacquisition to [%d]", reacquisition);
1199 debug_error("Error occurred : 0x%x", ret);
1203 debug_warning("Inside the focus cb thread, set focus reacquisition to [%d]", reacquisition);
1206 g_focus_sound_handle[index].auto_reacquire = reacquisition;
1207 debug_msg("set focus reacquisition(%d) for id(%d)", reacquisition, id);
1210 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1215 int mm_sound_client_get_focus_reacquisition(int id, bool *reacquisition)
1217 int ret = MM_ERROR_NONE;
1222 if (!reacquisition) {
1223 debug_error("Invalid parameter");
1224 return MM_ERROR_INVALID_ARGUMENT;
1227 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1229 index = focus_find_index_by_handle(id);
1231 debug_error("Could not find index");
1232 ret = MM_ERROR_INVALID_ARGUMENT;
1236 *reacquisition = g_focus_sound_handle[index].auto_reacquire;
1237 debug_msg("get focus reacquisition(%d) for id(%d)", *reacquisition, id);
1240 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1245 int mm_sound_client_get_acquired_focus_stream_type(int focus_type, char **stream_type, int *option, char **ext_info)
1247 int ret = MM_ERROR_NONE;
1251 ret = mm_sound_proxy_get_acquired_focus_stream_type(focus_type, stream_type, option, ext_info);
1252 if (ret == MM_ERROR_NONE)
1253 debug_msg("Success to get stream type of acquired focus, stream_type(%s), ext_info(%s)",
1254 *stream_type, *ext_info);
1256 debug_error("Error occurred : 0x%x", ret);
1263 int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, int option, const char *ext_info)
1265 int ret = MM_ERROR_NONE;
1269 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1271 index = focus_find_index_by_handle(id);
1273 debug_error("Could not find index");
1274 ret = MM_ERROR_INVALID_ARGUMENT;
1278 ret = mm_sound_proxy_acquire_focus(index, type, option, ext_info);
1279 if (ret == MM_ERROR_NONE)
1280 debug_msg("Success to acquire focus");
1282 debug_error("Error occurred : 0x%x", ret);
1285 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1290 int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, int option, const char *ext_info)
1292 int ret = MM_ERROR_NONE;
1296 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1298 index = focus_find_index_by_handle(id);
1300 debug_error("Could not find index");
1301 ret = MM_ERROR_INVALID_ARGUMENT;
1305 ret = mm_sound_proxy_release_focus(index, type, option, ext_info);
1306 if (ret == MM_ERROR_NONE)
1307 debug_msg("Success to release focus");
1309 debug_error("Error occurred : 0x%x", ret);
1312 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1317 int mm_sound_client_update_stream_focus_status(int id, unsigned int status)
1319 int ret = MM_ERROR_NONE;
1322 if ((ret = mm_sound_proxy_update_stream_focus_status(id, status)) != MM_ERROR_NONE)
1323 debug_error("failed to update stream focus status, ret[0x%x]", ret);
1329 int mm_sound_client_deliver_focus(int src_id, int dst_id, mm_sound_focus_type_e focus_type)
1331 int ret = MM_ERROR_NONE;
1337 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1339 src_index = focus_find_index_by_handle(src_id);
1340 if (src_index == -1) {
1341 debug_error("Could not find src index");
1342 ret = MM_ERROR_INVALID_ARGUMENT;
1345 dst_index = focus_find_index_by_handle(dst_id);
1346 if (dst_index == -1) {
1347 debug_error("Could not find dst index");
1348 ret = MM_ERROR_INVALID_ARGUMENT;
1351 if (g_focus_sound_handle[src_index].focus_pid != g_focus_sound_handle[dst_index].focus_pid) {
1352 debug_error("pid[%d/%d] are not same for dst/src",
1353 g_focus_sound_handle[src_index].focus_pid,
1354 g_focus_sound_handle[dst_index].focus_pid);
1355 ret = MM_ERROR_SOUND_INTERNAL;
1359 if ((ret = mm_sound_proxy_deliver_focus(src_index, dst_index, focus_type)) != MM_ERROR_NONE)
1360 debug_error("failed to deliver focus, ret[0x%x]", ret);
1363 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1368 int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focus_type,
1369 mm_sound_focus_changed_watch_cb callback, void* user_data, int *id)
1371 int ret = MM_ERROR_NONE;
1377 return MM_ERROR_INVALID_ARGUMENT;
1379 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1381 if (focus_find_empty_index(&index)) {
1382 ret = MM_ERROR_SOUND_INTERNAL;
1386 g_focus_sound_handle[index].focus_pid = pid;
1387 g_focus_sound_handle[index].watch_callback = callback;
1388 g_focus_sound_handle[index].user_data = user_data;
1389 g_focus_sound_handle[index].unset_watch_callback_requested = false;
1391 ret = mm_sound_proxy_add_focus_watch_callback(index, focus_type);
1392 if (ret == MM_ERROR_NONE) {
1393 *id = g_focus_sound_handle[index].handle;
1394 debug_msg("Success to add watch focus cb, id(%d)", *id);
1395 if (focus_init_context(index, true)) {
1396 ret = MM_ERROR_SOUND_INTERNAL;
1400 debug_error("Error occurred : 0x%x", ret);
1404 focus_init_callback(index, true);
1407 if (ret != MM_ERROR_NONE && index >= 0)
1408 g_focus_sound_handle[index].is_used = false;
1410 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1415 int mm_sound_client_request_unset_focus_watch_callback(int id)
1417 int ret = MM_ERROR_NONE;
1421 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1423 index = focus_watch_find_index_by_handle(id);
1425 debug_error("Could not find index");
1426 ret = MM_ERROR_INVALID_ARGUMENT;
1429 g_focus_sound_handle[index].unset_watch_callback_requested = true;
1432 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1437 int mm_sound_client_unset_focus_watch_callback(int id)
1439 int ret = MM_ERROR_NONE;
1443 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_index_mutex, MM_ERROR_SOUND_INTERNAL);
1445 index = focus_watch_find_index_by_handle(id);
1447 debug_error("Could not find index");
1448 ret = MM_ERROR_INVALID_ARGUMENT;
1452 g_mutex_lock(&g_focus_sound_handle[index].focus_lock);
1454 g_focus_sound_handle[index].is_used = false;
1456 ret = mm_sound_proxy_remove_focus_watch_callback(index);
1457 if (ret == MM_ERROR_NONE)
1458 debug_msg("Success to remove watch focus cb, id(%d)", g_focus_sound_handle[index].handle);
1460 debug_error("Error occurred : 0x%x", ret);
1463 g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1465 focus_deinit_callback(index, true);
1466 g_focus_sound_handle[index].focus_fd = 0;
1467 g_focus_sound_handle[index].focus_pid = 0;
1468 g_focus_sound_handle[index].client_fd = 0;
1469 g_focus_sound_handle[index].handle = 0;
1470 focus_deinit_context(index, true);
1473 MMSOUND_LEAVE_CRITICAL_SECTION(&g_index_mutex);
1478 static gboolean _idle_event_callback(void *data)
1480 focus_idle_event_t *idle_event_data = (focus_idle_event_t*)data;
1481 int ret = MM_ERROR_NONE;
1484 debug_error("data is null");
1488 debug_msg("idle_event_data(%p): type(%d), data(%d)",
1489 idle_event_data, idle_event_data->type, idle_event_data->data);
1491 switch (idle_event_data->type) {
1492 case IDLE_EVENT_TYPE_UNSET_FOCUS_WATCH_CB:
1493 if ((ret = mm_sound_client_unset_focus_watch_callback(idle_event_data->data)))
1494 debug_error("Could not unset focus watch callback, id(%d), ret = %x", idle_event_data->data, ret);
1496 case IDLE_EVENT_TYPE_UNREGISTER_FOCUS:
1497 if ((ret = mm_sound_client_unregister_focus(idle_event_data->data)))
1498 debug_error("Could not unregister focus, id(%d), ret = %x", idle_event_data->data, ret);
1501 debug_warning("invalid type(%d)", idle_event_data->type);
1505 g_free(idle_event_data);
1507 g_idle_event_src = 0;
1509 MMSOUND_LEAVE_CRITICAL_SECTION(&g_event_mutex);
1514 int mm_sound_client_execute_focus_func_in_main_context(focus_idle_event_type_e type, int data)
1516 focus_idle_event_t *idle_event_data = NULL;
1518 if (IDLE_EVENT_TYPE_MAX < type)
1519 return MM_ERROR_INVALID_ARGUMENT;
1521 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_event_mutex, MM_ERROR_SOUND_INTERNAL);
1523 idle_event_data = g_new0(focus_idle_event_t, 1);
1524 idle_event_data->type = type;
1525 idle_event_data->data = data;
1527 g_idle_event_src = g_idle_add_full(G_PRIORITY_HIGH,
1528 (GSourceFunc)_idle_event_callback,
1529 (gpointer)idle_event_data,
1532 return MM_ERROR_NONE;
1535 int mm_sound_client_add_ducking_state_changed_callback(mm_sound_ducking_state_changed_cb func, void* userdata, unsigned int *subs_id)
1537 int ret = MM_ERROR_NONE;
1538 struct callback_data *cb_data = NULL;
1542 GET_CB_DATA(cb_data, func, userdata, NULL);
1544 ret = mm_sound_proxy_add_ducking_state_changed_callback((mm_sound_ducking_state_changed_wrapper_cb)func,
1545 cb_data, g_free, subs_id);
1552 int mm_sound_client_remove_ducking_state_changed_callback(unsigned int subs_id)
1554 int ret = MM_ERROR_NONE;
1557 ret = mm_sound_proxy_remove_ducking_state_changed_callback(subs_id);
1563 int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data, unsigned int *subs_id)
1565 int ret = MM_ERROR_NONE;
1569 ret = mm_sound_proxy_add_test_callback(func, user_data, g_free, subs_id);
1575 int mm_sound_client_remove_test_callback(unsigned int subs_id)
1577 int ret = MM_ERROR_NONE;
1580 ret = mm_sound_proxy_remove_test_callback(subs_id);
1586 int mm_sound_client_test(int a, int b, int* getv)
1588 int ret = MM_ERROR_NONE;
1592 ret = mm_sound_proxy_test(a, b, getv);
1593 debug_log("%d * %d -> result : %d", a, b, *getv);