4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Seungbae Shin <seungbae.shin@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
35 #include "include/mm_sound_mgr_common.h"
36 #include "include/mm_sound_mgr_ipc.h"
37 #include "include/mm_sound_mgr_device.h"
38 #include "include/mm_sound_thread_pool.h"
39 #include "../include/mm_sound_msg.h"
40 #include "../include/mm_sound_common.h"
41 #include "../include/mm_sound_utils.h"
43 #include "include/mm_sound_mgr_session.h"
45 void _mm_sound_get_devices_from_route(mm_sound_route route, mm_sound_device_in *device_in, mm_sound_device_out *device_out);
47 static GList *g_active_device_cb_list = NULL;
48 static pthread_mutex_t g_active_device_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
49 static GList *g_available_route_cb_list = NULL;
50 static pthread_mutex_t g_available_route_cb_mutex = PTHREAD_MUTEX_INITIALIZER;
52 int _mm_sound_mgr_device_init(void)
60 int _mm_sound_mgr_device_fini(void)
68 int _mm_sound_mgr_device_is_route_available(const _mm_sound_mgr_device_param_t *param, bool *is_available)
70 mm_sound_route route = param->route;
71 mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
72 mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
73 int ret = MM_ERROR_NONE;
77 _mm_sound_get_devices_from_route(route, &device_in, &device_out);
79 /* check given input & output device is available */
80 ret = MMSoundMgrSessionIsDeviceAvailable(device_out, device_in, is_available);
86 int _mm_sound_mgr_device_foreach_available_route_cb(mm_ipc_msg_t *msg)
88 mm_sound_route *route_list = NULL;
89 int route_list_count = 0;
91 int available_count = 0;
92 bool is_available = 0;
93 int ret = MM_ERROR_NONE;
97 route_list_count = _mm_sound_get_valid_route_list(&route_list);
98 for (route_index = 0; route_index < route_list_count; route_index++) {
99 mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
100 mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
102 _mm_sound_get_devices_from_route(route_list[route_index], &device_in, &device_out);
103 /* check input & output device of given route is available */
104 ret = MMSoundMgrSessionIsDeviceAvailable(device_out, device_in, &is_available);
105 if (ret != MM_ERROR_NONE) {
106 debug_error("MMSoundMgrSessionIsDeviceAvailable() failed (%d)\n", ret);
110 /* add route to avaiable route list */
112 if (available_count >= (sizeof(msg->sound_msg.route_list) / sizeof(int))) {
113 debug_error("Cannot add available route, list is full\n");
114 ret = MM_ERROR_SOUND_INTERNAL;
117 msg->sound_msg.route_list[available_count++] = route_list[route_index];
125 int _mm_sound_mgr_device_set_active_route(const _mm_sound_mgr_device_param_t *param)
127 mm_sound_route route = param->route;
128 mm_sound_device_in device_in = MM_SOUND_DEVICE_IN_NONE;
129 mm_sound_device_out device_out = MM_SOUND_DEVICE_OUT_NONE;
130 bool is_available = 0;
131 int ret = MM_ERROR_NONE;
135 _mm_sound_get_devices_from_route(route, &device_in, &device_out);
136 /* check specific route is available */
137 ret = _mm_sound_mgr_device_is_route_available(param, &is_available);
138 if ((ret != MM_ERROR_NONE) || (!is_available)) {
142 ret = MMSoundMgrSessionSetDeviceActive(device_out, device_in);
148 int _mm_sound_mgr_device_get_active_device(const _mm_sound_mgr_device_param_t *param, mm_sound_device_in *device_in, mm_sound_device_out *device_out)
150 int ret = MM_ERROR_NONE;
154 ret = MMSoundMgrSessionGetDeviceActive(device_out, device_in);
160 int _mm_sound_mgr_device_add_active_device_callback(const _mm_sound_mgr_device_param_t *param)
162 int ret = MM_ERROR_NONE;
164 _mm_sound_mgr_device_param_t *cb_param = NULL;
165 bool is_already_set = FALSE;
169 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_active_device_cb_mutex, MM_ERROR_SOUND_INTERNAL);
171 for (list = g_active_device_cb_list; list != NULL; list = list->next)
173 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
174 if ((cb_param) && (cb_param->pid == param->pid))
176 cb_param->callback = param->callback;
177 cb_param->cbdata = param->cbdata;
178 is_already_set = TRUE;
182 if (!is_already_set) {
183 cb_param = g_malloc(sizeof(_mm_sound_mgr_device_param_t));
184 memcpy(cb_param, param, sizeof(_mm_sound_mgr_device_param_t));
185 g_active_device_cb_list = g_list_append(g_active_device_cb_list, cb_param);
186 if (g_active_device_cb_list) {
187 debug_log("active device cb registered for pid [%d]", cb_param->pid);
189 debug_error("g_list_append failed\n");
190 ret = MM_ERROR_SOUND_INTERNAL;
196 MMSOUND_LEAVE_CRITICAL_SECTION(&g_active_device_cb_mutex);
201 int _mm_sound_mgr_device_remove_active_device_callback(const _mm_sound_mgr_device_param_t *param)
203 int ret = MM_ERROR_NONE;
205 _mm_sound_mgr_device_param_t *cb_param = NULL;
209 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_active_device_cb_mutex, MM_ERROR_SOUND_INTERNAL);
211 for (list = g_active_device_cb_list; list != NULL; list = list->next)
213 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
214 if ((cb_param) && (cb_param->pid == param->pid))
216 g_active_device_cb_list = g_list_remove(g_active_device_cb_list, cb_param);
222 MMSOUND_LEAVE_CRITICAL_SECTION(&g_active_device_cb_mutex);
228 int _mm_sound_mgr_device_active_device_callback(mm_sound_device_in device_in, mm_sound_device_out device_out)
230 int ret = MM_ERROR_NONE;
232 _mm_sound_mgr_device_param_t *cb_param = NULL;
237 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_active_device_cb_mutex, MM_ERROR_SOUND_INTERNAL);
239 for (list = g_active_device_cb_list; list != NULL; list = list->next)
241 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
242 if ((cb_param) && (cb_param->callback))
244 memset(&msg, 0, sizeof(mm_ipc_msg_t));
245 SOUND_MSG_SET(msg.sound_msg, MM_SOUND_MSG_INF_ACTIVE_DEVICE_CB, 0, MM_ERROR_NONE, cb_param->pid);
246 msg.sound_msg.device_in = device_in;
247 msg.sound_msg.device_out = device_out;
248 msg.sound_msg.callback = cb_param->callback;
249 msg.sound_msg.cbdata = cb_param->cbdata;
251 ret = _MMIpcCBSndMsg(&msg);
252 if (ret != MM_ERROR_NONE) {
253 debug_error("Fail to send callback message (%x)\n", ret);
259 MMSOUND_LEAVE_CRITICAL_SECTION(&g_active_device_cb_mutex);
265 int _mm_sound_mgr_device_add_available_route_callback(const _mm_sound_mgr_device_param_t *param)
267 int ret = MM_ERROR_NONE;
269 _mm_sound_mgr_device_param_t *cb_param = NULL;
270 bool is_already_set = FALSE;
274 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_available_route_cb_mutex, MM_ERROR_SOUND_INTERNAL);
276 for (list = g_available_route_cb_list; list != NULL; list = list->next)
278 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
279 if ((cb_param) && (cb_param->pid == param->pid))
281 cb_param->callback = param->callback;
282 cb_param->cbdata = param->cbdata;
283 is_already_set = TRUE;
287 if (!is_already_set) {
288 cb_param = g_malloc(sizeof(_mm_sound_mgr_device_param_t));
289 memcpy(cb_param, param, sizeof(_mm_sound_mgr_device_param_t));
290 g_available_route_cb_list = g_list_append(g_available_route_cb_list, cb_param);
291 if (g_available_route_cb_list) {
292 debug_log("available route cb registered for pid [%d]", cb_param->pid);
294 debug_error("g_list_append failed\n");
295 ret = MM_ERROR_SOUND_INTERNAL;
300 MMSOUND_LEAVE_CRITICAL_SECTION(&g_available_route_cb_mutex);
306 int _mm_sound_mgr_device_remove_available_route_callback(const _mm_sound_mgr_device_param_t *param)
308 int ret = MM_ERROR_NONE;
310 _mm_sound_mgr_device_param_t *cb_param = NULL;
314 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_available_route_cb_mutex, MM_ERROR_SOUND_INTERNAL);
316 for (list = g_available_route_cb_list; list != NULL; list = list->next)
318 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
319 if ((cb_param) && (cb_param->pid == param->pid))
321 g_available_route_cb_list = g_list_remove(g_available_route_cb_list, cb_param);
327 MMSOUND_LEAVE_CRITICAL_SECTION(&g_available_route_cb_mutex);
333 int _mm_sound_mgr_device_available_device_callback(mm_sound_device_in device_in, mm_sound_device_out device_out, bool available)
335 int ret = MM_ERROR_NONE;
336 _mm_sound_mgr_device_param_t *cb_param = NULL;
338 int route_list_count = 0;
340 int available_count = 0;
341 mm_sound_route *route_list = NULL;
346 memset (&msg, 0, sizeof(mm_ipc_msg_t));
348 route_list_count = _mm_sound_get_valid_route_list(&route_list);
349 debug_log("in=[%x], out=[%x], route_list_count = [%d], available = [%d]", device_in, device_out, route_list_count, available);
350 for (route_index = 0; route_index < route_list_count; route_index++) {
351 mm_sound_device_in route_device_in = MM_SOUND_DEVICE_IN_NONE;
352 mm_sound_device_out route_device_out = MM_SOUND_DEVICE_OUT_NONE;
355 _mm_sound_get_devices_from_route(route_list[route_index], &route_device_in, &route_device_out);
357 if ((device_in != MM_SOUND_DEVICE_IN_NONE) && (device_in == route_device_in)) {
358 /* device(in&out) changed together & they can be combined as this route */
359 if ((device_out != MM_SOUND_DEVICE_OUT_NONE) && (device_out == route_device_out)) {
361 /* device(in) changed & this route has device(in) only */
362 } else if (route_device_out == MM_SOUND_DEVICE_OUT_NONE) {
364 /* device(in) changed & this route have device(in&out), we need to check availability of output device of this route */
366 MMSoundMgrSessionIsDeviceAvailableNoLock(route_device_out, MM_SOUND_DEVICE_IN_NONE, &is_changed);
369 if ((is_changed == 0) && (device_out != MM_SOUND_DEVICE_OUT_NONE) && (device_out == route_device_out)) {
370 /* device(out) changed & this route has device(out) only */
371 if (route_device_in == MM_SOUND_DEVICE_IN_NONE) {
373 /* device(out) changed & this route have device(in&out), we need to check availability of input device of this route */
375 MMSoundMgrSessionIsDeviceAvailableNoLock(MM_SOUND_DEVICE_OUT_NONE, route_device_in, &is_changed);
378 /* add route to avaiable route list */
380 if (available_count >= (sizeof(msg.sound_msg.route_list) / sizeof(int))) {
381 debug_error("Cannot add available route, list is full\n");
382 return MM_ERROR_SOUND_INTERNAL;
384 debug_log("route_index [%d] is added to route_list [%d]", route_index, available_count);
385 msg.sound_msg.route_list[available_count++] = route_list[route_index];
389 MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_available_route_cb_mutex, MM_ERROR_SOUND_INTERNAL);
391 for (list = g_available_route_cb_list; list != NULL; list = list->next)
393 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
394 if ((cb_param) && (cb_param->callback))
396 SOUND_MSG_SET(msg.sound_msg, MM_SOUND_MSG_INF_AVAILABLE_ROUTE_CB, 0, MM_ERROR_NONE, cb_param->pid);
397 msg.sound_msg.is_available = available;
398 msg.sound_msg.callback = cb_param->callback;
399 msg.sound_msg.cbdata = cb_param->cbdata;
401 ret = _MMIpcCBSndMsg(&msg);
402 if (ret != MM_ERROR_NONE) {
403 debug_error("Fail to send callback message\n");
409 MMSOUND_LEAVE_CRITICAL_SECTION(&g_available_route_cb_mutex);