+++ /dev/null
-/*
- * libmm-player
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
- * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <mm_debug.h>
-#include <mm_error.h>
-#include "mm_player_utils.h"
-#include "mm_player_priv.h"
-#include "mm_player_asm.h"
-#include <vconf.h>
-#include <vconf-internal-sound-keys.h>
-
-#define MMPLAYER_CHECK_SESSION_SKIP(x_player_asm) \
-do \
-{ \
- if (x_player_asm->skip_session == TRUE) \
- { \
- debug_log("skip session"); \
- return MM_ERROR_NONE; \
- } \
-}while(0);
-
-#define MMPLAYER_CHECK_SESSION_INSTANCE(x_player_asm) \
-do \
-{ \
- if (!x_player_asm) \
- { \
- debug_log("no session instance");\
- return MM_ERROR_SOUND_NOT_INITIALIZED; \
- } \
-}while(0);
-
-static ASM_sound_events_t __mmplayer_asm_get_event_type(gint type);
-
-const gchar *
-__mmplayer_asm_get_state_name ( int state )
-{
- switch ( state )
- {
- case ASM_STATE_NONE:
- return "NONE";
- case ASM_STATE_PLAYING:
- return "PLAYING";
- case ASM_STATE_PAUSE:
- return "PAUSED";
- case ASM_STATE_STOP:
- return "STOP";
- case ASM_STATE_WAITING:
- return "BUFFERING";
- default:
- return "INVAID";
- }
-}
-
-#define MMPLAYER_ASM_STATE_GET_NAME(state) __mmplayer_asm_get_state_name(state)
-
-gint
-_mmplayer_asm_register(MMPlayerASM* sm, ASM_sound_cb_t callback, void* param)
-{
- return MM_ERROR_NONE;
-
- gint session_type = MM_SESSION_TYPE_MEDIA;
- gint session_options = 0;
- gint errorcode = MM_ERROR_NONE;
- gint asm_handle = -1;
- gint event_type = ASM_EVENT_NONE;
- gint pid = -1;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_CHECK_SESSION_INSTANCE(sm);
- MMPLAYER_CHECK_SESSION_SKIP(sm);
-
- /* check if it's running on the media_server */
- if ( sm->pid > 0 )
- {
- pid = sm->pid;
- debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid);
- }
-
- /* read session information */
- errorcode = _mm_session_util_read_information(pid, &session_type, &session_options);
- if ( errorcode )
- {
- debug_warning("Read Session Type failed. use default \"media\" type\n");
- session_type = MM_SESSION_TYPE_MEDIA;
- }
-
- /* interpret session information */
- event_type = __mmplayer_asm_get_event_type(session_type);
-
- /* check if it's one of CALL series */
- if ( event_type == ASM_EVENT_CALL ||
- event_type == ASM_EVENT_VIDEOCALL ||
- event_type == ASM_EVENT_VOIP)
- {
- debug_warning("session type is one of CALL series(%d), skip registering ASM\n", session_type);
- sm->event = event_type;
- sm->skip_session = TRUE;
- return MM_ERROR_NONE;
- }
-
- /* register audio-session-manager handle and callback */
- if( ! ASM_register_sound(pid, &asm_handle, event_type, ASM_STATE_NONE, callback, (void*)param, ASM_RESOURCE_NONE, &errorcode))
- {
- debug_error("ASM_register_sound() failed, error(%x)\n", errorcode);
- return errorcode;
- }
- /* set session options */
- if (session_options)
- {
- if( ! ASM_set_session_option(asm_handle, session_options, &errorcode))
- {
- debug_error("ASM_set_session_options() failed, error(%x)\n", errorcode);
- return errorcode;
- }
- }
-
- /* now succeed to register our callback. take result */
- sm->handle = asm_handle;
- sm->state = ASM_STATE_NONE;
- sm->event = event_type;
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
-
-gint
-_mmplayer_asm_unregister(MMPlayerASM* sm)
-{
- gint event_type = ASM_EVENT_NONE;
- gint errorcode = 0;
- gint pid = -1;
-
- MMPLAYER_FENTER();
-
- MMPLAYER_CHECK_SESSION_INSTANCE(sm);
- MMPLAYER_CHECK_SESSION_SKIP(sm);
-
- /* check if it's running on the media_server */
- if ( sm->pid > 0 )
- {
- pid = sm->pid;
- debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid);
- }
-
- event_type = sm->event;
-
- if (sm->handle)
- {
- if( ! ASM_unregister_sound( sm->handle, event_type, &errorcode) )
- {
- debug_error("Unregister sound failed 0x%X\n", errorcode);
- return MM_ERROR_POLICY_INTERNAL;
- }
- }
- debug_warning("asm unregistered");
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
-
-gint _mmplayer_asm_set_state(MMHandleType hplayer, ASM_sound_states_t state, gboolean enable_safety_vol)
-{
- return MM_ERROR_NONE;
-
- gint event_type = ASM_EVENT_NONE;
- gint pid = -1;
-// int vconf_safety_vol_val = 0;
- ASM_resource_t resource = ASM_RESOURCE_NONE;
- mm_player_t *player = (mm_player_t *)hplayer;
- MMPlayerASM* sm = &player->sm;
- MMPLAYER_FENTER();
-
-#if 0
- if (player->set_mode.safety_volume)
- {
- /* get safety volume */
- if (vconf_get_int(VCONFKEY_SOUND_ENABLE_SAFETY_VOL, &vconf_safety_vol_val))
- {
- debug_error ("failed to get safety volume");
- }
-
- if (enable_safety_vol)
- {
- vconf_safety_vol_val = vconf_safety_vol_val | VCONFKEY_SOUND_SAFETY_VOL_FW_MMPLAYER;
- }
- else
- {
- vconf_safety_vol_val = vconf_safety_vol_val & ~VCONFKEY_SOUND_SAFETY_VOL_FW_MMPLAYER;
- }
-
- /* set safety volume */
- if (vconf_set_int(VCONFKEY_SOUND_ENABLE_SAFETY_VOL, vconf_safety_vol_val))
- {
- debug_error ("failed to set safety volume");
- }
- debug_log("safety vol : %d(0:false, 1:true), current result of vconf val : 0x%x", enable_safety_vol, vconf_safety_vol_val);
- }
-#endif
- MMPLAYER_CHECK_SESSION_INSTANCE(sm);
- MMPLAYER_CHECK_SESSION_SKIP(sm);
-
- /* check if it's running on the media_server */
- if ( sm->pid > 0 )
- {
- pid = sm->pid;
- debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid);
- }
-
- /* in case of stop, it should be stop first and post interrupt message to application */
- if ( !sm->by_asm_cb || state == ASM_STATE_STOP)//|| sm->state == ASM_STATE_PLAYING )
- {
- int ret = 0;
- event_type = sm->event;
- resource = sm->resource;
-
- /* check if there is video */
- /* NOTE: resource can be set as NONE when it's not occupied or unknown resource is used. */
- if(ASM_STATE_PLAYING == state || ASM_STATE_PAUSE == state || ASM_STATE_WAITING == state)
- {
- int surface_type = 0;
- mm_attrs_get_int_by_name (player->attrs, "display_surface_type", &surface_type);
- debug_log("surface type = %d", surface_type);
-
- if (player->pipeline && player->pipeline->videobin)
- {
- if(surface_type == MM_DISPLAY_SURFACE_X)
- {
- resource = ASM_RESOURCE_VIDEO_OVERLAY | ASM_RESOURCE_HW_DECODER;
- }
- else if (surface_type == MM_DISPLAY_SURFACE_EVAS)
- {
- resource = ASM_RESOURCE_HW_DECODER;
- }
- }
-
- if( __mmplayer_is_streaming (player))
- resource = resource | ASM_RESOURCE_STREAMING;
-
- /* reset */
- sm->keep_last_pos = FALSE;
- }
-
- if( ((sm->state != state) || (sm->resource != resource)) && ! ASM_set_sound_state( sm->handle, event_type, state, resource, &ret) )
- {
- gint retval = MM_ERROR_POLICY_INTERNAL;
-
- debug_error("Set state to [%d] failed 0x%X\n", state, ret);
- switch(ret)
- {
- case ERR_ASM_POLICY_CANNOT_PLAY:
- case ERR_ASM_POLICY_CANNOT_PLAY_BY_CALL:
- case ERR_ASM_POLICY_CANNOT_PLAY_BY_ALARM:
- retval = MM_ERROR_POLICY_BLOCKED;
- break;
- default:
- retval = MM_ERROR_POLICY_INTERNAL;
- break;
- }
-
- return retval;
- }
- }
- else
- {
- sm->by_asm_cb = FALSE;
- }
-
- sm->state = state;
-
- /* waiting to be changed because callback can be called */
- if (ASM_STATE_STOP == state)
- {
- ASM_sound_states_t session_state;
- ASM_get_sound_state(sm->handle, event_type, &session_state, NULL);
- }
-
- debug_error("ASM state changed to [%s]", MMPLAYER_ASM_STATE_GET_NAME(state));
- MMPLAYER_FLEAVE();
- return MM_ERROR_NONE;
-}
-
-static ASM_sound_events_t
-__mmplayer_asm_get_event_type(gint type)
-{
- gint event_type = ASM_EVENT_NONE;
-
- /* interpret session type */
- switch(type)
- {
- case MM_SESSION_TYPE_CALL:
- event_type = ASM_EVENT_CALL;
- break;
-
- case MM_SESSION_TYPE_VIDEOCALL:
- event_type = ASM_EVENT_VIDEOCALL;
- break;
-
- case MM_SESSION_TYPE_VOIP:
- event_type = ASM_EVENT_VOIP;
- break;
-
- case MM_SESSION_TYPE_MEDIA:
-// case MM_SESSION_TYPE_MEDIA_RECORD:
- event_type = ASM_EVENT_MEDIA_MMPLAYER;
- break;
-
- case MM_SESSION_TYPE_NOTIFY:
- event_type = ASM_EVENT_NOTIFY;
- break;
-
- case MM_SESSION_TYPE_ALARM:
- event_type = ASM_EVENT_ALARM;
- break;
-
- case MM_SESSION_TYPE_EMERGENCY:
- event_type = ASM_EVENT_EMERGENCY;
- break;
-#if 0
- case MM_SESSION_TYPE_RECORD_VIDEO:
- case MM_SESSION_TYPE_RECORD_AUDIO:
- event_type = ASM_EVENT_MEDIA_MMPLAYER;
- break;
-#endif
-
- default:
- debug_msg("unexpected case!\n");
- event_type = ASM_EVENT_MEDIA_MMPLAYER;
- break;
- }
-
- return event_type;
-}
-
-gint
-_mmplayer_asm_ignore_session(MMHandleType hplayer)
-{
- mm_player_t *player = (mm_player_t *)hplayer;
-
- MMPLAYER_FENTER();
-
- return_val_if_fail (player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
- /* check state */
- if (player->state != MM_PLAYER_STATE_NULL)
- {
- debug_log("invalid state to make session mix");
- return MM_ERROR_PLAYER_INVALID_STATE;
- }
-
- if (player->sm.skip_session == FALSE && player->sm.handle)
- {
- int error_code = 0;
-
- if (!ASM_unregister_sound(player->sm.handle, player->sm.event, &error_code))
- {
- debug_error("Unregister sound failed 0x%X", error_code);
- return MM_ERROR_POLICY_INTERNAL;
- }
- player->sm.skip_session = TRUE;
- player->sm.handle = 0;
-
- debug_log("session skip enabled");
- }
-
- MMPLAYER_FLEAVE();
-
- return MM_ERROR_NONE;
-}
#include <sched.h>
#include <mm_sound.h>
+#include <mm_sound_focus.h>
#define MM_SMOOTH_STREAMING
__mmplayer_set_state(mm_player_t* player, int state) // @
{
MMMessageParamType msg = {0, };
- int asm_result = MM_ERROR_NONE;
+ int sound_result = MM_ERROR_NONE;
gboolean post_bos = FALSE;
gboolean interrupted_by_asm = FALSE;
int ret = MM_ERROR_NONE;
MMPLAYER_PRINT_STATE(player);
/* do some FSM stuffs before posting new state to application */
- interrupted_by_asm = player->sm.by_asm_cb;
+ interrupted_by_asm = player->sound_focus.by_asm_cb;
switch ( MMPLAYER_CURRENT_STATE(player) )
{
{
if (player->cmd == MMPLAYER_COMMAND_STOP)
{
- asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_STOP, FALSE);
- if ( asm_result != MM_ERROR_NONE )
+ sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
+ if ( sound_result != MM_ERROR_NONE )
{
- debug_error("failed to set asm state to stop\n");
+ debug_error("failed to release sound focus\n");
return MM_ERROR_POLICY_INTERNAL;
}
}
if (!MMPLAYER_IS_STREAMING(player) || (player->streamer && !player->streamer->is_buffering))
{
- asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PAUSE, FALSE);
- if ( asm_result )
+ sound_result = _mmplayer_sound_release_focus(&player->sound_focus);
+ if ( sound_result != MM_ERROR_NONE )
{
- debug_error("failed to set asm state to PAUSE\n");
+ debug_error("failed to release sound focus\n");
return MM_ERROR_POLICY_INTERNAL;
}
}
{
__mmplayer_handle_missed_plugin ( player );
}
-
- /* update ASM state for video and streaming buffering */
- asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_PLAYING, TRUE);
- if (asm_result != MM_ERROR_NONE)
+ sound_result = _mmplayer_sound_acquire_focus(&player->sound_focus);
+ if (sound_result != MM_ERROR_NONE)
{
+ // FIXME : need to check history
if (player->pipeline->videobin)
{
MMMessageParamType msg = {0, };
}
else
{
- debug_error("failed to play by ASM error : 0x%X\n", asm_result);
+ debug_error("failed to play by sound focus error : 0x%X\n", sound_result);
_mmplayer_pause((MMHandleType)player);
- return asm_result;
+ return sound_result;
}
return MM_ERROR_POLICY_INTERNAL;
if ( interrupted_by_asm )
{
msg.union_type = MM_MSG_UNION_CODE;
- msg.code = player->sm.event_src;
+ msg.code = player->sound_focus.focus_changed_msg; /* FIXME: player.c convert function have to be modified. */
MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
}
/* state changed by usecase */
case GST_MESSAGE_BUFFERING:
{
MMMessageParamType msg_param = {0, };
- int asm_result = MM_ERROR_NONE;
if (!MMPLAYER_IS_STREAMING(player))
break;
break;
}
- /* update ASM state to ASM_STATE_PLAYING */
- /* fixed ASM_STATE_WAITING -> ASM_STATE_PLAYING for Samsunlink issue*/
- if ((player->streamer) && (player->streamer->is_buffering == FALSE) && (MMPLAYER_CURRENT_STATE(player) != MM_PLAYER_STATE_PAUSED))
- {
- asm_result = _mmplayer_asm_set_state((MMHandleType)player, ASM_STATE_WAITING, TRUE);
- if ( asm_result != MM_ERROR_NONE )
- {
- debug_warning("failed to set asm state to waiting, but keep going...\n");
- }
- }
-
__mmplayer_update_buffer_setting(player, msg);
__mmplayer_handle_buffering_message ( player );
};
/* hook sound_type if emergency case */
- if (player->sm.event == ASM_EVENT_EMERGENCY)
+ if (player->sound_focus.focus_changed_msg == MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY)
{
debug_log ("emergency session, hook sound_type from [%d] to [%d]\n", volume_type, MM_SOUND_VOLUME_TYPE_EMERGENCY);
volume_type = MM_SOUND_VOLUME_TYPE_EMERGENCY;
}
+#if 0 //need to check
+ if (player->sound_focus.user_route_policy != 0)
+ {
+ route_path = player->sound_focus.user_route_policy;
+ }
+
+ g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
+ "latency", latency_mode,
+ NULL);
+
+ debug_log("audiosink property status...volume type:%d, user-route=%d, latency=%d \n",
+ volume_type, route_path, latency_mode);
+ MMPLAYER_FLEAVE();
+
+#endif
g_object_set(player->pipeline->audiobin[MMPLAYER_A_SINK].gst,
"latency", latency,
/* cleanup running stuffs */
__mmplayer_cancel_eos_timer( player );
-
+#if 0 //need to change and test
/* remove sound cb */
if ( MM_ERROR_NONE != mm_sound_remove_device_information_changed_callback())
{
debug_error("failed to mm_sound_remove_device_information_changed_callback()");
}
-
+#endif
/* cleanup gst stuffs */
if ( player->pipeline )
{
mm_attrs_get_int_by_name(attrs, "sound_fadedown", &fadedown);
/* enable fadedown */
- if (fadedown || player->sm.by_asm_cb)
+ if (fadedown || player->sound_focus.by_asm_cb)
__mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
/* Just set state to PAUESED and the rewind. it's usual player behavior. */
ret = __mmplayer_gst_set_state( player, player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, state, async, timeout );
/* disable fadeout */
- if (fadedown || player->sm.by_asm_cb)
+ if (fadedown || player->sound_focus.by_asm_cb)
__mmplayer_undo_sound_fadedown(player);
/* return if set_state has failed */
pos_msec = player->duration;
}
- if (player->sm.keep_last_pos) {
+ if (player->sound_focus.keep_last_pos) {
debug_log("return last pos as stop by asm, %"GST_TIME_FORMAT, GST_TIME_ARGS(player->last_position));
pos_msec = player->last_position;
}
msg.union_type = MM_MSG_UNION_CODE;
- msg.code = player->sm.event_src;
+ msg.code = player->sound_focus.focus_changed_msg;
#if 0 // should remove
if (player->sm.event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
if (player->pipeline && player->pipeline->audiobin)
g_object_set(G_OBJECT(player->pipeline->audiobin[MMPLAYER_A_SINK].gst), "mute", 0, NULL);
- player->sm.by_asm_cb = FALSE; //should be reset here
+ player->sound_focus.by_asm_cb = FALSE; //should be reset here
MMPLAYER_FLEAVE();
goto FAILED;
}
- if ((player->sm.exit_cb) || (player->set_mode.pcm_extraction))
+ if ((player->sound_focus.exit_cb) || (player->set_mode.pcm_extraction))
{
- debug_warning("leave from asm cb right now, %d, %d", player->sm.exit_cb, player->set_mode.pcm_extraction);
+ debug_warning("leave from asm cb right now, %d, %d", player->sound_focus.exit_cb, player->set_mode.pcm_extraction);
goto FAILED;
}
return TRUE;
}
-ASM_cb_result_t
-__mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_commands_t command, unsigned int sound_status, void* cb_data)
+/* if you want to enable USE_ASM, please check the history get the ASM cb code. */
+static int
+__mmplayer_convert_sound_focus_state(gboolean acquire, const char *reason_for_change, MMPlayerFocusChangedMsg *msg)
+{
+ int ret = MM_ERROR_NONE;
+ MMPlayerFocusChangedMsg focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
+
+ if (strstr(reason_for_change, "alarm")) {
+ focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_ALARM;
+
+ } else if (strstr(reason_for_change, "notification")) {
+ focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_NOTIFICATION;
+
+ } else if (strstr(reason_for_change, "emergency")) {
+ focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY;
+
+ } else if (strstr(reason_for_change, "call-voice") ||
+ strstr(reason_for_change, "call-video") ||
+ strstr(reason_for_change, "voip") ||
+ strstr(reason_for_change, "ringtone-voip") ||
+ strstr(reason_for_change, "ringtone-call")) {
+ focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_CALL;
+
+ } else if (strstr(reason_for_change, "media") ||
+ strstr(reason_for_change, "radio") ||
+ strstr(reason_for_change, "loopback") ||
+ strstr(reason_for_change, "system") ||
+ strstr(reason_for_change, "voice-information") ||
+ strstr(reason_for_change, "voice-recognition")) {
+ focus_msg = MM_PLAYER_FOCUS_CHANGED_BY_MEDIA;
+
+ } else {
+ ret = MM_ERROR_INVALID_ARGUMENT;
+ debug_warning("not supported reason(%s), err(0x%08x)", reason_for_change, ret);
+ goto DONE;
+ }
+
+ if (acquire && (focus_msg != MM_PLAYER_FOCUS_CHANGED_BY_MEDIA))
+ {
+ /* can acqurie */
+ focus_msg = MM_PLAYER_FOCUS_CHANGED_COMPLETED;
+ }
+
+ debug_log("converted from reason(%s) to msg(%d)", reason_for_change, focus_msg);
+ *msg = focus_msg;
+
+DONE:
+ return ret;
+}
+
+/* FIXME: will be updated with new funct */
+void __mmplayer_sound_focus_watch_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
+ const char *reason_for_change, const char *additional_info, void *user_data)
+{
+ mm_player_t* player = (mm_player_t*) user_data;
+ int result = MM_ERROR_NONE;
+ MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
+
+ debug_warning("focus watch notified");
+
+ if (!__mmplayer_can_do_interrupt(player))
+ {
+ debug_warning("no need to interrupt, so leave");
+ goto EXIT;
+ }
+
+ if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE)
+ {
+ debug_warning("flags is UNINTERRUPTIBLE. do nothing.");
+ goto EXIT;
+ }
+
+ debug_warning("watch: state: %d, focus_type : %d, reason_for_change : %s",
+ focus_state, focus_type, (reason_for_change?reason_for_change:"N/A"));
+
+ player->sound_focus.cb_pending = TRUE;
+ player->sound_focus.by_asm_cb = TRUE;
+
+ if (focus_state == FOCUS_IS_ACQUIRED)
+ {
+ debug_warning("watch: FOCUS_IS_ACQUIRED");
+ if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
+ {
+ player->sound_focus.focus_changed_msg = (int)msg;
+ }
+
+ if (strstr(reason_for_change, "call") ||
+ strstr(reason_for_change, "voip") || /* FIXME: to check */
+ strstr(reason_for_change, "alarm") ||
+ strstr(reason_for_change, "media"))
+ {
+ if (!MMPLAYER_IS_RTSP_STREAMING(player))
+ {
+ // hold 0.7 second to excute "fadedown mute" effect
+ debug_warning ("do fade down->pause->undo fade down");
+
+ __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
+
+ result = _mmplayer_pause((MMHandleType)player);
+ if (result != MM_ERROR_NONE)
+ {
+ debug_warning("fail to set Pause state by asm");
+ goto EXIT;
+ }
+ __mmplayer_undo_sound_fadedown(player);
+ }
+ else
+ {
+ /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
+ _mmplayer_unrealize((MMHandleType)player);
+ }
+ }
+ else
+ {
+ debug_warning ("pause immediately");
+ result = _mmplayer_pause((MMHandleType)player);
+ if (result != MM_ERROR_NONE)
+ {
+ debug_warning("fail to set Pause state by asm");
+ goto EXIT;
+ }
+ }
+ }
+ else if (focus_state == FOCUS_IS_RELEASED)
+ {
+ debug_warning("FOCUS_IS_RELEASED: Got msg from asm to resume");
+ player->sound_focus.antishock = TRUE;
+ player->sound_focus.by_asm_cb = FALSE;
+
+ if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
+ {
+ player->sound_focus.focus_changed_msg = (int)msg;
+ }
+
+ //ASM server is single thread daemon. So use g_idle_add() to post resume msg
+ player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
+ goto DONE;
+ }
+ else
+ {
+ debug_warning("unknown focus state %d", focus_state);
+ }
+
+DONE:
+ player->sound_focus.by_asm_cb = FALSE;
+ player->sound_focus.cb_pending = FALSE;
+ MMPLAYER_CMD_UNLOCK( player );
+
+EXIT:
+ debug_warning("dispatched");
+ return;
+}
+
+void
+__mmplayer_sound_focus_callback(int id, mm_sound_focus_type_e focus_type, mm_sound_focus_state_e focus_state,
+ const char *reason_for_change, const char *additional_info, void *user_data)
{
- mm_player_t* player = (mm_player_t*) cb_data;
- ASM_cb_result_t cb_res = ASM_CB_RES_IGNORE;
+ mm_player_t* player = (mm_player_t*) user_data;
int result = MM_ERROR_NONE;
gboolean lazy_pause = FALSE;
+ MMPlayerFocusChangedMsg msg = MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN;
- debug_warning("get notified");
+ debug_warning("get focus notified");
if (!__mmplayer_can_do_interrupt(player))
{
goto EXIT;
}
- player->sm.cb_pending = TRUE;
- debug_warning("asm event src type : %d, command : 0x%x", event_src, command);
+ if (player->sound_focus.session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE)
+ {
+ debug_warning("flags is UNINTERRUPTIBLE. do nothing.");
+ goto EXIT;
+ }
+
+ debug_warning("state: %d, focus_type : %d, reason_for_change : %s",
+ focus_state, focus_type, (reason_for_change?reason_for_change:"N/A"));
- player->sm.by_asm_cb = TRUE;
- player->sm.event_src = event_src;
+ player->sound_focus.cb_pending = TRUE;
+ player->sound_focus.by_asm_cb = TRUE;
+// player->sound_focus.event_src = event_src;
+#if 0
/* first, check event source */
if(event_src == ASM_EVENT_SOURCE_EARJACK_UNPLUG)
{
}
else if (event_src == ASM_EVENT_SOURCE_RESOURCE_CONFLICT)
{
+ /* can use video overlay simultaneously */
+ /* video resource conflict */
if(player->pipeline->videobin)
{
- debug_log("video conflict so, resource will be freed.");
- result = _mmplayer_unrealize((MMHandleType)player);
- cb_res = ASM_CB_RES_STOP;
+ debug_log("video conflict but, can support multiple video");
+ result = _mmplayer_pause((MMHandleType)player);
+ cb_res = ASM_CB_RES_PAUSE;
}
else if (player->pipeline->audiobin)
{
else if (event_src == ASM_EVENT_SOURCE_RESUMABLE_CANCELED)
{
debug_warning("Got msg from asm for resumable canceled.\n");
- player->sm.antishock = TRUE;
- player->sm.by_asm_cb = FALSE;
+ player->sound_focus.antishock = TRUE;
+ player->sound_focus.by_asm_cb = FALSE;
player->resumable_cancel_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
cb_res = ASM_CB_RES_IGNORE;
goto DONE;
}
#endif
- /* then, check command */
- switch(command)
+#endif
+
+ if (focus_state == FOCUS_IS_RELEASED)
{
- case ASM_COMMAND_PLAY:
- debug_warning ("Got unexpected asm command (%d)", command);
- break;
+ debug_warning("FOCUS_IS_RELEASED");
- case ASM_COMMAND_STOP: // notification case
- {
- debug_warning("Got msg from asm to stop");
+ if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(FALSE, reason_for_change, &msg))
+ {
+ player->sound_focus.focus_changed_msg = (int)msg;
+ }
- if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &player->last_position)) {
- debug_error("failed to get position");
- player->last_position = 0;
- }
+ if (strstr(reason_for_change, "call") ||
+ strstr(reason_for_change, "voip") || /* FIXME: to check */
+ strstr(reason_for_change, "alarm") ||
+ strstr(reason_for_change, "media"))
+ {
+ if (!MMPLAYER_IS_RTSP_STREAMING(player))
+ {
+ //hold 0.7 second to excute "fadedown mute" effect
+ debug_warning ("do fade down->pause->undo fade down");
- debug_log ("pos_msec = %"GST_TIME_FORMAT"", GST_TIME_ARGS(player->last_position));
+ __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
- result = _mmplayer_stop((MMHandleType)player);
+ result = _mmplayer_pause((MMHandleType)player);
if (result != MM_ERROR_NONE)
{
- debug_warning("fail to set stop state by asm");
- cb_res = ASM_CB_RES_IGNORE;
- }
- else
- {
- cb_res = ASM_CB_RES_STOP;
+ debug_warning("fail to set Pause state by asm");
+ goto EXIT;
}
- player->sm.by_asm_cb = FALSE; // reset because no message any more from asm
- player->sm.keep_last_pos = TRUE;
+ __mmplayer_undo_sound_fadedown(player);
}
- break;
-
- case ASM_COMMAND_PAUSE:
+ else
{
- debug_warning("Got msg from asm to Pause");
- if(event_src == ASM_EVENT_SOURCE_CALL_START ||
- event_src == ASM_EVENT_SOURCE_ALARM_START ||
- event_src == ASM_EVENT_SOURCE_MEDIA)
- {
- if ( ! MMPLAYER_IS_RTSP_STREAMING(player) ) {
- //hold 0.7 second to excute "fadedown mute" effect
- debug_warning ("do fade down->pause->undo fade down");
-
- __mmplayer_do_sound_fadedown(player, MM_PLAYER_FADEOUT_TIME_DEFAULT);
-
- result = _mmplayer_pause((MMHandleType)player);
- if (result != MM_ERROR_NONE)
- {
- debug_warning("fail to set Pause state by asm");
- cb_res = ASM_CB_RES_IGNORE;
- break;
- }
- __mmplayer_undo_sound_fadedown(player);
- } else {
- /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
- _mmplayer_unrealize((MMHandleType)player);
- }
- }
+ /* rtsp should connect again in specific network becasue tcp session can't be kept any more */
+ _mmplayer_unrealize((MMHandleType)player);
+ }
+ }
+#if 0
#ifdef USE_LAZY_PAUSE // if enabled, should consider event id and context when removed
- else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
- {
- lazy_pause = TRUE; // return as soon as possible, for fast start of other app
+ else if(event_src == ASM_EVENT_SOURCE_OTHER_PLAYER_APP)
+ {
+ lazy_pause = TRUE; // return as soon as possible, for fast start of other app
- if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
- g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
+ if ( player->pipeline->audiobin && player->pipeline->audiobin[MMPLAYER_A_SINK].gst )
+ g_object_set( player->pipeline->audiobin[MMPLAYER_A_SINK].gst, "mute", 2, NULL);
- player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
- debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
- }
+ player->lazy_pause_event_id = g_timeout_add(LAZY_PAUSE_TIMEOUT_MSEC, (GSourceFunc)_asm_lazy_pause, (gpointer)player);
+ debug_warning ("set lazy pause timer (id=[%d], timeout=[%d ms])", player->lazy_pause_event_id, LAZY_PAUSE_TIMEOUT_MSEC);
+ }
#endif
- else
- {
- debug_warning ("pause immediately");
- result = _mmplayer_pause((MMHandleType)player);
- }
- cb_res = ASM_CB_RES_PAUSE;
- }
- break;
-
- case ASM_COMMAND_RESUME:
+#endif
+ else
+ {
+ debug_warning ("pause immediately");
+ result = _mmplayer_pause((MMHandleType)player);
+ if (result != MM_ERROR_NONE)
{
- debug_warning("Got msg from asm to Resume. So, application can resume. code (%d) \n", event_src);
- player->sm.antishock = TRUE;
- player->sm.by_asm_cb = FALSE;
-
- //ASM server is single thread daemon. So use g_idle_add() to post resume msg
- player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
- cb_res = ASM_CB_RES_IGNORE;
- goto DONE;
+ debug_warning("fail to set Pause state by asm");
+ goto EXIT;
}
- break;
+ }
+ }
+ else if (focus_state == FOCUS_IS_ACQUIRED)
+ {
+ debug_warning("FOCUS_IS_ACQUIRED: Got msg from asm to resume");
+ player->sound_focus.antishock = TRUE;
+ player->sound_focus.by_asm_cb = FALSE;
- default:
- break;
+ if (MM_ERROR_NONE == __mmplayer_convert_sound_focus_state(TRUE, reason_for_change, &msg))
+ {
+ player->sound_focus.focus_changed_msg = (int)msg;
+ }
+
+ //ASM server is single thread daemon. So use g_idle_add() to post resume msg
+ player->resume_event_id = g_idle_add((GSourceFunc)_asm_postmsg, (gpointer)player);
+ goto DONE;
+ }
+ else
+ {
+ debug_warning("unknown focus state %d", focus_state);
}
DONE:
if ( !lazy_pause )
{
- player->sm.by_asm_cb = FALSE;
+ player->sound_focus.by_asm_cb = FALSE;
}
- player->sm.cb_pending = FALSE;
+ player->sound_focus.cb_pending = FALSE;
MMPLAYER_CMD_UNLOCK( player );
EXIT:
debug_warning("dispatched");
- return cb_res;
+ return;
}
+
int
_mmplayer_create_player(MMHandleType handle) // @
{
debug_error("failed to initialize video capture\n");
goto ERROR;
}
-#if 0
+
/* register to asm */
- if ( MM_ERROR_NONE != _mmplayer_asm_register(&player->sm, (ASM_sound_cb_t)__mmplayer_asm_callback, (void*)player) )
+ if ( MM_ERROR_NONE != _mmplayer_sound_register(&player->sound_focus,
+ (mm_sound_focus_changed_cb)__mmplayer_sound_focus_callback,
+ (mm_sound_focus_changed_watch_cb)__mmplayer_sound_focus_watch_callback,
+ (void*)player) )
+
{
/* NOTE : we are dealing it as an error since we cannot expect it's behavior */
debug_error("failed to register asm server\n");
return MM_ERROR_POLICY_INTERNAL;
}
-
+#if 0 //need to change and test
/* to add active device callback */
if ( MM_ERROR_NONE != mm_sound_add_device_information_changed_callback(MM_SOUND_DEVICE_STATE_ACTIVATED_FLAG, __mmplayer_sound_device_info_changed_cb_func, (void*)player))
{
debug_error("failed mm_sound_add_device_information_changed_callback \n");
}
#endif
-
if (MMPLAYER_IS_HTTP_PD(player))
{
player->pd_downloader = NULL;
_mmplayer_release_video_capture(player);
/* flush any pending asm_cb */
- if (player->sm.cb_pending)
+ if (player->sound_focus.cb_pending)
{
/* set a flag for make sure asm_cb to be returned immediately */
debug_warning("asm cb has pending state");
- player->sm.exit_cb = TRUE;
+ player->sound_focus.exit_cb = TRUE;
/* make sure to release any pending asm_cb which locked by cmd_lock */
MMPLAYER_CMD_UNLOCK(player);
sched_yield();
MMPLAYER_CMD_LOCK(player);
}
-#if 0
+
/* withdraw asm */
- if ( MM_ERROR_NONE != _mmplayer_asm_unregister(&player->sm) )
+ if ( MM_ERROR_NONE != _mmplayer_sound_unregister(&player->sound_focus) )
{
debug_error("failed to deregister asm server\n");
}
-#endif
+
#ifdef USE_LAZY_PAUSE
if (player->lazy_pause_event_id)
{
}
mm_attrs_get_int_by_name(attrs, "sound_application_pid", &application_pid );
- player->sm.pid = application_pid;
+ player->sound_focus.pid = application_pid;
mm_attrs_get_string_by_name(attrs, "profile_uri", &uri);
mm_attrs_get_data_by_name(attrs, "profile_user_param", ¶m);
/* set asm stop if success */
if (MM_ERROR_NONE == ret)
{
- if (player->sm.state != ASM_STATE_STOP)
+ ret = _mmplayer_sound_release_focus(&player->sound_focus);
+ if ( ret != MM_ERROR_NONE )
{
- /* NOTE : Stop asm after pipeline unrealize. Keep this sequence. */
- ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_STOP, FALSE);
- if ( ret )
- {
- debug_error("failed to set asm state to STOP");
- return ret;
- }
+ debug_error("failed to release sound focus\n");
+ return ret;
}
}
else
/* check current state */
MMPLAYER_CHECK_STATE_RETURN_IF_FAIL( player, MMPLAYER_COMMAND_START );
- ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
+ ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
if ( ret != MM_ERROR_NONE )
{
- debug_error("failed to set asm state to PLAYING\n");
+ debug_error("failed to acquire sound focus.\n");
return ret;
}
return_val_if_fail ( player, MM_ERROR_PLAYER_NOT_INITIALIZED );
- ret = _mmplayer_asm_set_state(hplayer, ASM_STATE_PLAYING, TRUE);
- if ( ret )
+ ret = _mmplayer_sound_acquire_focus(&player->sound_focus);
+ if ( ret != MM_ERROR_NONE )
{
- debug_error("failed to set asm state to PLAYING\n");
+ debug_error("failed to acquire sound focus.\n");
return ret;
}
player->max_audio_channels = 0;
player->video_share_api_delta = 0;
player->video_share_clock_delta = 0;
- player->sm.keep_last_pos = FALSE;
+ player->sound_focus.keep_last_pos = FALSE;
+ player->sound_focus.acquired = FALSE;
player->is_subtitle_force_drop = FALSE;
player->play_subtitle = FALSE;
player->use_textoverlay = FALSE;
--- /dev/null
+/*
+ * libmm-player
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
+ * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <mm_debug.h>
+#include <mm_error.h>
+#include <vconf.h>
+#include <vconf-internal-sound-keys.h>
+
+#include "mm_player_utils.h"
+#include "mm_player_priv.h"
+#include "mm_player_sound_focus.h"
+
+#define MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(x_player_sound_focus) \
+do \
+{ \
+ if (!x_player_sound_focus) \
+ { \
+ debug_log("no sound focus instance");\
+ return MM_ERROR_SOUND_NOT_INITIALIZED; \
+ } \
+}while(0);
+
+void __mmplayer_sound_signal_callback (mm_sound_signal_name_t signal, int value, void *user_data)
+{
+ MMPlayerSoundFocus *sound_focus = (MMPlayerSoundFocus*)user_data;
+
+ debug_log("sound signal callback %d / %d", signal, value);
+
+ if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS)
+ {
+ if (value == 1)
+ {
+ if (sound_focus->watch_id > 0)
+ {
+ debug_log("unset the focus watch cb");
+
+ mm_sound_unset_focus_watch_callback(sound_focus->watch_id);
+ sound_focus->watch_id = 0;
+ /*
+ if (sound_focus->subscribe_id > 0)
+ mm_sound_unsubscribe_signal(sound_focus->subscribe_id);
+ */
+ }
+ }
+ }
+}
+
+const gchar *
+__mmplayer_sound_get_stream_type(gint type)
+{
+ switch ( type )
+ {
+ case MM_SESSION_TYPE_CALL:
+ case MM_SESSION_TYPE_VIDEOCALL:
+ case MM_SESSION_TYPE_VOIP:
+ return "ringtone-voip";
+ case MM_SESSION_TYPE_MEDIA:
+ return "media";
+ case MM_SESSION_TYPE_NOTIFY:
+ return "notification";
+ case MM_SESSION_TYPE_ALARM:
+ return "alarm";
+ case MM_SESSION_TYPE_EMERGENCY:
+ return "emergency";
+ default:
+ debug_warning("unexpected case!\n");
+ return "media";
+ }
+
+ return "media";
+}
+
+int
+_mmplayer_sound_acquire_focus(MMPlayerSoundFocus* sound_focus)
+{
+ int ret = MM_ERROR_NONE;
+ const gchar *stream_type = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
+
+ if (sound_focus->acquired)
+ {
+ debug_warning("focus is already acquired. can't acquire again.");
+ return MM_ERROR_NONE;
+ }
+
+ stream_type = __mmplayer_sound_get_stream_type(sound_focus->session_type);
+
+ if ((!strstr(stream_type, "media")) ||
+ (sound_focus->session_flags & MM_SESSION_OPTION_PAUSE_OTHERS))
+ {
+
+ ret = mm_sound_acquire_focus(sound_focus->focus_id, FOCUS_FOR_BOTH, NULL);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("failed to acquire sound focus\n");
+ return ret;
+ }
+
+ sound_focus->acquired = TRUE;
+ }
+
+ MMPLAYER_FLEAVE();
+ return ret;
+}
+
+int
+_mmplayer_sound_release_focus(MMPlayerSoundFocus* sound_focus)
+{
+ int ret = MM_ERROR_NONE;
+ const gchar *stream_type = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
+
+ if (!sound_focus->acquired)
+ {
+ debug_warning("focus is not acquired. no need to release.");
+ return MM_ERROR_NONE;
+ }
+
+ stream_type = __mmplayer_sound_get_stream_type(sound_focus->session_type);
+
+ if ((!strstr(stream_type, "media")) ||
+ (sound_focus->session_flags & MM_SESSION_OPTION_PAUSE_OTHERS))
+ {
+ ret = mm_sound_release_focus(sound_focus->focus_id, FOCUS_FOR_BOTH, NULL);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("failed to release sound focus\n");
+ return ret;
+ }
+
+ sound_focus->acquired = FALSE;
+ }
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}
+
+gint
+_mmplayer_sound_register(MMPlayerSoundFocus* sound_focus,
+ mm_sound_focus_changed_cb focus_cb, mm_sound_focus_changed_watch_cb watch_cb, void* param)
+{
+ gint pid = -1;
+ gint ret = MM_ERROR_NONE;
+ const gchar *stream_type = NULL;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
+
+ /* check if it's running on the media_server */
+ if (sound_focus->pid > 0)
+ {
+ pid = sound_focus->pid;
+ debug_log("mm-player is running on different process. Just faking pid to [%d]. :-p\n", pid);
+ }
+
+ /* read session information */
+ ret = _mm_session_util_read_information(pid, &sound_focus->session_type, &sound_focus->session_flags);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("Read Session Type failed. ret:0x%X \n", ret);
+
+ if (ret == MM_ERROR_INVALID_HANDLE)
+ {
+ int sig_value = 0;
+
+ mm_sound_get_signal_value(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &sig_value);
+ debug_warning("internal focus signal value=%d, id=%d\n", sig_value, sound_focus->subscribe_id);
+
+ if ((sig_value == 0) && (sound_focus->subscribe_id == 0))
+ {
+ ret = mm_sound_subscribe_signal(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, &sound_focus->subscribe_id,
+ (mm_sound_signal_callback)__mmplayer_sound_signal_callback, (void*)sound_focus);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("mm_sound_subscribe_signal is failed\n");
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+
+ debug_log("register focus watch callback for the value is 0, sub_cb id %d\n", sound_focus->subscribe_id);
+
+ ret = mm_sound_set_focus_watch_callback(FOCUS_FOR_BOTH, watch_cb, (void*)param, &sound_focus->watch_id);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("mm_sound_set_focus_watch_callback is failed\n");
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+
+ return MM_ERROR_NONE;
+ }
+ else
+ {
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+
+ /* interpret session information */
+ stream_type = __mmplayer_sound_get_stream_type(sound_focus->session_type);
+ debug_log("fid [%d] wid [%d] type[%s], flags[0x%02X]\n",
+ sound_focus->focus_id, sound_focus->watch_id, stream_type, sound_focus->session_flags);
+
+ if (sound_focus->focus_id == 0)
+ {
+ /* get unique id */
+ ret = mm_sound_focus_get_id(&sound_focus->focus_id);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("failed to get unique focus id\n");
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+
+ /* register sound focus callback */
+ ret = mm_sound_register_focus(sound_focus->focus_id, stream_type, focus_cb, (void*)param);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("mm_sound_register_focus is failed\n");
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+
+ if ((sound_focus->watch_id == 0) &&
+ (strstr(stream_type, "media")) &&
+ !(sound_focus->session_flags & ASM_SESSION_OPTION_PAUSE_OTHERS) &&
+ !(sound_focus->session_flags & ASM_SESSION_OPTION_UNINTERRUPTIBLE))
+ {
+ debug_log("register focus watch callback\n");
+
+ ret = mm_sound_set_focus_watch_callback(FOCUS_FOR_BOTH, watch_cb, (void*)param, &sound_focus->watch_id);
+ if (ret != MM_ERROR_NONE)
+ {
+ debug_error("mm_sound_set_focus_watch_callback is failed\n");
+ return MM_ERROR_POLICY_BLOCKED;
+ }
+ }
+
+ MMPLAYER_FLEAVE();
+
+ return MM_ERROR_NONE;
+}
+
+gint
+_mmplayer_sound_unregister(MMPlayerSoundFocus* sound_focus)
+{
+ MMPLAYER_FENTER();
+
+ MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
+
+ debug_log("unregister sound focus callback\n");
+
+ if (sound_focus->focus_id > 0)
+ {
+ mm_sound_unregister_focus(sound_focus->focus_id);
+ sound_focus->focus_id = 0;
+ }
+
+ if (sound_focus->watch_id > 0)
+ {
+ mm_sound_unset_focus_watch_callback(sound_focus->watch_id);
+ sound_focus->watch_id = 0;
+ }
+
+ if (sound_focus->subscribe_id > 0)
+ {
+ mm_sound_unsubscribe_signal(sound_focus->subscribe_id);
+ sound_focus->subscribe_id = 0;
+ }
+
+ MMPLAYER_FLEAVE();
+
+ return MM_ERROR_NONE;
+}
+