Applay sound focus 30/45130/3 accepted/tizen/mobile/20150810.101612 accepted/tizen/tv/20150810.101806 accepted/tizen/wearable/20150810.101951 submit/tizen/20150810.073809
authorHyunil Park <hyunil46.park@samsung.com>
Mon, 3 Aug 2015 00:45:57 +0000 (09:45 +0900)
committerHyunil Park <hyunil46.park@samsung.com>
Mon, 10 Aug 2015 05:32:37 +0000 (14:32 +0900)
Change-Id: Ibbafa04f4baea8ff125d087258128722031eb66f
Signed-off-by: Hyunil Park <hyunil46.park@samsung.com>
src/Makefile.am
src/include/mm_player.h [changed mode: 0644->0755]
src/include/mm_player_priv.h
src/include/mm_player_sound_focus.h [moved from src/include/mm_player_asm.h with 54% similarity]
src/mm_player.c [changed mode: 0644->0755]
src/mm_player_asm.c [deleted file]
src/mm_player_priv.c
src/mm_player_sound_focus.c [new file with mode: 0755]

index f54fc2a..9e4159b 100644 (file)
@@ -11,7 +11,7 @@ libmmfplayer_la_SOURCES = mm_player.c \
                          mm_player_priv.c \
                          mm_player_ini.c \
                          mm_player_utils.c \
-                         mm_player_asm.c \
+                         mm_player_sound_focus.c \
                          mm_player_attrs.c \
                          mm_player_capture.c \
                          mm_player_pd.c \
@@ -29,7 +29,6 @@ libmmfplayer_la_CFLAGS =  -I$(srcdir)/include \
                        $(GST_APP_CFLAGS) \
                        $(MMSESSION_CFLAGS) \
                        $(MMSOUND_CFLAGS) \
-                       $(AUDIOSESSIONMGR_CFLAGS) \
                        $(VCONF_CFLAGS) \
                        $(ICU_CFLAGS) \
                        $(UTILX_CFLAGS) \
@@ -39,7 +38,7 @@ libmmfplayer_la_CFLAGS =  -I$(srcdir)/include \
 noinst_HEADERS = include/mm_player_utils.h \
                 include/mm_player_ini.h \
                 include/mm_player_priv.h \
-                include/mm_player_asm.h \
+                include/mm_player_sound_focus.h \
                 include/mm_player_attrs.h \
                 include/mm_player_capture.h \
                 include/mm_player_pd.h \
@@ -56,7 +55,6 @@ libmmfplayer_la_LIBADD = $(GST_LIBS) \
                $(INIPARSER_LIBS) \
                $(MMSESSION_LIBS) \
                $(MMSOUND_LIBS) \
-               $(AUDIOSESSIONMGR_LIBS) \
                $(VCONF_LIBS) \
                $(ICU_LIBS) \
                $(MEDIAPACKET_LIBS) \
old mode 100644 (file)
new mode 100755 (executable)
index fff2ae4..1c326e3
@@ -774,6 +774,19 @@ typedef enum
        MM_PLAYER_SOUND_RESOURCE_PRELISTENING_MEDIA,
 } MMPlayerSoundResource;
 
