Add sound_manager_reserve_release_all_focus() function in sound_manager_internal.h 15/99115/3
authorSangchul Lee <sc11.lee@samsung.com>
Tue, 22 Nov 2016 02:27:14 +0000 (11:27 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 23 Nov 2016 06:00:28 +0000 (15:00 +0900)
[Version] 0.3.77
[Profile] Common
[Issue Type] Feature Enhancement

Change-Id: I65037215608bd6c4d982ab4611f38ada9c6856b5
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
include/sound_manager_internal.h
include/sound_manager_private.h
packaging/capi-media-sound-manager.spec
src/sound_manager.c
src/sound_manager_internal.c
test/sound_manager_test.c

index 884a901..64da3b5 100644 (file)
@@ -285,6 +285,30 @@ int sound_manager_start_virtual_stream(virtual_sound_stream_h virtual_stream);
  */
 int sound_manager_stop_virtual_stream(virtual_sound_stream_h virtual_stream);
 
+
+/**
+ * @internal
+ * @brief Reserve to release all the remained acquired focuses.
+ * @since_tizen 3.0
+ *
+ * @remarks    This function should be called within sound_stream_focus_state_changed_cb(),\n
+ *     otherwise #SOUND_MANAGER_ERROR_INVALID_OPERATION will be returned.
+ *
+ * @param[in]  stream_info     The handle of stream information
+ * @return @c 0 on success,
+ *         otherwise a negative error value
+ * @retval #SOUND_MANAGER_ERROR_NONE Success
+ * @retval #SOUND_MANAGER_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #SOUND_MANAGER_ERROR_INVALID_OPERATION Invalid operation
+  * @retval #SOUND_MANAGER_ERROR_INTERNAL Internal error inside the sound system
+ * @pre Call sound_manager_create_stream_information() and sound_manager_acquire_focus() before calling this function.
+ * @see sound_manager_create_stream_information()
+ * @see sound_manager_destroy_stream_information()
+ * @see sound_manager_acquire_focus()
+ * @see sound_manager_release_focus()
+ */
+int sound_manager_reserve_release_all_focus(sound_stream_info_h stream_info, const char* extra_info);
+
 /**
  * @}
  */
index fbaaee7..84e24d9 100644 (file)
@@ -167,6 +167,9 @@ typedef struct _sound_stream_info_s {
        sound_stream_focus_state_changed_cb user_cb;
        void *user_data;
        manual_route_info_s manual_route_info;
+       GMutex stream_info_mutex;
+       GCond idle_event_cond;
+       guint idle_event_id;
 } sound_stream_info_s;
 
 typedef enum {
index f035615..7132e37 100755 (executable)
@@ -1,6 +1,6 @@
 Name:       capi-media-sound-manager
 Summary:    Sound Manager library
-Version:    0.3.76
+Version:    0.3.77
 Release:    0
 Group:      Multimedia/API
 License:    Apache-2.0
index 36affde..bb33c99 100644 (file)
@@ -200,6 +200,8 @@ int sound_manager_create_stream_information(sound_stream_type_e stream_type, sou
        }
 
        memset(stream_h, 0, sizeof(sound_stream_info_s));
+       g_mutex_init(&stream_h->stream_info_mutex);
+       g_cond_init(&stream_h->idle_event_cond);
        ret = _convert_stream_type(stream_type, &stream_h->stream_type);
        if (ret == MM_ERROR_NONE) {
                ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data);
@@ -222,6 +224,7 @@ LEAVE:
 int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
 {
        int ret = MM_ERROR_NONE;
+       gint64 end_time = 0;
        sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
 
        LOGI(">> enter");
@@ -229,12 +232,26 @@ int sound_manager_destroy_stream_information(sound_stream_info_h stream_info)
        SM_INSTANCE_CHECK(stream_h);
 
        SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL);
+       g_mutex_lock(&stream_h->stream_info_mutex);
+
+       if (stream_h->idle_event_id > 0) {
+               end_time = g_get_monotonic_time() + G_TIME_SPAN_MILLISECOND * 1500;
+               if (g_cond_wait_until(&stream_h->idle_event_cond, &stream_h->stream_info_mutex, end_time))
+                       LOGW("signal received for idle_event_cond");
+               else
+                       LOGE("cond wait timeout");
+       }
+
        ret = _destroy_pa_connection_and_unregister_focus(stream_h);
+       g_mutex_unlock(&stream_h->stream_info_mutex);
        if (ret == MM_ERROR_NONE) {
+               g_cond_clear(&stream_h->idle_event_cond);
+               g_mutex_clear(&stream_h->stream_info_mutex);
                free(stream_h);
                stream_h = NULL;
                SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
        }
+
        SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
 
        LOGD("cnt(%d)", g_stream_info_count);
@@ -337,15 +354,18 @@ int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_fo
        LOGI(">> enter");
 
        SM_INSTANCE_CHECK(stream_h);
+       g_mutex_lock(&stream_h->stream_info_mutex);
 
        if (stream_h->is_focus_unavailable) {
                LOGE("acquiring focus is not allowed for this strema type(%s)", stream_h->stream_type);
-               return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
+               ret = MM_ERROR_POLICY_INTERNAL;
+               goto LEAVE;
        }
 
        if (stream_h->user_cb == NULL) {
                LOGE("focus state changed callback should be set before acquiring focus");
-               return _convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL);
+               ret = MM_ERROR_POLICY_INTERNAL;
+               goto LEAVE;
        }
 
        ret = mm_sound_acquire_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
@@ -354,6 +374,9 @@ int sound_manager_acquire_focus(sound_stream_info_h stream_info, sound_stream_fo
                _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
        }
 
+LEAVE:
+       g_mutex_unlock(&stream_h->stream_info_mutex);
+
        return _convert_sound_manager_error_code(__func__, ret);
 }
 
