From: Sangchul Lee Date: Fri, 8 May 2015 03:00:25 +0000 (+0900) Subject: Notify signal for releasing internal focus to the same process X-Git-Tag: submit/tizen/20150715.092047~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F15%2F41115%2F2;p=platform%2Fcore%2Fapi%2Fsound-manager.git Notify signal for releasing internal focus to the same process Change-Id: I3b153ccbd5cf12d9ae7550f01b15eddb0e2e41fa --- diff --git a/include/sound_manager_private.h b/include/sound_manager_private.h index d1e32aa..f82a568 100644 --- a/include/sound_manager_private.h +++ b/include/sound_manager_private.h @@ -60,6 +60,69 @@ extern "C" _CHECK_CONDITION(arg <= max,SOUND_MANAGER_ERROR_INVALID_PARAMETER,"SOUND_MANAGER_ERROR_INVALID_PARAMETER") \ _CHECK_CONDITION(arg >= min,SOUND_MANAGER_ERROR_INVALID_PARAMETER,"SOUND_MANAGER_ERROR_INVALID_PARAMETER") +#define SM_ENTER_CRITICAL_SECTION_WITH_RETURN(x_mutex,x_return) \ +switch ( pthread_mutex_lock( x_mutex ) ) \ +{ \ +case EINVAL: \ + LOGW("try mutex init..\n"); \ + if( 0 > pthread_mutex_init( x_mutex, NULL) ) { \ + return x_return; \ + } else { \ + break; \ + } \ + return x_return; \ +case 0: \ + break; \ +default: \ + LOGE("mutex lock failed\n"); \ + return x_return; \ +} + +#define SM_LEAVE_CRITICAL_SECTION(x_mutex) \ +if( pthread_mutex_unlock( x_mutex ) ) { \ + LOGE("mutex unlock failed\n"); \ +} + +#define SM_REF_FOR_STREAM_INFO(x_count, x_return) \ +{ \ + if (!x_count) { \ + /* send signal to other framework to release internal focus */ \ + x_return = mm_sound_send_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, 1); \ + } \ + if (x_return) \ + LOGW("failed to send signal for stream info creation"); \ + else \ + g_stream_info_count++; \ +} \ + +#define SM_UNREF_FOR_STREAM_INFO(x_count, x_return) \ +{ \ + x_count--; \ + if (!x_count) { \ + /* send signal to other framework to release internal focus */ \ + x_return = mm_sound_send_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, 0); \ + if (x_return) \ + LOGW("failed to send signal for stream info creation, ret(0x%x)", x_return); \ + } \ +} \ + +#define SM_STRNCPY(dst,src,size,err) \ +do { \ + if(src != NULL && dst != NULL && size > 0) { \ + strncpy(dst,src,size); \ + dst[size-1] = '\0'; \ + } else if(dst == NULL) { \ + LOGE("STRNCPY ERROR: Destination String is NULL\n"); \ + err = MM_ERROR_SOUND_INTERNAL; \ + } else if(size <= 0) { \ + LOGE("STRNCPY ERROR: Destination String is NULL\n"); \ + err = MM_ERROR_SOUND_INTERNAL; \ + } else { \ + LOGE("STRNCPY ERROR: Destination String is NULL\n"); \ + err = MM_ERROR_SOUND_INTERNAL; \ + } \ +} while(0) + #define SOUND_SESSION_TYPE_DEFAULT SOUND_SESSION_TYPE_MEDIA #define SOUND_STREAM_INFO_ARR_MAX 128 #define SOUND_STREAM_TYPE_LEN 64 @@ -158,23 +221,6 @@ typedef struct { sound_device_information_changed_cb user_cb; }_device_changed_info_s; -#define SOUND_STRNCPY(dst,src,size,err) \ -do { \ - if(src != NULL && dst != NULL && size > 0) { \ - strncpy(dst,src,size); \ - dst[size-1] = '\0'; \ - } else if(dst == NULL) { \ - LOGE("STRNCPY ERROR: Destination String is NULL\n"); \ - err = MM_ERROR_SOUND_INTERNAL; \ - } else if(size <= 0) { \ - LOGE("STRNCPY ERROR: Destination String is NULL\n"); \ - err = MM_ERROR_SOUND_INTERNAL; \ - } else { \ - LOGE("STRNCPY ERROR: Destination String is NULL\n"); \ - err = MM_ERROR_SOUND_INTERNAL; \ - } \ -} while(0) - void _focus_state_change_callback (int index, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data); void _focus_watch_callback (int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason_for_change, const char *additional_info, void *user_data); diff --git a/packaging/capi-media-sound-manager.spec b/packaging/capi-media-sound-manager.spec index 28e1999..b858fca 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.6 +Version: 0.3.7 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/sound_manager.c b/src/sound_manager.c index 5128ca1..cbfe3ca 100644 --- a/src/sound_manager.c +++ b/src/sound_manager.c @@ -26,6 +26,10 @@ _device_changed_info_s g_device_info_changed_cb_table = {NULL, NULL}; sound_session_type_e g_cached_session = -1; _session_mode_e g_cached_session_mode = -1; +/* These variables will be removed when session features are deprecated. */ +extern int g_stream_info_count; +extern pthread_mutex_t g_stream_info_count_mutex; + #ifdef TMP_CODE /*temporary variable for set/get voip session mode. When 2.4 feature for routing is fully implemented, it will be removed.*/ sound_session_voip_mode_e tmp_mode = -1; @@ -159,6 +163,9 @@ int sound_manager_create_stream_information (sound_stream_type_e stream_type, so SM_NULL_ARG_CHECK(stream_info); SM_NULL_ARG_CHECK(callback); + if (g_session_interrupt_cb_table.is_registered) + return __convert_sound_manager_error_code(__func__, MM_ERROR_SOUND_INTERNAL); + sound_stream_info_s *stream_h = malloc(sizeof(sound_stream_info_s)); if (!stream_h) { ret = MM_ERROR_OUT_OF_MEMORY; @@ -169,7 +176,7 @@ int sound_manager_create_stream_information (sound_stream_type_e stream_type, so ret = _make_pa_connection_and_register_focus(stream_h, callback, user_data); if (ret == MM_ERROR_NONE) { *stream_info = (sound_stream_info_h)stream_h; - LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, ret); + LOGI("<< leave : stream_h(%p), index(%u), user_cb(%p), cnt(%d), ret(%p)", stream_h, stream_h->index, stream_h->user_cb, g_stream_info_count, ret); } } if (ret) { @@ -191,7 +198,7 @@ int sound_manager_destroy_stream_information (sound_stream_info_h stream_info) ret = _destroy_pa_connection_and_unregister_focus(stream_h); - LOGI("<< leave : ret(%p)", ret); + LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret); return __convert_sound_manager_error_code(__func__, ret); } @@ -462,8 +469,10 @@ int sound_manager_set_focus_state_watch_cb (sound_stream_focus_mask_e focus_mask LOGI(">> enter"); SM_NULL_ARG_CHECK(callback); + SM_ENTER_CRITICAL_SECTION_WITH_RETURN( &g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL); if (!g_focus_watch_cb_table.user_cb) { + SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret); ret = mm_sound_set_focus_watch_callback((mm_sound_focus_type_e)focus_mask, _focus_watch_callback, user_data, &id); if (ret == MM_ERROR_NONE) { g_focus_watch_cb_table.index = id; @@ -474,7 +483,9 @@ int sound_manager_set_focus_state_watch_cb (sound_stream_focus_mask_e focus_mask ret = MM_ERROR_SOUND_INTERNAL; } - LOGI("<< leave : ret(%p)", ret); + SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex); + + LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret); return __convert_sound_manager_error_code(__func__, ret); } @@ -485,12 +496,15 @@ int sound_manager_unset_focus_state_watch_cb (void) LOGI(">> enter"); + SM_ENTER_CRITICAL_SECTION_WITH_RETURN( &g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL); + if (g_focus_watch_cb_table.user_cb) { ret = mm_sound_unset_focus_watch_callback(g_focus_watch_cb_table.index); if (ret == MM_ERROR_NONE) { g_focus_watch_cb_table.index = -1; g_focus_watch_cb_table.user_cb = NULL; g_focus_watch_cb_table.user_data = NULL; + SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret); } else { ret = MM_ERROR_SOUND_INTERNAL; } @@ -498,7 +512,9 @@ int sound_manager_unset_focus_state_watch_cb (void) ret = MM_ERROR_SOUND_INTERNAL; } - LOGI("<< leave : ret(%p)", ret); + SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex); + + LOGI("<< leave : cnt(%d), ret(%p)", g_stream_info_count, ret); return __convert_sound_manager_error_code(__func__, ret); } @@ -514,6 +530,10 @@ int sound_manager_set_session_type (sound_session_type_e type) if (type < SOUND_SESSION_TYPE_MEDIA || type > SOUND_SESSION_TYPE_VOIP) return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT); + /* it is not supported both session and stream feature at the same time */ + if (g_stream_info_count) + return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL); + switch (type) { case SOUND_SESSION_TYPE_MEDIA: new_session = MM_SESSION_TYPE_MEDIA; @@ -903,6 +923,10 @@ int sound_manager_set_session_interrupted_cb (sound_session_interrupted_cb callb if (callback == NULL) return __convert_sound_manager_error_code(__func__, MM_ERROR_INVALID_ARGUMENT); + /* it is not supported both session and stream feature at the same time */ + if (g_stream_info_count) + return __convert_sound_manager_error_code(__func__, MM_ERROR_POLICY_INTERNAL); + if (g_session_interrupt_cb_table.is_registered == 0) { ret = mm_session_init_ex(SOUND_SESSION_TYPE_DEFAULT /*default*/ , _session_interrupt_cb, NULL); if (ret != 0) diff --git a/src/sound_manager_private.c b/src/sound_manager_private.c index b47eea0..acd6d46 100644 --- a/src/sound_manager_private.c +++ b/src/sound_manager_private.c @@ -30,6 +30,8 @@ extern _session_interrupt_info_s g_session_interrupt_cb_table; extern _session_mode_e g_cached_session_mode; extern _focus_watch_info_s g_focus_watch_cb_table; extern sound_stream_info_s* sound_stream_info_arr[SOUND_STREAM_INFO_ARR_MAX]; +int g_stream_info_count = 0; +pthread_mutex_t g_stream_info_count_mutex = PTHREAD_MUTEX_INITIALIZER; int __convert_sound_manager_error_code (const char *func, int code) { int ret = SOUND_MANAGER_ERROR_NONE; @@ -102,31 +104,31 @@ int __convert_stream_type (sound_stream_type_e stream_type_enum, char *stream_ty switch (stream_type_enum) { case SOUND_STREAM_TYPE_MEDIA: - SOUND_STRNCPY(stream_type,"media",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"media",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_SYSTEM: - SOUND_STRNCPY(stream_type,"system",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"system",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_ALARM: - SOUND_STRNCPY(stream_type,"alarm",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"alarm",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_NOTIFICATION: - SOUND_STRNCPY(stream_type,"notification",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"notification",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_EMERGENCY: - SOUND_STRNCPY(stream_type,"emergency",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"emergency",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_VOICE_INFORMATION: - SOUND_STRNCPY(stream_type,"voice-information",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"voice-information",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_VOICE_RECOGNITION: - SOUND_STRNCPY(stream_type,"voice-recognition",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"voice-recognition",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_RINGTONE_VOIP: - SOUND_STRNCPY(stream_type,"ringtone-voip",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"ringtone-voip",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_VOIP: - SOUND_STRNCPY(stream_type,"voip",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"voip",SOUND_STREAM_TYPE_LEN,ret); break; default: LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum); @@ -148,19 +150,19 @@ int __convert_stream_type_for_internal (sound_stream_type_internal_e stream_type switch (stream_type_enum) { case SOUND_STREAM_TYPE_RINGTONE_CALL: - SOUND_STRNCPY(stream_type,"ringtone-call",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"ringtone-call",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_VOICE_CALL: - SOUND_STRNCPY(stream_type,"call-voice",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"call-voice",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_VIDEO_CALL: - SOUND_STRNCPY(stream_type,"call-video",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"call-video",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_RADIO: - SOUND_STRNCPY(stream_type,"radio",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"radio",SOUND_STREAM_TYPE_LEN,ret); break; case SOUND_STREAM_TYPE_LOOPBACK: - SOUND_STRNCPY(stream_type,"loopback",SOUND_STREAM_TYPE_LEN,ret); + SM_STRNCPY(stream_type,"loopback",SOUND_STREAM_TYPE_LEN,ret); break; default: LOGE("could not find the stream_type[%d] in this switch case statement", stream_type_enum); @@ -966,6 +968,9 @@ int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_ int ret = MM_ERROR_NONE; int pa_ret = PA_OK; int i = 0; + + SM_ENTER_CRITICAL_SECTION_WITH_RETURN( &g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL); + if (!(stream_h->pa_mainloop = pa_threaded_mainloop_new())) goto PA_ERROR; @@ -1010,6 +1015,8 @@ int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_ pa_threaded_mainloop_unlock(stream_h->pa_mainloop); + SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret); + /* register focus */ ret = mm_sound_register_focus(stream_h->index, stream_h->stream_type, _focus_state_change_callback, user_data); if (ret == MM_ERROR_NONE) { @@ -1025,9 +1032,12 @@ int _make_pa_connection_and_register_focus(sound_stream_info_s *stream_h, sound_ if (i == SOUND_STREAM_INFO_ARR_MAX) { LOGE("client sound stream info array is full"); ret = mm_sound_unregister_focus(stream_h->index); + SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret); goto PA_ERROR; } } else { + LOGE("failed to register focus, ret(0x%x)", ret); + SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret); /* disconnect */ goto PA_ERROR; } @@ -1068,7 +1078,10 @@ PA_ERROR: free(stream_h); ret = MM_ERROR_SOUND_INTERNAL; LOGE("pa_ret(%d), ret(%p)", pa_ret, ret); + SUCCESS: + SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex); + return ret; } @@ -1077,6 +1090,8 @@ int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h) int i = 0; int ret = MM_ERROR_NONE; + SM_ENTER_CRITICAL_SECTION_WITH_RETURN( &g_stream_info_count_mutex, MM_ERROR_SOUND_INTERNAL); + if (stream_h->pa_context) { pa_context_disconnect(stream_h->pa_context); pa_context_unref(stream_h->pa_context); @@ -1090,6 +1105,8 @@ int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h) /* unregister focus */ ret = mm_sound_unregister_focus(stream_h->index); + if (ret) + LOGE("failed to unregister focus, ret(0x%x)", ret); for (i = 0; i < AVAIL_DEVICES_MAX; i++) { if (stream_h->stream_conf_info.avail_in_devices[i]) { @@ -1117,5 +1134,9 @@ int _destroy_pa_connection_and_unregister_focus(sound_stream_info_s *stream_h) } free(stream_h); + SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret); + + SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex); + return ret; }