_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
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);
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
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;
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;
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) {
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);
}
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;
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);
}
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;
}
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);
}
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;
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)
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;
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);
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);
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;
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) {
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;
}
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;
}
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);
/* 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]) {
}
free(stream_h);
+ SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
+
+ SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
+
return ret;
}