@@ -365,6 +388,7 @@ int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_fo
        LOGI(">> enter");
 
        SM_INSTANCE_CHECK(stream_h);
+       g_mutex_lock(&stream_h->stream_info_mutex);
 
        ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)focus_mask, stream_h->requesting_flags, extra_info);
        if (ret == MM_ERROR_NONE) {
@@ -372,6 +396,8 @@ int sound_manager_release_focus(sound_stream_info_h stream_info, sound_stream_fo
                _update_focus_status(stream_h->index, (unsigned int)stream_h->acquired_focus);
        }
 
+       g_mutex_unlock(&stream_h->stream_info_mutex);
+
        return _convert_sound_manager_error_code(__func__, ret);
 }
 
index 6e883d4..6c2382d 100644 (file)
 extern int g_stream_info_count;
 extern pthread_mutex_t g_stream_info_count_mutex;
 
+typedef struct _idle_cb_user_data_s {
+       sound_stream_info_s *stream_h;
+       const char *extra_info;
+} idle_cb_user_data_s;
+
 #ifndef TIZEN_FEATURE_TV_PROD
 int sound_manager_get_max_master_volume(int *max_level)
 {
@@ -218,3 +223,87 @@ int sound_manager_stop_virtual_stream(virtual_sound_stream_h virtual_stream)
 
        return _convert_sound_manager_error_code(__func__, ret);
 }
+
+static bool _release_idle_event_cb(void *data)
+{
+       int ret = MM_ERROR_NONE;
+       idle_cb_user_data_s *cb_data = (idle_cb_user_data_s*)data;
+       sound_stream_info_s *stream_h = NULL;
+
+       LOGI(">> enter");
+
+       if (cb_data == NULL || cb_data->stream_h == NULL) {
+               LOGW("cb_data or stream_h is null");
+               if (cb_data)
+                       free(data);
+               return false;
+       }
+       stream_h = cb_data->stream_h;
+
+       g_mutex_lock(&stream_h->stream_info_mutex);
+
+       if (stream_h->acquired_focus == 0) {
+               LOGW("all the focuses are already released...");
+               goto LEAVE;
+       }
+
+       ret = mm_sound_release_focus_with_option(stream_h->index, (mm_sound_focus_type_e)stream_h->acquired_focus, stream_h->requesting_flags, cb_data->extra_info);
+       if (ret == MM_ERROR_NONE) {
+               stream_h->acquired_focus = 0x0;
+               _update_focus_status(stream_h->index, 0x0);
+       }
+
+LEAVE:
+       stream_h->idle_event_id = 0;
+       g_mutex_unlock(&stream_h->stream_info_mutex);
+       g_cond_signal(&stream_h->idle_event_cond);
+       free(data);
+       LOGI("<< leave");
+
+       return false;
+}
+
+int sound_manager_reserve_release_all_focus(sound_stream_info_h stream_info, const char* extra_info)
+{
+       int ret = MM_ERROR_NONE;
+       bool is_focus_cb_thread = false;
+       sound_stream_info_s *stream_h = (sound_stream_info_s*)stream_info;
+
+       LOGI(">> enter");
+
+       SM_INSTANCE_CHECK(stream_h);
+       g_mutex_lock(&stream_h->stream_info_mutex);
+
+       if (stream_h->acquired_focus == 0) {
+               LOGW("there's no acquired focus now...");
+               goto LEAVE;
+       }
+
+       if ((ret = mm_sound_focus_is_cb_thread(&is_focus_cb_thread)))
+               goto LEAVE;
+
+       if (!is_focus_cb_thread) {
+               LOGE("this API should be called in focus callback");
+               ret = MM_ERROR_SOUND_INVALID_OPERATION;
+               goto LEAVE;
+       }
+
+       idle_cb_user_data_s* cb_data = malloc(sizeof(idle_cb_user_data_s));
+       if (!cb_data) {
+               ret = MM_ERROR_OUT_OF_MEMORY;
+               goto LEAVE;
+       }
+
+       memset(cb_data, 0, sizeof(idle_cb_user_data_s));
+       cb_data->stream_h = stream_h;
+       cb_data->extra_info = extra_info;
+
+       stream_h->idle_event_id = g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)_release_idle_event_cb, (void*)cb_data, NULL);
+       if (stream_h->idle_event_id == 0)
+               ret = MM_ERROR_SOUND_INTERNAL;
+
+LEAVE:
+       g_mutex_unlock(&stream_h->stream_info_mutex);
+
+       return _convert_sound_manager_error_code(__func__, ret);
+}
index 3981aab..f5f2bec 100644 (file)
@@ -131,6 +131,11 @@ void focus_callback(sound_stream_info_h stream_info, sound_stream_focus_change_r
        if (!ret)
                g_print(" - focus_state : PLAYBACK(%d), RECORDING(%d) (0:released, 1:acquired)\n", playback_focus_state, recording_focus_state);
 
+#if 0
+       if (playback_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED || recording_focus_state == SOUND_STREAM_FOCUS_STATE_ACQUIRED)
+               sound_manager_reserve_release_all_focus(stream_info, "from_release_all_func");
+#endif
+
        g_print("*** FOCUS callback is ended, stream_info(%p) ****\n\n", stream_info);
 
        return;