4 * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Sangchul Lee <sc11.lee@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.
25 #include <sys/socket.h>
27 #include "include/mm_sound.h"
28 #include "include/mm_sound_common.h"
29 #include "include/mm_sound_focus_socket.h"
31 #define _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid) \
33 MMSOUND_STRNCPY(x_param.func_name, x_func_name, MM_SOUND_NAME_NUM); \
34 x_param.pid = x_pid; \
37 #define _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id) \
39 _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid); \
40 x_param.handle_id = x_id; \
43 #define FILL_SOCKET_PARAM_REGISTER(x_param, x_func_name, x_pid, x_stream_type) \
45 _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid); \
46 MMSOUND_STRNCPY(x_param.stream_type, x_stream_type, MM_SOUND_NAME_NUM); \
49 #define FILL_SOCKET_PARAM_UNREGISTER(x_param, x_func_name, x_pid, x_id) \
51 _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
54 #define FILL_SOCKET_PARAM_ADD_WATCH(x_param, x_func_name, x_pid, x_focus_type) \
56 _FILL_SOCKET_PARAM(x_param, x_func_name, x_pid); \
57 x_param.focus_type = x_focus_type; \
60 #define FILL_SOCKET_PARAM_REMOVE_WATCH(x_param, x_func_name, x_pid, x_id) \
62 _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
65 #define FILL_SOCKET_PARAM_SET_REACQUISITION(x_param, x_func_name, x_pid, x_id, x_reacquisition) \
67 _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
68 x_param.reacquisition = x_reacquisition; \
71 #define FILL_SOCKET_PARAM_DELIVER(x_param, x_func_name, x_pid, x_src_id, x_dst_id, x_focus_type) \
73 _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_src_id); \
74 x_param.handle_id_dst = x_dst_id; \
75 x_param.focus_type = x_focus_type; \
78 #define FILL_SOCKET_PARAM_GET_ACQUIRED(x_param, x_func_name, x_focus_type) \
80 MMSOUND_STRNCPY(x_param.func_name, x_func_name, MM_SOUND_NAME_NUM); \
81 x_param.focus_type = x_focus_type; \
84 #define FILL_SOCKET_PARAM(x_param, x_func_name, x_pid, x_id, x_focus_type, x_option, x_ext_info, x_is_in_thread) \
86 _FILL_SOCKET_PARAM_WITH_HANDLE(x_param, x_func_name, x_pid, x_id); \
87 x_param.focus_type = x_focus_type; \
88 x_param.option = x_option; \
89 MMSOUND_STRNCPY(x_param.ext_info, x_ext_info, MM_SOUND_NAME_NUM); \
90 x_param.is_in_thread = x_is_in_thread; \
93 static int _get_client_socket_fd(int *fd)
96 char str_error[128] = {'\0',};
99 debug_error("input param fd is null");
100 return MM_ERROR_INVALID_ARGUMENT;
103 socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
105 strerror_r(errno, str_error, sizeof(str_error));
106 debug_error("failed to socket(), err: %s", str_error);
107 return MM_ERROR_SOUND_INTERNAL;
110 debug_log("focus client socket fd[%d]", socket_fd);
114 return MM_ERROR_NONE;
117 static int _connect_socket_fd(int fd)
119 struct sockaddr_un addr_un;
120 char str_error[128] = {'\0',};
123 debug_error("invalid fd[%d]", fd);
124 return MM_ERROR_INVALID_ARGUMENT;
127 memset(&addr_un, 0, sizeof(addr_un));
128 addr_un.sun_family = AF_UNIX;
129 strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
131 if (connect(fd, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0) {
132 strerror_r(errno, str_error, sizeof(str_error));
133 debug_error("failed to connect() to %s, err: %s", addr_un.sun_path, str_error);
134 return MM_ERROR_SOUND_INTERNAL;
137 debug_log("connected successfully, fd[%d]", fd);
139 return MM_ERROR_NONE;
142 static int _send_data_to_server(int fd, _mm_sound_focus_socket_param_t *data, _mm_sound_focus_socket_result_t *result)
144 char str_error[MAX_ERROR_LEN] = {'\0',};
147 if (fd < 0 || data == NULL) {
148 debug_error("invalid parameter, fd[%d], data[%p]", fd, data);
149 return MM_ERROR_INVALID_ARGUMENT;
152 if (write(fd, data, sizeof(_mm_sound_focus_socket_param_t)) < 0) {
153 strerror_r(errno, str_error, sizeof(str_error));
154 debug_error("failed to write(), err: %s", str_error);
155 return MM_ERROR_SOUND_INTERNAL;
158 /* return message from server */
159 if ((rval = read(fd, result, sizeof(_mm_sound_focus_socket_result_t))) < 0) {
160 strerror_r(errno, str_error, sizeof(str_error));
161 debug_error("failed to read(), err: %s", str_error);
162 return MM_ERROR_SOUND_INTERNAL;
165 debug_log("func_name[%s], rval[%d], ret[0x%x]", data->func_name, rval, result->ret);
171 int mm_sound_focus_socket_register(int pid, const char *stream_type, int *client_fd, int *server_fd)
173 int ret = MM_ERROR_NONE;
174 _mm_sound_focus_socket_param_t data;
175 _mm_sound_focus_socket_result_t result;
179 if (!stream_type || !client_fd || !server_fd)
180 return MM_ERROR_INVALID_ARGUMENT;
182 if ((ret = _get_client_socket_fd(client_fd))) {
183 debug_error("failed to _get_client_socket_fd()");
184 return MM_ERROR_SOUND_INTERNAL;
186 if ((ret = _connect_socket_fd(*client_fd))) {
187 debug_error("failed to _connect_socket_fd()");
189 return MM_ERROR_SOUND_INTERNAL;
192 /* get accepted fd from server */
193 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
194 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
195 FILL_SOCKET_PARAM_REGISTER(data, FOCUS_FUNC_NAME_REGISTER, pid, stream_type);
196 if ((ret = _send_data_to_server(*client_fd, &data, &result))) {
197 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
202 debug_msg("CONNECTED : client fd[%d], server fd[%d]", *client_fd, result.handle_id);
203 *server_fd = result.handle_id;
211 int mm_sound_focus_socket_unregister(int pid, int client_fd, int server_fd)
213 int ret = MM_ERROR_NONE;
214 _mm_sound_focus_socket_param_t data;
215 _mm_sound_focus_socket_result_t result;
219 debug_msg("DISCONNECTING : client fd[%d], server fd[%d]", client_fd, server_fd);
221 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
222 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
223 FILL_SOCKET_PARAM_UNREGISTER(data, FOCUS_FUNC_NAME_UNREGISTER, pid, server_fd);
224 if ((ret = _send_data_to_server(client_fd, &data, &result)))
225 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
235 int mm_sound_focus_socket_add_watch_cb(int pid, mm_sound_focus_type_e focus_type, int *client_fd, int *server_fd)
237 int ret = MM_ERROR_NONE;
238 _mm_sound_focus_socket_param_t data;
239 _mm_sound_focus_socket_result_t result;
243 if (!client_fd || !server_fd)
244 return MM_ERROR_INVALID_ARGUMENT;
246 if ((ret = _get_client_socket_fd(client_fd))) {
247 debug_error("failed to _get_client_socket_fd()");
248 return MM_ERROR_SOUND_INTERNAL;
250 if ((ret = _connect_socket_fd(*client_fd))) {
251 debug_error("failed to _connect_socket_fd()");
253 return MM_ERROR_SOUND_INTERNAL;
256 /* get accepted fd from server */
257 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
258 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
259 FILL_SOCKET_PARAM_ADD_WATCH(data, FOCUS_FUNC_NAME_ADD_WATCH, pid, focus_type);
260 if ((ret = _send_data_to_server(*client_fd, &data, &result))) {
261 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
266 debug_msg("ADDED WATCH CB : client fd[%d], server fd[%d]", *client_fd, result.handle_id);
267 *server_fd = result.handle_id;
275 int mm_sound_focus_socket_remove_watch_cb(int pid, int client_fd, int server_fd)
277 int ret = MM_ERROR_NONE;
278 _mm_sound_focus_socket_param_t data;
279 _mm_sound_focus_socket_result_t result;
283 debug_msg("REMOVING WATCH CB : client fd[%d], server fd[%d]", client_fd, server_fd);
285 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
286 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
287 FILL_SOCKET_PARAM_REMOVE_WATCH(data, FOCUS_FUNC_NAME_REMOVE_WATCH, pid, server_fd);
288 if ((ret = _send_data_to_server(client_fd, &data, &result)))
289 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
299 int mm_sound_focus_socket_acquire(int pid, int client_fd, int server_fd, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread)
301 int ret = MM_ERROR_NONE;
302 _mm_sound_focus_socket_param_t data;
303 _mm_sound_focus_socket_result_t result;
307 if (pid <= 0 || client_fd < 0 || server_fd < 0 || option < 0) {
308 debug_error("invalid parameter, pid[%d], fd[%d/%d], option[%d]",
309 pid, client_fd, server_fd, option);
310 return MM_ERROR_INVALID_ARGUMENT;
312 if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
313 debug_error("focus type[%d] is not valid", focus_type);
314 return MM_ERROR_INVALID_ARGUMENT;
317 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
318 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
319 FILL_SOCKET_PARAM(data, FOCUS_FUNC_NAME_ACQUIRE, pid, server_fd, focus_type,
320 option, ext_info, is_in_thread);
322 if ((ret = _send_data_to_server(client_fd, &data, &result)))
323 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
331 int mm_sound_focus_socket_release(int pid, int client_fd, int server_fd, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread)
333 int ret = MM_ERROR_NONE;
334 _mm_sound_focus_socket_param_t data;
335 _mm_sound_focus_socket_result_t result;
339 if (pid <= 0 || client_fd < 0 || server_fd < 0 || option < 0) {
340 debug_error("invalid parameter, pid[%d], fd[%d/%d], option[%d]",
341 pid, client_fd, server_fd, option);
342 return MM_ERROR_INVALID_ARGUMENT;
344 if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
345 debug_error("focus type is not valid");
346 return MM_ERROR_INVALID_ARGUMENT;
349 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
350 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
351 FILL_SOCKET_PARAM(data, FOCUS_FUNC_NAME_RELEASE, pid, server_fd, focus_type,
352 option, ext_info, is_in_thread);
354 if ((ret = _send_data_to_server(client_fd, &data, &result)))
355 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
364 int mm_sound_focus_socket_set_reacquisition(int pid, int client_fd, int server_fd, bool reacquisition)
366 int ret = MM_ERROR_NONE;
367 _mm_sound_focus_socket_param_t data;
368 _mm_sound_focus_socket_result_t result;
372 if (pid <= 0 || client_fd < 0 || server_fd < 0) {
373 debug_error("invalid parameter, pid[%d], fd[%d/%d]", pid, client_fd, server_fd);
374 return MM_ERROR_INVALID_ARGUMENT;
377 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
378 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
379 FILL_SOCKET_PARAM_SET_REACQUISITION(data, FOCUS_FUNC_NAME_SET_REACQUISITION, pid, server_fd, reacquisition);
381 if ((ret = _send_data_to_server(client_fd, &data, &result)))
382 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
390 int mm_sound_focus_socket_deliver(int pid, int src_client_fd, int src_server_fd, int dst_client_fd, int dst_server_fd, mm_sound_focus_type_e focus_type)
392 int ret = MM_ERROR_NONE;
393 _mm_sound_focus_socket_param_t data;
394 _mm_sound_focus_socket_result_t result;
398 if (pid <= 0 || src_client_fd < 0 || src_server_fd < 0 || dst_client_fd < 0 || dst_server_fd < 0) {
399 debug_error("invalid parameter, pid[%d], src_fd[%d/%d], dst_fd[%d/%d]",
400 pid, src_client_fd, src_server_fd, dst_client_fd, dst_server_fd);
401 return MM_ERROR_INVALID_ARGUMENT;
404 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
405 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
406 FILL_SOCKET_PARAM_DELIVER(data, FOCUS_FUNC_NAME_DELIVER, pid, src_server_fd, dst_server_fd, focus_type);
408 if ((ret = _send_data_to_server(dst_client_fd, &data, &result)))
409 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
417 int mm_sound_focus_socket_get_acquired_focus_stream_type(mm_sound_focus_type_e focus_type, char **stream_type, int *option, char **ext_info)
419 int ret = MM_ERROR_NONE;
421 _mm_sound_focus_socket_param_t data;
422 _mm_sound_focus_socket_result_t result;
427 debug_error("invalid parameter, stream_type[%p]", stream_type);
428 return MM_ERROR_INVALID_ARGUMENT;
430 if ((ret = _get_client_socket_fd(&fd))) {
431 debug_error("failed to _get_client_socket_fd()");
432 return MM_ERROR_SOUND_INTERNAL;
434 if ((ret = _connect_socket_fd(fd))) {
435 debug_error("failed to _connect_socket_fd()");
437 return MM_ERROR_SOUND_INTERNAL;
440 memset(&data, 0x00, sizeof(_mm_sound_focus_socket_param_t));
441 memset(&result, 0x00, sizeof(_mm_sound_focus_socket_result_t));
442 FILL_SOCKET_PARAM_GET_ACQUIRED(data, FOCUS_FUNC_NAME_GET_ACQUIRED_INFO, focus_type);
444 if ((ret = _send_data_to_server(fd, &data, &result))) {
445 debug_error("failed to _send_data_to_server(), ret[0x%x]", ret);
450 debug_msg("stream_type[%s], option[%d], ext_info[%s]", result.stream_type, result.option, result.ext_info);
452 *stream_type = strdup(result.stream_type);
453 *ext_info = strdup(result.ext_info);
454 *option = result.option;