+typedef enum
+{
+       MM_PLAYER_FOCUS_CHANGED_COMPLETED = 0,
+       MM_PLAYER_FOCUS_CHANGED_BY_MEDIA,
+       MM_PLAYER_FOCUS_CHANGED_BY_CALL,
+       MM_PLAYER_FOCUS_CHANGED_BY_EARJACK_UNPLUG,
+       MM_PLAYER_FOCUS_CHANGED_BY_RESOURCE_CONFLICT,
+       MM_PLAYER_FOCUS_CHANGED_BY_ALARM,
+       MM_PLAYER_FOCUS_CHANGED_BY_EMERGENCY,
+       MM_PLAYER_FOCUS_CHANGED_BY_NOTIFICATION,
+       MM_PLAYER_FOCUS_CHANGED_BY_UNKNOWN,
+} MMPlayerFocusChangedMsg;
+
 
 /**
  * Edge Properties of the text.
index 050a5b2..9374fd2 100755 (executable)
@@ -43,7 +43,7 @@
 #include "mm_player_audioeffect.h"
 #include "mm_message.h"
 #include "mm_player_ini.h"
-#include "mm_player_asm.h"
+#include "mm_player_sound_focus.h"
 #include "mm_player_pd.h"
 #include "mm_player_streaming.h"
 
@@ -645,7 +645,7 @@ typedef struct {
        gboolean is_nv12_tiled;
        gboolean is_drm_file;
 
-       MMPlayerASM sm;
+       MMPlayerSoundFocus sound_focus;
 
        gboolean is_subtitle_off;
        gboolean is_external_subtitle_present;
similarity index 54%
rename from src/include/mm_player_asm.h
rename to src/include/mm_player_sound_focus.h
index 4ff18cf..ba8aa76 100755 (executable)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
  *
- * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
+ * Contact: Heechul Jeon <heechul.jeon@samsung.com>
  * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  *
  */
 
-#ifndef __MM_PLAYER_ASM_H__
-#define __MM_PLAYER_ASM_H__
+#ifndef __MM_PLAYER_SOUND_FOCUS_H__
+#define __MM_PLAYER_SOUND_FOCUS_H__
 
 #include <glib.h>
 #include <mm_types.h>
 
 #include <mm_session.h>
 #include <mm_session_private.h>
-#include <audio-session-manager.h>
+#include <mm_sound_focus.h>
+#include <mm_sound.h>
+
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef struct {
-       int handle;
+       int focus_id;
+       int watch_id;
+       unsigned int subscribe_id;
        int pid;
        bool by_asm_cb;
        int antishock;
-       int event_src;
-       int skip_session;
        bool keep_last_pos;
        int user_route_policy;
-       ASM_sound_states_t state;
-       ASM_sound_events_t event;
-       ASM_resource_t resource;
        bool exit_cb;
        bool cb_pending;
-} MMPlayerASM;
+       bool acquired;
+       int session_type;
+       int session_flags;
+       int focus_changed_msg;  // MMPlayerFocusChangedMsg
+
+} MMPlayerSoundFocus;
 
-gint _mmplayer_asm_register(MMPlayerASM* sm, ASM_sound_cb_t callback, void* param);
-gint _mmplayer_asm_unregister(MMPlayerASM* sm);
-gint _mmplayer_asm_set_state(MMHandleType player, ASM_sound_states_t state, gboolean enable_safety_vol);
-gint _mmplayer_asm_ignore_session(MMHandleType player);
-gint _mmplayer_asm_set_sound_resource(MMHandleType player, MMPlayerSoundResource mode);
-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);
+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 _mmplayer_sound_unregister(MMPlayerSoundFocus* sound_focus);
+int _mmplayer_sound_acquire_focus(MMPlayerSoundFocus* sound_focus);
+int _mmplayer_sound_release_focus(MMPlayerSoundFocus* sound_focus);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* __MM_PLAYER_ASM_H__ */
+#endif /* __MM_PLAYER_SOUND_FOCUS_H__ */
old mode 100644 (file)
new mode 100755 (executable)
index c3653bc..8e8528a
@@ -804,17 +804,6 @@ int mm_player_get_track_language_code(MMHandleType player,  MMPlayerTrackType ty
        return result;
 }
 
-int mm_player_ignore_session(MMHandleType player)
-{
-       int result = MM_ERROR_NONE;
-
-       return_val_if_fail(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
-
-       result = _mmplayer_asm_ignore_session(player);
-
-       return result;
-}
-
 int mm_player_set_display_zoom(MMHandleType player, float level, int x, int y)
 {
        int result = MM_ERROR_NONE;
diff --git a/src/mm_player_asm.c b/src/mm_player_asm.c
deleted file mode 100755 (executable)
index 6638363..0000000
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * 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;
-}
index de7fff7..f950110 100755 (executable)
@@ -53,6 +53,7 @@
 #include <sched.h>
 
 #include <mm_sound.h>
+#include <mm_sound_focus.h>
 
 #define MM_SMOOTH_STREAMING
 
@@ -1168,7 +1169,7 @@ int
 __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;
@@ -1198,7 +1199,7 @@ __mmplayer_set_state(mm_player_t* player, int state) // @
        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) )
        {
@@ -1207,10 +1208,10 @@ __mmplayer_set_state(mm_player_t* player, int state) // @
                {
                        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;
                                }
                        }
