*/
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);
+
/**
* @}
*/
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 {
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
}
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);
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");
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);
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);
_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);
}
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) {
_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);
}
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)
{
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);
+}
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;