From: Sangchul Lee Date: Tue, 22 Nov 2016 02:27:14 +0000 (+0900) Subject: Add sound_manager_reserve_release_all_focus() function in sound_manager_internal.h X-Git-Tag: accepted/tizen/common/20161202.233214~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1d8fe1b04be719b7f45a0163408c6fb51c00ee8f;p=platform%2Fcore%2Fapi%2Fsound-manager.git Add sound_manager_reserve_release_all_focus() function in sound_manager_internal.h [Version] 0.3.77 [Profile] Common [Issue Type] Feature Enhancement Change-Id: I65037215608bd6c4d982ab4611f38ada9c6856b5 Signed-off-by: Sangchul Lee --- diff --git a/include/sound_manager_internal.h b/include/sound_manager_internal.h index 884a901..64da3b5 100644 --- a/include/sound_manager_internal.h +++ b/include/sound_manager_internal.h @@ -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); + /** * @} */ diff --git a/include/sound_manager_private.h b/include/sound_manager_private.h index fbaaee7..84e24d9 100644 --- a/include/sound_manager_private.h +++ b/include/sound_manager_private.h @@ -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 { diff --git a/packaging/capi-media-sound-manager.spec b/packaging/capi-media-sound-manager.spec index f035615..7132e37 100755 --- a/packaging/capi-media-sound-manager.spec +++ b/packaging/capi-media-sound-manager.spec @@ -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 diff --git a/src/sound_manager.c b/src/sound_manager.c index 36affde..bb33c99 100644 --- a/src/sound_manager.c +++ b/src/sound_manager.c @@ -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); } diff --git a/src/sound_manager_internal.c b/src/sound_manager_internal.c index 6e883d4..6c2382d 100644 --- a/src/sound_manager_internal.c +++ b/src/sound_manager_internal.c @@ -23,6 +23,11 @@ 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); +} diff --git a/test/sound_manager_test.c b/test/sound_manager_test.c index 3981aab..f5f2bec 100644 --- a/test/sound_manager_test.c +++ b/test/sound_manager_test.c @@ -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;