- sound_manager_set[unset]_focus_state_watch_cb() has been revised as well as the callback prototype to pass the callback id.
- some API descriptions are revised.
[Version] Release 0.3.58
[Profile] Common
[Issue Type] Feature Enhancement
Change-Id: Ib351148853fd525304c09588a4ee82c84910c937
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
* <td> This callback is called when the state of focus that belongs to the stream_info is changed.</td>
* </tr>
* <tr>
- * <td> sound_manager_set_focus_state_watch_cb()</td>
- * <td> sound_manager_unset_foucs_state_watch_cb()</td>
+ * <td> sound_manager_add_focus_state_watch_cb()</td>
+ * <td> sound_manager_remove_foucs_state_watch_cb()</td>
* <td> sound_stream_focus_state_watch_cb()</td>
- * <td> This callback is called when the focus state for each sound stream type is changed.</td>
+ * <td> This callback is called when the focus state for each sound stream type is changed regardless of the process.</td>
* </tr>
* <tr>
* <td> sound_manager_set_session_interrupted_cb()</td>
/**
* @brief Called when the focus state for each sound stream type is changed regardless of the process.
* @since_tizen 3.0
+ *
+ * @remarks This function is invoked by the internal thread of the sound manager.\n
+ * Therefore it is recommended not to call functions which update the UI from this callback.
+ *
+ * @param[in] id The focus state change watch cb id
* @param[in] focus_mask The changed focus mask
* @param[in] focus_state The changed focus state
* @param[in] reason The reason for state change of the focus
* @param[in] extra_info The extra information
* @param[in] user_data The user data passed from the callback registration function
- *
- * @remarks This function is issued in the internal thread of the sound manager.\n
- * Therefore it is recommended not to call UI update function in this function.
- *
- * @pre You should register this callback using sound_manager_set_focus_state_watch_cb().
- * @see sound_manager_set_focus_state_watch_cb()
- * @see sound_manager_unset_focus_state_watch_cb()
+ * @pre You should register this callback using sound_manager_add_focus_state_watch_cb().
+ * @see sound_manager_add_focus_state_watch_cb()
+ * @see sound_manager_remove_focus_state_watch_cb()
*/
-typedef void (*sound_stream_focus_state_watch_cb) (sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason, const char *extra_info, void *user_data);
+typedef void (*sound_stream_focus_state_watch_cb) (int id, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason, const char *extra_info, void *user_data);
/**
* @}
/**
* @brief Registers the watch callback function to be invoked when the focus state for each sound stream type is changed regardless of the process.
* @since_tizen 3.0
- * @param[in] focus_mask The focus mask that user wants to watch
- * @param[in] callback The focus state change watch callback function
- * @param[in] user_data The user data to be passed to the callback function
*
- * @remarks The previous watch callback should be unset before setting new watch callback.\n
- * The registered callback is issued in the internal thread of the sound manager.\n
- * Do not call this API within sound_stream_focus_state_changed_cb() and sound_stream_focus_state_watch_cb(),\n
+ * @remarks The registered callback is invoked by the internal thread of the sound manager.\n
+ * Do not call this API within sound_stream_focus_state_changed_cb() or sound_stream_focus_state_watch_cb(),\n
* otherwise SOUND_MANAGER_ERROR_INVALID_OPERATION will be returned.
*
+ * @param[in] focus_mask The focus mask that user wants to watch
+ * @param[in] callback The focus state change watch callback function
+ * @param[in] user_data The user data to be passed to the callback function
+ * @param[out] id The focus state change watch callback id
* @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
- * @see sound_manager_unset_focus_state_watch_cb()
+ * @see sound_manager_remove_focus_state_watch_cb()
*/
-int sound_manager_set_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data);
+int sound_manager_add_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data, int *id);
/**
- * @brief Unregisters the focus state watch callback.
+ * @brief Unregisters the focus state change watch callback.
* @since_tizen 3.0
*
- * @remarks Do not call this API within sound_stream_focus_state_changed_cb() and sound_stream_focus_state_watch_cb(),\n
+ * @remarks Do not call this API within sound_stream_focus_state_changed_cb() or sound_stream_focus_state_watch_cb(),\n
* otherwise SOUND_MANAGER_ERROR_INVALID_OPERATION will be returned.
*
+ * @param[in] id The focus state change watch callback id
* @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
- * @see sound_manager_set_focus_state_watch_cb()
+ * @see sound_manager_add_focus_state_watch_cb()
*/
-int sound_manager_unset_focus_state_watch_cb(void);
+int sound_manager_remove_focus_state_watch_cb(int id);
/**
* @}
g_stream_info_count++; \
} \
-#define SM_UNREF_FOR_STREAM_INFO(x_count, x_return) \
+#define SM_UNREF_FOR_STREAM_INFO(x_count) \
{ \
x_count--; \
} \
} _session_interrupt_info_s;
typedef struct {
- unsigned int subs_id;
+ int id;
void *user_data;
- sound_manager_volume_changed_cb user_cb;
-} _volume_changed_info_s;
+ sound_stream_focus_state_watch_cb user_cb;
+} _focus_watch_info_s;
typedef struct {
- int index;
+ unsigned int subs_id;
void *user_data;
- sound_stream_focus_state_watch_cb user_cb;
-} _focus_watch_info_s;
+ sound_manager_volume_changed_cb user_cb;
+} _volume_changed_info_s;
typedef struct {
unsigned int subs_id;
Name: capi-media-sound-manager
Summary: Sound Manager library
-Version: 0.3.57
+Version: 0.3.58
Release: 0
Group: Multimedia/API
License: Apache-2.0
_session_interrupt_info_s g_session_interrupt_cb_table = {0, 0, NULL, NULL};
_volume_changed_info_s g_volume_changed_cb_table = {0, NULL, NULL};
-_focus_watch_info_s g_focus_watch_cb_table = {-1, NULL, NULL};
_device_connected_info_s g_device_connected_cb_table = {0, NULL, NULL};
_device_changed_info_s g_device_info_changed_cb_table = {0, NULL, NULL};
+_focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
sound_session_type_e g_cached_session = -1;
_session_mode_e g_cached_session_mode = -1;
if (ret == MM_ERROR_NONE) {
free(stream_h);
stream_h = NULL;
- SM_UNREF_FOR_STREAM_INFO(g_stream_info_count, ret);
+ SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
}
SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
return _convert_sound_manager_error_code(__func__, ret);
}
-int sound_manager_set_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data)
+int sound_manager_add_focus_state_watch_cb(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_watch_cb callback, void *user_data, int *id)
{
int ret = MM_ERROR_NONE;
- int id = -1;
+ int i = 0;
LOGI(">> enter");
SM_NULL_ARG_CHECK(callback);
+ SM_NULL_ARG_CHECK(id);
SM_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_stream_info_count_mutex, SOUND_MANAGER_ERROR_INTERNAL);
- if (g_focus_watch_cb_table.user_cb) {
+ for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
+ if (focus_watch_info_arr[i].id == 0)
+ break;
+ if (i == SOUND_STREAM_INFO_ARR_MAX) {
+ LOGE("focus watch info array is full");
ret = MM_ERROR_SOUND_INTERNAL;
goto LEAVE;
}
- 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);
+ 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;
- g_focus_watch_cb_table.user_cb = callback;
- g_focus_watch_cb_table.user_data = user_data;
+ SM_REF_FOR_STREAM_INFO(g_stream_info_count, ret);
+ focus_watch_info_arr[i].id = *id;
+ focus_watch_info_arr[i].user_data = user_data;
+ focus_watch_info_arr[i].user_cb = callback;
}
LEAVE:
SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
- LOGD("cnt(%d)", g_stream_info_count);
+ LOGD("cnt(%d), id(%d)", g_stream_info_count, *id);
return _convert_sound_manager_error_code(__func__, ret);
}
-int sound_manager_unset_focus_state_watch_cb(void)
+int sound_manager_remove_focus_state_watch_cb(int id)
{
int ret = MM_ERROR_NONE;
+ int i = 0;
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) {
+ for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
+ if (focus_watch_info_arr[i].id == id)
+ break;
+ if (i == SOUND_STREAM_INFO_ARR_MAX) {
+ LOGE("cound not find item in focus watch info array for this id(%d)", id);
ret = MM_ERROR_SOUND_INTERNAL;
goto LEAVE;
}
- ret = mm_sound_unset_focus_watch_callback(g_focus_watch_cb_table.index);
- if (ret != MM_ERROR_NONE) {
- ret = MM_ERROR_SOUND_INTERNAL;
- goto LEAVE;
+ ret = mm_sound_unset_focus_watch_callback(id);
+ if (ret == MM_ERROR_NONE) {
+ SM_UNREF_FOR_STREAM_INFO(g_stream_info_count);
+ focus_watch_info_arr[i].id = 0;
+ focus_watch_info_arr[i].user_data = NULL;
+ focus_watch_info_arr[i].user_cb = NULL;
}
- 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);
-
LEAVE:
SM_LEAVE_CRITICAL_SECTION(&g_stream_info_count_mutex);
extern _session_interrupt_info_s g_session_interrupt_cb_table;
extern _session_mode_e g_cached_session_mode;
extern int g_cached_voip_device_id;
-extern _focus_watch_info_s g_focus_watch_cb_table;
+extern _focus_watch_info_s focus_watch_info_arr[SOUND_STREAM_INFO_ARR_MAX];
sound_stream_info_s *sound_stream_info_arr[SOUND_STREAM_INFO_ARR_MAX];
sound_stream_info_s *g_voip_stream_info = NULL;
virtual_sound_stream_info_s *g_voip_vstream_h = NULL;
void _focus_watch_callback(int index, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e state, const char *reason, const char *extra_info, void *user_data)
{
int ret = MM_ERROR_NONE;
+ int i = 0;
sound_stream_focus_change_reason_e change_reason = SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA;
ret = _convert_stream_type_to_change_reason(reason, &change_reason);
- if (ret)
+ if (ret) {
LOGE("failed to _convert_stream_type_to_enum(), reason(%s), err(0x%08x)", reason, ret);
+ goto LEAVE;
+ }
- if (g_focus_watch_cb_table.user_cb)
- g_focus_watch_cb_table.user_cb(focus_type, state, change_reason, extra_info, g_focus_watch_cb_table.user_data);
+ for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
+ if ((focus_watch_info_arr[i].id > 0) && (focus_watch_info_arr[i].id == index)) {
+ LOGI("[FOCUS WATCH USER CALLBACK(%p, id:%d) START]", focus_watch_info_arr[i].user_cb, index);
+ focus_watch_info_arr[i].user_cb(index, focus_type, state, change_reason, extra_info, focus_watch_info_arr[i].user_data);
+ LOGI("[FOCUS WATCH USER CALLBACK(%p) END]", focus_watch_info_arr[i].user_cb);
+ break;
+ }
+ }
+ if (i == SOUND_STREAM_INFO_ARR_MAX)
+ LOGE("could not find index(%d), failed to call user callback", index);
+LEAVE:
+ LOGI("<< leave");
return;
}
if (is_focus_cb_thread)
return MM_ERROR_SOUND_INVALID_OPERATION;
+ if (!stream_h->is_focus_unavailable) {
+ for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++)
+ if (sound_stream_info_arr[i] == NULL)
+ break;
+ if (i == SOUND_STREAM_INFO_ARR_MAX) {
+ LOGE("client sound stream info array is full");
+ goto PA_ERROR;
+ }
+ }
+
/* get configuration information of this stream type */
if ((ret = _get_stream_conf_info(stream_h->stream_type, &stream_h->stream_conf_info)))
return ret;
if (!stream_h->is_focus_unavailable) {
ret = mm_sound_register_focus(stream_h->index, stream_h->stream_type, _focus_state_change_callback, user_data);
if (ret == MM_ERROR_NONE) {
- int i = 0;
stream_h->user_cb = callback;
stream_h->user_data = user_data;
- for (i = 0; i < SOUND_STREAM_INFO_ARR_MAX; i++) {
- if (sound_stream_info_arr[i] == NULL) {
- sound_stream_info_arr[i] = stream_h;
- break;
- }
- }
- if (i == SOUND_STREAM_INFO_ARR_MAX) {
- LOGE("client sound stream info array is full");
- ret = mm_sound_unregister_focus(stream_h->index);
- goto PA_ERROR;
- }
+ sound_stream_info_arr[i] = stream_h;
} else {
LOGE("failed to register focus, ret(0x%x)", ret);
/* disconnect */
}
}
goto SUCCESS;
+
PA_ERROR_WITH_UNLOCK:
pa_threaded_mainloop_unlock(stream_h->pa_mainloop);
+
PA_ERROR:
for (i = 0; i < AVAIL_DEVICES_MAX; i++) {
if (stream_h->stream_conf_info.avail_in_devices[i])
CURRENT_STATUS_GET_ACQUIRED_FOCUS,
CURRENT_STATUS_GET_SOUND_TYPE,
CURRENT_STATUS_DESTROY_STREAM_INFO,
- CURRENT_STATUS_SET_FOCUS_WATCH_CB,
- CURRENT_STATUS_UNSET_FOCUS_WATCH_CB,
+ CURRENT_STATUS_ADD_FOCUS_WATCH_CB,
+ CURRENT_STATUS_REMOVE_FOCUS_WATCH_CB,
CURRENT_STATUS_SET_FOCUS_REACQUISITION,
CURRENT_STATUS_GET_FOCUS_REACQUISITION,
CURRENT_STATUS_GET_REASON_FOR_P_FOCUS,
int ret = SOUND_MANAGER_ERROR_NONE;
sound_stream_focus_state_e playback_focus_state;
sound_stream_focus_state_e recording_focus_state;
- g_print("*** FOCUS callback is called, stream_info(%p) ***\n", stream_info);
+ g_print("\n*** FOCUS callback is called, stream_info(%p) ***\n", stream_info);
g_print(" - change_reason(%d), extra_info(%s), user_data(%p)\n", reason, extra_info, user_data);
ret = sound_manager_get_focus_state(stream_info, &playback_focus_state, &recording_focus_state);
return;
}
-void focus_watch_callback(sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason, const char *extra_info, void *user_data)
+void focus_watch_callback(int id, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, sound_stream_focus_change_reason_e reason, const char *extra_info, void *user_data)
{
- g_print("*** FOCUS WATCH callback is called ***\n");
+ g_print("\n*** FOCUS WATCH callback is called, id(%d) ***\n", id);
g_print(" - changed_focus_mask(%d), changed_focus_state(%d), change_reason(%d), extra_info(%s), user_data(%p)\n",
focus_mask, focus_state, reason, extra_info, user_data);
return;
g_menu_state = CURRENT_STATUS_GET_ACQUIRED_FOCUS;
else if (strncmp(cmd, "gst", 3) == 0)
g_menu_state = CURRENT_STATUS_GET_SOUND_TYPE;
- else if (strncmp(cmd, "sfw", 3) == 0)
- g_menu_state = CURRENT_STATUS_SET_FOCUS_WATCH_CB;
- else if (strncmp(cmd, "ufw", 3) == 0)
- g_menu_state = CURRENT_STATUS_UNSET_FOCUS_WATCH_CB;
+ else if (strncmp(cmd, "afw", 3) == 0)
+ g_menu_state = CURRENT_STATUS_ADD_FOCUS_WATCH_CB;
+ else if (strncmp(cmd, "rfw", 3) == 0)
+ g_menu_state = CURRENT_STATUS_REMOVE_FOCUS_WATCH_CB;
else if (strncmp(cmd, "sfr", 3) == 0)
g_menu_state = CURRENT_STATUS_SET_FOCUS_REACQUISITION;
else if (strncmp(cmd, "gfr", 3) == 0)
g_print("afc. Acquire Focus\t");
g_print("rfc. Release Focus\t");
g_print("gfs. Get Focus State\n");
- g_print("sfw. Set Focus State Watch CB\t");
- g_print("ufw. Unset Focus State Watch CB\n");
+ g_print("afw. Add Focus State Watch CB\t");
+ g_print("rfw. Remove Focus State Watch CB\n");
g_print("sfr. Set Focus Reacquisition\t");
g_print("gfr. Get Focus Reacquisition\n");
g_print("grp. Get Reason for Current Acquired Playback Focus\t");
g_print("*** press enter to get sound type\n");
else if (g_menu_state == CURRENT_STATUS_DESTROY_STREAM_INFO)
g_print("*** press enter to destroy stream information\n");
- else if (g_menu_state == CURRENT_STATUS_SET_FOCUS_WATCH_CB)
+ else if (g_menu_state == CURRENT_STATUS_ADD_FOCUS_WATCH_CB)
g_print("*** input focus type to watch for (0:playback, 1:recording, 2:both)\n");
- else if (g_menu_state == CURRENT_STATUS_UNSET_FOCUS_WATCH_CB)
- g_print("*** press enter to unset focus state watch cb\n");
+ else if (g_menu_state == CURRENT_STATUS_REMOVE_FOCUS_WATCH_CB)
+ g_print("*** input focus watch callback id to remove\n");
else if (g_menu_state == CURRENT_STATUS_SET_FOCUS_REACQUISITION)
g_print("*** input focus reacquisition property (1:enable, 2:disable)\n");
else if (g_menu_state == CURRENT_STATUS_GET_FOCUS_REACQUISITION)
}
ret = sound_manager_release_focus(g_stream_info_h, focus_mask, "sound_manager_test(release_focus)");
if (ret)
- g_print("fail to sound_manager_acquire_focus(), ret(0x%x)\n", ret);
+ g_print("fail to sound_manager_release_focus(), ret(0x%x)\n", ret);
reset_menu_state();
break;
reset_menu_state();
break;
}
- case CURRENT_STATUS_SET_FOCUS_WATCH_CB: {
+ case CURRENT_STATUS_ADD_FOCUS_WATCH_CB: {
int ret = SOUND_MANAGER_ERROR_NONE;
int focus_type = 0;
sound_stream_focus_mask_e focus_mask;
+ int id;
focus_type = atoi(cmd);
switch (focus_type) {
focus_mask = SOUND_STREAM_FOCUS_FOR_PLAYBACK;
break;
}
- ret = sound_manager_set_focus_state_watch_cb(focus_mask, focus_watch_callback, NULL);
+ ret = sound_manager_add_focus_state_watch_cb(focus_mask, focus_watch_callback, NULL, &id);
if (ret)
- g_print("fail to sound_manager_set_focus_state_watch_cb(), ret(0x%x)\n", ret);
+ g_print("fail to sound_manager_add_focus_state_watch_cb(), ret(0x%x)\n", ret);
+ else
+ g_print("id: %d\n", id);
reset_menu_state();
break;
}
- case CURRENT_STATUS_UNSET_FOCUS_WATCH_CB: {
+ case CURRENT_STATUS_REMOVE_FOCUS_WATCH_CB: {
int ret = SOUND_MANAGER_ERROR_NONE;
- ret = sound_manager_unset_focus_state_watch_cb();
+ int id = 0;
+
+ id = atoi(cmd);
+ ret = sound_manager_remove_focus_state_watch_cb(id);
if (ret)
- g_print("fail to sound_manager_unset_focus_state_watch_cb(), ret(0x%x)\n", ret);
+ g_print("fail to sound_manager_remove_focus_state_watch_cb(%d), ret(0x%x)\n", id, ret);
reset_menu_state();
break;
}