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.
25 #include <sys/types.h>
37 #include <semaphore.h>
43 #include "include/mm_sound.h"
44 #include "include/mm_sound_msg.h"
45 #include "include/mm_sound_client.h"
46 #include "include/mm_sound_client_dbus.h"
47 #include "include/mm_sound_common.h"
48 #include "include/mm_sound_device.h"
50 #include "include/mm_sound_focus.h"
53 #include <mm_session.h>
54 #include <mm_session_private.h>
56 #define __DIRECT_CALLBACK__
57 //#define __GIDLE_CALLBACK__
60 #if defined(__GSOURCE_CALLBACK__)
64 #define CLIENT_HANDLE_MAX 256
66 #define FOCUS_HANDLE_MAX 512
67 #define FOCUS_HANDLE_INIT_VAL -1
68 #define CONFIG_ENABLE_RETCB
70 #define VOLUME_TYPE_LEN 64
72 struct sigaction FOCUS_int_old_action;
73 struct sigaction FOCUS_abrt_old_action;
74 struct sigaction FOCUS_segv_old_action;
75 struct sigaction FOCUS_term_old_action;
76 struct sigaction FOCUS_sys_old_action;
77 struct sigaction FOCUS_xcpu_old_action;
90 GSourceFuncs* g_src_funcs;
96 mm_sound_focus_changed_cb focus_callback;
97 mm_sound_focus_changed_watch_cb watch_callback;
106 char stream_type [MAX_STREAM_TYPE_LEN];
107 char name [MM_SOUND_NAME_NUM];
111 mm_sound_focus_session_interrupt_cb user_cb;
113 } focus_session_interrupt_info_t;
115 typedef gboolean (*focus_gLoopPollHandler_t)(gpointer d);
117 GThread *g_focus_thread;
118 GMainLoop *g_focus_loop;
119 focus_sound_info_t g_focus_sound_handle[FOCUS_HANDLE_MAX];
120 focus_session_interrupt_info_t g_focus_session_interrupt_info = {NULL, NULL};
122 /* global variables for device list */
123 //static GList *g_device_list = NULL;
124 static mm_sound_device_list_t g_device_list_t;
125 static pthread_mutex_t g_device_list_mutex = PTHREAD_MUTEX_INITIALIZER;
126 static pthread_mutex_t g_id_mutex = PTHREAD_MUTEX_INITIALIZER;
128 guint g_focus_signal_handle = 0;
130 void _focus_signal_handler(int signo)
132 int ret = MM_ERROR_NONE;
135 sigset_t old_mask, all_mask;
137 debug_error("Got signal : signo(%d)", signo);
141 sigfillset(&all_mask);
142 sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
146 /* need implementation */
147 //send exit pid to focus server and focus server will clear focus or watch if necessary.
149 for (index = 0; index < FOCUS_HANDLE_MAX; index++) {
150 if (g_focus_sound_handle[index].is_used == true && g_focus_sound_handle[index].focus_tid == exit_pid) {
151 ret = mm_sound_client_dbus_emergent_exit_focus(exit_pid);
156 if (ret == MM_ERROR_NONE)
157 debug_msg("[Client] Success to emergnet_exit_focus\n");
159 debug_error("[Client] Error occurred : %d \n",ret);
161 sigprocmask(SIG_SETMASK, &old_mask, NULL);
166 sigaction(SIGINT, &FOCUS_int_old_action, NULL);
170 sigaction(SIGABRT, &FOCUS_abrt_old_action, NULL);
174 sigaction(SIGSEGV, &FOCUS_segv_old_action, NULL);
178 sigaction(SIGTERM, &FOCUS_term_old_action, NULL);
182 sigaction(SIGSYS, &FOCUS_sys_old_action, NULL);
186 sigaction(SIGXCPU, &FOCUS_xcpu_old_action, NULL);
193 debug_error("signal handling end");
196 int mm_sound_client_initialize(void)
198 int ret = MM_ERROR_NONE;
201 mm_sound_client_dbus_initialize();
205 struct sigaction FOCUS_action;
206 FOCUS_action.sa_handler = _focus_signal_handler;
207 FOCUS_action.sa_flags = SA_NOCLDSTOP;
209 sigemptyset(&FOCUS_action.sa_mask);
211 sigaction(SIGINT, &FOCUS_action, &FOCUS_int_old_action);
212 sigaction(SIGABRT, &FOCUS_action, &FOCUS_abrt_old_action);
213 sigaction(SIGSEGV, &FOCUS_action, &FOCUS_segv_old_action);
214 sigaction(SIGTERM, &FOCUS_action, &FOCUS_term_old_action);
215 sigaction(SIGSYS, &FOCUS_action, &FOCUS_sys_old_action);
216 sigaction(SIGXCPU, &FOCUS_action, &FOCUS_xcpu_old_action);
225 int mm_sound_client_finalize(void)
227 int ret = MM_ERROR_NONE;
231 ret = mm_sound_client_dbus_finalize();
240 for (index = 0; index < FOCUS_HANDLE_MAX; index++) {
241 if (g_focus_sound_handle[index].is_used == true && g_focus_sound_handle[index].focus_tid == exit_pid) {
242 mm_sound_client_dbus_emergent_exit_focus(exit_pid);
246 if (g_focus_thread) {
247 g_main_loop_quit(g_focus_loop);
248 g_thread_join(g_focus_thread);
249 debug_log("after thread join");
250 g_main_loop_unref(g_focus_loop);
251 g_focus_thread = NULL;
254 /* is it necessary? */
255 sigaction(SIGINT, &FOCUS_int_old_action, NULL);
256 sigaction(SIGABRT, &FOCUS_abrt_old_action, NULL);
257 sigaction(SIGSEGV, &FOCUS_segv_old_action, NULL);
258 sigaction(SIGTERM, &FOCUS_term_old_action, NULL);
259 sigaction(SIGSYS, &FOCUS_sys_old_action, NULL);
260 sigaction(SIGXCPU, &FOCUS_xcpu_old_action, NULL);
268 int mm_sound_client_is_route_available(mm_sound_route route, bool *is_available)
270 int ret = MM_ERROR_NONE;
273 ret = mm_sound_client_dbus_is_route_available(route, is_available);
280 int mm_sound_client_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
282 int ret = MM_ERROR_NONE;
285 ret = mm_sound_client_dbus_foreach_available_route_cb(available_route_cb, user_data);
291 int mm_sound_client_set_active_route(mm_sound_route route, bool need_broadcast)
293 int ret = MM_ERROR_NONE;
296 ret = mm_sound_client_dbus_set_active_route(route, need_broadcast);
303 int mm_sound_client_set_active_route_auto(void)
305 int ret = MM_ERROR_NONE;
308 ret = mm_sound_client_dbus_set_active_route_auto();
315 int mm_sound_client_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
318 int ret = MM_ERROR_NONE;
321 ret = mm_sound_client_dbus_get_active_device(device_in, device_out);
327 int mm_sound_client_add_active_device_changed_callback(const char *name, mm_sound_active_device_changed_cb func, void* user_data)
329 int ret = MM_ERROR_NONE;
332 ret = mm_sound_client_dbus_add_active_device_changed_callback(name, func, user_data);
338 int mm_sound_client_remove_active_device_changed_callback(const char *name)
340 int ret = MM_ERROR_NONE;
343 ret = mm_sound_client_dbus_remove_active_device_changed_callback(name);
348 int mm_sound_client_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void* user_data)
350 int ret = MM_ERROR_NONE;
353 ret = mm_sound_client_dbus_add_available_route_changed_callback(func, user_data);
359 int mm_sound_client_remove_available_route_changed_callback(void)
361 int ret = MM_ERROR_NONE;
364 ret = mm_sound_client_dbus_remove_available_route_changed_callback();
370 int mm_sound_client_set_sound_path_for_active_device(mm_sound_device_out device_out, mm_sound_device_in device_in)
372 int ret = MM_ERROR_NONE;
375 ret = mm_sound_client_dbus_set_sound_path_for_active_device(device_out, device_in);
381 void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_type)
383 switch (volume_type) {
384 case VOLUME_TYPE_SYSTEM:
385 strncpy(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN);
387 case VOLUME_TYPE_NOTIFICATION:
388 strncpy(stream_type, "notification", MM_SOUND_STREAM_TYPE_LEN);
390 case VOLUME_TYPE_ALARM:
391 strncpy(stream_type, "alarm", MM_SOUND_STREAM_TYPE_LEN);
393 case VOLUME_TYPE_RINGTONE:
394 strncpy(stream_type, "ringtone-voip", MM_SOUND_STREAM_TYPE_LEN);
396 case VOLUME_TYPE_MEDIA:
397 strncpy(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN);
399 case VOLUME_TYPE_CALL:
400 strncpy(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN);
402 case VOLUME_TYPE_VOIP:
403 strncpy(stream_type, "voip", MM_SOUND_STREAM_TYPE_LEN);
405 case VOLUME_TYPE_VOICE:
406 strncpy(stream_type, "voice-recognition", MM_SOUND_STREAM_TYPE_LEN);
409 strncpy(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN);
413 debug_error("volume type (%d) converted to stream type (%s)", volume_type, stream_type);
417 /*****************************************************************************************
418 DBUS SUPPORTED FUNCTIONS
419 ******************************************************************************************/
421 void _mm_sound_client_focus_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data)
423 int ret = MM_ERROR_NONE;
426 debug_error("focus signal received, value = %d", value);
429 ret = mm_sound_client_dbus_clear_focus(getpid());
431 debug_error("clear focus failed ret = 0x%x", ret);
432 mm_sound_unsubscribe_signal(g_focus_signal_handle);
433 g_focus_signal_handle = 0;
437 int mm_sound_client_play_tone(int number, int volume_config, double volume, int time, int *handle, bool enable_session)
439 int ret = MM_ERROR_NONE;
440 // int instance = -1; /* instance is unique to communicate with server : client message queue filter type */
441 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
442 char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, };
446 /* read session information */
447 int session_type = MM_SESSION_TYPE_MEDIA;
448 int session_options = 0;
449 int is_focus_registered = 0;
451 ret = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &is_focus_registered);
453 debug_error("mm_sound_get_signal_value failed [0x%x]", ret);
454 return MM_ERROR_POLICY_INTERNAL;
457 if (is_focus_registered)
458 enable_session = false;
462 if (MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options))
464 debug_warning("[Client] Read Session Information failed. use default \"media\" type\n");
465 session_type = MM_SESSION_TYPE_MEDIA;
467 if(MM_ERROR_NONE != mm_session_init(session_type))
469 debug_critical("[Client] MMSessionInit() failed\n");
470 return MM_ERROR_POLICY_INTERNAL;
475 // instance = getpid();
476 //debug_log("[Client] pid for client ::: [%d]\n", instance);
479 debug_msg("[Client] Input number : %d\n", number);
480 /* Send req memory */
482 mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type);
483 ret = mm_sound_client_dbus_play_tone(number, time, volume, volume_config,
484 session_type, session_options, getpid(), enable_session, handle, stream_type, -1);
486 if (enable_session && !g_focus_signal_handle) {
487 ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL);
489 debug_error("mm_sound_subscribe_signal failed [0x%x]", ret);
490 return MM_ERROR_POLICY_INTERNAL;
498 int mm_sound_client_play_tone_with_stream_info(int tone, char *stream_type, int stream_id, double volume, int duration, int *handle)
500 int ret = MM_ERROR_NONE;
504 ret = mm_sound_client_dbus_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle);
510 void _mm_sound_stop_callback_wrapper_func(int ended_handle, void *userdata)
512 client_cb_data_t *cb_data = (client_cb_data_t*) userdata;
514 debug_log("[Wrapper CB][Play Stop] ended_handle : %d", ended_handle);
516 if (cb_data == NULL) {
517 debug_warning("stop callback data null");
520 if (ended_handle == cb_data->mask) {
521 debug_log("Interested playing handle end : %d", ended_handle);
522 ((mm_sound_stop_callback_func)(cb_data->user_cb))(cb_data->user_data, ended_handle);
523 if (mm_sound_client_dbus_remove_play_sound_end_callback(cb_data->subs_id) != MM_ERROR_NONE)
524 debug_error("mm_sound_client_dbus_remove_play_file_end_callback failed");
526 debug_log("Not interested playing handle : %d", ended_handle);
530 int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle)
532 int ret = MM_ERROR_NONE;
533 int session_type = MM_SESSION_TYPE_MEDIA;
534 int session_options = 0;
535 int is_focus_registered = 0;
536 // int instance = -1; /* instance is unique to communicate with server : client message queue filter type */
537 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
538 char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, };
539 client_cb_data_t *cb_data = NULL;
543 /* read session information */
545 ret = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &is_focus_registered);
547 debug_error("mm_sound_get_signal_value failed [0x%x]", ret);
548 return MM_ERROR_POLICY_INTERNAL;
551 if (is_focus_registered)
552 param->skip_session = true;
554 if (param->skip_session == false) {
555 if(MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options))
557 debug_warning("[Client] Read MMSession Type failed. use default \"media\" type\n");
558 session_type = MM_SESSION_TYPE_MEDIA;
560 if(MM_ERROR_NONE != mm_session_init(session_type))
562 debug_critical("[Client] MMSessionInit() failed\n");
563 return MM_ERROR_POLICY_INTERNAL;
568 // instance = getpid();
569 // debug_msg("[Client] pid for client ::: [%d]\n", instance);
572 if ((param->mem_ptr && param->mem_size))
574 // Play memory, deprecated
575 return MM_ERROR_INVALID_ARGUMENT;
578 mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type);
579 ret = mm_sound_client_dbus_play_sound(param->filename, tone, param->loop, param->volume, param->volume_config,
580 param->priority, session_type, session_options, getpid(), param->handle_route,
581 !param->skip_session, handle, stream_type, -1);
582 if (ret != MM_ERROR_NONE) {
583 debug_error("Play Sound Failed");
586 if (param->callback) {
587 cb_data = g_malloc0(sizeof(client_cb_data_t));
588 cb_data->user_cb = param->callback;
589 cb_data->user_data = param->data;
590 cb_data->mask = *handle;
592 ret = mm_sound_client_dbus_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data, &cb_data->subs_id);
593 if (ret != MM_ERROR_NONE) {
594 debug_error("Add callback for play sound(%d) Failed", *handle);
597 if (!param->skip_session && !g_focus_signal_handle) {
598 ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL);
600 debug_error("mm_sound_subscribe_signal failed [0x%x]", ret);
601 return MM_ERROR_POLICY_INTERNAL;
611 int mm_sound_client_play_sound_with_stream_info(MMSoundPlayParam *param, int *handle, char* stream_type, int stream_id)
613 int ret = MM_ERROR_NONE;
614 client_cb_data_t *cb_data = NULL;
616 ret = mm_sound_client_dbus_play_sound_with_stream_info(param->filename, param->loop, param->volume,
617 param->priority, getpid(), param->handle_route, handle, stream_type, stream_id);
618 if (ret != MM_ERROR_NONE) {
619 debug_error("Play Sound Failed");
622 if (param->callback) {
623 cb_data = g_malloc0(sizeof(client_cb_data_t));
624 cb_data->user_cb = param->callback;
625 cb_data->user_data = param->data;
626 cb_data->mask = *handle;
628 ret = mm_sound_client_dbus_add_play_sound_end_callback(_mm_sound_stop_callback_wrapper_func, cb_data, &cb_data->subs_id);
629 if (ret != MM_ERROR_NONE) {
630 debug_error("Add callback for play sound(%d) Failed", *handle);
641 int mm_sound_client_stop_sound(int handle)
643 int ret = MM_ERROR_NONE;
646 if (handle < 0 || handle > CLIENT_HANDLE_MAX) {
647 ret = MM_ERROR_INVALID_ARGUMENT;
651 ret = mm_sound_client_dbus_stop_sound(handle);
657 static int _mm_sound_client_device_list_clear ()
659 int ret = MM_ERROR_NONE;
661 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_list_mutex, MM_ERROR_SOUND_INTERNAL);
663 if (g_device_list_t.list) {
664 g_list_free_full(g_device_list_t.list, g_free);
665 g_device_list_t.list = NULL;
668 MMSOUND_LEAVE_CRITICAL_SECTION(&g_device_list_mutex);
673 static int _mm_sound_client_device_list_dump (GList *device_list)
675 int ret = MM_ERROR_NONE;
677 mm_sound_device_t *device_node = NULL;
680 debug_error("Device list NULL, cannot dump list");
681 return MM_ERROR_SOUND_INTERNAL;
684 debug_log("======================== device list : start ==========================\n");
685 for (list = device_list; list != NULL; list = list->next) {
686 device_node = (mm_sound_device_t *)list->data;
688 debug_log(" list idx[%d]: type[%17s], id[%02d], io_direction[%d], state[%d], name[%s]\n",
689 count++, device_node->type, device_node->id, device_node->io_direction, device_node->state, device_node->name);
692 debug_log("======================== device list : end ============================\n");
697 int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t **device_list)
699 int ret = MM_ERROR_NONE;
702 ret = _mm_sound_client_device_list_clear();
704 debug_error("[Client] failed to __mm_sound_client_device_list_clear(), ret[0x%x]\n", ret);
708 if ((ret = mm_sound_client_dbus_get_current_connected_device_list(device_flags, &g_device_list_t.list)) != MM_ERROR_NONE) {
709 debug_error("[Client] failed to get current connected device list with dbus, ret[0x%x]", ret);
712 if (!g_device_list_t.list) {
713 debug_error("Got device list null");
714 ret = MM_ERROR_SOUND_NO_DATA;
717 // g_device_list_t.list = g_device_list;
718 _mm_sound_client_device_list_dump(g_device_list_t.list);
719 *device_list = &g_device_list_t;
726 void _mm_sound_device_connected_callback_wrapper_func(int device_id, const char *device_type, int io_direction, int state, const char *name, gboolean is_connected, void *userdata)
728 mm_sound_device_t device_h;
729 client_cb_data_t *cb_data = (client_cb_data_t*) userdata;
731 debug_log("[Wrapper CB][Device Connnected] device_id : %d, device_type : %s, direction : %d, state : %d, name : %s, is_connected : %d",
732 device_id, device_type, io_direction, state, name, is_connected);
734 if (cb_data == NULL) {
735 debug_warning("device connected changed callback data null");
739 device_h.id = device_id;
740 device_h.io_direction = io_direction;
741 device_h.state = state;
742 MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM);
743 MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN);
745 ((mm_sound_device_connected_cb)(cb_data->user_cb))(&device_h, is_connected, cb_data->user_data);
748 int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func, void* user_data, unsigned int *subs_id)
750 int ret = MM_ERROR_NONE;
751 client_cb_data_t *cb_data = NULL;
755 cb_data = g_malloc0(sizeof(client_cb_data_t));
756 cb_data->user_cb = func;
757 cb_data->user_data = user_data;
759 ret = mm_sound_client_dbus_add_device_connected_callback(device_flags, _mm_sound_device_connected_callback_wrapper_func, cb_data, subs_id);
765 int mm_sound_client_remove_device_connected_callback(unsigned int subs_id)
767 int ret = MM_ERROR_NONE;
770 ret = mm_sound_client_dbus_remove_device_connected_callback(subs_id);
776 static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction, int state, const char *name, int changed_device_info_type, void *userdata)
778 mm_sound_device_t device_h;
779 client_cb_data_t *cb_data = (client_cb_data_t*) userdata;
781 debug_log("[Wrapper CB][Device Info Changed] device_id : %d, device_type : %s, direction : %d, state : %d, name : %s, changed_info_type : %d",
782 device_id, device_type, io_direction, state, name, changed_device_info_type);
784 if (cb_data == NULL) {
785 debug_warning("device info changed callback data null");
789 device_h.id = device_id;
790 device_h.io_direction = io_direction;
791 device_h.state = state;
792 MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM);
793 MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN);
795 ((mm_sound_device_info_changed_cb)(cb_data->user_cb))(&device_h, changed_device_info_type, cb_data->user_data);
798 int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func, void *userdata, unsigned int *subs_id)
800 int ret = MM_ERROR_NONE;
801 client_cb_data_t *cb_data = (client_cb_data_t*) userdata;
805 cb_data = g_malloc0(sizeof(client_cb_data_t));
806 cb_data->user_cb = func;
807 cb_data->user_data = userdata;
809 ret = mm_sound_client_dbus_add_device_info_changed_callback(device_flags, _mm_sound_device_info_changed_callback_wrapper_func, cb_data, subs_id);
815 int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id)
817 int ret = MM_ERROR_NONE;
820 ret = mm_sound_client_dbus_remove_device_info_changed_callback(subs_id);
826 int mm_sound_client_is_bt_a2dp_on (bool *connected, char** bt_name)
828 int ret = MM_ERROR_NONE;
832 ret = mm_sound_client_dbus_is_bt_a2dp_on(connected, bt_name);
838 int __convert_volume_type_to_str(int volume_type, char **volume_type_str)
840 int ret = MM_ERROR_NONE;
842 if (!volume_type_str) {
843 return MM_ERROR_COMMON_INVALID_ARGUMENT;
846 switch (volume_type) {
847 case VOLUME_TYPE_SYSTEM:
848 *volume_type_str = "system";
850 case VOLUME_TYPE_NOTIFICATION:
851 *volume_type_str = "notification";
853 case VOLUME_TYPE_ALARM:
854 *volume_type_str = "alarm";
856 case VOLUME_TYPE_RINGTONE:
857 *volume_type_str = "ringtone";
859 case VOLUME_TYPE_MEDIA:
860 *volume_type_str = "media";
862 case VOLUME_TYPE_CALL:
863 *volume_type_str = "call";
865 case VOLUME_TYPE_VOIP:
866 *volume_type_str = "voip";
868 case VOLUME_TYPE_VOICE:
869 *volume_type_str = "voice";
872 if (!strncmp(*volume_type_str,"", VOLUME_TYPE_LEN)) {
873 debug_error("could not find the volume_type[%d] in this switch case statement", volume_type);
874 ret = MM_ERROR_SOUND_INTERNAL;
876 debug_log("volume_type[%s]", *volume_type_str);
881 static int __convert_volume_type_to_int(const char *volume_type_str, volume_type_t *volume_type)
883 int ret = MM_ERROR_NONE;
885 if (!volume_type || !volume_type_str) {
886 return MM_ERROR_COMMON_INVALID_ARGUMENT;
889 if (!strncmp(volume_type_str, "system", VOLUME_TYPE_LEN)) {
890 *volume_type = VOLUME_TYPE_SYSTEM;
891 } else if (!strncmp(volume_type_str, "notification", VOLUME_TYPE_LEN)) {
892 *volume_type = VOLUME_TYPE_NOTIFICATION;
893 } else if (!strncmp(volume_type_str, "alarm", VOLUME_TYPE_LEN)) {
894 *volume_type = VOLUME_TYPE_ALARM;
895 } else if (!strncmp(volume_type_str, "ringtone", VOLUME_TYPE_LEN)) {
896 *volume_type = VOLUME_TYPE_RINGTONE;
897 } else if (!strncmp(volume_type_str, "media", VOLUME_TYPE_LEN)) {
898 *volume_type = VOLUME_TYPE_MEDIA;
899 } else if (!strncmp(volume_type_str, "call", VOLUME_TYPE_LEN)) {
900 *volume_type = VOLUME_TYPE_CALL;
901 } else if (!strncmp(volume_type_str, "voip", VOLUME_TYPE_LEN)) {
902 *volume_type = VOLUME_TYPE_VOIP;
903 } else if (!strncmp(volume_type_str, "voice", VOLUME_TYPE_LEN)) {
904 *volume_type = VOLUME_TYPE_VOICE;
906 debug_log("Invalid volume type : [%s]", volume_type_str);
907 ret = MM_ERROR_SOUND_INTERNAL;
913 int mm_sound_client_set_volume_by_type(const int volume_type, const unsigned int volume_level)
915 int ret = MM_ERROR_NONE;
916 char *type_str = NULL;
919 if ((ret = __convert_volume_type_to_str(volume_type, &type_str)) != MM_ERROR_NONE) {
920 debug_error("volume type convert failed");
924 ret = mm_sound_client_dbus_set_volume_by_type(type_str, volume_level);
931 static void _mm_sound_volume_changed_callback_wrapper_func(const char *direction, const char *volume_type_str, int volume_level, void *userdata)
933 volume_type_t volume_type = 0;
934 client_cb_data_t *cb_data = (client_cb_data_t*) userdata;
936 debug_log("[Wrapper CB][Volume Changed] direction : %s, volume_type : %s, volume_level : %d", direction, volume_type_str, volume_level);
938 if (cb_data == NULL) {
939 debug_warning("volume changed callback data null");
943 if (__convert_volume_type_to_int(volume_type_str, &volume_type) != MM_ERROR_NONE) {
944 debug_error("volume type convert failed");
947 debug_log("Call volume changed user cb, direction : %s, vol_type : %s(%d), level : %u", direction, volume_type_str, volume_type, volume_level);
948 ((mm_sound_volume_changed_cb)(cb_data->user_cb))(volume_type, volume_level, cb_data->user_data);
951 int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* user_data, unsigned int *subs_id)
953 int ret = MM_ERROR_NONE;
954 client_cb_data_t *cb_data = NULL;
958 cb_data = g_malloc0(sizeof(client_cb_data_t));
959 cb_data->user_cb = func;
960 cb_data->user_data = user_data;
962 ret = mm_sound_client_dbus_add_volume_changed_callback(_mm_sound_volume_changed_callback_wrapper_func, cb_data, subs_id);
969 int mm_sound_client_remove_volume_changed_callback(unsigned int subs_id)
971 int ret = MM_ERROR_NONE;
974 ret = mm_sound_client_dbus_remove_volume_changed_callback(subs_id);
981 int mm_sound_client_get_audio_path(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
983 int ret = MM_ERROR_NONE;
987 ret = mm_sound_client_dbus_get_audio_path(device_in, device_out);
996 int mm_sound_client_set_session_interrupt_callback(mm_sound_focus_session_interrupt_cb callback, void* user_data)
998 int ret = MM_ERROR_NONE;
1003 return MM_ERROR_INVALID_ARGUMENT;
1005 g_focus_session_interrupt_info.user_cb = callback;
1006 g_focus_session_interrupt_info.user_data = user_data;
1012 int mm_sound_client_unset_session_interrupt_callback(void)
1014 int ret = MM_ERROR_NONE;
1018 if (!g_focus_session_interrupt_info.user_cb) {
1019 debug_error("no callback to unset");
1020 return MM_ERROR_SOUND_INTERNAL;
1023 g_focus_session_interrupt_info.user_cb = NULL;
1024 g_focus_session_interrupt_info.user_data = NULL;
1030 int mm_sound_client_get_uniq_id(int *id)
1032 static int uniq_id = 0;
1033 int ret = MM_ERROR_NONE;
1035 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_id_mutex, MM_ERROR_SOUND_INTERNAL);
1039 ret = MM_ERROR_INVALID_ARGUMENT;
1044 MMSOUND_LEAVE_CRITICAL_SECTION(&g_id_mutex);
1049 static gpointer _focus_thread_func(gpointer data)
1051 debug_log(">>> thread func..ID of this thread(%u)\n", (unsigned int)pthread_self());
1052 g_main_loop_run(g_focus_loop);
1053 debug_log("<<< quit thread func..\n");
1057 static gboolean _focus_fd_check(GSource * source)
1063 debug_error("GSource is null");
1066 fd_list = source->poll_fds;
1068 debug_error("fd_list is null");
1072 temp = (GPollFD*)fd_list->data;
1074 debug_error("fd_list->data is null");
1077 if (temp->revents & (POLLIN | POLLPRI)) {
1080 fd_list = fd_list->next;
1083 return FALSE; /* there is no change in any fd state */
1086 static gboolean _focus_fd_prepare(GSource *source, gint *timeout)
1091 static gboolean _focus_fd_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
1093 callback(user_data);
1098 static int _focus_find_index_by_handle(int handle)
1101 for(i = 0; i< FOCUS_HANDLE_MAX; i++) {
1102 if (handle == g_focus_sound_handle[i].handle) {
1103 //debug_msg("found index(%d) for handle(%d)", i, handle);
1104 if (handle == FOCUS_HANDLE_INIT_VAL) {
1113 static gboolean _focus_callback_handler(gpointer d)
1115 GPollFD *data = (GPollFD*)d;
1118 int focus_index = 0;
1119 focus_cb_data_lib cb_data;
1120 debug_log(">>> focus_callback_handler()..ID of this thread(%u)\n", (unsigned int)pthread_self());
1122 memset(&cb_data, 0, sizeof(focus_cb_data_lib));
1125 debug_error("GPollFd is null");
1128 if (data->revents & (POLLIN | POLLPRI)) {
1129 int changed_state = -1;
1131 count = read(data->fd, &cb_data, sizeof(cb_data));
1133 char str_error[256];
1134 strerror_r(errno, str_error, sizeof(str_error));
1135 debug_error("GpollFD read fail, errno=%d(%s)",errno, str_error);
1138 changed_state = cb_data.state;
1139 focus_index = _focus_find_index_by_handle(cb_data.handle);
1140 if (focus_index == -1) {
1141 debug_error("Can not find index");
1145 g_mutex_lock(&g_focus_sound_handle[focus_index].focus_lock);
1147 tid = g_focus_sound_handle[focus_index].focus_tid;
1149 if (changed_state != -1) {
1150 debug_error("Got and start CB : TID(%d), handle(%d), type(%d), state(%d,(DEACTIVATED(0)/ACTIVATED(1)), trigger(%s)", tid, cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type);
1151 if (g_focus_sound_handle[focus_index].focus_callback== NULL) {
1152 debug_error("callback is null..");
1153 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1156 debug_error("[CALLBACK(%p) START]",g_focus_sound_handle[focus_index].focus_callback);
1157 (g_focus_sound_handle[focus_index].focus_callback)(cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type, cb_data.name, g_focus_sound_handle[focus_index].user_data);
1158 debug_error("[CALLBACK END]");
1159 if (g_focus_session_interrupt_info.user_cb) {
1160 debug_error("sending session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb);
1161 (g_focus_session_interrupt_info.user_cb)(cb_data.state, cb_data.stream_type, false, g_focus_session_interrupt_info.user_data);
1164 #ifdef CONFIG_ENABLE_RETCB
1169 char *filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[focus_index].focus_tid, cb_data.handle);
1170 tmpfd = open(filename2, O_WRONLY | O_NONBLOCK);
1172 char str_error[256];
1173 strerror_r(errno, str_error, sizeof(str_error));
1174 debug_error("[RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error);
1176 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1179 buf = cb_data.handle;
1180 rett = write(tmpfd, &buf, sizeof(buf));
1183 debug_msg("[RETCB] tid(%d) finishing CB (write=%d)\n", tid, rett);
1187 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1192 static gboolean _focus_watch_callback_handler( gpointer d)
1194 GPollFD *data = (GPollFD*)d;
1197 int focus_index = 0;
1198 focus_cb_data_lib cb_data;
1202 memset(&cb_data, 0, sizeof(focus_cb_data_lib));
1205 debug_error("GPollFd is null");
1208 if (data->revents & (POLLIN | POLLPRI)) {
1209 count = read(data->fd, &cb_data, sizeof(cb_data));
1211 char str_error[256];
1212 strerror_r(errno, str_error, sizeof(str_error));
1213 debug_error("GpollFD read fail, errno=%d(%s)",errno, str_error);
1217 focus_index = cb_data.handle - 1;
1218 if (focus_index < 0) {
1219 debug_error("index is not valid, %d", focus_index);
1223 debug_error("lock focus_lock = %p", &g_focus_sound_handle[focus_index].focus_lock);
1224 g_mutex_lock(&g_focus_sound_handle[focus_index].focus_lock);
1226 tid = g_focus_sound_handle[focus_index].focus_tid;
1228 debug_error("Got and start CB : TID(%d), handle(%d), type(%d), state(%d,(DEACTIVATED(0)/ACTIVATED(1)), trigger(%s)", tid, cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type);
1230 if (g_focus_sound_handle[focus_index].watch_callback == NULL) {
1231 debug_msg("callback is null..");
1232 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1236 debug_msg("[CALLBACK(%p) START]",g_focus_sound_handle[focus_index].watch_callback);
1237 (g_focus_sound_handle[focus_index].watch_callback)(cb_data.handle, cb_data.type, cb_data.state, cb_data.stream_type, cb_data.name, g_focus_sound_handle[focus_index].user_data);
1238 debug_msg("[CALLBACK END]");
1239 if (g_focus_session_interrupt_info.user_cb) {
1240 debug_error("sending session interrupt callback(%p)", g_focus_session_interrupt_info.user_cb);
1241 (g_focus_session_interrupt_info.user_cb)(cb_data.state, cb_data.stream_type, true, g_focus_session_interrupt_info.user_data);
1244 #ifdef CONFIG_ENABLE_RETCB
1249 char *filename2 = g_strdup_printf("/tmp/FOCUS.%d.wchr", g_focus_sound_handle[focus_index].focus_tid);
1250 tmpfd = open(filename2, O_WRONLY | O_NONBLOCK);
1252 char str_error[256];
1253 strerror_r(errno, str_error, sizeof(str_error));
1254 debug_error("[RETCB][Failed(May Server Close First)]tid(%d) fd(%d) %s errno=%d(%s)\n", tid, tmpfd, filename2, errno, str_error);
1256 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1259 buf = cb_data.handle;
1260 rett = write(tmpfd, &buf, sizeof(buf));
1263 debug_msg("[RETCB] tid(%d) finishing CB (write=%d)\n", tid, rett);
1269 debug_error("unlock focus_lock = %p", &g_focus_sound_handle[focus_index].focus_lock);
1270 g_mutex_unlock(&g_focus_sound_handle[focus_index].focus_lock);
1278 static void _focus_open_callback(int index, bool is_for_watching)
1285 if (is_for_watching) {
1286 filename = g_strdup_printf("/tmp/FOCUS.%d.wch", g_focus_sound_handle[index].focus_tid);
1288 filename = g_strdup_printf("/tmp/FOCUS.%d.%d", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1290 pre_mask = umask(0);
1291 if (mknod(filename, S_IFIFO|0666, 0)) {
1292 debug_error("mknod() failure, errno(%d)", errno);
1295 g_focus_sound_handle[index].focus_fd = open( filename, O_RDWR|O_NONBLOCK);
1296 if (g_focus_sound_handle[index].focus_fd == -1) {
1297 debug_error("Open fail : index(%d), file open error(%d)", index, errno);
1299 debug_log("Open sucess : index(%d), filename(%s), fd(%d)", index, filename, g_focus_sound_handle[index].focus_fd);
1304 #ifdef CONFIG_ENABLE_RETCB
1307 if (is_for_watching) {
1308 filename2 = g_strdup_printf("/tmp/FOCUS.%d.wchr", g_focus_sound_handle[index].focus_tid);
1310 filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1312 pre_mask = umask(0);
1313 if (mknod(filename2, S_IFIFO | 0666, 0)) {
1314 debug_error("mknod() failure, errno(%d)", errno);
1324 void _focus_close_callback(int index, bool is_for_watching)
1328 if (g_focus_sound_handle[index].focus_fd < 0) {
1329 debug_error("Close fail : fd error.");
1332 if (is_for_watching) {
1333 filename = g_strdup_printf("/tmp/FOCUS.%d.wch", g_focus_sound_handle[index].focus_tid);
1335 filename = g_strdup_printf("/tmp/FOCUS.%d.%d", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1337 close(g_focus_sound_handle[index].focus_fd);
1338 if (remove(filename)) {
1339 debug_error("remove() failure, filename(%s), errno(%d)", filename, errno);
1341 debug_log("Close Sucess : index(%d), filename(%s)", index, filename);
1346 #ifdef CONFIG_ENABLE_RETCB
1350 if (is_for_watching) {
1351 filename2 = g_strdup_printf("/tmp/FOCUS.%d.wchr", g_focus_sound_handle[index].focus_tid);
1353 filename2 = g_strdup_printf("/tmp/FOCUS.%d.%dr", g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle);
1356 /* Defensive code - wait until callback timeout although callback is removed */
1357 int buf = MM_ERROR_NONE; //no need to specify cb result to server, just notice if the client got the callback properly or not
1360 tmpfd = open(filename2, O_WRONLY | O_NONBLOCK);
1362 char str_error[256];
1363 strerror_r(errno, str_error, sizeof(str_error));
1364 debug_warning("could not open file(%s) (may server close it first), tid(%d) fd(%d) %s errno=%d(%s)",
1365 filename2, g_focus_sound_handle[index].focus_tid, tmpfd, filename2, errno, str_error);
1367 debug_msg("write MM_ERROR_NONE(tid:%d) for waiting server", g_focus_sound_handle[index].focus_tid);
1368 written = write(tmpfd, &buf, sizeof(buf));
1372 if (remove(filename2)) {
1373 debug_error("remove() failure, filename(%s), errno(%d)", filename2, errno);
1381 static bool _focus_add_sound_callback(int index, int fd, gushort events, focus_gLoopPollHandler_t p_gloop_poll_handler )
1383 GSource* g_src = NULL;
1384 GSourceFuncs *g_src_funcs = NULL; /* handler function */
1385 guint gsource_handle;
1386 GPollFD *g_poll_fd = NULL; /* file descriptor */
1390 g_mutex_init(&g_focus_sound_handle[index].focus_lock);
1392 /* 1. make GSource Object */
1393 g_src_funcs = (GSourceFuncs *)g_malloc(sizeof(GSourceFuncs));
1395 debug_error("g_malloc failed on g_src_funcs");
1399 g_src_funcs->prepare = _focus_fd_prepare;
1400 g_src_funcs->check = _focus_fd_check;
1401 g_src_funcs->dispatch = _focus_fd_dispatch;
1402 g_src_funcs->finalize = NULL;
1403 g_src = g_source_new(g_src_funcs, sizeof(GSource));
1405 debug_error("g_malloc failed on m_readfd");
1408 g_focus_sound_handle[index].focus_src = g_src;
1409 g_focus_sound_handle[index].g_src_funcs = g_src_funcs;
1411 /* 2. add file description which used in g_loop() */
1412 g_poll_fd = (GPollFD *)g_malloc(sizeof(GPollFD));
1414 debug_error("g_malloc failed on g_poll_fd");
1418 g_poll_fd->events = events;
1419 g_focus_sound_handle[index].g_poll_fd = g_poll_fd;
1421 /* 3. combine g_source object and file descriptor */
1422 g_source_add_poll(g_src, g_poll_fd);
1423 gsource_handle = g_source_attach(g_src, g_main_loop_get_context(g_focus_loop));
1424 if (!gsource_handle) {
1425 debug_error(" Failed to attach the source to context");
1428 //g_source_unref(g_src);
1430 /* 4. set callback */
1431 g_source_set_callback(g_src, p_gloop_poll_handler,(gpointer)g_poll_fd, NULL);
1433 debug_log(" g_malloc:g_src_funcs(%#X),g_poll_fd(%#X) g_source_add_poll:g_src_id(%d) g_source_set_callback:errno(%d)",
1434 g_src_funcs, g_poll_fd, gsource_handle, errno);
1442 static bool _focus_remove_sound_callback(int index, gushort events)
1448 g_mutex_clear(&g_focus_sound_handle[index].focus_lock);
1450 GSourceFuncs *g_src_funcs = g_focus_sound_handle[index].g_src_funcs;
1451 GPollFD *g_poll_fd = g_focus_sound_handle[index].g_poll_fd; /* store file descriptor */
1453 debug_error("g_poll_fd is null..");
1457 g_poll_fd->fd = g_focus_sound_handle[index].focus_fd;
1458 g_poll_fd->events = events;
1460 if (!g_focus_sound_handle[index].focus_src) {
1461 debug_error("FOCUS_sound_handle[%d].focus_src is null..", index);
1464 debug_log(" g_source_remove_poll : fd(%d), event(%x), errno(%d)", g_poll_fd->fd, g_poll_fd->events, errno);
1465 g_source_remove_poll(g_focus_sound_handle[index].focus_src, g_poll_fd);
1469 if (g_focus_sound_handle[index].focus_src) {
1470 g_source_destroy(g_focus_sound_handle[index].focus_src);
1471 if (!g_source_is_destroyed (g_focus_sound_handle[index].focus_src)) {
1472 debug_warning(" failed to g_source_destroy(), focus_src(0x%p)", g_focus_sound_handle[index].focus_src);
1475 debug_log(" g_free : g_src_funcs(%#X), g_poll_fd(%#X)", g_src_funcs, g_poll_fd);
1478 g_free(g_src_funcs);
1486 g_focus_sound_handle[index].g_src_funcs = NULL;
1487 g_focus_sound_handle[index].g_poll_fd = NULL;
1488 g_focus_sound_handle[index].focus_src = NULL;
1489 g_focus_sound_handle[index].focus_callback = NULL;
1490 g_focus_sound_handle[index].watch_callback = NULL;
1497 static void _focus_add_callback(int index, bool is_for_watching)
1500 if (!is_for_watching) {
1501 if (!_focus_add_sound_callback(index, g_focus_sound_handle[index].focus_fd, (gushort)POLLIN | POLLPRI, _focus_callback_handler)) {
1502 debug_error("failed to _focus_add_sound_callback()");
1505 } else { // need to check if it's necessary
1506 if (!_focus_add_sound_callback(index, g_focus_sound_handle[index].focus_fd, (gushort)POLLIN | POLLPRI, _focus_watch_callback_handler)) {
1507 debug_error("failed to _focus_add_sound_callback()");
1514 static void _focus_remove_callback(int index)
1517 if (!_focus_remove_sound_callback(index, (gushort)POLLIN | POLLPRI)) {
1518 debug_error("failed to __focus_remove_sound_callback()");
1524 static void _focus_init_callback(int index, bool is_for_watching)
1527 _focus_open_callback(index, is_for_watching);
1528 _focus_add_callback(index, is_for_watching);
1532 static void _focus_destroy_callback(int index, bool is_for_watching)
1535 _focus_remove_callback(index);
1536 _focus_close_callback(index, is_for_watching);
1540 int mm_sound_client_register_focus(int id, int pid, const char *stream_type, mm_sound_focus_changed_cb callback, bool is_for_session, void* user_data)
1542 int ret = MM_ERROR_NONE;
1549 for (index = 0; index < FOCUS_HANDLE_MAX; index++) {
1550 if (g_focus_sound_handle[index].is_used == false) {
1551 g_focus_sound_handle[index].is_used = true;
1556 g_focus_sound_handle[index].focus_tid = instance;
1557 g_focus_sound_handle[index].handle = id;
1558 g_focus_sound_handle[index].focus_callback = callback;
1559 g_focus_sound_handle[index].user_data = user_data;
1560 g_focus_sound_handle[index].is_for_session = is_for_session;
1562 ret = mm_sound_client_dbus_register_focus(id, pid, stream_type, callback, is_for_session, user_data);
1564 if (ret == MM_ERROR_NONE) {
1565 debug_msg("[Client] Success to register focus\n");
1566 if (!g_focus_thread) {
1567 GMainContext* focus_context = g_main_context_new ();
1568 g_focus_loop = g_main_loop_new (focus_context, FALSE);
1569 g_main_context_unref(focus_context);
1570 g_focus_thread = g_thread_new("focus-register-thread", _focus_thread_func, NULL);
1571 if (g_focus_thread == NULL) {
1572 debug_error ("could not create thread..");
1573 g_main_loop_unref(g_focus_loop);
1574 g_focus_sound_handle[index].is_used = false;
1575 ret = MM_ERROR_SOUND_INTERNAL;
1580 debug_error("[Client] Error occurred : %d \n",ret);
1581 g_focus_sound_handle[index].is_used = false;
1585 _focus_init_callback(index, false);
1593 int mm_sound_client_unregister_focus(int id)
1595 int ret = MM_ERROR_NONE;
1600 index = _focus_find_index_by_handle(id);
1601 instance = g_focus_sound_handle[index].focus_tid;
1603 if (!g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) {
1604 debug_warning("maybe focus_callback is being called, try one more time..");
1605 usleep(2500000); // 2.5 sec
1606 if (g_mutex_trylock(&g_focus_sound_handle[index].focus_lock)) {
1607 debug_msg("finally got focus_lock");
1611 ret = mm_sound_client_dbus_unregister_focus(instance, id, g_focus_sound_handle[index].is_for_session);
1613 if (ret == MM_ERROR_NONE)
1614 debug_msg("[Client] Success to unregister focus\n");
1616 debug_error("[Client] Error occurred : %d \n",ret);
1618 g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1620 _focus_destroy_callback(index, false);
1621 g_focus_sound_handle[index].focus_fd = 0;
1622 g_focus_sound_handle[index].focus_tid = 0;
1623 g_focus_sound_handle[index].handle = 0;
1624 g_focus_sound_handle[index].is_used = false;
1630 int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, const char *option)
1632 int ret = MM_ERROR_NONE;
1637 index = _focus_find_index_by_handle(id);
1638 instance = g_focus_sound_handle[index].focus_tid;
1640 ret = mm_sound_client_dbus_acquire_focus(instance, id, type, option, g_focus_sound_handle[index].is_for_session);
1642 if (ret == MM_ERROR_NONE)
1643 debug_msg("[Client] Success to acquire focus\n");
1645 debug_error("[Client] Error occurred : %d \n",ret);
1651 int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, const char *option)
1653 int ret = MM_ERROR_NONE;
1658 index = _focus_find_index_by_handle(id);
1659 instance = g_focus_sound_handle[index].focus_tid;
1661 ret = mm_sound_client_dbus_release_focus(instance, id, type, option, g_focus_sound_handle[index].is_for_session);
1663 if (ret == MM_ERROR_NONE)
1664 debug_msg("[Client] Success to release focus\n");
1666 debug_error("[Client] Error occurred : %d \n",ret);
1673 int mm_sound_client_set_focus_watch_callback(int pid, mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, bool is_for_session, void* user_data, int *id)
1675 int ret = MM_ERROR_NONE;
1681 return MM_ERROR_INVALID_ARGUMENT;
1683 //pthread_mutex_lock(&g_thread_mutex2);
1687 for (index = 0; index < FOCUS_HANDLE_MAX; index++) {
1688 if (g_focus_sound_handle[index].is_used == false) {
1689 g_focus_sound_handle[index].is_used = true;
1694 g_focus_sound_handle[index].focus_tid = instance;
1695 g_focus_sound_handle[index].handle = index + 1;
1696 g_focus_sound_handle[index].watch_callback = callback;
1697 g_focus_sound_handle[index].user_data = user_data;
1698 g_focus_sound_handle[index].is_for_session = is_for_session;
1700 ret = mm_sound_client_dbus_set_focus_watch_callback(pid, g_focus_sound_handle[index].handle, focus_type, callback, is_for_session, user_data);
1702 if (ret == MM_ERROR_NONE) {
1703 debug_msg("[Client] Success to watch focus");
1704 if (!g_focus_thread) {
1705 GMainContext* focus_context = g_main_context_new ();
1706 g_focus_loop = g_main_loop_new (focus_context, FALSE);
1707 g_main_context_unref(focus_context);
1708 g_focus_thread = g_thread_new("focus-watch-thread", _focus_thread_func, NULL);
1709 if (g_focus_thread == NULL) {
1710 debug_error ("could not create thread..");
1711 g_main_loop_unref(g_focus_loop);
1712 ret = MM_ERROR_SOUND_INTERNAL;
1717 debug_error("[Client] Error occurred : %d",ret);
1721 _focus_init_callback(index, true);
1723 *id = g_focus_sound_handle[index].handle;
1728 g_focus_sound_handle[index].is_used = false;
1735 int mm_sound_client_unset_focus_watch_callback(int id)
1737 int ret = MM_ERROR_NONE;
1742 if (index < 0 || FOCUS_HANDLE_MAX <= index) {
1743 debug_error("index is not valid, %d", index);
1747 g_mutex_lock(&g_focus_sound_handle[index].focus_lock);
1749 ret = mm_sound_client_dbus_unset_focus_watch_callback(g_focus_sound_handle[index].focus_tid, g_focus_sound_handle[index].handle, g_focus_sound_handle[index].is_for_session);
1751 if (ret == MM_ERROR_NONE)
1752 debug_msg("[Client] Success to unwatch focus\n");
1754 debug_error("[Client] Error occurred : %d \n",ret);
1757 g_mutex_unlock(&g_focus_sound_handle[index].focus_lock);
1759 _focus_destroy_callback(index, true);
1760 g_focus_sound_handle[index].focus_fd = 0;
1761 g_focus_sound_handle[index].focus_tid = 0;
1762 g_focus_sound_handle[index].handle = 0;
1763 g_focus_sound_handle[index].is_used = false;
1771 int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data, unsigned int *subs_id)
1773 int ret = MM_ERROR_NONE;
1777 ret = mm_sound_client_dbus_add_test_callback(func, user_data, subs_id);
1783 int mm_sound_client_remove_test_callback(unsigned int subs_id)
1785 int ret = MM_ERROR_NONE;
1788 ret = mm_sound_client_dbus_remove_test_callback(subs_id);
1795 int mm_sound_client_test(int a, int b, int* getv)
1797 int ret = MM_ERROR_NONE;
1801 ret = mm_sound_client_dbus_test(a, b, getv);
1802 debug_log("%d * %d -> result : %d", a, b, *getv);