2 This file is part of PulseAudio.
4 Copyright 2012 Jaska Uimonen
5 Copyright 2012 Janos Kovacs
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <pulse/context.h>
28 #include <pulse/xmalloc.h>
29 #include <pulse/fork-detect.h>
30 #include <pulse/operation.h>
32 #include <pulsecore/macro.h>
33 #include <pulsecore/pstream-util.h>
36 #include "ext-node-manager.h"
42 SUBCOMMAND_DISCONNECT,
47 static void ext_node_manager_test_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
48 pa_operation *o = userdata;
49 uint32_t version = PA_INVALID_INDEX;
53 pa_assert(PA_REFCNT_VALUE(o) >= 1);
58 if (command != PA_COMMAND_REPLY) {
59 if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
62 } else if (pa_tagstruct_getu32(t, &version) < 0 ||
63 !pa_tagstruct_eof(t)) {
65 pa_context_fail(o->context, PA_ERR_PROTOCOL);
70 pa_ext_node_manager_test_cb_t cb = (pa_ext_node_manager_test_cb_t) o->callback;
71 cb(o->context, version, o->userdata);
76 pa_operation_unref(o);
79 pa_operation *pa_ext_node_manager_test(
81 pa_ext_node_manager_test_cb_t cb,
89 pa_assert(PA_REFCNT_VALUE(c) >= 1);
91 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
92 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
93 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
95 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
97 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
98 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
99 pa_tagstruct_puts(t, "module-murphy-ivi");
100 pa_tagstruct_putu32(t, SUBCOMMAND_TEST);
101 pa_pstream_send_tagstruct(c->pstream, t);
102 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_node_manager_test_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
107 static void ext_node_manager_read_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
108 pa_operation *o = userdata;
109 pa_ext_node_manager_info i;
113 pa_assert(PA_REFCNT_VALUE(o) >= 1);
118 if (command != PA_COMMAND_REPLY) {
119 if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
123 while (!pa_tagstruct_eof(t)) {
125 memset(&i, 0, sizeof(i));
127 i.props = pa_proplist_new();
129 if (pa_tagstruct_gets(t, &i.name) < 0 ||
130 pa_tagstruct_get_proplist(t, i.props) < 0) {
132 pa_context_fail(o->context, PA_ERR_PROTOCOL);
137 pa_ext_node_manager_read_cb_t cb = (pa_ext_node_manager_read_cb_t) o->callback;
138 cb(o->context, &i, 0, o->userdata);
141 pa_proplist_free(i.props);
144 /* let's send end marker */
146 pa_ext_node_manager_read_cb_t cb = (pa_ext_node_manager_read_cb_t) o->callback;
147 cb(o->context, &i, 1, o->userdata);
152 pa_operation_done(o);
153 pa_operation_unref(o);
156 pa_operation *pa_ext_node_manager_read_nodes(
158 pa_ext_node_manager_read_cb_t cb,
166 pa_assert(PA_REFCNT_VALUE(c) >= 1);
168 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
169 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
170 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
172 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
174 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
175 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
176 pa_tagstruct_puts(t, "module-murphy-ivi");
177 pa_tagstruct_putu32(t, SUBCOMMAND_READ);
178 pa_pstream_send_tagstruct(c->pstream, t);
179 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_node_manager_read_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
184 static void ext_node_manager_connect_cb(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
185 pa_operation *o = userdata;
186 uint32_t connection = PA_INVALID_INDEX;
190 pa_assert(PA_REFCNT_VALUE(o) >= 1);
195 if (command != PA_COMMAND_REPLY) {
196 if (pa_context_handle_error(o->context, command, t, FALSE) < 0)
199 } else if (pa_tagstruct_getu32(t, &connection) < 0 ||
200 !pa_tagstruct_eof(t)) {
202 pa_context_fail(o->context, PA_ERR_PROTOCOL);
207 pa_ext_node_manager_connect_cb_t cb = (pa_ext_node_manager_connect_cb_t) o->callback;
208 cb(o->context, connection, o->userdata);
212 pa_operation_done(o);
213 pa_operation_unref(o);
216 pa_operation *pa_ext_node_manager_connect_nodes(
218 uint32_t source_node_id,
219 uint32_t sink_node_id,
220 pa_ext_node_manager_connect_cb_t cb,
224 pa_operation *o = NULL;
225 pa_tagstruct *t = NULL;
228 pa_assert(PA_REFCNT_VALUE(c) >= 1);
230 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
231 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
232 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
234 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
236 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
237 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
238 pa_tagstruct_puts(t, "module-murphy-ivi");
239 pa_tagstruct_putu32(t, SUBCOMMAND_CONNECT);
241 pa_tagstruct_putu32(t, source_node_id);
242 pa_tagstruct_putu32(t, sink_node_id);
244 pa_pstream_send_tagstruct(c->pstream, t);
245 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, ext_node_manager_connect_cb, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
250 pa_operation *pa_ext_node_manager_disconnect_nodes(
253 pa_context_success_cb_t cb,
257 pa_operation *o = NULL;
258 pa_tagstruct *t = NULL;
261 pa_assert(PA_REFCNT_VALUE(c) >= 1);
263 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
264 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
265 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
267 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
269 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
270 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
271 pa_tagstruct_puts(t, "module-murphy-ivi");
272 pa_tagstruct_putu32(t, SUBCOMMAND_DISCONNECT);
274 pa_tagstruct_putu32(t, conn_id);
276 pa_pstream_send_tagstruct(c->pstream, t);
277 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
282 pa_operation *pa_ext_node_manager_subscribe(
285 pa_context_success_cb_t cb,
293 pa_assert(PA_REFCNT_VALUE(c) >= 1);
295 PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
296 PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
297 PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 14, PA_ERR_NOTSUPPORTED);
299 o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
301 t = pa_tagstruct_command(c, PA_COMMAND_EXTENSION, &tag);
302 pa_tagstruct_putu32(t, PA_INVALID_INDEX);
303 pa_tagstruct_puts(t, "module-murphy-ivi");
304 pa_tagstruct_putu32(t, SUBCOMMAND_SUBSCRIBE);
305 pa_tagstruct_put_boolean(t, enable);
306 pa_pstream_send_tagstruct(c->pstream, t);
307 pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
312 void pa_ext_node_manager_set_subscribe_cb(
314 pa_ext_node_manager_subscribe_cb_t cb,
318 pa_assert(PA_REFCNT_VALUE(c) >= 1);
320 if (pa_detect_fork())
323 c->ext_node_manager.callback = cb;
324 c->ext_node_manager.userdata = userdata;
327 void pa_ext_node_manager_command(pa_context *c, uint32_t tag, pa_tagstruct *t) {
331 pa_assert(PA_REFCNT_VALUE(c) >= 1);
334 if (pa_tagstruct_getu32(t, &subcommand) < 0 ||
335 !pa_tagstruct_eof(t)) {
337 pa_context_fail(c, PA_ERR_PROTOCOL);
341 if (subcommand != SUBCOMMAND_EVENT) {
342 pa_context_fail(c, PA_ERR_PROTOCOL);
346 if (c->ext_node_manager.callback)
347 c->ext_node_manager.callback(c, c->ext_node_manager.userdata);