Added socket infrastructure for new IPC.
Added signal handler to deinitialize resources.
[Version] 0.11.1
[Issue Type] Enhancement
Change-Id: Ia497cc7e651221cc5dcfeb58518194c877cf7458
Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
mm_sound_device.c \
mm_sound_pa_client.c
if USE_FOCUS
-includelibmmfsound_HEADERS += include/mm_sound_focus.h
-libmmfsound_la_SOURCES += mm_sound_focus.c
+includelibmmfsound_HEADERS += include/mm_sound_focus.h \
+ include/mm_sound_focus_socket.h
+libmmfsound_la_SOURCES += mm_sound_focus.c \
+ mm_sound_focus_socket.c
endif
libmmfsound_la_DEPENDENCIES = common/libmmfsoundcommon.la
bin_PROGRAMS = focus_server
focus_server_SOURCES = mm_sound_mgr_focus_ipc.c \
mm_sound_mgr_focus_dbus.c \
+ mm_sound_mgr_focus_socket.c \
mm_sound_focus_server.c \
mm_sound_mgr_focus.c
void *callback;
void *cbdata;
bool reacquisition;
+ bool is_in_thread;
/* It will be removed when the session concept is completely left out*/
bool is_for_session;
int __mm_sound_mgr_focus_ipc_register_focus(int client_pid, int handle_id, const char* stream_type, bool is_for_session);
int __mm_sound_mgr_focus_ipc_set_focus_reacquisition(int pid, int handle_id, bool reacquisition, bool is_for_session);
int __mm_sound_mgr_focus_ipc_get_acquired_focus_stream_type(int focus_type, char **stream_type, int *option, char **ext_info);
-int __mm_sound_mgr_focus_ipc_acquire_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_for_session);
-int __mm_sound_mgr_focus_ipc_release_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_for_session);
+int __mm_sound_mgr_focus_ipc_acquire_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session);
+int __mm_sound_mgr_focus_ipc_release_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session);
int __mm_sound_mgr_focus_ipc_watch_focus(int pid, int handle_id, int focus_type, bool is_for_session, bool is_for_monitor);
int __mm_sound_mgr_focus_ipc_unwatch_focus(int pid, int handle_id);
int __mm_sound_mgr_focus_ipc_unregister_focus(int pid, int handle_id, bool is_for_session);
--- /dev/null
+#ifndef __MM_SOUND_MGR_FOCUS_SOCKET_H__
+#define __MM_SOUND_MGR_FOCUS_SOCKET_H__
+
+int MMSoundMgrFocusSocketInit(int *fd);
+void MMSoundMgrFocusSocketFini(int fd);
+int MMSoundMgrFocusSocketReadyToWork(int fd);
+
+
+#endif /* __MM_SOUND_MGR_FOCUS_SOCKET_H__ */
#include "../include/mm_sound_common.h"
#include "include/mm_sound_mgr_focus.h"
#include "include/mm_sound_mgr_focus_dbus.h"
+#include "include/mm_sound_mgr_focus_socket.h"
#define USE_SYSTEM_SERVER_PROCESS_MONITORING
}
}
+int g_socket_fd = -1;
+struct sigaction _int_old_action;
+struct sigaction _abrt_old_action;
+struct sigaction _segv_old_action;
+struct sigaction _term_old_action;
+struct sigaction _sys_old_action;
+struct sigaction _xcpu_old_action;
+static void _signal_handler(int signo)
+{
+ debug_warning("ENTER, sig.num(%d)", signo);
+
+ MMSoundMgrFocusDbusFini();
+ MMSoundMgrFocusFini();
+ MMSoundMgrFocusSocketFini(g_socket_fd);
+
+ /* signal block -------------- */
+ sigset_t old_mask, all_mask;
+ sigfillset(&all_mask);
+ sigprocmask(SIG_BLOCK, &all_mask, &old_mask);
+
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
+ /* signal unblock ------------ */
+
+ switch (signo) {
+ case SIGINT:
+ sigaction(SIGINT, &_int_old_action, NULL);
+ raise(signo);
+ break;
+ case SIGABRT:
+ sigaction(SIGABRT, &_abrt_old_action, NULL);
+ raise(signo);
+ break;
+ case SIGSEGV:
+ sigaction(SIGSEGV, &_segv_old_action, NULL);
+ raise(signo);
+ break;
+ case SIGTERM:
+ sigaction(SIGTERM, &_term_old_action, NULL);
+ raise(signo);
+ break;
+ case SIGSYS:
+ sigaction(SIGSYS, &_sys_old_action, NULL);
+ raise(signo);
+ break;
+ case SIGXCPU:
+ sigaction(SIGXCPU, &_xcpu_old_action, NULL);
+ raise(signo);
+ break;
+ default:
+ break;
+ }
+ debug_warning("LEAVE");
+}
+
+static void _signal_initialize(void)
+{
+ struct sigaction _action;
+ _action.sa_handler = _signal_handler;
+ _action.sa_flags = SA_NOCLDSTOP;
+
+ sigemptyset(&_action.sa_mask);
+
+ sigaction(SIGINT, &_action, &_int_old_action);
+ sigaction(SIGABRT, &_action, &_abrt_old_action);
+ sigaction(SIGSEGV, &_action, &_segv_old_action);
+ sigaction(SIGTERM, &_action, &_term_old_action);
+ sigaction(SIGSYS, &_action, &_sys_old_action);
+ sigaction(SIGXCPU, &_action, &_xcpu_old_action);
+
+}
+
+static void _signal_finalize(void)
+{
+ sigaction(SIGINT, &_int_old_action, NULL);
+ sigaction(SIGABRT, &_abrt_old_action, NULL);
+ sigaction(SIGSEGV, &_segv_old_action, NULL);
+ sigaction(SIGTERM, &_term_old_action, NULL);
+ sigaction(SIGSYS, &_sys_old_action, NULL);
+ sigaction(SIGXCPU, &_xcpu_old_action, NULL);
+}
+
int main(int argc, char **argv)
{
sem_t *sem = NULL;
#if !defined(USE_SYSTEM_SERVER_PROCESS_MONITORING)
int pid;
#endif
+ int socket_fd = -1;
if (_get_option(argc, argv, &serveropt))
return 1;
debug_warning("focus_server [%d] init \n", getpid());
+ _signal_initialize();
+
if (serveropt.startserver) {
sem = _sem_create_n_wait();
}
}
#endif
if (serveropt.startserver) {
+ if (MMSoundMgrFocusSocketInit(&socket_fd)) {
+ debug_error("focus_server [%d] terminating, due to the error of socket init.\n", getpid());
+ return 0;
+ }
+ if (MMSoundMgrFocusSocketReadyToWork(socket_fd)) {
+ debug_error("focus_server [%d] terminating, due to the error of thread init.\n", getpid());
+ return 0;
+ }
MMSoundMgrFocusDbusInit();
MMSoundMgrFocusInit();
+ g_socket_fd = socket_fd;
}
debug_warning("focus_server [%d] initialization complete...now, start running!!\n", getpid());
if (serveropt.startserver) {
MMSoundMgrFocusDbusFini();
MMSoundMgrFocusFini();
+ MMSoundMgrFocusSocketFini(socket_fd);
}
+ _signal_finalize();
+
debug_warning("focus_server [%d] exit ----------------- END \n", getpid());
return 0;
debug_fenter();
- MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
+ if (!param->is_in_thread)
+ MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
/* Update list for dead process */
g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
continue;
if (param->request_type == FOCUS_TYPE_BOTH || node->status == FOCUS_STATUS_ACTIVATED_BOTH ||
(node->status & param->request_type)) {
- if (node->status > FOCUS_STATUS_DEACTIVATED) {
- if ((my_node->priority < node->priority)) {
- ret = MM_ERROR_POLICY_BLOCKED;
- need_to_trigger_cb = false;
- break;
- } else {
- need_to_trigger_cb = true;
- }
+ if (node->status <= FOCUS_STATUS_DEACTIVATED)
+ continue;
+
+ if ((my_node->priority < node->priority)) {
+ ret = MM_ERROR_POLICY_BLOCKED;
+ need_to_trigger_cb = false;
+ break;
+ } else {
+ need_to_trigger_cb = true;
}
}
}
continue;
if (param_s->request_type == FOCUS_TYPE_BOTH || node->status == FOCUS_STATUS_ACTIVATED_BOTH ||
(node->status & param_s->request_type)) {
- if (node->status > FOCUS_STATUS_DEACTIVATED) {
- if (my_node->priority >= node->priority) {
- /* do callback for interruption */
- if ((ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_RELEASE, node, param_s))) {
- debug_error("Fail to _focus_do_callback for COMMAND RELEASE to node[%x], ret[0x%x]\n", node, ret);
- /* but, keep going */
- ret = MM_ERROR_NONE;
- }
- if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
- need_to_trigger_watch_cb = false;
- }
- need_to_trigger_monitor_cb = false;
+ if (node->status <= FOCUS_STATUS_DEACTIVATED)
+ continue;
+ if (my_node->priority >= node->priority) {
+ /* do callback for interruption */
+ if ((ret = _mm_sound_mgr_focus_do_callback(FOCUS_COMMAND_RELEASE, node, param_s))) {
+ debug_error("Fail to _focus_do_callback for COMMAND RELEASE to node[%x], ret[0x%x]\n", node, ret);
+ /* but, keep going */
+ ret = MM_ERROR_NONE;
}
+ if (!strncmp(my_node->stream_type, node->stream_type, MAX_STREAM_TYPE_LEN)) {
+ need_to_trigger_watch_cb = false;
+ }
+ need_to_trigger_monitor_cb = false;
}
}
}
_mm_sound_mgr_focus_list_dump();
_mm_sound_mgr_focus_watch_list_dump ();
FINISH:
- MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
+ if (!param->is_in_thread)
+ MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
debug_fleave();
return ret;
debug_fenter();
- MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
+ if (!param->is_in_thread)
+ MMSOUND_ENTER_CRITICAL_SECTION_WITH_RETURN(&g_focus_node_list_mutex, MM_ERROR_SOUND_INTERNAL);
/* Update list for dead process */
g_list_foreach (g_focus_node_list, (GFunc)_clear_focus_node_list_func, NULL);
_mm_sound_mgr_focus_list_dump();
_mm_sound_mgr_focus_watch_list_dump ();
FINISH:
- MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
+ if (!param->is_in_thread)
+ MMSOUND_LEAVE_CRITICAL_SECTION(&g_focus_node_list_mutex);
debug_fleave();
return ret;
}
g_variant_get(params, "(iiiisb)", &pid, &handle_id, &focus_type, &option, &ext_info, &is_for_session);
- ret = __mm_sound_mgr_focus_ipc_acquire_focus((is_for_session) ? pid : _get_sender_pid(invocation), handle_id, focus_type, option, ext_info, is_for_session);
+ ret = __mm_sound_mgr_focus_ipc_acquire_focus((is_for_session) ? pid : _get_sender_pid(invocation),
+ handle_id, focus_type, option, ext_info, false, is_for_session);
send_reply:
if (ret == MM_ERROR_NONE) {
}
g_variant_get(params, "(iiiisb)", &pid, &handle_id, &focus_type, &option, &ext_info, &is_for_session);
- ret = __mm_sound_mgr_focus_ipc_release_focus((is_for_session) ? pid : _get_sender_pid(invocation), handle_id, focus_type, option, ext_info, is_for_session);
+ ret = __mm_sound_mgr_focus_ipc_release_focus((is_for_session) ? pid : _get_sender_pid(invocation),
+ handle_id, focus_type, option, ext_info, false, is_for_session);
send_reply:
if (ret == MM_ERROR_NONE) {
}
}
-
static GVariant* handle_get_property(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
debug_leave();
}
-
-
-
}
// method -> callback
-int __mm_sound_mgr_focus_ipc_acquire_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_for_session)
+int __mm_sound_mgr_focus_ipc_acquire_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session)
{
_mm_sound_mgr_focus_param_t param;
int ret = MM_ERROR_NONE;
param.handle_id = handle_id;
param.request_type = focus_type;
param.option = option;
+ param.is_in_thread = is_in_thread;
param.is_for_session = is_for_session;
MMSOUND_STRNCPY(param.ext_info, ext_info, MM_SOUND_NAME_NUM);
}
// method -> callback
-int __mm_sound_mgr_focus_ipc_release_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_for_session)
+int __mm_sound_mgr_focus_ipc_release_focus(int pid, int handle_id, int focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session)
{
_mm_sound_mgr_focus_param_t param;
int ret = MM_ERROR_NONE;
param.handle_id = handle_id;
param.request_type = focus_type;
param.option = option;
+ param.is_in_thread = is_in_thread;
param.is_for_session = is_for_session;
MMSOUND_STRNCPY(param.ext_info, ext_info, MM_SOUND_NAME_NUM);
--- /dev/null
+/*
+ * libmm-sound
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sangchul Lee <sc11.lee@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mm_error.h>
+#include <mm_debug.h>
+
+#include <gio/gio.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include "../include/mm_sound_focus_socket.h"
+#include "include/mm_sound_mgr_focus.h"
+#include "include/mm_sound_mgr_focus_ipc.h"
+
+static pthread_t g_focus_work_thread_id = 0;
+
+
+typedef int (*focus_function_handler) (_mm_sound_mgr_focus_socket_param_t *param);
+static int handle_acquire_focus(_mm_sound_mgr_focus_socket_param_t *param);
+static int handle_release_focus(_mm_sound_mgr_focus_socket_param_t *param);
+
+enum {
+ FOCUS_FUNCTION_ACQUIRE,
+ FOCUS_FUNCTION_RELEASE,
+ FOCUS_FUNCTION_MAX,
+};
+
+typedef struct mm_sound_focus_function_intf {
+ const char *name;
+ focus_function_handler handler;
+} mm_sound_focus_function_intf_t;
+
+static mm_sound_focus_function_intf_t functions[FOCUS_FUNCTION_MAX] = {
+ [FOCUS_FUNCTION_ACQUIRE] = {
+ .name = FOCUS_FUNC_NAME_ACQUIRE,
+ .handler = handle_acquire_focus
+ },
+ [FOCUS_FUNCTION_RELEASE] = {
+ .name = FOCUS_FUNC_NAME_RELEASE,
+ .handler = handle_release_focus
+ },
+};
+
+static const char* convert_error_string_from_int(int error)
+{
+ switch (error) {
+ case MM_ERROR_NONE:
+ return FOCUS_ERROR_NONE;
+
+ case MM_ERROR_INVALID_ARGUMENT:
+ return FOCUS_ERROR_INVALID_PARAMETER;
+
+ case MM_ERROR_POLICY_BLOCKED:
+ case MM_ERROR_POLICY_INTERNAL:
+ return FOCUS_ERROR_POLICY;
+
+ case MM_ERROR_SOUND_INVALID_STATE:
+ return FOCUS_ERROR_INVALID_STATE;
+
+ case MM_ERROR_SOUND_INTERNAL:
+ return FOCUS_ERROR_INTERNAL;
+
+ default:
+ return FOCUS_ERROR_INTERNAL;
+ }
+}
+
+static int handle_acquire_focus(_mm_sound_mgr_focus_socket_param_t *param)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ ret = __mm_sound_mgr_focus_ipc_acquire_focus(param->pid, param->handle_id, param->focus_type,
+ param->option, param->ext_info, true, param->is_for_session);
+
+ debug_fleave();
+
+ return ret;
+}
+
+static int handle_release_focus(_mm_sound_mgr_focus_socket_param_t *param)
+{
+ int ret = MM_ERROR_NONE;
+
+ debug_fenter();
+
+ ret = __mm_sound_mgr_focus_ipc_release_focus(param->pid, param->handle_id, param->focus_type,
+ param->option, param->ext_info, true, param->is_for_session);
+
+ debug_fleave();
+
+ return ret;
+}
+
+static int focus_functions_handler(_mm_sound_mgr_focus_socket_param_t *param)
+{
+ int i = 0;
+ int ret = MM_ERROR_SOUND_INTERNAL;
+
+ if (param == NULL)
+ return MM_ERROR_SOUND_INTERNAL;
+
+ debug_log("param[%p], function_name[%s]", param, param->func_name);
+
+ for (i = 0; i < FOCUS_FUNCTION_MAX; i++) {
+ if (!strncmp(param->func_name, functions[i].name, MAX_ERROR_LEN))
+ ret = functions[i].handler(param);
+ }
+
+ return ret;
+}
+
+static void *thread_func(void *data)
+{
+ int fd = -1;
+ int accepted_fd = -1;
+ char str_error[MAX_ERROR_LEN] = {'\0',};
+ _mm_sound_mgr_focus_socket_param_t read_data;
+ int rval = 0;
+ char ret_buf[MAX_ERROR_LEN] = {'\0',};
+
+ if (data == NULL) {
+ debug_error("invalid data\n");
+ pthread_exit(NULL);
+ }
+
+ fd = (int)data;
+
+ if (listen(fd, 5)) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to listen(), err: %s", str_error);
+ goto LEAVE;
+ }
+ debug_log("listen for fd [%d] success", fd);
+
+ do {
+ accepted_fd = accept(fd, NULL, NULL);
+ if (accepted_fd == -1) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to accept(), err: %s", str_error);
+ goto LEAVE;
+ }
+
+ debug_log("accepted fd [%d]", accepted_fd);
+
+ memset(&read_data, 0x00, sizeof(_mm_sound_mgr_focus_socket_param_t));
+ if ((rval = read(accepted_fd, &read_data, sizeof(_mm_sound_mgr_focus_socket_param_t))) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to read(), err: %s", str_error);
+ } else if (rval == sizeof(_mm_sound_mgr_focus_socket_param_t)) {
+ int ret = MM_ERROR_NONE;
+ debug_log("data read successfully..\n");
+ debug_log(" : pid[%d], handle_id[%d], focus_type[%d]\n", read_data.pid, read_data.handle_id, read_data.focus_type);
+ debug_log(" : option[%d], ext_info[%s], is_for_session[%d]\n", read_data.option, read_data.ext_info, read_data.is_for_session);
+
+ if ((ret = focus_functions_handler(&read_data)))
+ debug_log("failed to focus_function_handler(), err[0x%x]", ret);
+
+ snprintf(ret_buf, sizeof(ret_buf), "%s", convert_error_string_from_int(ret));
+ if (write(accepted_fd, ret_buf, sizeof(ret_buf)) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to write(), err: %s\n", str_error);
+ }
+ } else {
+ debug_error("failed to read(), read size mismatched, rval(%d), expect size(%d)", rval,sizeof(_mm_sound_mgr_focus_socket_param_t));
+ }
+
+ close(accepted_fd);
+ } while (1);
+
+LEAVE:
+ close(fd);
+ pthread_exit(NULL);
+}
+
+int MMSoundMgrFocusSocketInit(int *fd)
+{
+ int socket_fd;
+ struct sockaddr_un addr_un;
+ char str_error[128] = {'\0',};
+
+ if (fd == NULL) {
+ debug_error("input param fd is null\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (socket_fd < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to socket(), err: %s\n", str_error);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_log("focus server socket fd [%d]", socket_fd);
+
+ memset(&addr_un, 0, sizeof(addr_un));
+ addr_un.sun_family = AF_UNIX;
+ strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
+
+ if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to bind(), err: %s\n", str_error);
+ if (errno == EADDRINUSE) {
+ unlink(FOCUS_SERVER_SOCK);
+ debug_msg("unlink socket and bind again...\n");
+ if (bind(socket_fd, (struct sockaddr *)&addr_un, sizeof(addr_un))) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to bind() again, err: %s\n", str_error);
+ close(socket_fd);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ } else {
+ close(socket_fd);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ }
+
+ debug_log("focus server socket binding success");
+
+ *fd = socket_fd;
+
+ debug_leave();
+
+ return MM_ERROR_NONE;
+}
+
+void MMSoundMgrFocusSocketFini(int fd)
+{
+ debug_enter();
+
+ if (g_focus_work_thread_id) {
+ unlink(FOCUS_SERVER_SOCK);
+ shutdown(fd,SHUT_RDWR);
+ close(fd);
+ pthread_join(g_focus_work_thread_id, NULL);
+ debug_msg("pthread join well");
+ g_focus_work_thread_id = 0;
+ }
+
+ debug_leave();
+}
+
+int MMSoundMgrFocusSocketReadyToWork(int fd)
+{
+ debug_enter();
+
+ if (fd < 0) {
+ debug_error("input param fd [%d] is not valid\n", fd);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ debug_log("fd [%d]\n", fd);
+ if (pthread_create(&g_focus_work_thread_id, NULL, (void *)thread_func, (void *)fd)) {
+ debug_error("failed to start work thread");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_leave();
+
+ return MM_ERROR_NONE;
+}
--- /dev/null
+/*
+ * libmm-sound
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sangchul Lee <sc11.lee@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_SOUND_FOCUS_SOCKET_H__
+#define __MM_SOUND_FOCUS_SOCKET_H__
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+#include "include/mm_sound.h"
+#include "include/mm_sound_focus.h"
+
+#define FOCUS_SERVER_SOCK "/tmp/.focus_server.socket"
+#define MAX_ERROR_LEN 64
+
+typedef struct {
+ char func_name[MM_SOUND_NAME_NUM];
+ int pid;
+ int handle_id;
+ mm_sound_focus_type_e focus_type;
+ int option;
+ char ext_info[MM_SOUND_NAME_NUM];
+ bool is_in_thread; /* Called within focus callback thread */
+ bool is_for_session; /* will be removed when the session concept is completely left out*/
+} _mm_sound_mgr_focus_socket_param_t;
+
+/* Function names */
+#define FOCUS_FUNC_NAME_ACQUIRE "AcquireFocus"
+#define FOCUS_FUNC_NAME_RELEASE "ReleaseFocus"
+
+/* Error defines */
+#define FOCUS_ERROR_NONE "error_none"
+#define FOCUS_ERROR_INVALID_PARAMETER "error_invalid_parameter"
+#define FOCUS_ERROR_POLICY "error_policy"
+#define FOCUS_ERROR_INTERNAL "error_internal"
+#define FOCUS_ERROR_INVALID_STATE "error_invalid_state"
+
+int mm_sound_focus_socket_acquire(int instance, int id, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session);
+int mm_sound_focus_socket_release(int instance, int id, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_SOUND_FOCUS_SOCKET_H__ */
+
debug_fenter();
- RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
-
if (id < 0) {
debug_error("id is not valid\n");
return MM_ERROR_INVALID_ARGUMENT;
debug_fenter();
- RETURN_ERROR_IF_FOCUS_CB_THREAD(g_thread_self());
-
if (id < 0) {
debug_error("id is not valid\n");
return MM_ERROR_INVALID_ARGUMENT;
--- /dev/null
+/*
+ * libmm-sound
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Sangchul Lee <sc11.lee@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <mm_debug.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include "include/mm_sound.h"
+#include "include/mm_sound_common.h"
+#include "include/mm_sound_focus_socket.h"
+
+#define FILL_SOCKET_PARAM(x_param, x_func_name, x_instance, x_id, x_focus_type, x_option, x_ext_info, x_is_in_thread, x_is_for_session) \
+do { \
+ MMSOUND_STRNCPY(x_param.func_name, x_func_name, MM_SOUND_NAME_NUM); \
+ x_param.pid = x_instance; \
+ x_param.handle_id = x_id; \
+ x_param.focus_type = x_focus_type; \
+ x_param.option = x_option; \
+ MMSOUND_STRNCPY(x_param.ext_info, x_ext_info, MM_SOUND_NAME_NUM); \
+ x_param.is_in_thread = x_is_in_thread; \
+ x_param.is_for_session = x_is_for_session; \
+} while(0) \
+
+static int _convert_error_from_string(const char *error_string)
+{
+ int ret = MM_ERROR_NONE;
+
+ if (error_string == NULL) {
+ debug_error("error_string is null\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (!strncmp(error_string, FOCUS_ERROR_NONE, MAX_ERROR_LEN))
+ ret = MM_ERROR_NONE;
+ else if (!strncmp(error_string, FOCUS_ERROR_INVALID_PARAMETER, MAX_ERROR_LEN))
+ ret = MM_ERROR_INVALID_ARGUMENT;
+ else if (!strncmp(error_string, FOCUS_ERROR_POLICY, MAX_ERROR_LEN))
+ ret = MM_ERROR_POLICY_BLOCKED;
+ else if (!strncmp(error_string, FOCUS_ERROR_INVALID_STATE, MAX_ERROR_LEN))
+ ret = MM_ERROR_SOUND_INVALID_STATE;
+ else if (!strncmp(error_string, FOCUS_ERROR_INTERNAL, MAX_ERROR_LEN))
+ ret = MM_ERROR_SOUND_INTERNAL;
+ else
+ ret = MM_ERROR_SOUND_INTERNAL;
+
+ debug_msg("error_string[%s], ret[0x%x]\n", error_string, ret);
+
+ return ret;
+}
+
+static int _get_client_socket_fd(int *fd)
+{
+ int socket_fd;
+ char str_error[128] = {'\0',};
+
+ if (fd == NULL) {
+ debug_error("input param fd is null\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (socket_fd < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to socket(), err: %s", str_error);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_log("focus client socket fd[%d]", socket_fd);
+
+ *fd = socket_fd;
+
+ return MM_ERROR_NONE;
+}
+
+static int _connect_socket_fd(int fd)
+{
+ struct sockaddr_un addr_un;
+ char str_error[128] = {'\0',};
+
+ if (fd < 0) {
+ debug_error("invalid fd[%d]\n", fd);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ memset(&addr_un, 0, sizeof(addr_un));
+ addr_un.sun_family = AF_UNIX;
+ strncpy(addr_un.sun_path, FOCUS_SERVER_SOCK, sizeof(addr_un.sun_path));
+
+ if (connect(fd, (struct sockaddr *)&addr_un, sizeof(addr_un)) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to connect() to %s, err: %s", addr_un.sun_path, fd, str_error);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_log("connected successfully, fd[%d]", fd);
+
+ return MM_ERROR_NONE;
+}
+
+static int _send_data_to_server(int fd, _mm_sound_mgr_focus_socket_param_t *data)
+{
+ char str_error[MAX_ERROR_LEN] = {'\0',};
+ char ret_buf[MAX_ERROR_LEN] = {'\0',};
+ int rval = 0;
+
+ if (fd < 0 || data == NULL) {
+ debug_error("invalid parameter, fd[%d], data[%p]", fd, data);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (write(fd, data, sizeof(_mm_sound_mgr_focus_socket_param_t)) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to write(), err: %s", str_error);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ /* return message from server */
+ if ((rval = read(fd, ret_buf, sizeof(ret_buf))) < 0) {
+ strerror_r(errno, str_error, sizeof(str_error));
+ debug_error("failed to read(), err: %s", str_error);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ debug_log("rval[%d], ret_buf[%s]", rval, ret_buf);
+
+ return _convert_error_from_string(ret_buf);
+}
+
+EXPORT_API
+int mm_sound_focus_socket_acquire(int instance, int id, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session)
+{
+ int ret = MM_ERROR_NONE;
+ int fd = -1;
+ _mm_sound_mgr_focus_socket_param_t data;
+
+ debug_fenter();
+
+ if (instance <= 0 || id < 0 || option < 0) {
+ debug_error("invalid parameter, instance[%d], id[%d], option[%d]", instance, id, option);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+ if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
+ debug_error("focus type[%d] is not valid", focus_type);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if ((ret = _get_client_socket_fd(&fd))) {
+ debug_error("failed to _get_client_socket_fd()\n");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ if ((ret = _connect_socket_fd(fd))) {
+ debug_error("failed to _connect_socket_fd()\n");
+ close(fd);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ memset(&data, 0x00, sizeof(_mm_sound_mgr_focus_socket_param_t));
+ FILL_SOCKET_PARAM(data, FOCUS_FUNC_NAME_ACQUIRE, instance, id, focus_type,
+ option, ext_info, is_in_thread, is_for_session);
+
+ if ((ret = _send_data_to_server(fd, &data))) {
+ debug_error("failed to _send_data_to_server(), ret[0x%x]\n", ret);
+ close(fd);
+ return ret;
+ }
+
+ close(fd);
+
+ debug_fleave();
+
+ return MM_ERROR_NONE;
+}
+
+EXPORT_API
+int mm_sound_focus_socket_release(int instance, int id, mm_sound_focus_type_e focus_type, int option, const char *ext_info, bool is_in_thread, bool is_for_session)
+{
+ int ret = MM_ERROR_NONE;
+ int fd = -1;
+ _mm_sound_mgr_focus_socket_param_t data;
+
+ debug_fenter();
+
+ if (instance <= 0 || id < 0 || option < 0) {
+ debug_error("invalid parameter, instance[%d], id[%d], option[%d]", instance, id, option);
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+ if (focus_type < FOCUS_FOR_PLAYBACK || focus_type > FOCUS_FOR_BOTH) {
+ debug_error("focus type is not valid\n");
+ return MM_ERROR_INVALID_ARGUMENT;
+ }
+
+ if ((ret = _get_client_socket_fd(&fd))) {
+ debug_error("failed to _get_client_socket_fd()");
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+ if ((ret = _connect_socket_fd(fd))) {
+ debug_error("failed to _connect_socket_fd()");
+ close(fd);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ memset(&data, 0x00, sizeof(_mm_sound_mgr_focus_socket_param_t));
+ FILL_SOCKET_PARAM(data, FOCUS_FUNC_NAME_RELEASE, instance, id, focus_type,
+ option, ext_info, is_in_thread, is_for_session);
+
+ if ((ret = _send_data_to_server(fd, &data))) {
+ debug_error("failed to _send_data_to_server()");
+ close(fd);
+ return MM_ERROR_SOUND_INTERNAL;
+ }
+
+ close(fd);
+
+ debug_fleave();
+
+ return ret;
+}
#include "include/mm_sound_common.h"
#include "include/mm_sound_dbus.h"
#include "include/mm_sound_intf.h"
+#include "include/mm_sound_focus_socket.h"
struct callback_data {
void *user_cb;
return MM_ERROR_SOUND_INTERNAL;
}
- if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_CLIENT_SUBSCRIBED, params))) {
+ if ((ret = mm_sound_dbus_emit_signal(AUDIO_PROVIDER_AUDIO_CLIENT, AUDIO_EVENT_CLIENT_SUBSCRIBED, params)))
debug_error("dbus send signal for client subscribed failed");
- }
debug_fleave();
return ret;
int ret = MM_ERROR_NONE;
debug_fenter();
- if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
debug_error("remove test callback failed");
- }
debug_fleave();
return ret;
int ret = MM_ERROR_NONE;
debug_fenter();
- if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
debug_error("remove device info changed callback failed");
- }
debug_fleave();
return ret;
int ret = MM_ERROR_NONE;
debug_fenter();
- if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
debug_error("remove device state changed callback failed");
- }
debug_fleave();
return ret;
int ret = MM_ERROR_NONE;
debug_fenter();
- if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
debug_error("Remove Volume changed callback failed");
- }
debug_fleave();
return ret;
debug_fenter();
params = g_variant_new("(iiiiiiibsi)", tone, repeat, volume, volume_config, session_type,
- session_options, client_pid , _enable_session, stream_type, stream_index);
+ session_options, client_pid , _enable_session, stream_type, stream_index);
if (params) {
if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_METHOD_PLAY_DTMF, params, &result)) != MM_ERROR_NONE) {
debug_error("dbus play tone failed");
debug_fenter();
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_METHOD_CLEAR_FOCUS, g_variant_new("(i)", pid), &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_SOUND_SERVER, AUDIO_METHOD_CLEAR_FOCUS, g_variant_new("(i)", pid), &result)) != MM_ERROR_NONE)
debug_error("dbus clear focus failed");
- }
if (result)
g_variant_unref(result);
int ret = MM_ERROR_NONE;
debug_fenter();
- if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_signal_unsubscribe(subs_id)) != MM_ERROR_NONE)
debug_error("Remove Play File End callback failed");
- }
debug_fleave();
return ret;
debug_fenter();
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_GET_UNIQUE_ID, NULL, &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_GET_UNIQUE_ID, NULL, &result)) != MM_ERROR_NONE)
debug_error("dbus get unique id failed");
- }
if (result) {
g_variant_get(result, "(i)", &res);
params = g_variant_new("(iisb)", instance, id, stream_type, is_for_session);
if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_REGISTER_FOCUS, params, &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_REGISTER_FOCUS, params, &result)) != MM_ERROR_NONE)
debug_error("dbus register focus failed");
- }
} else {
debug_error("Construct Param for method call failed");
}
params = g_variant_new("(iib)", instance, id, is_for_session);
if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_UNREGISTER_FOCUS, params, &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_UNREGISTER_FOCUS, params, &result)) != MM_ERROR_NONE)
debug_error("dbus unregister focus failed");
- }
} else {
debug_error("Construct Param for method call failed");
}
params = g_variant_new("(iibb)", instance, id, reacquisition, is_for_session);
if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_SET_FOCUS_REACQUISITION, params, &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_SET_FOCUS_REACQUISITION, params, &result)) != MM_ERROR_NONE)
debug_error("dbus set focus reacquisition failed");
- }
} else {
debug_error("Construct Param for method call failed");
}
int mm_sound_proxy_acquire_focus(int instance, int id, mm_sound_focus_type_e type, int option, const char *ext_info, bool is_for_session)
{
int ret = MM_ERROR_NONE;
- GVariant *params = NULL, *result = NULL;
+ bool is_in_focus_cb_thread = false;
debug_fenter();
- params = g_variant_new("(iiiisb)", instance, id, type, option, ext_info ? ext_info : "", is_for_session);
- if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_ACQUIRE_FOCUS, params, &result)) != MM_ERROR_NONE) {
- debug_error("dbus acquire focus failed");
- }
+ mm_sound_client_is_focus_cb_thread(g_thread_self(), &is_in_focus_cb_thread);
+ if (is_in_focus_cb_thread) {
+ if ((ret = mm_sound_focus_socket_acquire(instance, id, type, option, ext_info ? ext_info : "", true, is_for_session)))
+ debug_error("failed to mm_sound_focus_socket_acquire(), ret[0x%x]", ret);
} else {
- debug_error("Construct Param for method call failed");
- }
+ GVariant *params = NULL, *result = NULL;
- if (ret != MM_ERROR_NONE)
- g_variant_get(result, "(i)", &ret);
- if (result)
- g_variant_unref(result);
+ params = g_variant_new("(iiiisb)", instance, id, type, option, ext_info ? ext_info : "", is_for_session);
+ if (params) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_ACQUIRE_FOCUS, params, &result)) != MM_ERROR_NONE)
+ debug_error("dbus acquire focus failed");
+ } else {
+ debug_error("Construct Param for method call failed");
+ }
+
+ if (ret != MM_ERROR_NONE)
+ g_variant_get(result, "(i)", &ret);
+ if (result)
+ g_variant_unref(result);
+ }
debug_fleave();
return ret;
int mm_sound_proxy_release_focus(int instance, int id, mm_sound_focus_type_e type, int option, const char *ext_info, bool is_for_session)
{
int ret = MM_ERROR_NONE;
- GVariant *params = NULL, *result = NULL;
+ bool is_in_focus_cb_thread = false;
debug_fenter();
- params = g_variant_new("(iiiisb)", instance, id, type, option, ext_info ? ext_info : "", is_for_session);
- if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_RELEASE_FOCUS, params, &result)) != MM_ERROR_NONE) {
- debug_error("dbus release focus failed");
- }
+ mm_sound_client_is_focus_cb_thread(g_thread_self(), &is_in_focus_cb_thread);
+ if (is_in_focus_cb_thread) {
+ if ((ret = mm_sound_focus_socket_release(instance, id, type, option, ext_info ? ext_info : "", true, is_for_session)))
+ debug_error("failed to mm_sound_focus_socket_release(), ret[0x%x]", ret);
} else {
- debug_error("Construct Param for method call failed");
- }
+ GVariant *params = NULL, *result = NULL;
- if (ret != MM_ERROR_NONE)
- g_variant_get(result, "(i)", &ret);
- if (result)
- g_variant_unref(result);
+ params = g_variant_new("(iiiisb)", instance, id, type, option, ext_info ? ext_info : "", is_for_session);
+ if (params) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_RELEASE_FOCUS, params, &result)) != MM_ERROR_NONE)
+ debug_error("dbus release focus failed");
+ } else {
+ debug_error("Construct Param for method call failed");
+ }
+
+ if (ret != MM_ERROR_NONE)
+ g_variant_get(result, "(i)", &ret);
+ if (result)
+ g_variant_unref(result);
+ }
debug_fleave();
return ret;
params = g_variant_new("(iiibb)", instance, handle, type, is_for_session, is_for_monitor);
if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_WATCH_FOCUS, params, &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_WATCH_FOCUS, params, &result)) != MM_ERROR_NONE)
debug_error("dbus set watch focus failed");
- }
} else {
debug_error("Construct Param for method call failed");
}
params = g_variant_new("(iib)", focus_tid, handle, is_for_session);
if (params) {
- if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_UNWATCH_FOCUS, params, &result)) != MM_ERROR_NONE) {
+ if ((ret = mm_sound_dbus_method_call_to(AUDIO_PROVIDER_FOCUS_SERVER, AUDIO_METHOD_UNWATCH_FOCUS, params, &result)) != MM_ERROR_NONE)
debug_error("dbus unset watch focus failed");
- }
} else {
debug_error("Construct Param for method call failed");
}
Name: libmm-sound
Summary: MMSound Package contains client lib and sound_server binary
-Version: 0.10.116
+Version: 0.11.1
Release: 0
Group: System/Libraries
License: Apache-2.0
%{_includedir}/mmf/mm_sound.h
%{_includedir}/mmf/mm_sound_focus.h
%{_includedir}/mmf/mm_sound_device.h
+%exclude %{_includedir}/mmf/mm_sound_focus_socket.h
%exclude %{_includedir}/mmf/mm_sound_pa_client.h
%{_libdir}/pkgconfig/mm-keysound.pc
%{_libdir}/pkgconfig/mm-bootsound.pc