4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, YeJin Cho <cho.yejin@samsung.com>,
7 * Seungbae Shin <seungbae.shin@samsung.com>, YoungHwan An <younghwan_.an@samsung.com>
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
22 #include <sys/types.h>
27 #include <vconf-internal-sound-keys.h>
29 #include "mm_player_utils.h"
30 #include "mm_player_priv.h"
31 #include "mm_player_sound_focus.h"
33 #define MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(x_player_sound_focus) \
36 if (!x_player_sound_focus) \
38 LOGD("no sound focus instance");\
39 return MM_ERROR_SOUND_NOT_INITIALIZED; \
43 void __mmplayer_sound_signal_callback (mm_sound_signal_name_t signal, int value, void *user_data)
45 MMPlayerSoundFocus *sound_focus = (MMPlayerSoundFocus*)user_data;
46 int ret = MM_ERROR_NONE;
48 LOGD("sound signal callback %d / %d", signal, value);
50 if (signal == MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS)
54 /* unregister watch callback */
55 if (sound_focus->watch_id > 0)
57 LOGD("unset the focus watch cb %d", sound_focus->watch_id);
59 ret = mm_sound_unset_focus_watch_callback(sound_focus->watch_id);
60 sound_focus->watch_id = 0;
61 if (ret != MM_ERROR_NONE)
62 LOGE("failed to mm_sound_unset_focus_watch_callback()");
64 if (sound_focus->subscribe_id > 0)
65 mm_sound_unsubscribe_signal(sound_focus->subscribe_id);
68 /* unregister focus callback */
69 if (sound_focus->focus_id > 0)
71 ret = mm_sound_unregister_focus(sound_focus->focus_id);
72 sound_focus->focus_id = 0;
73 if (ret != MM_ERROR_NONE)
74 LOGE("failed to mm_sound_unregister_focus() %d", sound_focus->focus_id);
76 /* unregister device connected callback */
77 if (sound_focus->connected_id > 0)
79 LOGD("unset the device connected cb %d", sound_focus->connected_id);
80 ret = mm_sound_remove_device_connected_callback(sound_focus->connected_id);
81 sound_focus->connected_id = 0;
82 if (ret != MM_ERROR_NONE)
83 LOGE("failed to mm_sound_remove_device_connected_callback()");
90 __mmplayer_sound_device_connected_cb_func(MMSoundDevice_t device_h, bool is_connected, void *user_data)
92 mm_player_t* player = (mm_player_t*) user_data;
93 MMPLAYER_RETURN_IF_FAIL( player );
95 mm_sound_device_type_e device_type;
97 MMMessageParamType msg = {0, };
99 LOGW("device_connected_cb is called, device_h[0x%x], is_connected[%d]\n", device_h, is_connected);
101 /* get device type with device_h*/
102 ret = mm_sound_get_device_type(device_h, &device_type);
104 if (!is_connected && MMPLAYER_CURRENT_STATE(player) == MM_PLAYER_STATE_PLAYING
105 && (player->sound_focus.focus_id > 0 || player->sound_focus.watch_id > 0))
109 case MM_SOUND_DEVICE_TYPE_AUDIOJACK:
110 case MM_SOUND_DEVICE_TYPE_BLUETOOTH:
111 case MM_SOUND_DEVICE_TYPE_HDMI:
112 case MM_SOUND_DEVICE_TYPE_USB_AUDIO:
114 ret = gst_element_set_state(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_STATE_PAUSED);
115 if (ret != GST_STATE_CHANGE_SUCCESS)
117 LOGE("focus_id [%d], watch_id [%d], connected_id [%d], change_state result[%d]",
118 player->sound_focus.focus_id, player->sound_focus.watch_id,
119 player->sound_focus.connected_id, ret);
121 msg.union_type = MM_MSG_UNION_CODE;
122 msg.code = MM_MSG_CODE_INTERRUPTED_BY_EARJACK_UNPLUG;
123 MMPLAYER_POST_MSG( player, MM_MESSAGE_STATE_INTERRUPTED, &msg );
134 __mmplayer_sound_get_stream_type(gint type)
138 case MM_SESSION_TYPE_CALL:
139 case MM_SESSION_TYPE_VIDEOCALL:
140 case MM_SESSION_TYPE_VOIP:
141 return "ringtone-voip";
142 case MM_SESSION_TYPE_MEDIA:
144 case MM_SESSION_TYPE_NOTIFY:
145 return "notification";
146 case MM_SESSION_TYPE_ALARM:
148 case MM_SESSION_TYPE_EMERGENCY:
151 LOGW("unexpected case!\n");
159 _mmplayer_sound_acquire_focus(MMPlayerSoundFocus* sound_focus)
161 int ret = MM_ERROR_NONE;
162 const gchar *stream_type = NULL;
165 MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
167 if (sound_focus->acquired)
169 LOGW("focus is already acquired. can't acquire again.");
170 return MM_ERROR_NONE;
173 stream_type = __mmplayer_sound_get_stream_type(sound_focus->session_type);
175 if ((!strstr(stream_type, "media")) ||
176 (sound_focus->session_flags & MM_SESSION_OPTION_PAUSE_OTHERS))
179 ret = mm_sound_acquire_focus(sound_focus->focus_id, FOCUS_FOR_BOTH, NULL);
180 if (ret != MM_ERROR_NONE)
182 LOGE("failed to acquire sound focus\n");
186 sound_focus->acquired = TRUE;
194 _mmplayer_sound_release_focus(MMPlayerSoundFocus* sound_focus)
196 int ret = MM_ERROR_NONE;
197 const gchar *stream_type = NULL;
200 MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
202 if (!sound_focus->acquired)
204 LOGW("focus is not acquired. no need to release.");
205 return MM_ERROR_NONE;
208 stream_type = __mmplayer_sound_get_stream_type(sound_focus->session_type);
210 if ((!strstr(stream_type, "media")) ||
211 (sound_focus->session_flags & MM_SESSION_OPTION_PAUSE_OTHERS))
213 ret = mm_sound_release_focus(sound_focus->focus_id, FOCUS_FOR_BOTH, NULL);
214 if (ret != MM_ERROR_NONE)
216 LOGE("failed to release sound focus\n");
220 sound_focus->acquired = FALSE;
224 return MM_ERROR_NONE;
228 _mmplayer_sound_register(MMPlayerSoundFocus* sound_focus,
229 mm_sound_focus_changed_cb focus_cb, mm_sound_focus_changed_watch_cb watch_cb, void* param)
232 gint ret = MM_ERROR_NONE;
233 const gchar *stream_type = NULL;
236 MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
238 /* check if it's running on the media_server */
239 if (sound_focus->pid > 0)
240 pid = sound_focus->pid;
242 return MM_ERROR_INVALID_ARGUMENT;
244 LOGD("sound register focus pid[%d]", pid);
245 /* read session information */
246 ret = _mm_session_util_read_information(pid, &sound_focus->session_type, &sound_focus->session_flags);
247 LOGW("Read Session Type -> ret:0x%X \n", ret);
249 /* case 1. if there is no session */
250 if (ret == MM_ERROR_INVALID_HANDLE)
252 LOGW("subscribe_id=%d\n", sound_focus->subscribe_id);
254 if (sound_focus->subscribe_id == 0)
256 ret = mm_sound_subscribe_signal_for_daemon(MM_SOUND_SIGNAL_RELEASE_INTERNAL_FOCUS, pid, &sound_focus->subscribe_id,
257 (mm_sound_signal_callback)__mmplayer_sound_signal_callback, (void*)sound_focus);
258 if (ret != MM_ERROR_NONE)
260 LOGE("mm_sound_subscribe_signal is failed\n");
261 return MM_ERROR_POLICY_BLOCKED;
264 LOGD("register focus watch callback for the value is 0, sub_cb id %d\n", sound_focus->subscribe_id);
265 /* register watch callback */
266 ret = mm_sound_set_focus_watch_callback_for_session(pid ,
267 FOCUS_FOR_BOTH, watch_cb, (void*)param, &sound_focus->watch_id);
268 if (ret != MM_ERROR_NONE)
270 LOGE("mm_sound_set_focus_watch_callback is failed\n");
271 return MM_ERROR_POLICY_BLOCKED;
273 /* register device connected callback */
274 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG,
275 (mm_sound_device_connected_cb)__mmplayer_sound_device_connected_cb_func, (void*)param, &sound_focus->connected_id);
276 if (ret != MM_ERROR_NONE)
278 LOGE("mm_sound_add_device_connected_callback is failed\n");
279 return MM_ERROR_POLICY_BLOCKED;
281 LOGD("register device connected callback for the value is 0, sub_cb id %d\n", sound_focus->connected_id);
285 /* case 2. if sessoin exists */
286 else if (ret == MM_ERROR_NONE)
288 /* in this case, this process is using stream info created by using sound-manager,
289 * we're going to skip working on backward compatibility of session. */
290 if (sound_focus->session_type == MM_SESSION_TYPE_REPLACED_BY_STREAM)
292 LOGW("this process is using stream info. skip it..");
296 /* interpret session information */
297 stream_type = __mmplayer_sound_get_stream_type(sound_focus->session_type);
298 LOGD("fid [%d] wid [%d] type[%s], flags[0x%02X]\n",
299 sound_focus->focus_id, sound_focus->watch_id, stream_type, sound_focus->session_flags);
301 if (sound_focus->focus_id == 0)
304 ret = mm_sound_focus_get_id(&sound_focus->focus_id);
305 if (ret != MM_ERROR_NONE)
307 LOGE("failed to get unique focus id\n");
308 return MM_ERROR_POLICY_BLOCKED;
311 /* register sound focus callback */
312 ret = mm_sound_register_focus_for_session(sound_focus->focus_id, pid,
313 stream_type, focus_cb, (void*)param);
314 if (ret != MM_ERROR_NONE)
316 LOGE("mm_sound_register_focus is failed\n");
317 return MM_ERROR_POLICY_BLOCKED;
321 if ((sound_focus->watch_id == 0) &&
322 (strstr(stream_type, "media")) &&
323 !(sound_focus->session_flags & MM_SESSION_OPTION_PAUSE_OTHERS) &&
324 !(sound_focus->session_flags & MM_SESSION_OPTION_UNINTERRUPTIBLE))
326 LOGD("register focus watch callback\n");
327 /* register watch callback */
328 ret = mm_sound_set_focus_watch_callback_for_session(pid,
329 FOCUS_FOR_BOTH, watch_cb, (void*)param, &sound_focus->watch_id);
330 if (ret != MM_ERROR_NONE)
332 LOGE("mm_sound_set_focus_watch_callback is failed\n");
333 return MM_ERROR_POLICY_BLOCKED;
337 if(sound_focus->connected_id == 0)
339 /* register device connected callback */
340 ret = mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_TYPE_EXTERNAL_FLAG,
341 (mm_sound_device_connected_cb)__mmplayer_sound_device_connected_cb_func, (void*)param, &sound_focus->connected_id);
342 if (ret != MM_ERROR_NONE)
344 LOGE("mm_sound_add_device_connected_callback is failed\n");
345 return MM_ERROR_POLICY_BLOCKED;
347 LOGD("register device connected callback for the value is 0, sub_cb id %d\n", sound_focus->connected_id);
354 LOGE("_mm_session_util_read_information is failed");
355 ret = MM_ERROR_POLICY_BLOCKED;
363 _mmplayer_sound_unregister(MMPlayerSoundFocus* sound_focus)
365 int ret = MM_ERROR_NONE;
369 MMPLAYER_CHECK_SOUND_FOCUS_INSTANCE(sound_focus);
371 LOGD("unregister sound focus callback\n");
373 if (sound_focus->focus_id > 0)
375 ret = mm_sound_unregister_focus(sound_focus->focus_id);
376 if(ret != MM_ERROR_NONE)
377 LOGE("failed to mm_sound_unregister_focus() %d", sound_focus->focus_id);
378 sound_focus->focus_id = 0;
381 if (sound_focus->watch_id > 0)
383 ret = mm_sound_unset_focus_watch_callback(sound_focus->watch_id);
384 if(ret != MM_ERROR_NONE)
385 LOGE("failed to mm_sound_unset_focus_watch_callback() %d", sound_focus->watch_id);
386 sound_focus->watch_id = 0;
389 if (sound_focus->subscribe_id > 0)
391 mm_sound_unsubscribe_signal(sound_focus->subscribe_id);
392 sound_focus->subscribe_id = 0;
394 if( sound_focus->connected_id > 0 )
396 ret = mm_sound_remove_device_connected_callback(sound_focus->connected_id);
397 if(ret != MM_ERROR_NONE)
398 LOGE("failed to mm_sound_remove_device_connected_callback() %d", sound_focus->connected_id);
399 sound_focus->connected_id = 0;
404 return MM_ERROR_NONE;