+++ /dev/null
-/***
- This file is part of PulseAudio.
-
- Copyright 2021 Jaechul Lee <jcsing.lee@samsung.com>
-
- PulseAudio is free software; you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2.1 of the License,
- or (at your option) any later version.
-
- PulseAudio is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with PulseAudio; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- USA.
-***/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <pulsecore/sink.h>
-#include <pulsecore/source.h>
-#include <pulsecore/core-util.h>
-#include <pulsecore/core-error.h>
-#include <pulsecore/macro.h>
-
-#include <pulsecore/dbus-shared.h>
-#include <pulsecore/protocol-dbus.h>
-#include <pulsecore/dbus-util.h>
-
-#include "aec-manager.h"
-
-#define AEC_MANAGER_OBJECT_PATH "/org/pulseaudio/AecManager"
-#define AEC_MANAGER_INTERFACE "org.pulseaudio.AecManager"
-
-#define AEC_MANAGER_METHOD_NAME_ON "On"
-#define AEC_MANAGER_METHOD_NAME_OFF "Off"
-#define AEC_MANAGER_METHOD_NAME_GET_SINK_PARAMS "GetSinkParam"
-#define AEC_MANAGER_METHOD_NAME_GET_SOURCE_PARAMS "GetSourceParam"
-
-#define AEC_UNIX_SOCKET_PATH "/tmp/.aec.socket"
-
-static struct aec_manager {
- pa_dbus_connection *dbus_conn;
- pa_source *source; /* builtin-mic */
- pa_sink *sink; /* builtin-spk */
-} am;
-
-enum {
- SINK_MESSAGE_SET_AEC_STATE = PA_SINK_MESSAGE_MAX,
- SINK_MESSAGE_GET_AEC_PARAMS,
-};
-
-enum {
- SOURCE_MESSAGE_SET_AEC_STATE = PA_SOURCE_MESSAGE_MAX,
- SOURCE_MESSAGE_GET_AEC_PARAMS,
-};
-
-#define AEC_MANAGER_INTROSPECT_XML \
- DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
- "<node>" \
- " <interface name=\"AEC_MANAGER_INTERFACE\">" \
- " <method name=\"AEC_MANAGER_METHOD_NAME_ON\">" \
- " </method>" \
- " <method name=\"AEC_MANAGER_METHOD_NAME_OFF\">" \
- " </method>" \
- " <method name=\"AEC_MANAGER_METHOD_NAME_GET_SINK_PARAMS\">" \
- " <arg name=\"rate\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"channels\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"format\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"frag_size\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"nfrags\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"card\" direction=\"out\" type=\"s\"/>" \
- " <arg name=\"device\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " <method name=\"AEC_MANAGER_METHOD_NAME_GET_SOURCE_PARAMS\">" \
- " <arg name=\"rate\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"channels\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"format\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"frag_size\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"nfrags\" direction=\"out\" type=\"i\"/>" \
- " <arg name=\"card\" direction=\"out\" type=\"s\"/>" \
- " <arg name=\"device\" direction=\"out\" type=\"s\"/>" \
- " </method>" \
- " </interface>" \
- " <interface name=\"org.freedesktop.DBus.Introspectable\">" \
- " <method name=\"Introspect\">" \
- " <arg name=\"data\" type=\"s\" direction=\"out\"/>" \
- " </method>" \
- " </interface>" \
- "</node>"
-
-enum method_handler_index {
- METHOD_HANDLER_ON,
- METHOD_HANDLER_OFF,
- METHOD_HANDLER_GET_SINK_PARAMS,
- METHOD_HANDLER_GET_SOURCE_PARAMS,
- METHOD_HANDLER_MAX
-};
-
-static void handle_method_on(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_method_off(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_method_get_sink_params(DBusConnection *conn, DBusMessage *msg, void *userdata);
-static void handle_method_get_source_params(DBusConnection *conn, DBusMessage *msg, void *userdata);
-
-static pa_dbus_method_handler method_handlers[METHOD_HANDLER_MAX] = {
- [METHOD_HANDLER_ON] = {
- .method_name = AEC_MANAGER_METHOD_NAME_ON,
- .receive_cb = handle_method_on },
- [METHOD_HANDLER_OFF] = {
- .method_name = AEC_MANAGER_METHOD_NAME_OFF,
- .receive_cb = handle_method_off },
- [METHOD_HANDLER_GET_SINK_PARAMS] = {
- .method_name = AEC_MANAGER_METHOD_NAME_GET_SINK_PARAMS,
- .receive_cb = handle_method_get_sink_params },
- [METHOD_HANDLER_GET_SOURCE_PARAMS] = {
- .method_name = AEC_MANAGER_METHOD_NAME_GET_SOURCE_PARAMS,
- .receive_cb = handle_method_get_source_params },
-};
-
-static void send_get_param_reply(DBusConnection *conn, DBusMessage *msg, aec_params_t* param) {
- DBusMessage *reply = NULL;
- DBusMessageIter msg_iter;
-
- const char *ptr1 = param->card;
- const char *ptr2 = param->device;
-
- reply = dbus_message_new_method_return(msg);
- if (!reply) {
- pa_log_error("Failed to alloc reply");
- return;
- }
-
- dbus_message_iter_init_append(reply, &msg_iter);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, ¶m->rate);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, ¶m->channels);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, ¶m->format);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, ¶m->frag_size);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_INT32, ¶m->nfrags);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &ptr1);
- dbus_message_iter_append_basic(&msg_iter, DBUS_TYPE_STRING, &ptr2);
- if (!dbus_connection_send(conn, reply, NULL))
- pa_log_error("reply send error!");
-
- dbus_message_unref(reply);
-}
-
-static void handle_method_on(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_asyncmsgq_post(am.sink->asyncmsgq, PA_MSGOBJECT(am.sink),
- SINK_MESSAGE_SET_AEC_STATE, (void *)TRUE, 0, NULL, NULL);
- pa_asyncmsgq_post(am.source->asyncmsgq, PA_MSGOBJECT(am.source),
- SOURCE_MESSAGE_SET_AEC_STATE, (void *)TRUE, 0, NULL, NULL);
-
- pa_dbus_send_empty_reply(conn, msg);
-}
-
-static void handle_method_off(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- pa_asyncmsgq_post(am.sink->asyncmsgq, PA_MSGOBJECT(am.sink),
- SINK_MESSAGE_SET_AEC_STATE, (void *)FALSE, 0, NULL, NULL);
- pa_asyncmsgq_post(am.source->asyncmsgq, PA_MSGOBJECT(am.source),
- SOURCE_MESSAGE_SET_AEC_STATE, (void *)FALSE, 0, NULL, NULL);
-
- pa_dbus_send_empty_reply(conn, msg);
-}
-
-static void handle_method_get_sink_params(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- aec_params_t param;
-
- pa_asyncmsgq_send(am.sink->asyncmsgq, PA_MSGOBJECT(am.sink),
- SINK_MESSAGE_GET_AEC_PARAMS, ¶m, 0, NULL);
-
- send_get_param_reply(conn, msg, ¶m);
-}
-
-static void handle_method_get_source_params(DBusConnection *conn, DBusMessage *msg, void *userdata) {
- aec_params_t param;
-
- pa_asyncmsgq_send(am.source->asyncmsgq, PA_MSGOBJECT(am.source),
- SOURCE_MESSAGE_GET_AEC_PARAMS, ¶m, 0, NULL);
-
- send_get_param_reply(conn, msg, ¶m);
-}
-
-static DBusHandlerResult method_handler_for_vt(DBusConnection *conn, DBusMessage *m, void *userdata) {
- const char *path, *interface, *member;
- DBusMessage *r = NULL;
-
- pa_assert(conn);
- pa_assert(m);
-
- path = dbus_message_get_path(m);
- interface = dbus_message_get_interface(m);
- member = dbus_message_get_member(m);
-
- pa_log_debug("dbus: path=%s, interface=%s, member=%s", path, interface, member);
-
- if (!pa_safe_streq(path, AEC_MANAGER_OBJECT_PATH))
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- if (dbus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
- r = dbus_message_new_method_return(m);
- if (r) {
- const char *xml = AEC_MANAGER_INTROSPECT_XML;
- if (dbus_message_append_args(r, DBUS_TYPE_STRING, &xml, DBUS_TYPE_INVALID)) {
- if (!dbus_connection_send(conn, r, NULL))
- pa_log_error("reply send error!");
- } else {
- pa_log_error("args append error!");
- }
-
- dbus_message_unref(r);
- }
- } else {
- int i;
- for (i = 0; i < METHOD_HANDLER_MAX; i++) {
- if (dbus_message_is_method_call(m, AEC_MANAGER_INTERFACE,
- method_handlers[i].method_name))
- method_handlers[i].receive_cb(conn, m, NULL);
- }
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-int aec_manager_init(pa_core *core, pa_source *source, pa_sink *sink) {
- DBusError err;
- pa_dbus_connection *conn = NULL;
- static const DBusObjectPathVTable vtable = {
- .message_function = method_handler_for_vt,
- };
-
- if (!source || !sink) {
- pa_log_error("AEC init failed. source(%p)/sink(%p) is null.", source, sink);
- return -1;
- }
-
- dbus_error_init(&err);
- if (!(conn = pa_dbus_bus_get(core, DBUS_BUS_SYSTEM, &err)) || dbus_error_is_set(&err)) {
- if (conn)
- pa_dbus_connection_unref(conn);
-
- dbus_error_free(&err);
- pa_log_error("Unable to contact D-Bus system bus: %s: %s", err.name, err.message);
- return -1;
- }
-
- am.dbus_conn = conn;
- if (!dbus_connection_register_object_path(pa_dbus_connection_get(conn),
- AEC_MANAGER_OBJECT_PATH, &vtable, NULL)) {
- pa_dbus_connection_unref(conn);
- pa_log_error("Failed to register object path");
- return -1;
- }
-
- am.source = source;
- am.sink = sink;
-
- pa_log_info("AEC init success");
-
- return 0;
-}
-
-void aec_manager_deinit(void) {
- if (am.dbus_conn)
- pa_dbus_connection_unref(am.dbus_conn);
-
- pa_log_info("AEC deinit success");
-}
#include "hal-interface.h"
-#ifdef SUPPORT_AEC
-#include "aec-manager.h"
-#endif
-
PA_MODULE_AUTHOR("Tizen");
PA_MODULE_DESCRIPTION("Tizen Audio Sink");
PA_MODULE_VERSION(PACKAGE_VERSION);
#define DEVICE_NAME_MAX 30
#define SMALL_AVAIL_LOG_PERIOD 20
-#ifdef SUPPORT_AEC
-enum {
- PA_SINK_MESSAGE_SET_AEC_STATE = PA_SINK_MESSAGE_MAX,
- PA_SINK_MESSAGE_GET_AEC_PARAMS,
-};
-#endif
-
struct userdata {
pa_core *core;
pa_module *module;
uint64_t small_avail_count;
uint64_t write_count;
pa_hal_interface *hal_interface;
-
-#ifdef SUPPORT_AEC
- bool aec_enable;
- pa_sample_spec ss;
-#endif
};
static const char* const valid_modargs[] = {
u->rtpoll_item = NULL;
}
- pa_log_info("Device suspended...");
+ pa_log_info("Device suspended...[%s,%s]", u->card, u->device);
return 0;
}
int32_t ret;
size_t frame_size;
- char *card = u->card;
- char *device = u->device;
-
pa_assert(u);
pa_assert(!u->pcm_handle);
goto fail;
}
-#ifdef SUPPORT_AEC
- if (u->aec_enable) {
- card = "Loopback";
- device = "0,0";
- }
-#endif
-
ret = pa_hal_interface_pcm_open(u->hal_interface,
- card,
- device,
+ u->card,
+ u->device,
DIRECTION_OUT,
&sample_spec,
u->frag_size / frame_size,
u->write_count = 0;
u->first = true;
- pa_log_info("Resumed successfully...device(%s:%s)", card, device);
+ pa_log_info("Resumed successfully...");
return 0;
*((pa_usec_t*)data) = latency;
return 0;
}
-#ifdef SUPPORT_AEC
- case PA_SINK_MESSAGE_SET_AEC_STATE: {
- pa_sink *s = PA_SINK(o);
- bool enable = (bool)data;
-
- if (u->aec_enable == enable)
- return 0;
-
- pa_log_info("AEC enable(%d)", enable);
-
- u->aec_enable = enable;
- if (s->thread_info.state == PA_SINK_RUNNING) {
- suspend(u);
- unsuspend(u);
- }
-
- return 0;
- }
- case PA_SINK_MESSAGE_GET_AEC_PARAMS: {
- aec_params_t *params = (aec_params_t *)data;
- params->rate = u->ss.rate;
- params->channels = u->ss.channels;
- params->format = u->ss.format;
- params->frag_size = u->frag_size;
- params->nfrags = u->nfrags;
- snprintf(params->card, DEVICE_NAME_MAX, "%s", u->card);
- snprintf(params->device, DEVICE_NAME_MAX, "%s", u->device);
- return 0;
- }
-#endif
}
return pa_sink_process_msg(o, code, data, offset, chunk);
u->first = true;
u->hal_interface = pa_hal_interface_get(u->core);
u->rtpoll = pa_rtpoll_new();
-#ifdef SUPPORT_AEC
- u->ss = ss;
-#endif
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
if (!(modarg_device = pa_modargs_get_value(ma, "device", NULL))) {
#include "hal-interface.h"
-#ifdef SUPPORT_AEC
-#include "aec-manager.h"
-#endif
-
PA_MODULE_AUTHOR("Tizen");
PA_MODULE_DESCRIPTION("Tizen Audio Source");
PA_MODULE_VERSION(PACKAGE_VERSION);
#define DEVICE_NAME_MAX 30
-#ifdef SUPPORT_AEC
-enum {
- PA_SOURCE_MESSAGE_SET_AEC_STATE = PA_SOURCE_MESSAGE_MAX,
- PA_SOURCE_MESSAGE_GET_AEC_PARAMS,
-};
-#endif
-
struct userdata {
pa_core *core;
pa_module *module;
uint64_t read_count;
pa_usec_t latency_time;
pa_hal_interface *hal_interface;
-
-#ifdef SUPPORT_AEC
- bool aec_enable;
- pa_sample_spec ss;
-#endif
};
static const char* const valid_modargs[] = {
u->rtpoll_item = NULL;
}
- pa_log_info("Device suspended...");
+ pa_log_info("Device suspended...[%s,%s]", u->card, u->device);
return 0;
}
int32_t ret;
size_t frame_size;
- char *card = u->card;
- char *device = u->device;
-
pa_assert(u);
pa_assert(!u->pcm_handle);
goto fail;
}
-#ifdef SUPPORT_AEC
- if (u->aec_enable) {
- card = "Loopback";
- device = "1,1";
- }
-#endif
-
ret = pa_hal_interface_pcm_open(u->hal_interface,
- card,
- device,
+ u->card,
+ u->device,
DIRECTION_IN,
&sample_spec,
u->frag_size / frame_size,
u->read_count = 0;
u->first = true;
- pa_log_info("Resumed successfully...device(%s:%s)", card, device);
+ pa_log_info("Resumed successfully...");
return 0;
*((pa_usec_t*)data) = u->timestamp > now ? 0ULL : now - u->timestamp;
return 0;
}
-#ifdef SUPPORT_AEC
- case PA_SOURCE_MESSAGE_SET_AEC_STATE: {
- pa_source *s = PA_SOURCE(o);
- bool enable = (bool)data;
-
- if (u->aec_enable == enable)
- return 0;
-
- pa_log_info("AEC enable(%d)", enable);
-
- u->aec_enable = enable;
- if (s->thread_info.state == PA_SOURCE_RUNNING) {
- suspend(u);
- unsuspend(u);
- }
-
- return 0;
- }
- case PA_SOURCE_MESSAGE_GET_AEC_PARAMS: {
- aec_params_t *params = (aec_params_t *)data;
- params->rate = u->ss.rate;
- params->channels = u->ss.channels;
- params->format = u->ss.format;
- params->frag_size = u->frag_size;
- params->nfrags = u->nfrags;
- snprintf(params->card, DEVICE_NAME_MAX, "%s", u->card);
- snprintf(params->device, DEVICE_NAME_MAX, "%s", u->device);
- return 0;
- }
-#endif
}
return pa_source_process_msg(o, code, data, offset, chunk);
u->first = true;
u->hal_interface = pa_hal_interface_get(u->core);
u->rtpoll = pa_rtpoll_new();
-#ifdef SUPPORT_AEC
- u->ss = ss;
-#endif
pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
if (!(modarg_device = pa_modargs_get_value(ma, "device", NULL))) {