Notify signal for releasing internal focus to the same process 15/41115/2
authorSangchul Lee <sc11.lee@samsung.com>
Fri, 8 May 2015 03:00:25 +0000 (12:00 +0900)
committerSangchul Lee <sc11.lee@samsung.com>
Wed, 8 Jul 2015 05:37:50 +0000 (14:37 +0900)
Change-Id: I3b153ccbd5cf12d9ae7550f01b15eddb0e2e41fa

include/sound_manager_private.h
packaging/capi-media-sound-manager.spec
src/sound_manager.c
src/sound_manager_private.c

index d1e32aaea6f41da39cc2c26029f0da8db176214c..f82a568e9deed023ebe5cca31543b242e2571c79 100644 (file)
@@ -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);
index 28e19999625809fd8486804085b452567ff3cd1e..b858fca60f13c00bb92f71fc039732481433ea42 100755 (executable)
@@ -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
index 5128ca172137c3d24b6a1d94db02dd183a3468c5..cbfe3ca30a360c0b1fff3f2b2fd49d3e7aa11632 100644 (file)
@@ -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)
index b47eea03c4a280564f58c2e5eba59418f337db01..acd6d465dba440dbaa9c9e396bfec1b8e0c24591 100644 (file)
@@ -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;
 }