summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2018-07-18 10:30:17 +0300
committerGeorge Kiagiadakis <george.kiagiadakis@collabora.com>2018-08-28 12:14:08 +0300
commit30dc02f090dfb68e874297ea8b9c88e41a9d9428 (patch)
treea426ce25b6b95d4e1e1e9d24e00ef5d3982865eb
parent699e0ab7dd2ff86192e92d038ca0d008ec0bfb34 (diff)
switch to using a unix socket with afb-proto-ws
Change-Id: I58861247f7ca23be9cf05d2055d948713547e3d5 Signed-off-by: George Kiagiadakis <george.kiagiadakis@collabora.com>
-rw-r--r--m4a_afb_comm.c274
-rw-r--r--m4a_afb_comm.h12
-rw-r--r--module-4a-client.c85
3 files changed, 154 insertions, 217 deletions
diff --git a/m4a_afb_comm.c b/m4a_afb_comm.c
index 63b8d61..30e1521 100644
--- a/m4a_afb_comm.c
+++ b/m4a_afb_comm.c
@@ -24,6 +24,8 @@
#include "m4a_afb_comm.h"
+#define _GNU_SOURCE
+#include <stdio.h>
#include <errno.h>
#include <unistd.h>
@@ -33,40 +35,30 @@
#include <pulse/xmalloc.h>
#include <systemd/sd-event.h>
-#include <afb/afb-wsj1.h>
+#include <afb/afb-proto-ws.h>
#include <afb/afb-ws-client.h>
-typedef struct _m4a_ws_comm_pipe_data m4a_ws_comm_pipe_data;
-typedef struct _m4a_afb_api_call_data m4a_afb_api_call_data;
-
-enum m4a_ws_comm_pipe_opcode {
+enum m4a_internal_pipe_opcode {
OPCODE_CALL_ASYNC = 1,
OPCODE_EXIT
};
-struct _m4a_ws_comm_pipe_data {
- enum m4a_ws_comm_pipe_opcode opcode;
- void *data;
-};
-
-struct _m4a_afb_comm {
- struct afb_wsj1 *wsj1;
-
- pa_thread *thread;
- sd_event *loop;
- int pipe[2];
- sd_event_source *source;
+typedef struct _m4a_internal_pipe_data m4a_internal_pipe_data;
+typedef struct _m4a_afb_api_call_data m4a_afb_api_call_data;
- pa_mutex *pending_calls_lock;
- PA_LLIST_HEAD(m4a_afb_api_call_data, pending_calls);
+/* structure sent over the internal pipe
+ * for communication between the two threads */
+struct _m4a_internal_pipe_data {
+ enum m4a_internal_pipe_opcode opcode;
+ void *data;
};
+/* structure holding data related to an ongoing AFB API call */
struct _m4a_afb_api_call_data {
m4a_afb_comm *comm;
- const char *api;
const char *verb;
- char *object;
+ json_object *object;
m4a_afb_done_cb_t done_cb;
void *userdata;
@@ -74,9 +66,30 @@ struct _m4a_afb_api_call_data {
PA_LLIST_FIELDS(m4a_afb_api_call_data);
};
-static void afb_api_call_data_free(m4a_afb_api_call_data *c) {
+/* the main structure of this class */
+struct _m4a_afb_comm {
+ struct afb_proto_ws *afbhandle;
+
+ char *sessid;
+
+ /* the thread that runs the loop below */
+ pa_thread *thread;
+ /* our internal event loop */
+ sd_event *loop;
+ /* the pipe fd pair used to send commands from
+ * the pulse threads to our internal thread */
+ int tx_pipe[2];
+ /* the source for listening to the above pipe from our event loop */
+ sd_event_source *tx_source;
+
+ /* a list of pending API calls, protected with a mutex */
+ pa_mutex *pending_calls_lock;
+ PA_LLIST_HEAD(m4a_afb_api_call_data, pending_calls);
+};
+
+static void m4a_afb_api_call_data_free(m4a_afb_api_call_data *c) {
if (c->object)
- pa_xfree(c->object);
+ json_object_put(c->object);
pa_mutex_lock(c->comm->pending_calls_lock);
PA_LLIST_REMOVE(m4a_afb_api_call_data, c->comm->pending_calls, c);
@@ -85,101 +98,30 @@ static void afb_api_call_data_free(m4a_afb_api_call_data *c) {
pa_xfree(c);
}
-static void afb_call_async_step3(void *cb_data, struct afb_wsj1_msg *msg) {
- m4a_afb_api_call_data *c = cb_data;
- pa_json_object *j;
- const pa_json_object *jr = NULL;
-
- j = pa_json_parse(afb_wsj1_msg_object_s(msg));
- if (pa_json_object_get_type(j) != PA_JSON_TYPE_OBJECT) {
- pa_log_warn("4a reply is not a json object");
- } else if (afb_wsj1_msg_is_reply_ok(msg)) {
- jr = pa_json_object_get_object_member(j, "response");
- } else {
- jr = pa_json_object_get_object_member(j, "request");
- }
-
- if (afb_wsj1_msg_is_reply_ok(msg)) {
- pa_log_debug("Got OK reply from 4a in call to %s/%s", c->api, c->verb);
- c->done_cb(M4A_AFB_REPLY_OK, jr, c->userdata);
- } else if (jr && pa_json_object_get_type(jr) == PA_JSON_TYPE_OBJECT) {
- const pa_json_object *status, *info;
- const char *status_str, *info_str;
+static void m4a_afb_on_reply(void *ctx, void *handle, json_object *response,
+ const char *error, const char *info) {
+ m4a_afb_api_call_data *c = handle;
- status = pa_json_object_get_object_member(jr, "status");
- info = pa_json_object_get_object_member(jr, "info");
-
- if (status && pa_json_object_get_type(status) == PA_JSON_TYPE_STRING)
- status_str = pa_json_object_get_string(status);
- else
- status_str = "(null)";
-
- if (info && pa_json_object_get_type(info) == PA_JSON_TYPE_STRING)
- info_str = pa_json_object_get_string(info);
- else
- info_str = "(null)";
-
- pa_log("Got error reply from 4a, status: '%s', info: '%s'", status_str, info_str);
- c->done_cb(M4A_AFB_REPLY_ERROR, jr, c->userdata);
- } else {
- pa_log("Got error reply from 4a");
- c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
- }
-
- pa_json_object_free(j);
- afb_api_call_data_free(c);
-}
-
-static void afb_call_async_step2(m4a_afb_api_call_data *c) {
- pa_log_debug("calling afb: %s/%s", c->api, c->verb);
-
- if (afb_wsj1_call_s(c->comm->wsj1, c->api, c->verb, c->object, afb_call_async_step3, c) < 0) {
- pa_log("afb_wsj1_call_s: failed to call %s/%s: %s", c->api, c->verb, strerror(errno));
- c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
- afb_api_call_data_free(c);
- }
-}
-
-static void discard_pending_calls(m4a_afb_comm *comm) {
- m4a_afb_api_call_data *c;
-
- pa_mutex_lock(comm->pending_calls_lock);
- while ((c = comm->pending_calls)) {
+ if (error) {
+ pa_log("Got error reply from 4a: %s", error);
c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
- afb_api_call_data_free(c);
+ } else {
+ pa_log_debug("Got OK reply from 4a in call to %s", c->verb);
+ c->done_cb(M4A_AFB_REPLY_OK, response, c->userdata);
}
- pa_mutex_unlock(comm->pending_calls_lock);
-}
-
-static void on_wsj1_hangup(void *closure, struct afb_wsj1 *wsj1) {
- m4a_afb_comm *comm = closure;
-
- pa_log_warn("afb closed the communication websocket!");
- discard_pending_calls(comm);
-
- //TODO: attempt to re-connect
-}
-static void on_wsj1_call(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg) {
- /* we don't implement any method calls */
- afb_wsj1_reply_error_s(msg, "\"unimplemented\"", NULL);
+ m4a_afb_api_call_data_free(c);
}
-static void on_wsj1_event(void *closure, const char *event, struct afb_wsj1_msg *msg) {
- //TODO dispatch events
-}
-
-static struct afb_wsj1_itf wsj1_itf = {
- .on_hangup = on_wsj1_hangup,
- .on_call = on_wsj1_call,
- .on_event = on_wsj1_event
+static struct afb_proto_ws_client_itf itf = {
+ .on_reply = m4a_afb_on_reply
};
-static int ws_comm_thread_event(sd_event_source *s, int fd, uint32_t revents, m4a_afb_comm *comm) {
+static int internal_thread_event(sd_event_source *s, int fd, uint32_t revents, m4a_afb_comm *comm) {
ssize_t r;
- m4a_ws_comm_pipe_data d = { 0 };
+ m4a_internal_pipe_data d = { 0 };
- if ((r = read(fd, &d, sizeof(m4a_ws_comm_pipe_data))) < (ssize_t) sizeof(m4a_ws_comm_pipe_data)) {
+ if ((r = read(fd, &d, sizeof(m4a_internal_pipe_data))) < (ssize_t) sizeof(m4a_internal_pipe_data)) {
if (errno == EINTR)
return 0;
@@ -190,7 +132,14 @@ static int ws_comm_thread_event(sd_event_source *s, int fd, uint32_t revents, m4
switch(d.opcode) {
case OPCODE_CALL_ASYNC: {
m4a_afb_api_call_data *c = d.data;
- afb_call_async_step2(c);
+
+ if (afb_proto_ws_client_call(c->comm->afbhandle, c->verb, c->object,
+ c->comm->sessid, c, NULL) < 0) {
+ pa_log("afb_proto_ws_client_call: failed to call %s: %s",
+ c->verb, strerror(errno));
+ c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
+ m4a_afb_api_call_data_free(c);
+ }
break;
}
case OPCODE_EXIT:
@@ -203,24 +152,24 @@ static int ws_comm_thread_event(sd_event_source *s, int fd, uint32_t revents, m4
return 0;
}
-static void ws_comm_thread(m4a_afb_comm *comm) {
- pa_log_debug("websocket thread starting...");
+static void internal_thread(m4a_afb_comm *comm) {
+ pa_log_debug("afb comm thread starting...");
sd_event_loop(comm->loop);
- pa_log_debug("websocket thread exiting...");
+ pa_log_debug("afb comm thread exiting...");
}
-static bool ws_comm_thread_send(int fd, char opcode, void *data) {
- m4a_ws_comm_pipe_data d;
+static bool internal_thread_send(m4a_afb_comm *comm, char opcode, void *data) {
+ m4a_internal_pipe_data d;
ssize_t ret;
d.opcode = opcode;
d.data = data;
do {
- ret = write(fd, &d, sizeof(m4a_ws_comm_pipe_data));
+ ret = write(comm->tx_pipe[1], &d, sizeof(m4a_internal_pipe_data));
} while (ret < 0 && errno == EINTR);
- if (ret < (ssize_t) sizeof(m4a_ws_comm_pipe_data)) {
+ if (ret < (ssize_t) sizeof(m4a_internal_pipe_data)) {
pa_log("write: %s", strerror(errno));
return false;
}
@@ -228,58 +177,36 @@ static bool ws_comm_thread_send(int fd, char opcode, void *data) {
return true;
}
-bool m4a_afb_call_async(m4a_afb_comm *comm, const char *api, const char *verb,
- char *object, m4a_afb_done_cb_t done_cb, void *userdata) {
- m4a_afb_api_call_data *c;
-
- c = pa_xnew0(m4a_afb_api_call_data, 1);
- c->comm = comm;
- c->api = api;
- c->verb = verb;
- c->object = object;
- c->done_cb = done_cb;
- c->userdata = userdata;
-
- pa_mutex_lock(comm->pending_calls_lock);
- PA_LLIST_PREPEND(m4a_afb_api_call_data, comm->pending_calls, c);
- pa_mutex_unlock(comm->pending_calls_lock);
-
- if (!ws_comm_thread_send(comm->pipe[1], OPCODE_CALL_ASYNC, c)) {
- c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
- afb_api_call_data_free(c);
- return false;
- }
- return true;
-}
-
m4a_afb_comm *m4a_afb_comm_new(const char *uri) {
int ret;
m4a_afb_comm *comm;
comm = pa_xnew0(m4a_afb_comm, 1);
+ asprintf(&comm->sessid, "pulseaudio:%d", getpid());
if ((ret = sd_event_new(&comm->loop)) < 0) {
pa_log("Failed to create systemd event loop: %s", strerror(-ret));
goto fail;
}
- if (!(comm->wsj1 = afb_ws_client_connect_wsj1(comm->loop, uri, &wsj1_itf, comm))) {
+ if (!(comm->afbhandle = afb_ws_client_connect_api(comm->loop, uri, &itf, comm))) {
pa_log("Connection to %s failed: %s", uri, strerror(errno));
goto fail;
}
- if (pipe(comm->pipe) < 0) {
- pa_log("pipe2 failed: %s", strerror(errno));
+ if (pipe(comm->tx_pipe) < 0) {
+ pa_log("pipe failed: %s", strerror(errno));
goto fail;
}
- if ((ret = sd_event_add_io(comm->loop, &comm->source, comm->pipe[0], EPOLLIN,
- (sd_event_io_handler_t) ws_comm_thread_event, comm)) < 0) {
+ if ((ret = sd_event_add_io(comm->loop, &comm->tx_source, comm->tx_pipe[0], EPOLLIN,
+ (sd_event_io_handler_t) internal_thread_event, comm)) < 0) {
pa_log("sd_event_add_io failed: %s", strerror(-ret));
goto fail;
}
- if (!(comm->thread = pa_thread_new("afb_comm_loop", (pa_thread_func_t) ws_comm_thread, comm))) {
+ if (!(comm->thread = pa_thread_new("m4a_afb_comm_internal_thread",
+ (pa_thread_func_t) internal_thread, comm))) {
pa_log("Failed to start websocket communication thread");
goto fail;
}
@@ -296,32 +223,69 @@ fail:
return NULL;
}
+
+static void discard_pending_calls(m4a_afb_comm *comm) {
+ m4a_afb_api_call_data *c;
+
+ pa_mutex_lock(comm->pending_calls_lock);
+ while ((c = comm->pending_calls)) {
+ c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
+ m4a_afb_api_call_data_free(c);
+ }
+ pa_mutex_unlock(comm->pending_calls_lock);
+}
+
void m4a_afb_comm_free(m4a_afb_comm *comm) {
if (comm->thread) {
- if (!ws_comm_thread_send(comm->pipe[1], OPCODE_EXIT, NULL)) {
+ if (!internal_thread_send(comm, OPCODE_EXIT, NULL)) {
pa_log("failed to shutdown thread gracefully");
pa_thread_free_nojoin(comm->thread);
} else {
pa_thread_free(comm->thread);
}
}
- if (comm->source)
- sd_event_source_unref(comm->source);
+ if (comm->tx_source)
+ sd_event_source_unref(comm->tx_source);
if (comm->loop)
sd_event_unref(comm->loop);
- if (comm->wsj1)
- afb_wsj1_unref(comm->wsj1);
+ if (comm->afbhandle)
+ afb_proto_ws_unref(comm->afbhandle);
if (comm->pending_calls_lock) {
discard_pending_calls(comm);
pa_mutex_free(comm->pending_calls_lock);
}
- if (comm->pipe[0] > 0)
- close(comm->pipe[0]);
- if (comm->pipe[1] > 0)
- close(comm->pipe[1]);
+ if (comm->tx_pipe[0] > 0)
+ close(comm->tx_pipe[0]);
+ if (comm->tx_pipe[1] > 0)
+ close(comm->tx_pipe[1]);
+ free(comm->sessid);
pa_xfree(comm);
}
+
+bool m4a_afb_call_async(m4a_afb_comm *comm, const char *verb,
+ json_object *object, m4a_afb_done_cb_t done_cb,
+ void *userdata) {
+ m4a_afb_api_call_data *c;
+
+ c = pa_xnew0(m4a_afb_api_call_data, 1);
+ c->comm = comm;
+ c->verb = verb;
+ c->object = object;
+ c->done_cb = done_cb;
+ c->userdata = userdata;
+
+ pa_mutex_lock(comm->pending_calls_lock);
+ PA_LLIST_PREPEND(m4a_afb_api_call_data, comm->pending_calls, c);
+ pa_mutex_unlock(comm->pending_calls_lock);
+
+ if (!internal_thread_send(comm, OPCODE_CALL_ASYNC, c)) {
+ c->done_cb(M4A_AFB_REPLY_ERROR, NULL, c->userdata);
+ m4a_afb_api_call_data_free(c);
+ return false;
+ }
+ return true;
+}
diff --git a/m4a_afb_comm.h b/m4a_afb_comm.h
index 7760bf9..7b072a2 100644
--- a/m4a_afb_comm.h
+++ b/m4a_afb_comm.h
@@ -21,7 +21,8 @@
#ifndef __M4A_AFB_COMM_H__
#define __M4A_AFB_COMM_H__
-#include <pulse/json.h>
+#include <stdbool.h>
+#include <json-c/json.h>
typedef struct _m4a_afb_comm m4a_afb_comm;
@@ -31,11 +32,14 @@ enum m4a_afb_reply {
};
typedef void (*m4a_afb_done_cb_t)(enum m4a_afb_reply r,
- const pa_json_object *response,
+ json_object *response,
void *userdata);
-bool m4a_afb_call_async(m4a_afb_comm *comm, const char *api, const char *verb,
- char *object, m4a_afb_done_cb_t done_cb, void *userdata);
+bool m4a_afb_call_async(m4a_afb_comm *comm,
+ const char *verb,
+ json_object *object,
+ m4a_afb_done_cb_t done_cb,
+ void *userdata);
m4a_afb_comm *m4a_afb_comm_new(const char *uri);
void m4a_afb_comm_free(m4a_afb_comm *comm);
diff --git a/module-4a-client.c b/module-4a-client.c
index 64502c8..9eda2fa 100644
--- a/module-4a-client.c
+++ b/module-4a-client.c
@@ -34,8 +34,7 @@
#include "m4a_afb_comm.h"
-#define DEFAULT_URI "ws://localhost:1234/api?token="
-#define AHL_4A_API "ahl-4a"
+#define DEFAULT_URI "sd:ahl-4a"
PA_MODULE_AUTHOR("George Kiagiadakis");
PA_MODULE_DESCRIPTION("Makes PulseAudio work as a client of the AGL Advanced Audio Architecture");
@@ -78,13 +77,9 @@ typedef struct {
/* operational data */
pa_mutex *lock;
- bool null_sink_loaded;
- uint32_t null_sink_id;
- uint32_t null_sink_module_id;
pa_dynarray *roles; /* element-type: char* */
PA_LLIST_HEAD(m4a_stream, streams);
pa_hook_slot
- *sink_input_new_slot,
*sink_input_put_slot,
*sink_input_unlink_post_slot;
m4a_afb_comm *comm;
@@ -146,21 +141,21 @@ static pa_sink *load_sink_module(pa_core *core, const char *module, char *params
/* invoked in the afb communication thread */
static void got_roles_cb(enum m4a_afb_reply r,
- const pa_json_object *response,
+ json_object *response,
pa_module *self) {
m4a_data *d = self->userdata;
int length, i;
- const pa_json_object *jr;
+ json_object *jr;
char *role;
pa_mutex_lock(d->lock);
- if (r == M4A_AFB_REPLY_OK && pa_json_object_get_type(response) == PA_JSON_TYPE_ARRAY) {
- length = pa_json_object_get_array_length(response);
+ if (r == M4A_AFB_REPLY_OK && json_object_get_type(response) == json_type_array) {
+ length = json_object_array_length(response);
for (i = 0; i < length; i++) {
- jr = pa_json_object_get_array_member(response, i);
- if (pa_json_object_get_type(jr) == PA_JSON_TYPE_STRING) {
- role = pa_xstrdup(pa_json_object_get_string(jr));
+ jr = json_object_array_get_idx(response, i);
+ if (json_object_get_type(jr) == json_type_string) {
+ role = pa_xstrdup(json_object_get_string(jr));
pa_log_debug("Found 4a role: %s", role);
pa_dynarray_append(d->roles, role);
}
@@ -201,35 +196,18 @@ static void m4a_stream_free(m4a_stream *stream) {
pa_xfree(stream);
}
-static pa_hook_result_t sink_input_new_cb(pa_core *core,
- pa_sink_input *i,
- pa_module *self) {
- m4a_data *d = self->userdata;
- pa_sink *sink;
-
- pa_core_assert_ref(core);
-
- /* first, forcibly set the sink to be our null sink */
- sink = pa_idxset_get_by_index(core->sinks, d->null_sink_id);
- if (sink) {
- i->sink = sink;
- i->sink_requested_by_application = false;
- }
-
- return PA_HOOK_OK;
-}
-
/* invoked in the afb communication thread */
static void device_open_cb(enum m4a_afb_reply r,
- const pa_json_object *response,
+ json_object *response,
m4a_stream *stream) {
- const pa_json_object *jdu;
+ json_object *jdu;
const char *device_uri = NULL;
- if (r == M4A_AFB_REPLY_OK && pa_json_object_get_type(response) == PA_JSON_TYPE_OBJECT) {
- jdu = pa_json_object_get_object_member(response, "device_uri");
- if (jdu && pa_json_object_get_type(jdu) == PA_JSON_TYPE_STRING) {
- device_uri = pa_json_object_get_string(jdu);
+ if (r == M4A_AFB_REPLY_OK && json_object_get_type(response) == json_type_object) {
+ json_object_object_get_ex(response, "device_uri", &jdu);
+ if (json_object_object_get_ex(response, "device_uri", &jdu) &&
+ json_object_get_type(jdu) == json_type_string) {
+ device_uri = json_object_get_string(jdu);
}
}
@@ -245,6 +223,7 @@ static pa_hook_result_t sink_input_put_cb(pa_core *core,
pa_sink_input *i,
pa_module *self) {
m4a_data *d = self->userdata;
+ json_object *jparams;
char *role;
pa_mutex_lock(d->lock);
@@ -260,8 +239,10 @@ static pa_hook_result_t sink_input_put_cb(pa_core *core,
pa_log_debug("Calling 4A to open the device");
- m4a_afb_call_async(d->comm, AHL_4A_API, role,
- pa_xstrdup("{\"action\":\"open\"}"),
+ jparams = json_object_new_object();
+ json_object_object_add(jparams, "action", json_object_new_string("open"));
+
+ m4a_afb_call_async(d->comm, role, jparams,
(m4a_afb_done_cb_t) device_open_cb, stream);
pa_log_debug("waiting for 4A to reply");
@@ -298,7 +279,7 @@ static pa_hook_result_t sink_input_put_cb(pa_core *core,
/* invoked in the afb communication thread */
static void device_close_cb(enum m4a_afb_reply r,
- const pa_json_object *response,
+ json_object *response,
m4a_stream *stream) {
pa_log_debug("4A replied: %s",
(r == M4A_AFB_REPLY_OK) ? "OK" : "ERROR");
@@ -310,6 +291,7 @@ static pa_hook_result_t sink_input_unlink_post_cb(pa_core *core,
pa_module *self) {
m4a_data *d = self->userdata;
m4a_stream *stream = NULL;
+ json_object *jparams;
PA_LLIST_FOREACH(stream, d->streams) {
if (stream->sink_input == i)
@@ -323,8 +305,10 @@ static pa_hook_result_t sink_input_unlink_post_cb(pa_core *core,
stream->entity_module_id, false);
stream->entity_loaded = false;
- m4a_afb_call_async(d->comm, AHL_4A_API, stream->role,
- pa_xstrdup("{\"action\":\"close\"}"),
+ jparams = json_object_new_object();
+ json_object_object_add(jparams, "action", json_object_new_string("close"));
+
+ m4a_afb_call_async(d->comm, stream->role, jparams,
(m4a_afb_done_cb_t) device_close_cb, stream);
}
@@ -334,7 +318,6 @@ static pa_hook_result_t sink_input_unlink_post_cb(pa_core *core,
int pa__init(pa_module *self) {
m4a_data *d;
const char *uri;
- pa_sink *null_sink;
pa_assert(self);
@@ -352,20 +335,11 @@ int pa__init(pa_module *self) {
goto fail;
}
- if (!m4a_afb_call_async(d->comm, AHL_4A_API, "get_roles", NULL,
+ if (!m4a_afb_call_async(d->comm, "get_roles", NULL,
(m4a_afb_done_cb_t) got_roles_cb, self)) {
goto fail;
}
- null_sink = load_sink_module(self->core, "module-null-sink", pa_sprintf_malloc(
- "sink_name=aaaa_null_sink sink_properties='device.description=\"%s\"'",
- _("4A Null Output")));
- d->null_sink_id = null_sink->index;
- d->null_sink_module_id = null_sink->module->index;
- d->null_sink_loaded = true;
-
- d->sink_input_new_slot = pa_hook_connect(&self->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW],
- PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_new_cb, self);
d->sink_input_put_slot = pa_hook_connect(&self->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT],
PA_HOOK_NORMAL, (pa_hook_cb_t) sink_input_put_cb, self);
d->sink_input_unlink_post_slot = pa_hook_connect(&self->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK_POST],
@@ -393,16 +367,11 @@ void pa__done(pa_module *self) {
if (d->ma)
pa_modargs_free(d->ma);
- if (d->sink_input_new_slot)
- pa_hook_slot_free(d->sink_input_new_slot);
if (d->sink_input_put_slot)
pa_hook_slot_free(d->sink_input_put_slot);
if (d->sink_input_unlink_post_slot)
pa_hook_slot_free(d->sink_input_unlink_post_slot);
- if (d->null_sink_loaded)
- pa_module_unload_request_by_index(self->core, d->null_sink_module_id, false);
-
if (d->comm)
m4a_afb_comm_free(d->comm);
}