From: Hyunil Park Date: Mon, 3 Aug 2015 00:45:57 +0000 (+0900) Subject: Applay sound focus X-Git-Tag: accepted/tizen/tv/20150810.101806 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b46a0381b92a3e6ab6507f787b3f33c8ff6807e2;p=platform%2Fcore%2Fmultimedia%2Flibmm-player.git Applay sound focus Change-Id: Ibbafa04f4baea8ff125d087258128722031eb66f Signed-off-by: Hyunil Park --- diff --git a/src/Makefile.am b/src/Makefile.am index f54fc2a..9e4159b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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) \ diff --git a/src/include/mm_player.h b/src/include/mm_player.h old mode 100644 new mode 100755 index fff2ae4..1c326e3 --- a/src/include/mm_player.h +++ b/src/include/mm_player.h @@ -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. diff --git a/src/include/mm_player_priv.h b/src/include/mm_player_priv.h index 050a5b2..9374fd2 100755 --- a/src/include/mm_player_priv.h +++ b/src/include/mm_player_priv.h @@ -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; diff --git a/src/include/mm_player_asm.h b/src/include/mm_player_sound_focus.h similarity index 54% rename from src/include/mm_player_asm.h rename to src/include/mm_player_sound_focus.h index 4ff18cf..ba8aa76 100755 --- a/src/include/mm_player_asm.h +++ b/src/include/mm_player_sound_focus.h @@ -3,7 +3,7 @@ * * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. * - * Contact: JongHyuk Choi , YeJin Cho , + * Contact: Heechul Jeon * Seungbae Shin , YoungHwan An * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,45 +20,47 @@ * */ -#ifndef __MM_PLAYER_ASM_H__ -#define __MM_PLAYER_ASM_H__ +#ifndef __MM_PLAYER_SOUND_FOCUS_H__ +#define __MM_PLAYER_SOUND_FOCUS_H__ #include #include #include #include -#include +#include +#include + #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__ */ diff --git a/src/mm_player.c b/src/mm_player.c old mode 100644 new mode 100755 index c3653bc..8e8528a --- a/src/mm_player.c +++ b/src/mm_player.c @@ -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 index 6638363..0000000 --- a/src/mm_player_asm.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * libmm-player - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: JongHyuk Choi , YeJin Cho , - * Seungbae Shin , YoungHwan An - * - * 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 -#include -#include "mm_player_utils.h" -#include "mm_player_priv.h" -#include "mm_player_asm.h" -#include -#include - -#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; -} diff --git a/src/mm_player_priv.c b/src/mm_player_priv.c index de7fff7..f950110 100755 --- a/src/mm_player_priv.c +++ b/src/mm_player_priv.c @@ -53,6 +53,7 @@ #include #include +#include #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", ¶m); @@ -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 index 0000000..e9f2818 --- /dev/null +++ b/src/mm_player_sound_focus.c @@ -0,0 +1,295 @@ +/* + * libmm-player + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: JongHyuk Choi , YeJin Cho , + * Seungbae Shin , YoungHwan An + * + * 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 +#include +#include +#include + +#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; +} +