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.
33 #include <semaphore.h>
39 #include "include/mm_sound.h"
40 #include "include/mm_sound_msg.h"
41 #include "include/mm_sound_client.h"
42 #include "include/mm_sound_client_dbus.h"
43 #include "include/mm_sound_common.h"
44 #include "include/mm_sound_device.h"
46 #include "include/mm_sound_focus.h"
49 #include <mm_session.h>
50 #include <mm_session_private.h>
52 #define __DIRECT_CALLBACK__
53 //#define __GIDLE_CALLBACK__
56 #if defined(__GSOURCE_CALLBACK__)
60 #define CLIENT_HANDLE_MAX 256
62 /* global variables for device list */
63 //static GList *g_device_list = NULL;
64 static mm_sound_device_list_t g_device_list_t;
65 static pthread_mutex_t g_device_list_mutex = PTHREAD_MUTEX_INITIALIZER;
66 static pthread_mutex_t g_id_mutex = PTHREAD_MUTEX_INITIALIZER;
68 guint g_focus_signal_handle = 0;
70 int mm_sound_client_initialize(void)
72 int ret = MM_ERROR_NONE;
75 mm_sound_client_dbus_initialize();
81 int mm_sound_client_finalize(void)
83 int ret = MM_ERROR_NONE;
87 ret = mm_sound_client_dbus_finalize();
93 int mm_sound_client_is_route_available(mm_sound_route route, bool *is_available)
95 int ret = MM_ERROR_NONE;
98 ret = mm_sound_client_dbus_is_route_available(route, is_available);
105 int mm_sound_client_foreach_available_route_cb(mm_sound_available_route_cb available_route_cb, void *user_data)
107 int ret = MM_ERROR_NONE;
110 ret = mm_sound_client_dbus_foreach_available_route_cb(available_route_cb, user_data);
116 int mm_sound_client_set_active_route(mm_sound_route route, bool need_broadcast)
118 int ret = MM_ERROR_NONE;
121 ret = mm_sound_client_dbus_set_active_route(route, need_broadcast);
128 int mm_sound_client_set_active_route_auto(void)
130 int ret = MM_ERROR_NONE;
133 ret = mm_sound_client_dbus_set_active_route_auto();
140 int mm_sound_client_get_active_device(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
143 int ret = MM_ERROR_NONE;
146 ret = mm_sound_client_dbus_get_active_device(device_in, device_out);
152 int mm_sound_client_add_active_device_changed_callback(const char *name, mm_sound_active_device_changed_cb func, void* user_data)
154 int ret = MM_ERROR_NONE;
157 ret = mm_sound_client_dbus_add_active_device_changed_callback(name, func, user_data);
163 int mm_sound_client_remove_active_device_changed_callback(const char *name)
165 int ret = MM_ERROR_NONE;
168 ret = mm_sound_client_dbus_remove_active_device_changed_callback(name);
173 int mm_sound_client_add_available_route_changed_callback(mm_sound_available_route_changed_cb func, void* user_data)
175 int ret = MM_ERROR_NONE;
178 ret = mm_sound_client_dbus_add_available_route_changed_callback(func, user_data);
184 int mm_sound_client_remove_available_route_changed_callback(void)
186 int ret = MM_ERROR_NONE;
189 ret = mm_sound_client_dbus_remove_available_route_changed_callback();
195 int mm_sound_client_set_sound_path_for_active_device(mm_sound_device_out device_out, mm_sound_device_in device_in)
197 int ret = MM_ERROR_NONE;
200 ret = mm_sound_client_dbus_set_sound_path_for_active_device(device_out, device_in);
206 void mm_sound_convert_volume_type_to_stream_type(int volume_type, char *stream_type)
208 switch (volume_type) {
209 case VOLUME_TYPE_SYSTEM:
210 strncpy(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN);
212 case VOLUME_TYPE_NOTIFICATION:
213 strncpy(stream_type, "notification", MM_SOUND_STREAM_TYPE_LEN);
215 case VOLUME_TYPE_ALARM:
216 strncpy(stream_type, "alarm", MM_SOUND_STREAM_TYPE_LEN);
218 case VOLUME_TYPE_RINGTONE:
219 strncpy(stream_type, "ringtone-voip", MM_SOUND_STREAM_TYPE_LEN);
221 case VOLUME_TYPE_MEDIA:
222 strncpy(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN);
224 case VOLUME_TYPE_CALL:
225 strncpy(stream_type, "system", MM_SOUND_STREAM_TYPE_LEN);
227 case VOLUME_TYPE_VOIP:
228 strncpy(stream_type, "voip", MM_SOUND_STREAM_TYPE_LEN);
230 case VOLUME_TYPE_VOICE:
231 strncpy(stream_type, "voice-recognition", MM_SOUND_STREAM_TYPE_LEN);
234 strncpy(stream_type, "media", MM_SOUND_STREAM_TYPE_LEN);
238 debug_error("volume type (%d) converted to stream type (%s)", volume_type, stream_type);
242 /*****************************************************************************************
243 DBUS SUPPORTED FUNCTIONS
244 ******************************************************************************************/
246 void _mm_sound_client_focus_signal_callback(mm_sound_signal_name_t signal, int value, void *user_data)
248 int ret = MM_ERROR_NONE;
251 debug_error("focus signal received, value = %d", value);
254 ret = mm_sound_client_dbus_clear_focus(getpid());
256 debug_error("clear focus failed ret = 0x%x", ret);
257 mm_sound_unsubscribe_signal(g_focus_signal_handle);
258 g_focus_signal_handle = 0;
262 int mm_sound_client_play_tone(int number, int volume_config, double volume, int time, int *handle, bool enable_session)
264 int ret = MM_ERROR_NONE;
265 // int instance = -1; /* instance is unique to communicate with server : client message queue filter type */
266 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(volume_config);
267 char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, };
271 /* read session information */
272 int session_type = MM_SESSION_TYPE_MEDIA;
273 int session_options = 0;
274 int is_focus_registered = 0;
276 ret = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &is_focus_registered);
278 debug_error("mm_sound_get_signal_value failed [0x%x]", ret);
279 return MM_ERROR_POLICY_INTERNAL;
282 if (is_focus_registered)
283 enable_session = false;
287 if (MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options))
289 debug_warning("[Client] Read Session Information failed. use default \"media\" type\n");
290 session_type = MM_SESSION_TYPE_MEDIA;
292 if(MM_ERROR_NONE != mm_session_init(session_type))
294 debug_critical("[Client] MMSessionInit() failed\n");
295 return MM_ERROR_POLICY_INTERNAL;
300 // instance = getpid();
301 //debug_log("[Client] pid for client ::: [%d]\n", instance);
304 debug_msg("[Client] Input number : %d\n", number);
305 /* Send req memory */
307 mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type);
308 ret = mm_sound_client_dbus_play_tone(number, time, volume, volume_config,
309 session_type, session_options, getpid(), enable_session, handle, stream_type, -1);
311 if (enable_session && !g_focus_signal_handle) {
312 ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL);
314 debug_error("mm_sound_subscribe_signal failed [0x%x]", ret);
315 return MM_ERROR_POLICY_INTERNAL;
323 int mm_sound_client_play_tone_with_stream_info(int tone, char *stream_type, int stream_id, double volume, int duration, int *handle)
325 int ret = MM_ERROR_NONE;
329 ret = mm_sound_client_dbus_play_tone_with_stream_info(getpid(), tone, stream_type, stream_id, volume, duration, handle);
335 int mm_sound_client_play_sound(MMSoundPlayParam *param, int tone, int *handle)
337 int ret = MM_ERROR_NONE;
338 int session_type = MM_SESSION_TYPE_MEDIA;
339 int session_options = 0;
340 int is_focus_registered = 0;
341 // int instance = -1; /* instance is unique to communicate with server : client message queue filter type */
342 int volume_type = MM_SOUND_VOLUME_CONFIG_TYPE(param->volume_config);
343 char stream_type[MM_SOUND_STREAM_TYPE_LEN] = {0, };
347 /* read session information */
349 ret = mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &is_focus_registered);
351 debug_error("mm_sound_get_signal_value failed [0x%x]", ret);
352 return MM_ERROR_POLICY_INTERNAL;
355 if (is_focus_registered)
356 param->skip_session = true;
358 if (param->skip_session == false) {
359 if(MM_ERROR_NONE != _mm_session_util_read_information(-1, &session_type, &session_options))
361 debug_warning("[Client] Read MMSession Type failed. use default \"media\" type\n");
362 session_type = MM_SESSION_TYPE_MEDIA;
364 if(MM_ERROR_NONE != mm_session_init(session_type))
366 debug_critical("[Client] MMSessionInit() failed\n");
367 return MM_ERROR_POLICY_INTERNAL;
372 // instance = getpid();
373 // debug_msg("[Client] pid for client ::: [%d]\n", instance);
376 if ((param->mem_ptr && param->mem_size))
378 // Play memory, deprecated
379 return MM_ERROR_INVALID_ARGUMENT;
382 mm_sound_convert_volume_type_to_stream_type(volume_type, stream_type);
383 ret = mm_sound_client_dbus_play_sound(param->filename, tone, param->loop, param->volume, param->volume_config,
384 param->priority, session_type, session_options, getpid(), param->handle_route,
385 !param->skip_session, handle, stream_type, -1);
386 if (ret != MM_ERROR_NONE) {
387 debug_error("Play Sound Failed");
390 if (param->callback) {
391 ret = mm_sound_client_dbus_add_play_sound_end_callback(*handle, param->callback, param->data);
392 if (ret != MM_ERROR_NONE) {
393 debug_error("Add callback for play sound(%d) Failed", *handle);
396 if (!param->skip_session && !g_focus_signal_handle) {
397 ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &g_focus_signal_handle, _mm_sound_client_focus_signal_callback, NULL);
399 debug_error("mm_sound_subscribe_signal failed [0x%x]", ret);
400 return MM_ERROR_POLICY_INTERNAL;
410 int mm_sound_client_play_sound_with_stream_info(MMSoundPlayParam *param, int *handle, char* stream_type, int stream_id)
412 int ret = MM_ERROR_NONE;
414 ret = mm_sound_client_dbus_play_sound_with_stream_info(param->filename, param->loop, param->volume,
415 param->priority, getpid(), param->handle_route, handle, stream_type, stream_id);
416 if (ret != MM_ERROR_NONE) {
417 debug_error("Play Sound Failed");
420 if (param->callback) {
421 ret = mm_sound_client_dbus_add_play_sound_end_callback(*handle, param->callback, param->data);
422 if (ret != MM_ERROR_NONE) {
423 debug_error("Add callback for play sound(%d) Failed", *handle);
434 int mm_sound_client_stop_sound(int handle)
436 int ret = MM_ERROR_NONE;
439 if (handle < 0 || handle > CLIENT_HANDLE_MAX) {
440 ret = MM_ERROR_INVALID_ARGUMENT;
444 ret = mm_sound_client_dbus_stop_sound(handle);
450 static int _mm_sound_client_device_list_clear ()
452 int ret = MM_ERROR_NONE;
454 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_device_list_mutex, MM_ERROR_SOUND_INTERNAL);
456 if (g_device_list_t.list) {
457 g_list_free_full(g_device_list_t.list, g_free);
458 g_device_list_t.list = NULL;
461 MMSOUND_LEAVE_CRITICAL_SECTION(&g_device_list_mutex);
466 static int _mm_sound_client_device_list_dump (GList *device_list)
468 int ret = MM_ERROR_NONE;
470 mm_sound_device_t *device_node = NULL;
473 debug_error("Device list NULL, cannot dump list");
474 return MM_ERROR_SOUND_INTERNAL;
477 debug_log("======================== device list : start ==========================\n");
478 for (list = device_list; list != NULL; list = list->next) {
479 device_node = (mm_sound_device_t *)list->data;
481 debug_log(" list idx[%d]: type[%17s], id[%02d], io_direction[%d], state[%d], name[%s]\n",
482 count++, device_node->type, device_node->id, device_node->io_direction, device_node->state, device_node->name);
485 debug_log("======================== device list : end ============================\n");
490 int mm_sound_client_get_current_connected_device_list(int device_flags, mm_sound_device_list_t **device_list)
492 int ret = MM_ERROR_NONE;
495 ret = _mm_sound_client_device_list_clear();
497 debug_error("[Client] failed to __mm_sound_client_device_list_clear(), ret[0x%x]\n", ret);
501 if ((ret = mm_sound_client_dbus_get_current_connected_device_list(device_flags, &g_device_list_t.list)) != MM_ERROR_NONE) {
502 debug_error("[Client] failed to get current connected device list with dbus, ret[0x%x]", ret);
505 if (!g_device_list_t.list) {
506 debug_error("Got device list null");
507 ret = MM_ERROR_SOUND_NO_DATA;
510 // g_device_list_t.list = g_device_list;
511 _mm_sound_client_device_list_dump(g_device_list_t.list);
512 *device_list = &g_device_list_t;
519 int mm_sound_client_add_device_connected_callback(int device_flags, mm_sound_device_connected_cb func, void* user_data)
521 int ret = MM_ERROR_NONE;
525 ret = mm_sound_client_dbus_add_device_connected_callback(device_flags, func, user_data);
532 int mm_sound_client_remove_device_connected_callback(void)
534 int ret = MM_ERROR_NONE;
537 ret = mm_sound_client_dbus_remove_device_connected_callback();
543 int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_device_info_changed_cb func, void* user_data)
545 int ret = MM_ERROR_NONE;
549 ret = mm_sound_client_dbus_add_device_info_changed_callback(device_flags, func, user_data);
555 int mm_sound_client_remove_device_info_changed_callback(void)
557 int ret = MM_ERROR_NONE;
560 ret = mm_sound_client_dbus_remove_device_info_changed_callback();
566 int mm_sound_client_is_bt_a2dp_on (bool *connected, char** bt_name)
568 int ret = MM_ERROR_NONE;
572 ret = mm_sound_client_dbus_is_bt_a2dp_on(connected, bt_name);
578 int mm_sound_client_set_volume_by_type(const int volume_type, const unsigned int volume_level)
580 int ret = MM_ERROR_NONE;
584 ret = mm_sound_client_dbus_set_volume_by_type(volume_type, volume_level);
590 int mm_sound_client_add_volume_changed_callback(mm_sound_volume_changed_cb func, void* user_data)
592 int ret = MM_ERROR_NONE;
596 ret = mm_sound_client_dbus_add_volume_changed_callback(func, user_data);
602 int mm_sound_client_remove_volume_changed_callback(void)
604 int ret = MM_ERROR_NONE;
607 ret = mm_sound_client_dbus_remove_volume_changed_callback();
614 int mm_sound_client_get_audio_path(mm_sound_device_in *device_in, mm_sound_device_out *device_out)
616 int ret = MM_ERROR_NONE;
620 ret = mm_sound_client_dbus_get_audio_path(device_in, device_out);
629 int mm_sound_client_get_uniq_id(int *id)
631 static int uniq_id = 0;
632 int ret = MM_ERROR_NONE;
634 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_id_mutex, MM_ERROR_SOUND_INTERNAL);
638 ret = MM_ERROR_INVALID_ARGUMENT;
643 MMSOUND_LEAVE_CRITICAL_SECTION(&g_id_mutex);
648 int mm_sound_client_register_focus(int id, const char *stream_type, mm_sound_focus_changed_cb callback, void* user_data)
650 int ret = MM_ERROR_NONE;
653 ret = mm_sound_client_dbus_register_focus(id, stream_type, callback, user_data);
659 int mm_sound_client_unregister_focus(int id)
661 int ret = MM_ERROR_NONE;
664 ret = mm_sound_client_dbus_unregister_focus(id);
670 int mm_sound_client_acquire_focus(int id, mm_sound_focus_type_e type, const char *option)
672 int ret = MM_ERROR_NONE;
675 ret = mm_sound_client_dbus_acquire_focus(id, type, option);
681 int mm_sound_client_release_focus(int id, mm_sound_focus_type_e type, const char *option)
683 int ret = MM_ERROR_NONE;
686 mm_sound_client_dbus_release_focus(id, type, option);
692 int mm_sound_client_set_focus_watch_callback(mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, void* user_data, int *id)
694 int ret = MM_ERROR_NONE;
697 mm_sound_client_dbus_set_focus_watch_callback(focus_type, callback, user_data, id);
703 int mm_sound_client_unset_focus_watch_callback(int id)
705 int ret = MM_ERROR_NONE;
708 ret = mm_sound_client_dbus_unset_focus_watch_callback(id);
716 int mm_sound_client_add_test_callback(mm_sound_test_cb func, void* user_data)
718 int ret = MM_ERROR_NONE;
722 ret = mm_sound_client_dbus_add_test_callback(func, user_data);
728 int mm_sound_client_remove_test_callback(void)
730 int ret = MM_ERROR_NONE;
733 ret = mm_sound_client_dbus_remove_test_callback();
740 int mm_sound_client_test(int a, int b, int* getv)
742 int ret = MM_ERROR_NONE;
746 ret = mm_sound_client_dbus_test(a, b, getv);
747 debug_log("%d * %d -> result : %d", a, b, *getv);