Merge "Removed unused result variable from sound_codec_asm_callback" into tizen
[platform/core/multimedia/libmm-sound.git] / server / mm_sound_mgr_device.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Seungbae Shin <seungbae.shin@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <pthread.h>
26 #include <sys/stat.h>
27 #include <glib.h>
28 #include <errno.h>
29
30 #include <mm_error.h>
31 #include <mm_types.h>
32 #include <mm_debug.h>
33 #include <mm_ipc.h>
34
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"
42
43 #include "include/mm_sound_mgr_session.h"
44
45 void _mm_sound_get_devices_from_route(mm_sound_route route, mm_sound_device_in *device_in, mm_sound_device_out *device_out);
46
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;
51
52 int _mm_sound_mgr_device_init(void)
53 {
54         debug_fenter();
55
56         debug_fleave();
57         return MM_ERROR_NONE;
58 }
59
60 int _mm_sound_mgr_device_fini(void)
61 {
62         debug_fenter();
63
64         debug_fleave();
65         return MM_ERROR_NONE;
66 }
67
68 int _mm_sound_mgr_device_is_route_available(const _mm_sound_mgr_device_param_t *param, bool *is_available)
69 {
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;
74
75         debug_fenter();
76
77         _mm_sound_get_devices_from_route(route, &device_in, &device_out);
78
79         /* check given input & output device is available */
80         ret = MMSoundMgrSessionIsDeviceAvailable(device_out, device_in, is_available);
81
82         debug_fleave();
83         return ret;
84 }
85
86 int _mm_sound_mgr_device_foreach_available_route_cb(mm_ipc_msg_t *msg)
87 {
88         mm_sound_route *route_list = NULL;
89         int route_list_count = 0;
90         int route_index = 0;
91         int available_count = 0;
92         bool is_available = 0;
93         int ret = MM_ERROR_NONE;
94
95         debug_fenter();
96
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;
101
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);
107                         goto FINISH;
108                 }
109
110                 /* add route to avaiable route list */
111                 if (is_available) {
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;
115                                 goto FINISH;
116                         }
117                         msg->sound_msg.route_list[available_count++] = route_list[route_index];
118                 }
119         }
120 FINISH:
121         debug_fleave();
122         return ret;
123 }
124
125 int _mm_sound_mgr_device_set_active_route(const _mm_sound_mgr_device_param_t *param)
126 {
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;
132
133         debug_fenter();
134
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)) {
139
140         }
141
142         ret = MMSoundMgrSessionSetDeviceActive(device_out, device_in);
143
144         debug_fleave();
145         return ret;
146 }
147
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)
149 {
150         int ret = MM_ERROR_NONE;
151
152         debug_fenter();
153
154         ret = MMSoundMgrSessionGetDeviceActive(device_out, device_in);
155
156         debug_fleave();
157         return ret;
158 }
159
160 int _mm_sound_mgr_device_add_active_device_callback(const _mm_sound_mgr_device_param_t *param)
161 {
162         int ret = MM_ERROR_NONE;
163         GList *list = NULL;
164         _mm_sound_mgr_device_param_t *cb_param = NULL;
165         bool is_already_set = FALSE;
166
167         debug_fenter();
168
169         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_active_device_cb_mutex, MM_ERROR_SOUND_INTERNAL);
170
171         for (list = g_active_device_cb_list; list != NULL; list = list->next)
172         {
173                 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
174                 if ((cb_param) && (cb_param->pid == param->pid))
175                 {
176                         cb_param->callback = param->callback;
177                         cb_param->cbdata = param->cbdata;
178                         is_already_set = TRUE;
179                         break;
180                 }
181         }
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);
188                 } else {
189                         debug_error("g_list_append failed\n");
190                         ret = MM_ERROR_SOUND_INTERNAL;
191                         goto FINISH;
192                 }
193         }
194
195 FINISH:
196         MMSOUND_LEAVE_CRITICAL_SECTION(&g_active_device_cb_mutex);
197         debug_fleave();
198         return ret;
199 }
200
201 int _mm_sound_mgr_device_remove_active_device_callback(const _mm_sound_mgr_device_param_t *param)
202 {
203         int ret = MM_ERROR_NONE;
204         GList *list = NULL;
205         _mm_sound_mgr_device_param_t *cb_param = NULL;
206
207         debug_fenter();
208
209         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_active_device_cb_mutex, MM_ERROR_SOUND_INTERNAL);
210
211         for (list = g_active_device_cb_list; list != NULL; list = list->next)
212         {
213                 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
214                 if ((cb_param) && (cb_param->pid == param->pid))
215                 {
216                         g_active_device_cb_list = g_list_remove(g_active_device_cb_list, cb_param);
217                         g_free(cb_param);
218                         break;
219                 }
220         }
221
222         MMSOUND_LEAVE_CRITICAL_SECTION(&g_active_device_cb_mutex);
223
224         debug_fleave();
225         return ret;
226 }
227
228 int _mm_sound_mgr_device_active_device_callback(mm_sound_device_in device_in, mm_sound_device_out device_out)
229 {
230         int ret = MM_ERROR_NONE;
231         GList *list = NULL;
232         _mm_sound_mgr_device_param_t *cb_param = NULL;
233         mm_ipc_msg_t msg;
234
235         debug_fenter();
236
237         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_active_device_cb_mutex, MM_ERROR_SOUND_INTERNAL);
238
239         for (list = g_active_device_cb_list; list != NULL; list = list->next)
240         {
241                 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
242                 if ((cb_param) && (cb_param->callback))
243                 {
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;
250
251                         ret = _MMIpcCBSndMsg(&msg);
252                         if (ret != MM_ERROR_NONE) {
253                                 debug_error("Fail to send callback message (%x)\n", ret);
254                                 goto FINISH;
255                         }
256                 }
257         }
258 FINISH:
259         MMSOUND_LEAVE_CRITICAL_SECTION(&g_active_device_cb_mutex);
260
261         debug_fleave();
262         return ret;
263 }
264
265 int _mm_sound_mgr_device_add_available_route_callback(const _mm_sound_mgr_device_param_t *param)
266 {
267         int ret = MM_ERROR_NONE;
268         GList *list = NULL;
269         _mm_sound_mgr_device_param_t *cb_param = NULL;
270         bool is_already_set = FALSE;
271
272         debug_fenter();
273
274         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_available_route_cb_mutex, MM_ERROR_SOUND_INTERNAL);
275
276         for (list = g_available_route_cb_list; list != NULL; list = list->next)
277         {
278                 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
279                 if ((cb_param) && (cb_param->pid == param->pid))
280                 {
281                         cb_param->callback = param->callback;
282                         cb_param->cbdata = param->cbdata;
283                         is_already_set = TRUE;
284                         break;
285                 }
286         }
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);
293                 } else {
294                         debug_error("g_list_append failed\n");
295                         ret = MM_ERROR_SOUND_INTERNAL;
296                         goto FINISH;
297                 }
298         }
299 FINISH:
300         MMSOUND_LEAVE_CRITICAL_SECTION(&g_available_route_cb_mutex);
301
302         debug_fleave();
303         return ret;
304 }
305
306 int _mm_sound_mgr_device_remove_available_route_callback(const _mm_sound_mgr_device_param_t *param)
307 {
308         int ret = MM_ERROR_NONE;
309         GList *list = NULL;
310         _mm_sound_mgr_device_param_t *cb_param = NULL;
311
312         debug_fenter();
313
314         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_available_route_cb_mutex, MM_ERROR_SOUND_INTERNAL);
315
316         for (list = g_available_route_cb_list; list != NULL; list = list->next)
317         {
318                 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
319                 if ((cb_param) && (cb_param->pid == param->pid))
320                 {
321                         g_available_route_cb_list = g_list_remove(g_available_route_cb_list, cb_param);
322                         g_free(cb_param);
323                         break;
324                 }
325         }
326
327         MMSOUND_LEAVE_CRITICAL_SECTION(&g_available_route_cb_mutex);
328
329         debug_fleave();
330         return ret;
331 }
332
333 int _mm_sound_mgr_device_available_device_callback(mm_sound_device_in device_in, mm_sound_device_out device_out, bool available)
334 {
335         int ret = MM_ERROR_NONE;
336         _mm_sound_mgr_device_param_t *cb_param = NULL;
337         mm_ipc_msg_t msg;
338         int route_list_count = 0;
339         int route_index = 0;
340         int available_count = 0;
341         mm_sound_route *route_list = NULL;
342         GList *list = NULL;
343
344         debug_fenter();
345
346         memset (&msg, 0, sizeof(mm_ipc_msg_t));
347
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;
353                 bool is_changed = 0;
354
355                 _mm_sound_get_devices_from_route(route_list[route_index], &route_device_in, &route_device_out);
356
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)) {
360                                 is_changed = 1;
361                         /* device(in) changed & this route has device(in) only */
362                         } else if (route_device_out == MM_SOUND_DEVICE_OUT_NONE) {
363                                 is_changed = 1;
364                         /* device(in) changed & this route have device(in&out), we need to check availability of output device of this route */
365                         } else {
366                                 MMSoundMgrSessionIsDeviceAvailableNoLock(route_device_out, MM_SOUND_DEVICE_IN_NONE, &is_changed);
367                         }
368                 }
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) {
372                                 is_changed = 1;
373                         /* device(out) changed & this route have device(in&out), we need to check availability of input device of this route */
374                         } else {
375                                 MMSoundMgrSessionIsDeviceAvailableNoLock(MM_SOUND_DEVICE_OUT_NONE, route_device_in, &is_changed);
376                         }
377                 }
378                 /* add route to avaiable route list */
379                 if (is_changed) {
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;
383                         }
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];
386                 }
387         }
388
389         MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_available_route_cb_mutex, MM_ERROR_SOUND_INTERNAL);
390
391         for (list = g_available_route_cb_list; list != NULL; list = list->next)
392         {
393                 cb_param = (_mm_sound_mgr_device_param_t *)list->data;
394                 if ((cb_param) && (cb_param->callback))
395                 {
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;
400
401                         ret = _MMIpcCBSndMsg(&msg);
402                         if (ret != MM_ERROR_NONE) {
403                                 debug_error("Fail to send callback message\n");
404                                 goto FINISH;
405                         }
406                 }
407         }
408 FINISH:
409         MMSOUND_LEAVE_CRITICAL_SECTION(&g_available_route_cb_mutex);
410
411         debug_fleave();
412         return ret;
413 }
414