Fix memory leak after wav playback
[platform/core/multimedia/libmm-sound.git] / mm_sound_focus.c
1 /*
2  * libmm-sound
3  *
4  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Sangchul Lee <sc11.lee@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 <unistd.h>
24
25 #include <mm_debug.h>
26
27 #include "include/mm_sound.h"
28 #include "include/mm_sound_client.h"
29
30 #define RETURN_ERROR_IF_FOCUS_CB_THREAD(x_thread) \
31 { \
32         int ret = MM_ERROR_NONE; \
33         bool result = false; \
34         ret = mm_sound_client_is_focus_cb_thread(x_thread, &result); \
35         if (ret) \
36                 return ret; \
37         if (result) { \
38                 debug_error("it might be called in the thread of focus callback, it is not allowed"); \
39                 return MM_ERROR_SOUND_INVALID_OPERATION; \
40         } \
41 } \
42
43 EXPORT_API
44 int mm_sound_focus_set_session_interrupt_callback(mm_sound_focus_session_interrupt_cb callback, void *user_data)
45 {
46         int ret = MM_ERROR_NONE;
47         debug_fenter();
48
49         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
50
51         if (!callback)
52                 return MM_ERROR_INVALID_ARGUMENT;
53
54         ret = mm_sound_client_set_session_interrupt_callback(callback, user_data);
55
56         debug_fleave();
57
58         return ret;
59 }
60
61 EXPORT_API
62 int mm_sound_focus_unset_session_interrupt_callback(void)
63 {
64         int ret = MM_ERROR_NONE;
65         debug_fenter();
66
67         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
68
69         ret = mm_sound_client_unset_session_interrupt_callback();
70         if (ret)
71                 debug_error("Failed to mm_sound_client_unset_session_interrupt_callback(), ret[0x%x]", ret);
72
73         debug_fleave();
74
75         return ret;
76 }
77
78 EXPORT_API
79 int mm_sound_focus_get_id(int *id)
80 {
81         int ret = MM_ERROR_NONE;
82
83         debug_fenter();
84
85         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
86
87         ret = mm_sound_client_get_unique_id(id);
88         if (ret)
89                 debug_error("Failed to mm_sound_client_get_unique_id(), ret[0x%x]", ret);
90
91         debug_fleave();
92
93         return ret;
94 }
95
96 EXPORT_API
97 int mm_sound_focus_is_cb_thread(bool *result)
98 {
99         int ret = MM_ERROR_NONE;
100
101         debug_fenter();
102
103         ret = mm_sound_client_is_focus_cb_thread(g_thread_self(), result);
104         if (!ret) {
105                 if (*result)
106                         debug_msg("it might be called in the thread of focus callback");
107         }
108
109         debug_fleave();
110
111         return ret;
112 }
113
114 EXPORT_API
115 int mm_sound_register_focus(int id, const char *stream_type, mm_sound_focus_changed_cb callback, void *user_data)
116 {
117         int ret = MM_ERROR_NONE;
118
119         debug_fenter();
120
121         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
122
123         if (id < 0 || callback == NULL) {
124                 debug_error("argument is not valid");
125                 return MM_ERROR_INVALID_ARGUMENT;
126         }
127
128         ret = mm_sound_client_register_focus(id, getpid(), stream_type, false, callback, user_data);
129         if (ret)
130                 debug_error("Could not register focus, ret[0x%x]", ret);
131
132         debug_fleave();
133
134         return ret;
135 }
136
137 EXPORT_API
138 int mm_sound_register_focus_for_session(int id, int pid, const char *stream_type, mm_sound_focus_changed_cb callback, void *user_data)
139 {
140         int ret = MM_ERROR_NONE;
141
142         debug_fenter();
143
144         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
145
146         if (id < 0 || callback == NULL) {
147                 debug_error("argument is not valid");
148                 return MM_ERROR_INVALID_ARGUMENT;
149         }
150
151         ret = mm_sound_client_register_focus(id, pid, stream_type, true, callback, user_data);
152         if (ret)
153                 debug_error("Could not register focus for session, ret[0x%x]", ret);
154
155         debug_fleave();
156
157         return ret;
158 }
159
160 EXPORT_API
161 int mm_sound_unregister_focus(int id)
162 {
163         int ret = MM_ERROR_NONE;
164         bool result = false;
165
166         debug_fenter();
167
168         if (id < 0) {
169                 debug_error("argument is not valid");
170                 return MM_ERROR_INVALID_ARGUMENT;
171         }
172
173         mm_sound_client_is_focus_cb_thread(g_thread_self(), &result);
174         if (!result) {
175                 if ((ret = mm_sound_client_unregister_focus(id)))
176                         debug_error("Could not unregister focus, ret = %x", ret);
177         } else {
178                 ret = mm_sound_client_execute_focus_func_in_main_context(IDLE_EVENT_TYPE_UNREGISTER_FOCUS, id);
179         }
180
181         debug_fleave();
182
183         return ret;
184 }
185
186 EXPORT_API
187 int mm_sound_set_focus_reacquisition(int id, bool reacquisition)
188 {
189         int ret = MM_ERROR_NONE;
190
191         debug_fenter();
192
193         if (id < 0) {
194                 debug_error("argument is not valid");
195                 return MM_ERROR_INVALID_ARGUMENT;
196         }
197
198         if ((ret = mm_sound_client_set_focus_reacquisition(id, reacquisition, false)))
199                 debug_error("Could not set focus reacquisition, ret[0x%x]", ret);
200
201         debug_fleave();
202
203         return ret;
204 }
205
206 EXPORT_API
207 int mm_sound_set_focus_reacquisition_for_session(int id, bool reacquisition)
208 {
209         int ret = MM_ERROR_NONE;
210
211         debug_fenter();
212
213         if (id < 0) {
214                 debug_error("argument is not valid");
215                 return MM_ERROR_INVALID_ARGUMENT;
216         }
217
218         if ((ret = mm_sound_client_set_focus_reacquisition(id, reacquisition, true)))
219                 debug_error("Could not set focus reacquisition, ret[0x%x]", ret);
220
221         debug_fleave();
222
223         return ret;
224 }
225
226 EXPORT_API
227 int mm_sound_get_focus_reacquisition(int id, bool *reacquisition)
228 {
229         int ret = MM_ERROR_NONE;
230
231         debug_fenter();
232
233         if (id < 0 || !reacquisition) {
234                 debug_error("argument is not valid");
235                 return MM_ERROR_INVALID_ARGUMENT;
236         }
237
238         ret = mm_sound_client_get_focus_reacquisition(id, reacquisition);
239         if (ret)
240                 debug_error("Could not get focus reacquisition, ret[0x%x]", ret);
241
242         debug_fleave();
243
244         return ret;
245 }
246
247 EXPORT_API
248 int mm_sound_get_stream_type_of_acquired_focus(int focus_type, char **stream_type, int *option, char **ext_info)
249 {
250         int ret = MM_ERROR_NONE;
251
252         debug_fenter();
253
254         if (stream_type == NULL) {
255                 debug_error("argument is not valid");
256                 return MM_ERROR_INVALID_ARGUMENT;
257         }
258
259         ret = mm_sound_client_get_acquired_focus_stream_type(focus_type, stream_type, option, ext_info);
260         if (ret)
261                 debug_error("Could not get acquired focus stream type, ret[0x%x]", ret);
262
263         debug_fleave();
264
265         return ret;
266 }
267
268 EXPORT_API
269 int mm_sound_acquire_focus(int id, mm_sound_focus_type_e focus_type, const char *ext_info)
270 {
271         int ret = MM_ERROR_NONE;
272
273         debug_fenter();
274
275         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
276
277         if (id < 0) {
278                 debug_error("argument is not valid");
279                 return MM_ERROR_INVALID_ARGUMENT;
280         }
281         if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
282                 debug_error("argument is not valid");
283                 return MM_ERROR_INVALID_ARGUMENT;
284         }
285
286         ret = mm_sound_client_acquire_focus(id, focus_type, 0, ext_info);
287         if (ret)
288                 debug_error("Could not acquire focus, ret[0x%x]", ret);
289
290         debug_fleave();
291
292         return ret;
293 }
294
295 EXPORT_API
296 int mm_sound_release_focus(int id, mm_sound_focus_type_e focus_type, const char *ext_info)
297 {
298         int ret = MM_ERROR_NONE;
299
300         debug_fenter();
301
302         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
303
304         if (id < 0) {
305                 debug_error("argument is not valid");
306                 return MM_ERROR_INVALID_ARGUMENT;
307         }
308         if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
309                 debug_error("argument is not valid");
310                 return MM_ERROR_INVALID_ARGUMENT;
311         }
312
313         ret = mm_sound_client_release_focus(id, focus_type, 0, ext_info);
314         if (ret)
315                 debug_error("Could not release focus, ret[0x%x]", ret);
316
317         debug_fleave();
318
319         return ret;
320 }
321
322 EXPORT_API
323 int mm_sound_acquire_focus_with_option(int id, mm_sound_focus_type_e focus_type, int option, const char *ext_info)
324 {
325         int ret = MM_ERROR_NONE;
326
327         debug_fenter();
328
329         if (id < 0) {
330                 debug_error("id is not valid");
331                 return MM_ERROR_INVALID_ARGUMENT;
332         }
333
334         if (option < 0) {
335                 debug_error("option is not valid");
336                 return MM_ERROR_INVALID_ARGUMENT;
337         }
338
339         if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
340                 debug_error("focus type is not valid");
341                 return MM_ERROR_INVALID_ARGUMENT;
342         }
343
344         ret = mm_sound_client_acquire_focus(id, focus_type, option, ext_info);
345         if (ret)
346                 debug_error("Could not acquire focus, ret[0x%x]", ret);
347
348         debug_fleave();
349
350         return ret;
351 }
352
353 EXPORT_API
354 int mm_sound_release_focus_with_option(int id, mm_sound_focus_type_e focus_type, int option, const char *ext_info)
355 {
356         int ret = MM_ERROR_NONE;
357
358         debug_fenter();
359
360         if (id < 0) {
361                 debug_error("id is not valid");
362                 return MM_ERROR_INVALID_ARGUMENT;
363         }
364
365         if (option < 0) {
366                 debug_error("option is not valid");
367                 return MM_ERROR_INVALID_ARGUMENT;
368         }
369
370         if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
371                 debug_error("focus type is not valid");
372                 return MM_ERROR_INVALID_ARGUMENT;
373         }
374
375         ret = mm_sound_client_release_focus(id, focus_type, option, ext_info);
376         if (ret)
377                 debug_error("Could not release focus, ret[0x%x]", ret);
378
379         debug_fleave();
380
381         return ret;
382 }
383
384 EXPORT_API
385 int mm_sound_update_focus_status(int id, unsigned int status)
386 {
387         int ret = MM_ERROR_NONE;
388
389         if ((ret = mm_sound_client_update_stream_focus_status(id, status)))
390                 debug_error("failed to mm_sound_client_update_stream_focus_status(), id(%d), status(%d, ret[0x%x]",
391                                         id, status, ret);
392
393         return ret;
394 }
395
396 EXPORT_API
397 int mm_sound_deliver_focus(int src_id, int dst_id, mm_sound_focus_type_e focus_type)
398 {
399         int ret = MM_ERROR_NONE;
400
401         if ((ret = mm_sound_client_deliver_focus(getpid(), src_id, dst_id, focus_type)))
402                 debug_error("failed to mm_sound_client_deliver_focus(), ret[0x%x]", ret);
403
404         return ret;
405 }
406
407 EXPORT_API
408 int mm_sound_set_focus_watch_callback(mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, void *user_data, int *id)
409 {
410         int ret = MM_ERROR_NONE;
411
412         debug_fenter();
413
414         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
415
416         if (callback == NULL || id == NULL) {
417                 debug_error("argument is not valid");
418                 return MM_ERROR_INVALID_ARGUMENT;
419         }
420         ret = mm_sound_client_set_focus_watch_callback(getpid(), focus_type, false, false, callback, user_data, id);
421         if (ret)
422                 debug_error("Could not set focus watch callback, ret[0x%x]", ret);
423
424         debug_fleave();
425
426         return ret;
427 }
428
429 EXPORT_API
430 int mm_sound_set_focus_watch_callback_for_session(int pid, mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, void *user_data, int *id)
431 {
432         int ret = MM_ERROR_NONE;
433
434         debug_fenter();
435
436         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
437
438         if (callback == NULL || id == NULL) {
439                 debug_error("argument is not valid");
440                 return MM_ERROR_INVALID_ARGUMENT;
441         }
442         ret = mm_sound_client_set_focus_watch_callback(pid, focus_type, true, false, callback, user_data, id);
443         if (ret)
444                 debug_error("Could not set focus watch callback, ret[0x%x]", ret);
445
446         debug_fleave();
447
448         return ret;
449 }
450
451 EXPORT_API
452 int mm_sound_set_focus_watch_callback_for_session_monitor(int pid, mm_sound_focus_type_e focus_type, mm_sound_focus_changed_watch_cb callback, void *user_data, int *id)
453 {
454         int ret = MM_ERROR_NONE;
455
456         debug_fenter();
457
458         RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
459
460         if (callback == NULL || id == NULL) {
461                 debug_error("argument is not valid");
462                 return MM_ERROR_INVALID_ARGUMENT;
463         }
464         ret = mm_sound_client_set_focus_watch_callback(pid, focus_type, true, true, callback, user_data, id);
465         if (ret)
466                 debug_error("Could not set focus watch callback, ret[0x%x]", ret);
467
468         debug_fleave();
469
470         return ret;
471 }
472
473 EXPORT_API
474 int mm_sound_unset_focus_watch_callback(int id)
475 {
476         int ret = MM_ERROR_NONE;
477         bool result = false;
478
479         debug_fenter();
480
481         if (id < 0) {
482                 debug_error("argument is not valid");
483                 return MM_ERROR_INVALID_ARGUMENT;
484         }
485
486         if ((ret = mm_sound_client_request_unset_focus_watch_callback(id))) {
487                 debug_error("failed to mm_sound_client_request_unset_focus_watch_callback, ret[0x%x]", ret);
488                 return ret;
489         }
490
491         mm_sound_client_is_focus_cb_thread(g_thread_self(), &result);
492         if (!result) {
493                 if ((ret = mm_sound_client_unset_focus_watch_callback(id)))
494                         debug_error("Could not unset focus watch callback, id(%d), ret[0x%x]", id, ret);
495         } else {
496                 ret = mm_sound_client_execute_focus_func_in_main_context(IDLE_EVENT_TYPE_UNSET_FOCUS_WATCH_CB, id);
497                 debug_msg("mm_sound_client_execute_focus_func_in_main_context() is called, id(%d), ret[0x%x]", id, ret);
498         }
499
500         debug_fleave();
501
502         return ret;
503 }