stream is on device 59/104159/4 accepted/tizen/3.0/common/20161215.162945 accepted/tizen/3.0/ivi/20161215.043853 accepted/tizen/3.0/mobile/20161215.043654 accepted/tizen/3.0/tv/20161215.043749 accepted/tizen/3.0/wearable/20161215.043806 submit/tizen_3.0/20161213.132802 submit/tizen_3.0/20161214.084609
authorJeongho Mok <jho.mok@samsung.com>
Fri, 9 Dec 2016 11:29:20 +0000 (20:29 +0900)
committerJeongho Mok <jho.mok@samsung.com>
Tue, 13 Dec 2016 06:51:49 +0000 (15:51 +0900)
[Version] 0.10.70
[Profile] Common
[Issue Type] API

Change-Id: I80c2f9d4cd1d66b3e443822919aeb21073f3552b

common/mm_sound_dbus.c
include/mm_sound.h
include/mm_sound_client.h
include/mm_sound_device.h
include/mm_sound_intf.h
include/mm_sound_proxy.h
mm_sound_client.c
mm_sound_device.c
mm_sound_proxy.c
packaging/libmm-sound.spec

index 72c6b34..7cb760c 100644 (file)
@@ -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",
        },
index 73efcf7..94a9015 100644 (file)
@@ -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);
 
 /**
        @}
index 12ad054..486711a 100644 (file)
@@ -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__ */
index ccbb7fb..a910d1b 100644 (file)
 #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 {
index d004e4f..b562f8f 100644 (file)
@@ -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,
 
index 447e4d9..026dd6a 100644 (file)
@@ -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);
index 26b0dbf..e71d8f9 100644 (file)
@@ -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)
index 5a1e2cc..457c7c2 100644 (file)
@@ -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;
+}
+
+
index af96967..4052d09 100644 (file)
@@ -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);
index 762f06c..0974375 100644 (file)
@@ -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