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