From 4dfe70abd318b43b9918977b836ee92ac3411f70 Mon Sep 17 00:00:00 2001 From: Jeongho Mok Date: Fri, 9 Dec 2016 20:29:20 +0900 Subject: [PATCH] stream is on device [Version] 0.10.70 [Profile] Common [Issue Type] API Change-Id: I80c2f9d4cd1d66b3e443822919aeb21073f3552b (cherry picked from commit 1a45b32b1fa3b9a90fa5618a2b9fe840498e2736) --- common/mm_sound_dbus.c | 3 + include/mm_sound.h | 1 + include/mm_sound_client.h | 7 +- include/mm_sound_device.h | 6 ++ include/mm_sound_intf.h | 1 + include/mm_sound_proxy.h | 1 + mm_sound_client.c | 96 ++++++++++++++++++++------- mm_sound_device.c | 37 +++++++++++ mm_sound_proxy.c | 161 ++++++++++++++++++++++++++++++++++++++++----- packaging/libmm-sound.spec | 2 +- 10 files changed, 271 insertions(+), 44 deletions(-) diff --git a/common/mm_sound_dbus.c b/common/mm_sound_dbus.c index 72c6b34..7cb760c 100644 --- a/common/mm_sound_dbus.c +++ b/common/mm_sound_dbus.c @@ -81,6 +81,9 @@ const mm_sound_dbus_method_info_t g_methods[AUDIO_METHOD_MAX] = { [AUDIO_METHOD_GET_CONNECTED_DEVICE_LIST] = { .name = "GetConnectedDeviceList", }, + [AUDIO_METHOD_IS_STREAM_ON_DEVICE] = { + .name = "IsStreamOnDevice", + }, [AUDIO_METHOD_GET_UNIQUE_ID] = { .name = "GetUniqueId", }, diff --git a/include/mm_sound.h b/include/mm_sound.h index cd6db54..2b10cdb 100644 --- a/include/mm_sound.h +++ b/include/mm_sound.h @@ -1036,6 +1036,7 @@ int mm_sound_subscribe_signal_for_daemon(mm_sound_signal_name_t signal, int clie void mm_sound_unsubscribe_signal(unsigned int subscribe_id); int mm_sound_send_signal(mm_sound_signal_name_t signal, int value); int mm_sound_get_signal_value(mm_sound_signal_name_t signal, int *value); +int mm_sound_is_stream_on_device(int stream_id, MMSoundDevice_t device_h, bool *is_on); /** @} diff --git a/include/mm_sound_client.h b/include/mm_sound_client.h index 12ad054..486711a 100644 --- a/include/mm_sound_client.h +++ b/include/mm_sound_client.h @@ -47,6 +47,7 @@ int mm_sound_client_add_device_info_changed_callback(int device_flags, mm_sound_ int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id); int mm_sound_client_add_device_state_changed_callback(int device_flags, mm_sound_device_state_changed_cb func, void *userdata, unsigned int *id); int mm_sound_client_remove_device_state_changed_callback(unsigned int id); +int mm_sound_client_is_stream_on_device(int stream_id, int device_id, bool *is_on); #ifdef USE_FOCUS int mm_sound_client_set_session_interrupt_callback(mm_sound_focus_session_interrupt_cb callback, void* user_data); int mm_sound_client_unset_session_interrupt_callback(void); @@ -69,11 +70,11 @@ int mm_sound_client_test(int a, int b, int* get); typedef void (*mm_sound_volume_changed_wrapper_cb)(const char *direction, const char *volume_type_str, int volume_level, void *userdata); typedef void (*mm_sound_device_connected_wrapper_cb)(int device_id, const char *device_type, int io_direction, int state, - const char *name, gboolean is_connected, void *userdata); + const char *name, int *stream_id, int stream_num, gboolean is_connected, void *userdata); typedef void (*mm_sound_device_info_changed_wrapper_cb)(int device_id, const char *device_type, int io_direction, int state, - const char *name, int changed_device_info_type, void *userdata); + const char *name, int *stream_id, int stream_num, int changed_device_info_type, void *userdata); typedef void (*mm_sound_device_state_changed_wrapper_cb)(int device_id, const char *device_type, int io_direction, int state, - const char *name, void *userdata); + const char *name, int *stream_id, int stream_num, void *userdata); typedef void (*mm_sound_stop_callback_wrapper_func)(int id, void *userdata); #endif /* __MM_SOUND_CLIENT_H__ */ diff --git a/include/mm_sound_device.h b/include/mm_sound_device.h index ccbb7fb..a910d1b 100644 --- a/include/mm_sound_device.h +++ b/include/mm_sound_device.h @@ -39,12 +39,18 @@ #endif #define MAX_DEVICE_NAME_NUM 256 #define MAX_DEVICE_TYPE_STR_LEN 30 +#define MAX_STREAM_ON_DEVICE 32 typedef struct { char type[MAX_DEVICE_TYPE_STR_LEN]; int io_direction; int id; char name[MAX_DEVICE_NAME_NUM]; int state; + + /* This is filled only when device handle is passed through callback */ + int stream_id[MAX_STREAM_ON_DEVICE]; + /* When this value is less than 0, should query to server-side */ + int stream_num; } mm_sound_device_t; typedef struct { diff --git a/include/mm_sound_intf.h b/include/mm_sound_intf.h index d004e4f..b562f8f 100644 --- a/include/mm_sound_intf.h +++ b/include/mm_sound_intf.h @@ -54,6 +54,7 @@ typedef enum audio_method { AUDIO_METHOD_GET_BT_A2DP_STATUS, AUDIO_METHOD_SET_PATH_FOR_ACTIVE_DEVICE, AUDIO_METHOD_GET_CONNECTED_DEVICE_LIST, + AUDIO_METHOD_IS_STREAM_ON_DEVICE, AUDIO_METHOD_GET_AUDIO_PATH, AUDIO_METHOD_SET_VOLUME_LEVEL, diff --git a/include/mm_sound_proxy.h b/include/mm_sound_proxy.h index 447e4d9..026dd6a 100644 --- a/include/mm_sound_proxy.h +++ b/include/mm_sound_proxy.h @@ -60,6 +60,7 @@ int mm_sound_proxy_add_device_info_changed_callback(int device_flags, mm_sound_d int mm_sound_proxy_remove_device_info_changed_callback(unsigned subs_id); int mm_sound_proxy_add_device_state_changed_callback(int device_flags, mm_sound_device_state_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id); int mm_sound_proxy_remove_device_state_changed_callback(unsigned subs_id); +int mm_sound_proxy_is_stream_on_device(int stream_id, int device_id, bool *is_on); int mm_sound_proxy_set_volume_by_type(const char *volume_type, const unsigned volume_level); int mm_sound_proxy_add_volume_changed_callback(mm_sound_volume_changed_wrapper_cb func, void* userdata, mm_sound_proxy_userdata_free freefunc, unsigned *subs_id); int mm_sound_proxy_remove_volume_changed_callback(unsigned subs_id); diff --git a/mm_sound_client.c b/mm_sound_client.c index 26b0dbf..e71d8f9 100644 --- a/mm_sound_client.c +++ b/mm_sound_client.c @@ -645,15 +645,52 @@ static bool device_is_match_with_mask(const char *type, int direction, int state device_is_match_type(type, mask & DEVICE_TYPE_FLAGS)); } +static int _fill_sound_device(mm_sound_device_t *device_h, int device_id, const char *device_type, + int direction, int state, const char *name, int *stream_id, int stream_num) +{ + int i; + + if (stream_num > 0 && stream_id == NULL) { + debug_error("stream_num is %d, but stream_id is NULL", stream_num); + return -1; + } + + if (stream_num > MAX_STREAM_ON_DEVICE) { + debug_error("too many streams on this device"); + return -1; + } + + device_h->id = device_id; + device_h->io_direction = direction; + device_h->state = state; + MMSOUND_STRNCPY(device_h->name, name, MAX_DEVICE_NAME_NUM); + MMSOUND_STRNCPY(device_h->type, device_type, MAX_DEVICE_TYPE_STR_LEN); + + if (stream_num > 0) { + device_h->stream_num = stream_num; + debug_log("%d streams on this device", stream_num); + for (i = 0; i < stream_num; i++) { + debug_log(" stream_id : %d", stream_id[i]); + device_h->stream_id[i] = stream_id[i]; + } + } else { + device_h->stream_num = 0; + debug_log("There is no stream on this device"); + } + + return 0; +} + static 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) + int state, const char *name, int *stream_id, int stream_num, gboolean is_connected, void *userdata) { mm_sound_device_t device_h; struct callback_data *cb_data = (struct callback_data*) userdata; int device_flags; - debug_log("[Device Connnected] id(%d) type(%s) direction(%d) state(%d) name(%s) is_connected(%d)", - device_id, device_type, io_direction, state, name, is_connected); + debug_log("[Device %s] id(%d) type(%s) direction(%d) state(%d) name(%s)", + is_connected ? "Connected" : "Disconnected", device_id, device_type, io_direction, + state, name, is_connected); if (cb_data == NULL) { debug_warning("device connected changed callback data null"); @@ -661,15 +698,13 @@ static void _mm_sound_device_connected_callback_wrapper_func(int device_id, cons } device_flags = (int) cb_data->extra_data; - if (!device_is_match_with_mask(device_type, io_direction, state, device_flags)) return; - device_h.id = device_id; - device_h.io_direction = io_direction; - device_h.state = state; - MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM); - MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN); + if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name, stream_id, stream_num) < 0) { + debug_error("Failed to fill sound device"); + return; + } ((mm_sound_device_connected_cb)(cb_data->user_cb))(&device_h, is_connected, cb_data->user_data); } @@ -703,7 +738,7 @@ int mm_sound_client_remove_device_connected_callback(unsigned int subs_id) } 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) + int state, const char *name, int *stream_id, int stream_num, int changed_device_info_type, void *userdata) { mm_sound_device_t device_h; struct callback_data *cb_data = (struct callback_data*) userdata; @@ -718,15 +753,13 @@ static void _mm_sound_device_info_changed_callback_wrapper_func(int device_id, c } device_flags = (int) cb_data->extra_data; - if (!device_is_match_with_mask(device_type, io_direction, state, device_flags)) return; - device_h.id = device_id; - device_h.io_direction = io_direction; - device_h.state = state; - MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM); - MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN); + if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name, stream_id, stream_num) < 0) { + debug_error("Failed to fill sound device"); + return; + } ((mm_sound_device_info_changed_cb)(cb_data->user_cb))(&device_h, changed_device_info_type, cb_data->user_data); } @@ -759,7 +792,7 @@ int mm_sound_client_remove_device_info_changed_callback(unsigned int subs_id) } static void _mm_sound_device_state_changed_callback_wrapper_func(int device_id, const char *device_type, int io_direction, - int state, const char *name, void *userdata) + int state, const char *name, int *stream_id, int stream_num, void *userdata) { mm_sound_device_t device_h; struct callback_data *cb_data = (struct callback_data*) userdata; @@ -778,11 +811,10 @@ static void _mm_sound_device_state_changed_callback_wrapper_func(int device_id, if (!device_is_match_with_mask(device_type, io_direction, state, device_flags)) return; - device_h.id = device_id; - device_h.io_direction = io_direction; - device_h.state = state; - MMSOUND_STRNCPY(device_h.name, name, MAX_DEVICE_NAME_NUM); - MMSOUND_STRNCPY(device_h.type, device_type, MAX_DEVICE_TYPE_STR_LEN); + if (_fill_sound_device(&device_h, device_id, device_type, io_direction, state, name, stream_id, stream_num) < 0) { + debug_error("Failed to fill sound device"); + return; + } ((mm_sound_device_state_changed_cb)(cb_data->user_cb))(&device_h, state, cb_data->user_data); } @@ -811,7 +843,27 @@ int mm_sound_client_remove_device_state_changed_callback(unsigned int id) debug_fleave(); return ret; +} + +int mm_sound_client_is_stream_on_device(int stream_id, int device_id, bool *is_on) +{ + int ret = MM_ERROR_NONE; + debug_fenter(); + + if (!is_on) { + debug_error("Invalid Parameter"); + ret = MM_ERROR_COMMON_INVALID_ARGUMENT; + goto failed; + } + if ((ret = mm_sound_proxy_is_stream_on_device(stream_id, device_id, is_on)) != MM_ERROR_NONE) { + debug_error("[Client] failed to query is stream on device, ret[0x%x]", ret); + goto failed; + } + +failed: + debug_fleave(); + return ret; } int __convert_volume_type_to_str(int volume_type, char **volume_type_str) diff --git a/mm_sound_device.c b/mm_sound_device.c index 5a1e2cc..457c7c2 100644 --- a/mm_sound_device.c +++ b/mm_sound_device.c @@ -407,3 +407,40 @@ int mm_sound_get_device_name(MMSoundDevice_t device_h, char **name) return MM_ERROR_NONE; } +EXPORT_API +int mm_sound_is_stream_on_device(int stream_id, MMSoundDevice_t device_h, bool *is_on) +{ + int ret = MM_ERROR_NONE; + int i; + mm_sound_device_t *device = (mm_sound_device_t*)device_h; + bool _is_on = false; + + if(!device || !is_on) { + debug_error("invalid argument\n"); + return MM_ERROR_INVALID_ARGUMENT; + } + + if (device->stream_num >= 0) { + debug_log("device_handle has stream id"); + for (i = 0; i < device->stream_num; i++) { + if (device->stream_id[i] == stream_id) { + _is_on = true; + break; + } + } + } else { + debug_log("device_handle dosn't have stream id"); + /* No information about stream in client-side, should ask to server-side */ + if ((ret = mm_sound_client_is_stream_on_device(stream_id, device->id, &_is_on)) < 0) { + debug_error("Failed to query is stream on"); + return MM_ERROR_SOUND_INTERNAL; + } + } + + debug_log("device(%d) %s stream(%d)\n", device->id, _is_on ? "has" : "doesn't have", stream_id); + *is_on = _is_on; + + return ret; +} + + diff --git a/mm_sound_proxy.c b/mm_sound_proxy.c index af96967..4052d09 100644 --- a/mm_sound_proxy.c +++ b/mm_sound_proxy.c @@ -79,12 +79,63 @@ static int _notify_signal_handled(audio_event_t event, uint32_t event_id, uint32 return ret; } +static int parse_device_variant(GVariant *v, int *device_id, const char **device_type, int *direction, int *state, + const char **device_name, int *stream_id, int *stream_num) +{ + const char *v_type; + GVariant *array_v; + GVariantIter iter, array_iter; + int i = 0; + int ret = MM_ERROR_NONE; + + if (v == NULL) { + debug_error("Variant NULL"); + return MM_ERROR_NONE; + } + + v_type = g_variant_get_type_string(v); + if (g_variant_type_equal(v_type, "(isiisai)") == FALSE) { + debug_error("device variant type not matching '%s'", v_type); + return MM_ERROR_NONE; + } + + g_variant_iter_init(&iter, v); + g_variant_iter_next(&iter, "i", device_id); + g_variant_iter_next(&iter, "&s", device_type); + g_variant_iter_next(&iter, "i", direction); + g_variant_iter_next(&iter, "i", state); + g_variant_iter_next(&iter, "&s", device_name); + + array_v = g_variant_iter_next_value(&iter); + *stream_num = g_variant_iter_init(&array_iter, array_v); + if (*stream_num > MAX_STREAM_ON_DEVICE) { + debug_error("too many streams on device %d", *stream_num); + ret = MM_ERROR_SOUND_INTERNAL; + goto finish; + } + + while (g_variant_iter_loop(&array_iter, "i", &stream_id[i++])) ; +finish: + g_variant_unref(array_v); + + return ret; +} + /* This callback unmarshall general-formed paramters to subject specific parameters, * and call proper callback */ static void dbus_callback(audio_event_t event, GVariant *params, void *userdata) { struct callback_data *cb_data = (struct callback_data*) userdata; uint32_t event_id; + const char *name = NULL, *device_type = NULL; + int device_id, direction, state; + const gchar *v_type; + GVariantIter iter; + GVariant *device_v; + int stream_id[MAX_STREAM_ON_DEVICE]; + int stream_num; + + v_type = g_variant_get_type_string(params); if (event == AUDIO_EVENT_VOLUME_CHANGED) { char *volume_type_str = NULL, *direction = NULL; @@ -93,32 +144,63 @@ static void dbus_callback(audio_event_t event, GVariant *params, void *userdata) g_variant_get(params, "(&s&su)", &direction, &volume_type_str, &volume_level); ((mm_sound_volume_changed_wrapper_cb)(cb_data->user_cb))(direction, volume_type_str, volume_level, cb_data->user_data); } else if (event == AUDIO_EVENT_DEVICE_CONNECTED) { - const char *name = NULL, *device_type = NULL; gboolean is_connected = FALSE; - int device_id, io_direction, state; - g_variant_get(params, "(u(i&sii&s)b)", &event_id, &device_id, &device_type, &io_direction, - &state, &name, &is_connected); - ((mm_sound_device_connected_wrapper_cb)(cb_data->user_cb))(device_id, device_type, io_direction, - state, name, is_connected, cb_data->user_data); + if (g_variant_type_equal(v_type, "(u(isiisai)b)") == FALSE) { + debug_error("Device connection changed signature not matching : %s", v_type); + return ; + } + g_variant_iter_init(&iter, params); + g_variant_iter_next(&iter, "u", &event_id); + device_v = g_variant_iter_next_value(&iter); + if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state, + &name, stream_id, &stream_num) < 0) { + debug_error("Failed to parse device variant"); + return ; + } + g_variant_iter_next(&iter, "b", &is_connected); + + ((mm_sound_device_connected_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction, + state, name, stream_id, stream_num, is_connected, cb_data->user_data); _notify_signal_handled(event, event_id, cb_data->subs_id, g_variant_new("(ib)", device_id, is_connected)); } else if (event == AUDIO_EVENT_DEVICE_INFO_CHANGED) { - const char *name = NULL, *device_type = NULL; int changed_device_info_type = 0; - int device_id, io_direction, state; - g_variant_get(params, "(u(i&sii&s)i)", &event_id, &device_id, &device_type, &io_direction, - &state, &name, &changed_device_info_type); - ((mm_sound_device_info_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, io_direction, - state, name, changed_device_info_type, cb_data->user_data); + if (g_variant_type_equal(v_type, "(u(isiisai)i)") == FALSE) { + debug_error("Device information changed signature not matching : %s", v_type); + return ; + } + + g_variant_iter_init(&iter, params); + g_variant_iter_next(&iter, "u", &event_id); + device_v = g_variant_iter_next_value(&iter); + if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state, + &name, stream_id, &stream_num) < 0) { + debug_error("Failed to parse device variant"); + return ; + } + g_variant_iter_next(&iter, "i", &changed_device_info_type); + + ((mm_sound_device_info_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction, + state, name, stream_id, stream_num, changed_device_info_type, cb_data->user_data); } else if (event == AUDIO_EVENT_DEVICE_STATE_CHANGED) { - const char *name = NULL, *device_type = NULL; - int device_id, io_direction, state; - g_variant_get(params, "(u(i&sii&s))", &event_id, &device_id, &device_type, &io_direction, - &state, &name); - ((mm_sound_device_state_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, io_direction, - state, name, cb_data->user_data); + if (g_variant_type_equal(v_type, "(u(isiisai))") == FALSE) { + debug_error("Device state changed signature not matching : %s", v_type); + return ; + } + + g_variant_iter_init(&iter, params); + g_variant_iter_next(&iter, "u", &event_id); + device_v = g_variant_iter_next_value(&iter); + if (parse_device_variant(device_v, &device_id, &device_type, &direction, &state, + &name, stream_id, &stream_num) < 0) { + debug_error("Failed to parse device variant"); + return ; + } + + ((mm_sound_device_state_changed_wrapper_cb)(cb_data->user_cb))(device_id, device_type, direction, + state, name, stream_id, stream_num, cb_data->user_data); } else if (event == AUDIO_EVENT_FOCUS_CHANGED) { } else if (event == AUDIO_EVENT_FOCUS_WATCH) { } else if (event == AUDIO_EVENT_TEST) { @@ -209,6 +291,48 @@ cleanup: return ret; } +int mm_sound_proxy_is_stream_on_device(int stream_id, int device_id, bool *is_on) +{ + int ret = MM_ERROR_NONE; + GVariant *params, *result; + gboolean _is_on; + + debug_fenter(); + + if (!is_on) { + debug_error("Invalid Parameter, is_on null"); + return MM_ERROR_INVALID_ARGUMENT; + } + + if ((params = g_variant_new("(ii)", stream_id, device_id)) == NULL) { + debug_error("Construct Param for query is stream on device failed"); + return MM_ERROR_SOUND_INTERNAL; + } + + if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_DEVICE_MANAGER, AUDIO_METHOD_IS_STREAM_ON_DEVICE, params, &result)) != MM_ERROR_NONE) { + debug_error("is stream on device failed"); + goto cleanup; + } + + if (result) { + g_variant_get(result, "(b)", &_is_on); + debug_log("is_on : %d", _is_on); + *is_on = (bool)_is_on; + } else { + debug_error("reply null"); + ret = MM_ERROR_SOUND_INTERNAL; + } + +cleanup: + if (params) + g_variant_unref(params); + if (result) + g_variant_unref(result); + + debug_fleave(); + return ret; +} + int mm_sound_proxy_get_current_connected_device_list(int device_flags, GList** device_list) { int ret = MM_ERROR_NONE; @@ -251,6 +375,7 @@ int mm_sound_proxy_get_current_connected_device_list(int device_flags, GList** d debug_log("Added device id(%d) type(%17s) direction(%d) state(%d) name(%s)", device_item->id, device_item->type,device_item->io_direction, device_item->state, device_item->name); + device_item->stream_num = -1; } else { if (device_item) g_free(device_item); diff --git a/packaging/libmm-sound.spec b/packaging/libmm-sound.spec index 762f06c..0974375 100644 --- a/packaging/libmm-sound.spec +++ b/packaging/libmm-sound.spec @@ -1,6 +1,6 @@ Name: libmm-sound Summary: MMSound Package contains client lib and sound_server binary -Version: 0.10.69 +Version: 0.10.70 Release: 0 Group: System/Libraries License: Apache-2.0 -- 2.7.4