@@ -1249,10 +1250,10 @@ __mmplayer_set_state(mm_player_t* player, int state) // @
 
                        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;
                                }
                        }
@@ -1276,11 +1277,10 @@ __mmplayer_set_state(mm_player_t* player, int state) // @
                                {
                                        __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, };
@@ -1295,9 +1295,9 @@ __mmplayer_set_state(mm_player_t* player, int state) // @
                                        }
                                        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;
@@ -1374,7 +1374,7 @@ __mmplayer_set_state(mm_player_t* player, int state) // @
                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 */
@@ -1984,7 +1984,6 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
                case GST_MESSAGE_BUFFERING:
                {
                        MMMessageParamType msg_param = {0, };
-                       int asm_result = MM_ERROR_NONE;
 
                        if (!MMPLAYER_IS_STREAMING(player))
                                break;
@@ -2005,17 +2004,6 @@ __mmplayer_gst_callback(GstBus *bus, GstMessage *msg, gpointer data) // @
                                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 );
@@ -5366,11 +5354,26 @@ void __mmplayer_gst_set_audiosink_property(mm_player_t* player, MMHandleType att
        };
 
        /* 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,
@@ -8016,13 +8019,13 @@ __mmplayer_gst_destroy_pipeline(mm_player_t* player) // @
 
        /* 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 )
        {
@@ -8361,7 +8364,7 @@ static int __gst_stop(mm_player_t* player) // @
        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. */
@@ -8390,7 +8393,7 @@ static int __gst_stop(mm_player_t* player) // @
        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 */
@@ -8825,7 +8828,7 @@ __gst_get_position(mm_player_t* player, int format, unsigned long* position) //
                        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;
                }
@@ -9295,7 +9298,7 @@ gboolean _asm_postmsg(gpointer *data)
 
 
        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)
@@ -9343,7 +9346,7 @@ gboolean _asm_lazy_pause(gpointer *data)
        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();
 
@@ -9359,9 +9362,9 @@ __mmplayer_can_do_interrupt(mm_player_t *player)
                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;
        }
 
@@ -9404,15 +9407,169 @@ INTERRUPT:
        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))
        {
@@ -9420,12 +9577,20 @@ __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_com
                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)
        {
@@ -9436,11 +9601,13 @@ __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_com
        }
        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)
                {
@@ -9458,124 +9625,110 @@ __mmplayer_asm_callback(int handle, ASM_event_sources_t event_src, ASM_sound_com
        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) // @
 {
@@ -9648,22 +9801,25 @@ _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;
@@ -9934,24 +10090,24 @@ _mmplayer_destroy(MMHandleType handle) // @
        _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)
        {
@@ -10066,7 +10222,7 @@ _mmplayer_realize(MMHandleType hplayer) // @
        }
 
        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", &param);
@@ -10187,15 +10343,11 @@ _mmplayer_unrealize(MMHandleType hplayer)
        /* 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
@@ -10612,10 +10764,10 @@ _mmplayer_start(MMHandleType hplayer) // @
        /* 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;
        }
 
@@ -10879,10 +11031,10 @@ _mmplayer_resume(MMHandleType hplayer)
 
        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;
        }
 
@@ -13529,7 +13681,8 @@ __mmplayer_release_misc(mm_player_t* player)
        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;
diff --git a/src/mm_player_sound_focus.c b/src/mm_player_sound_focus.c
new file mode 100755 (executable)
index 0000000..e9f2818
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * 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;
+}
+