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.
27 #include <sys/types.h>
36 #include <mm_message.h>
38 #include "include/mm_sound_private.h"
39 #include "include/mm_sound.h"
40 #include "include/mm_sound_utils.h"
41 #include "include/mm_sound_client.h"
42 #include "include/mm_sound_pa_client.h"
43 #include "include/mm_ipc.h"
44 #include "include/mm_sound_common.h"
47 #define VOLUME_MAX_MULTIMEDIA 16
48 #define VOLUME_MAX_BASIC 8
49 #define VOLUME_MAX_SINGLE 1
52 #define MASTER_VOLUME_MAX 100
53 #define MASTER_VOLUME_MIN 0
57 volume_callback_fn func;
62 volume_cb_param g_volume_param[VOLUME_TYPE_MAX];
64 static pthread_mutex_t g_volume_mutex = PTHREAD_MUTEX_INITIALIZER;
68 static GList *g_subscribe_cb_list = NULL;
69 static pthread_mutex_t g_subscribe_cb_list_mutex = PTHREAD_MUTEX_INITIALIZER;
71 #define MM_SOUND_DBUS_BUS_NAME_PREPIX "org.tizen.MMSound"
72 #define MM_SOUND_DBUS_OBJECT_PATH "/org/tizen/MMSound"
73 #define MM_SOUND_DBUS_INTERFACE "org.tizen.mmsound"
75 GDBusConnection *g_dbus_conn_mmsound;
77 int g_dbus_signal_values[MM_SOUND_SIGNAL_MAX] = {0,};
79 const char* dbus_signal_name_str[] = {
80 "ReleaseInternalFocus",
83 typedef struct _subscribe_cb {
84 mm_sound_signal_name_t signal_type;
85 mm_sound_signal_callback callback;
90 static const char* _get_volume_str (volume_type_t type)
92 static const char *volume_type_str[VOLUME_TYPE_MAX] =
93 { "SYSTEM", "NOTIFICATION", "ALARM", "RINGTONE", "MEDIA", "CALL", "VOIP", "VOICE", "FIXED"};
95 return (type >= VOLUME_TYPE_SYSTEM && type < VOLUME_TYPE_MAX)? volume_type_str[type] : "Unknown";
98 static int _validate_volume(volume_type_t type, int value)
105 case VOLUME_TYPE_CALL:
106 case VOLUME_TYPE_VOIP:
107 if (value >= VOLUME_MAX_BASIC) {
111 case VOLUME_TYPE_SYSTEM:
112 case VOLUME_TYPE_MEDIA:
113 case VOLUME_TYPE_ALARM:
114 case VOLUME_TYPE_NOTIFICATION:
115 case VOLUME_TYPE_RINGTONE:
116 case VOLUME_TYPE_VOICE:
117 if (value >= VOLUME_MAX_MULTIMEDIA) {
128 static void _volume_changed_cb(keynode_t* node, void* data)
130 volume_cb_param* param = (volume_cb_param*) data;
132 debug_msg("%s changed callback called\n",vconf_keynode_get_name(node));
134 MMSOUND_ENTER_CRITICAL_SECTION( &g_volume_mutex )
136 if(param && (param->func != NULL)) {
137 debug_log("function 0x%x\n", param->func);
138 ((volume_callback_fn)param->func)(param->data);
141 MMSOUND_LEAVE_CRITICAL_SECTION( &g_volume_mutex )
145 int mm_sound_volume_add_callback(volume_type_t type, volume_callback_fn func, void* user_data)
147 debug_msg("type = (%d)%15s, func = %p, user_data = %p", type, _get_volume_str(type), func, user_data);
149 /* Check input param */
150 if (type < 0 || type >= VOLUME_TYPE_MAX) {
151 debug_error("invalid argument\n");
152 return MM_ERROR_INVALID_ARGUMENT;
155 debug_warning("callback function is null\n");
156 return MM_ERROR_INVALID_ARGUMENT;
159 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &g_volume_mutex, MM_ERROR_SOUND_INTERNAL );
161 g_volume_param[type].func = func;
162 g_volume_param[type].data = user_data;
163 g_volume_param[type].type = type;
165 MMSOUND_LEAVE_CRITICAL_SECTION( &g_volume_mutex );
167 return mm_sound_util_volume_add_callback(type, _volume_changed_cb, (void*)&g_volume_param[type]);
171 int mm_sound_volume_remove_callback(volume_type_t type)
173 debug_msg("type = (%d)%s", type, _get_volume_str(type));
175 if(type < 0 || type >=VOLUME_TYPE_MAX) {
176 debug_error("invalid argument\n");
177 return MM_ERROR_INVALID_ARGUMENT;
180 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN( &g_volume_mutex, MM_ERROR_SOUND_INTERNAL );
182 g_volume_param[type].func = NULL;
183 g_volume_param[type].data = NULL;
184 g_volume_param[type].type = type;
186 MMSOUND_LEAVE_CRITICAL_SECTION( &g_volume_mutex );
188 return mm_sound_util_volume_remove_callback(type, _volume_changed_cb);
192 int mm_sound_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* user_data, unsigned int *subs_id)
194 int ret = MM_ERROR_NONE;
196 if (func == NULL || subs_id == NULL) {
197 debug_error("argument is not valid\n");
198 return MM_ERROR_INVALID_ARGUMENT;
201 ret = mm_sound_client_add_volume_changed_callback(func, user_data, subs_id);
203 debug_error("Can not add volume changed callback, ret = %x\n", ret);
210 int mm_sound_remove_volume_changed_callback(unsigned int subs_id)
212 int ret = MM_ERROR_NONE;
214 ret = mm_sound_client_remove_volume_changed_callback(subs_id);
216 debug_error("Can not remove volume changed callback, ret = %x\n", ret);
223 int mm_sound_volume_get_step(volume_type_t type, int *step)
225 return MM_ERROR_SOUND_NOT_SUPPORTED_OPERATION;
229 int mm_sound_volume_set_value(volume_type_t volume_type, const unsigned int volume_level)
231 int ret = MM_ERROR_NONE;
233 debug_msg("type = (%d)%s, value = %d", volume_type, _get_volume_str(volume_type), volume_level);
235 /* Check input param */
236 if (0 > _validate_volume(volume_type, (int)volume_level)) {
237 debug_error("invalid volume type %d, value %u\n", volume_type, volume_level);
238 return MM_ERROR_INVALID_ARGUMENT;
241 ret = mm_sound_util_volume_set_value_by_type(volume_type, volume_level);
242 if (ret == MM_ERROR_NONE) {
243 /* update shared memory value */
244 if(MM_ERROR_NONE != mm_sound_client_set_volume_by_type(volume_type, volume_level)) {
245 debug_error("Can not set volume to shared memory 0x%x\n", ret);
253 int mm_sound_volume_get_value(volume_type_t type, unsigned int *value)
255 int ret = MM_ERROR_NONE;
257 /* Check input param */
259 debug_error("invalid argument\n");
260 return MM_ERROR_INVALID_ARGUMENT;
262 if (type < 0 || type >= VOLUME_TYPE_MAX) {
263 debug_error("invalid volume type value %d\n", type);
264 return MM_ERROR_INVALID_ARGUMENT;
267 ret = mm_sound_util_volume_get_value_by_type(type, value);
269 debug_msg("returned %s = %d", _get_volume_str(type), *value);
274 int mm_sound_volume_primary_type_set(volume_type_t type)
276 int ret = MM_ERROR_NONE;
278 /* Check input param */
279 if(type < VOLUME_TYPE_UNKNOWN || type >= VOLUME_TYPE_MAX) {
280 debug_error("invalid argument\n");
281 return MM_ERROR_INVALID_ARGUMENT;
284 if (vconf_set_int(VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, type)) {
285 debug_error("could not set vconf for RIMARY_VOLUME_TYPE\n");
286 ret = MM_ERROR_SOUND_INTERNAL;
288 debug_msg("set primary volume type forcibly %d(%s)", type, _get_volume_str(type));
295 int mm_sound_volume_primary_type_get(volume_type_t *type)
297 int ret = MM_ERROR_NONE;
298 int voltype = VOLUME_TYPE_RINGTONE;
300 /* Check input param */
302 debug_error("invalid argument\n");
303 return MM_ERROR_INVALID_ARGUMENT;
306 /* check force set */
307 if (vconf_get_int(VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, &voltype)) {
308 debug_error("could not get vconf for PRIMARY_VOLUME_TYPE\n");
309 ret = MM_ERROR_SOUND_INTERNAL;
311 debug_msg("get primary volume type %d(%s)", voltype, _get_volume_str(voltype));
318 /* it will be removed */
320 int mm_sound_volume_primary_type_clear(void)
322 int ret = MM_ERROR_NONE;
324 if (vconf_set_int(VCONFKEY_SOUND_PRIMARY_VOLUME_TYPE, -1)) {
325 debug_error("could not reset vconf for PRIMARY_VOLUME_TYPE\n");
326 ret = MM_ERROR_SOUND_INTERNAL;
328 debug_msg("clear primary volume type forcibly %d(%s)", -1, "none");
334 ///////////////////////////////////
335 //// MMSOUND PLAY APIs
336 ///////////////////////////////////
337 static inline void _mm_sound_fill_play_param(MMSoundPlayParam *param, const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int priority, int handle_route)
339 param->filename = filename;
340 param->volume = 0; //volume value dose not effect anymore
341 param->callback = callback;
344 param->volume_config = volume_config;
345 param->priority = priority;
346 param->handle_route = handle_route;
350 int mm_sound_play_loud_solo_sound_no_restore(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
352 MMSoundPlayParam param = { 0, };
354 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, HANDLE_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_SPEAKER_NO_RESTORE);
355 return mm_sound_play_sound_ex(¶m, handle);
359 int mm_sound_play_loud_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
361 MMSoundPlayParam param = { 0, };
363 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, HANDLE_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_SPEAKER);
364 return mm_sound_play_sound_ex(¶m, handle);
368 int mm_sound_play_solo_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
370 MMSoundPlayParam param = { 0, };
372 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, HANDLE_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
373 return mm_sound_play_sound_ex(¶m, handle);
377 int mm_sound_play_sound_without_session(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
379 MMSoundPlayParam param = { 0, };
381 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, HANDLE_PRIORITY_SOLO, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
382 param.skip_session = true;
383 return mm_sound_play_sound_ex(¶m, handle);
387 int mm_sound_play_sound(const char *filename, int volume_config, mm_sound_stop_callback_func callback, void *data, int *handle)
389 MMSoundPlayParam param = { 0, };
391 _mm_sound_fill_play_param(¶m, filename, volume_config, callback, data, HANDLE_PRIORITY_NORMAL, MM_SOUND_HANDLE_ROUTE_USING_CURRENT);
392 return mm_sound_play_sound_ex(¶m, handle);
396 int mm_sound_play_sound_ex(MMSoundPlayParam *param, int *handle)
401 /* Check input param */
403 debug_error("param is null\n");
404 return MM_ERROR_INVALID_ARGUMENT;
407 volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
409 if (param->filename == NULL) {
410 debug_error("filename is NULL\n");
411 return MM_ERROR_SOUND_FILE_NOT_FOUND;
413 if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
414 debug_error("Volume type is invalid %d\n", volume_type);
415 return MM_ERROR_INVALID_ARGUMENT;
418 debug_warning ("play sound : priority=[%d], handle_route=[%d]\n", param->priority, param->handle_route);
421 err = mm_sound_client_play_sound(param, 0, &lhandle);
423 debug_error("Failed to play sound\n");
427 /* Set handle to return */
431 debug_critical("The sound hadle cannot be get [%d]\n", lhandle);
434 debug_warning ("success : handle=[%p]\n", handle);
436 return MM_ERROR_NONE;
440 int mm_sound_play_sound_with_stream_info(const char *filename, char *stream_type, int stream_id, mm_sound_stop_callback_func callback, void *data, int *handle)
442 MMSoundPlayParam param = { 0, };
445 param.filename = filename;
446 param.volume = 0; //volume value dose not effect anymore
447 param.callback = callback;
450 param.priority = HANDLE_PRIORITY_NORMAL;
451 param.handle_route = MM_SOUND_HANDLE_ROUTE_USING_CURRENT;
453 err = mm_sound_client_play_sound_with_stream_info(¶m, handle, stream_type, stream_id);
455 debug_error("Failed to play sound\n");
459 debug_warning ("success : handle=[%p]\n", handle);
461 return MM_ERROR_NONE;
467 int mm_sound_stop_sound(int handle)
471 debug_warning ("enter : handle=[%p]\n", handle);
473 err = mm_sound_client_stop_sound(handle);
475 debug_error("Fail to stop sound\n");
478 debug_warning ("success : handle=[%p]\n", handle);
480 return MM_ERROR_NONE;
483 ///////////////////////////////////
484 //// MMSOUND TONE APIs
485 ///////////////////////////////////
487 int mm_sound_play_tone_ex (MMSoundTone_t num, int volume_config, const double volume, const int duration, int *handle, bool enable_session)
490 int err = MM_ERROR_NONE;
491 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
495 /* Check input param */
497 debug_error("number is invalid %d\n", duration);
498 return MM_ERROR_INVALID_ARGUMENT;
500 if (num < MM_SOUND_TONE_DTMF_0 || num >= MM_SOUND_TONE_NUM) {
501 debug_error("TONE Value is invalid %d\n", num);
502 return MM_ERROR_INVALID_ARGUMENT;
504 if (volume_type < 0 || volume_type >= VOLUME_TYPE_MAX) {
505 debug_error("Volume type is invalid %d\n", volume_type);
506 return MM_ERROR_INVALID_ARGUMENT;
508 if (volume < 0.0 || volume > 1.0) {
509 debug_error("Volume Value is invalid %d\n", volume);
510 return MM_ERROR_INVALID_ARGUMENT;
514 debug_msg("Call MMSoundClientPlayTone\n");
515 err = mm_sound_client_play_tone(num, volume_config, volume, duration, &lhandle, enable_session);
517 debug_error("Failed to play sound\n");
521 /* Set handle to return */
525 debug_critical("The sound handle cannot be get [%d]\n", lhandle);
528 return MM_ERROR_NONE;
532 int mm_sound_play_tone_with_stream_info(MMSoundTone_t tone, char *stream_type, int stream_id, const double volume, const int duration, int *handle)
535 int err = MM_ERROR_NONE;
537 err = mm_sound_client_play_tone_with_stream_info(tone, stream_type, stream_id, volume, duration, handle);
539 debug_error("Failed to play sound\n");
549 int mm_sound_play_tone (MMSoundTone_t num, int volume_config, const double volume, const int duration, int *handle)
551 return mm_sound_play_tone_ex (num, volume_config, volume, duration, handle, true);
554 ///////////////////////////////////
555 //// MMSOUND ROUTING APIs
556 ///////////////////////////////////
559 int mm_sound_route_get_a2dp_status (bool *connected, char **bt_name)
561 int ret = MM_ERROR_NONE;
563 if (connected == NULL || bt_name == NULL) {
564 debug_error ("argument is not valid\n");
565 return MM_ERROR_INVALID_ARGUMENT;
568 ret = mm_sound_client_is_bt_a2dp_on (connected, bt_name);
569 debug_msg ("connected=[%d] bt_name[%s]\n", *connected, *bt_name);
571 debug_error("MMSoundClientIsBtA2dpOn() Failed\n");
579 int mm_sound_is_route_available(mm_sound_route route, bool *is_available)
581 int ret = MM_ERROR_NONE;
583 debug_warning ("enter : route=[%x], is_available=[%p]\n", route, is_available);
585 if (!mm_sound_util_is_route_valid(route)) {
586 debug_error("route is invalid %d\n", route);
587 return MM_ERROR_INVALID_ARGUMENT;
590 debug_error("is_available is invalid\n");
591 return MM_ERROR_INVALID_ARGUMENT;
594 ret = mm_sound_client_is_route_available(route, is_available);
596 debug_error("Can not check given route is available, ret = %x\n", ret);
598 debug_warning ("success : route=[%x], available=[%d]\n", route, *is_available);
605 int mm_sound_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
607 int ret = MM_ERROR_NONE;
609 if (!available_route_cb) {
610 debug_error("available_route_cb is invalid\n");
611 return MM_ERROR_INVALID_ARGUMENT;
614 ret = mm_sound_client_foreach_available_route_cb(available_route_cb, user_data);
616 debug_error("Can not set foreach available route callback, ret = %x\n", ret);
623 int mm_sound_set_active_route(mm_sound_route route)
625 int ret = MM_ERROR_NONE;
627 debug_warning ("enter : route=[%x]\n", route);
628 if (!mm_sound_util_is_route_valid(route)) {
629 debug_error("route is invalid %d\n", route);
630 return MM_ERROR_INVALID_ARGUMENT;
633 ret = mm_sound_client_set_active_route(route, true);
635 debug_error("Can not set active route, ret = %x\n", ret);
637 debug_warning ("success : route=[%x]\n", route);
644 int mm_sound_set_active_route_auto(void)
646 int ret = MM_ERROR_NONE;
648 ret = mm_sound_client_set_active_route_auto();
650 debug_error("fail to set active route auto, ret = %x\n", ret);
652 debug_msg ("success !!\n");
659 int mm_sound_set_active_route_without_broadcast(mm_sound_route route)
661 int ret = MM_ERROR_NONE;
663 debug_warning ("enter : route=[%x]\n", route);
664 if (!mm_sound_util_is_route_valid(route)) {
665 debug_error("route is invalid %d\n", route);
666 return MM_ERROR_INVALID_ARGUMENT;
669 ret = mm_sound_client_set_active_route(route, false);
671 debug_error("Can not set active route, ret = %x\n", ret);
673 debug_warning ("success : route=[%x]\n", route);
680 int mm_sound_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
682 int ret = MM_ERROR_NONE;
684 if (device_in == NULL || device_out == NULL) {
685 debug_error("argument is not valid\n");
686 return MM_ERROR_INVALID_ARGUMENT;
689 ret = mm_sound_client_get_active_device(device_in, device_out);
691 debug_error("Can not add active device callback, ret = %x\n", ret);
693 debug_msg ("success : in=[%x], out=[%x]\n", *device_in, *device_out);
700 int mm_sound_get_audio_path(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
702 int ret = MM_ERROR_NONE;
704 if (device_in == NULL || device_out == NULL) {
705 debug_error("argument is not valid\n");
706 return MM_ERROR_INVALID_ARGUMENT;
709 ret = mm_sound_client_get_audio_path(device_in, device_out);
711 debug_error("Can not add active device callback, ret = %x\n", ret);
713 debug_msg ("success : in=[%x], out=[%x]\n", *device_in, *device_out);
720 int mm_sound_add_active_device_changed_callback(const char *name, mm_sound_active_device_changed_cb func, void *user_data)
722 int ret = MM_ERROR_NONE;
724 debug_warning ("enter %s\n", name);
726 debug_error("argument is not valid\n");
727 return MM_ERROR_INVALID_ARGUMENT;
730 ret = mm_sound_client_add_active_device_changed_callback(name, func, user_data);
732 debug_error("Can not add active device changed callback, ret = %x\n", ret);
739 int mm_sound_remove_active_device_changed_callback(const char *name)
741 int ret = MM_ERROR_NONE;
743 debug_warning ("enter name %s \n", name);
744 ret = mm_sound_client_remove_active_device_changed_callback(name);
746 debug_error("Can not remove active device changed callback, ret = %x\n", ret);
753 int mm_sound_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void *user_data)
755 int ret = MM_ERROR_NONE;
758 debug_error("argument is not valid\n");
759 return MM_ERROR_INVALID_ARGUMENT;
762 ret = mm_sound_client_add_available_route_changed_callback(func, user_data);
764 debug_error("Can not add available route changed callback, ret = %x\n", ret);
771 int mm_sound_remove_available_route_changed_callback(void)
773 int ret = MM_ERROR_NONE;
775 ret = mm_sound_client_remove_available_route_changed_callback();
777 debug_error("Can not remove available route changed callback, ret = %x\n", ret);
784 int mm_sound_set_sound_path_for_active_device(mm_sound_device_out device_out, mm_sound_device_in device_in)
786 int ret = MM_ERROR_NONE;
788 ret = mm_sound_client_set_sound_path_for_active_device(device_out, device_in);
790 debug_error("Can not mm sound set sound path for active device, ret = %x\n", ret);
798 int mm_sound_test(int a, int b, int* getv)
800 int ret = MM_ERROR_NONE;
802 debug_log("mm_sound_test enter");
804 debug_error("argu null");
805 return MM_ERROR_INVALID_ARGUMENT;
807 ret = mm_sound_client_test(a, b, getv);
809 debug_error("Can not mm sound test, ret = %x\n", ret);
811 debug_log("mm_sound_test leave");
817 int mm_sound_add_test_callback(mm_sound_test_cb func, void *user_data, unsigned int *subs_id)
819 int ret = MM_ERROR_NONE;
821 debug_log("mm_sound_add_test_callback enter");
822 if (!func || !subs_id) {
823 debug_error("argument is not valid\n");
824 return MM_ERROR_INVALID_ARGUMENT;
827 ret = mm_sound_client_add_test_callback(func, user_data, subs_id);
829 debug_error("Can not add test callback, ret = %x\n", ret);
831 debug_log("mm_sound_add_test_callback leave");
837 int mm_sound_remove_test_callback(unsigned int subs_id)
839 int ret = MM_ERROR_NONE;
841 debug_log("mm_sound_remove_test_callback enter");
842 ret = mm_sound_client_remove_test_callback(subs_id);
844 debug_error("Can not remove test callback, ret = %x\n", ret);
846 debug_log("mm_sound_remove_test_callback leave");
851 static int _convert_signal_name_str_to_enum (const char *name_str, mm_sound_signal_name_t *name_enum) {
852 int ret = MM_ERROR_NONE;
854 if (!name_str || !name_enum)
855 return MM_ERROR_INVALID_ARGUMENT;
857 if (!strncmp(name_str, "ReleaseInternalFocus", strlen("ReleaseInternalFocus"))) {
858 *name_enum = MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS;
860 ret = MM_ERROR_INVALID_ARGUMENT;
861 LOGE("not supported signal name(%s), err(0x%08x)", name_str, ret);
866 static void _dbus_signal_callback (const char *signal_name, int value, void *user_data)
868 int ret = MM_ERROR_NONE;
869 mm_sound_signal_name_t signal;
870 subscribe_cb_t *subscribe_cb = (subscribe_cb_t*)user_data;
877 ret = _convert_signal_name_str_to_enum(signal_name, &signal);
881 debug_msg ("signal_name[%s], value[%d], user_data[0x%x]\n", signal_name, value, user_data);
883 if (subscribe_cb->signal_type == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
884 /* trigger the signal callback when it comes from the same process */
885 if (getpid() == ((value & 0xFFFF0000) >> 16)) {
886 subscribe_cb->callback(signal, (value & 0x0000FFFF), subscribe_cb->user_data);
889 subscribe_cb->callback(signal, value, subscribe_cb->user_data);
897 static void signal_callback(GDBusConnection *conn,
898 const gchar *sender_name,
899 const gchar *object_path,
900 const gchar *interface_name,
901 const gchar *signal_name,
902 GVariant *parameters,
906 const GVariantType* value_type;
908 debug_msg ("sender : %s, object : %s, interface : %s, signal : %s",
909 sender_name, object_path, interface_name, signal_name);
910 if (g_variant_is_of_type(parameters, G_VARIANT_TYPE("(i)"))) {
911 g_variant_get(parameters, "(i)",&value);
912 debug_msg(" - value : %d\n", value);
913 _dbus_signal_callback(signal_name, value, user_data);
915 value_type = g_variant_get_type(parameters);
916 debug_warning("signal type is %s", value_type);
921 int mm_sound_subscribe_signal(mm_sound_signal_name_t signal, unsigned int *subscribe_id, mm_sound_signal_callback callback, void *user_data)
923 int ret = MM_ERROR_NONE;
926 subscribe_cb_t *subscribe_cb = NULL;
930 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_subscribe_cb_list_mutex, MM_ERROR_SOUND_INTERNAL);
932 if (signal < 0 || signal >= MM_SOUND_SIGNAL_MAX || !subscribe_id) {
933 debug_error ("invalid argument, signal(%d), subscribe_id(0x%p)", signal, subscribe_id);
934 ret = MM_ERROR_INVALID_ARGUMENT;
938 subscribe_cb = malloc(sizeof(subscribe_cb_t));
940 ret = MM_ERROR_SOUND_INTERNAL;
943 memset(subscribe_cb, 0, sizeof(subscribe_cb_t));
945 g_dbus_conn_mmsound = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
946 if (!g_dbus_conn_mmsound && err) {
947 debug_error ("g_bus_get_sync() error (%s) ", err->message);
949 ret = MM_ERROR_SOUND_INTERNAL;
953 subscribe_cb->signal_type = signal;
954 subscribe_cb->callback = callback;
955 subscribe_cb->user_data = user_data;
957 *subscribe_id = g_dbus_connection_signal_subscribe(g_dbus_conn_mmsound,
958 NULL, MM_SOUND_DBUS_INTERFACE, dbus_signal_name_str[signal], MM_SOUND_DBUS_OBJECT_PATH, NULL, 0,
959 signal_callback, subscribe_cb, NULL);
960 if (*subscribe_id == 0) {
961 debug_error ("g_dbus_connection_signal_subscribe() error (%d)", *subscribe_id);
962 ret = MM_ERROR_SOUND_INTERNAL;
966 subscribe_cb->id = *subscribe_id;
968 g_subscribe_cb_list = g_list_append(g_subscribe_cb_list, subscribe_cb);
969 if (g_subscribe_cb_list) {
970 debug_log("new subscribe_cb(0x%x)[user_callback(0x%x), subscribe_id(%u)] is added\n", subscribe_cb, subscribe_cb->callback, subscribe_cb->id);
972 debug_error("g_list_append failed\n");
973 ret = MM_ERROR_SOUND_INTERNAL;
977 MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
984 g_dbus_connection_signal_unsubscribe(g_dbus_conn_mmsound, *subscribe_id);
985 g_object_unref(g_dbus_conn_mmsound);
991 MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
997 void mm_sound_unsubscribe_signal(unsigned int subscribe_id)
1000 subscribe_cb_t *subscribe_cb = NULL;
1004 MMSOUND_ENTER_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
1006 if (g_dbus_conn_mmsound && subscribe_id) {
1007 g_dbus_connection_signal_unsubscribe(g_dbus_conn_mmsound, subscribe_id);
1008 g_object_unref(g_dbus_conn_mmsound);
1009 for (list = g_subscribe_cb_list; list != NULL; list = list->next) {
1010 subscribe_cb = (subscribe_cb_t *)list->data;
1011 if (subscribe_cb && (subscribe_cb->id == subscribe_id)) {
1012 g_subscribe_cb_list = g_list_remove(g_subscribe_cb_list, subscribe_cb);
1013 debug_log("subscribe_cb(0x%x) is removed\n", subscribe_cb);
1014 free (subscribe_cb);
1019 MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
1025 int mm_sound_send_signal(mm_sound_signal_name_t signal, int value)
1027 int ret = MM_ERROR_NONE;
1029 GDBusConnection *conn = NULL;
1030 gboolean dbus_ret = TRUE;
1034 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_subscribe_cb_list_mutex, MM_ERROR_SOUND_INTERNAL);
1036 if (signal < 0 || signal >= MM_SOUND_SIGNAL_MAX) {
1037 debug_error ("invalid argument, signal(%d)", signal);
1038 ret = MM_ERROR_INVALID_ARGUMENT;
1042 conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
1044 debug_error ("g_bus_get_sync() error (%s)", err->message);
1045 ret = MM_ERROR_SOUND_INTERNAL;
1049 g_dbus_signal_values[signal] = value;
1050 if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS) {
1051 /* trigger the signal callback when it comes from the same process */
1052 value |= ((int)getpid() << 16);
1054 dbus_ret = g_dbus_connection_emit_signal (conn,
1055 NULL, MM_SOUND_DBUS_OBJECT_PATH, MM_SOUND_DBUS_INTERFACE, dbus_signal_name_str[signal],
1056 g_variant_new ("(i)", value),
1058 if (!dbus_ret && err) {
1059 debug_error ("g_dbus_connection_emit_signal() error (%s)", err->message);
1060 ret = MM_ERROR_SOUND_INTERNAL;
1064 dbus_ret = g_dbus_connection_flush_sync(conn, NULL, &err);
1065 if (!dbus_ret && err) {
1066 debug_error ("g_dbus_connection_flush_sync() error (%s)", err->message);
1067 ret = MM_ERROR_SOUND_INTERNAL;
1071 g_object_unref(conn);
1072 debug_msg ("sending signal[%s], value[%d] success", dbus_signal_name_str[signal], value);
1074 MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
1084 g_object_unref(conn);
1086 MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
1092 int mm_sound_get_signal_value(mm_sound_signal_name_t signal, int *value)
1094 int ret = MM_ERROR_NONE;
1098 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_subscribe_cb_list_mutex, MM_ERROR_SOUND_INTERNAL);
1100 *value = g_dbus_signal_values[signal];
1102 MMSOUND_LEAVE_CRITICAL_SECTION(&g_subscribe_cb_list_mutex);
1109 __attribute__ ((constructor))
1110 static void _mm_sound_initialize(void)
1112 mm_sound_client_initialize();
1116 __attribute__ ((destructor))
1117 static void _mm_sound_finalize(void)
1119 mm_sound_client_finalize();