2 This file is part of PulseAudio.
4 Copyright 2008 Lennart Poettering
5 Copyright 2009 Colin Guthrie
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/gccmacro.h>
30 #include <pulsecore/macro.h>
31 #include <pulsecore/pstream-util.h>
34 #include "operation.h"
35 #include "fork-detect.h"
37 #include "ext-device-manager.h"
44 SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
,
49 static void ext_device_manager_test_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
50 pa_operation
*o
= userdata
;
51 uint32_t version
= PA_INVALID_INDEX
;
55 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
60 if (command
!= PA_COMMAND_REPLY
) {
61 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
64 } else if (pa_tagstruct_getu32(t
, &version
) < 0 ||
65 !pa_tagstruct_eof(t
)) {
67 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
72 pa_ext_device_manager_test_cb_t cb
= (pa_ext_device_manager_test_cb_t
) o
->callback
;
73 cb(o
->context
, version
, o
->userdata
);
78 pa_operation_unref(o
);
81 pa_operation
*pa_ext_device_manager_test(
83 pa_ext_device_manager_test_cb_t cb
,
91 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
93 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
94 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
95 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
97 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
99 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
100 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
101 pa_tagstruct_puts(t
, "module-device-manager");
102 pa_tagstruct_putu32(t
, SUBCOMMAND_TEST
);
103 pa_pstream_send_tagstruct(c
->pstream
, t
);
104 pa_pdispatch_register_reply(c
->pdispatch
, tag
, DEFAULT_TIMEOUT
, ext_device_manager_test_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
109 static void ext_device_manager_read_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
110 pa_operation
*o
= userdata
;
115 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
120 if (command
!= PA_COMMAND_REPLY
) {
121 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
127 while (!pa_tagstruct_eof(t
)) {
128 pa_ext_device_manager_info i
;
130 memset(&i
, 0, sizeof(i
));
132 if (pa_tagstruct_gets(t
, &i
.name
) < 0 ||
133 pa_tagstruct_gets(t
, &i
.description
) < 0) {
135 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
140 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
141 cb(o
->context
, &i
, 0, o
->userdata
);
147 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
148 cb(o
->context
, NULL
, eol
, o
->userdata
);
152 pa_operation_done(o
);
153 pa_operation_unref(o
);
156 pa_operation
*pa_ext_device_manager_read(
158 pa_ext_device_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-device-manager");
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_device_manager_read_cb
, pa_operation_ref(o
), (pa_free_cb_t
) pa_operation_unref
);
184 pa_operation
*pa_ext_device_manager_write(
186 pa_update_mode_t mode
,
187 const pa_ext_device_manager_info data
[],
189 int apply_immediately
,
190 pa_context_success_cb_t cb
,
194 pa_operation
*o
= NULL
;
195 pa_tagstruct
*t
= NULL
;
198 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
199 pa_assert(mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
|| mode
== PA_UPDATE_SET
);
202 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
203 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
204 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
206 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
208 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
209 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
210 pa_tagstruct_puts(t
, "module-device-manager");
211 pa_tagstruct_putu32(t
, SUBCOMMAND_WRITE
);
213 pa_tagstruct_putu32(t
, mode
);
214 pa_tagstruct_put_boolean(t
, apply_immediately
);
216 for (; n
> 0; n
--, data
++) {
217 if (!data
->name
|| !*data
->name
)
220 pa_tagstruct_puts(t
, data
->name
);
221 pa_tagstruct_puts(t
, data
->description
);
224 pa_pstream_send_tagstruct(c
->pstream
, t
);
225 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
);
231 pa_operation_cancel(o
);
232 pa_operation_unref(o
);
236 pa_tagstruct_free(t
);
238 pa_context_set_error(c
, PA_ERR_INVALID
);
242 pa_operation
*pa_ext_device_manager_delete(
244 const char *const s
[],
245 pa_context_success_cb_t cb
,
249 pa_operation
*o
= NULL
;
250 pa_tagstruct
*t
= NULL
;
251 const char *const *k
;
254 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
257 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
258 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
259 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
261 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
263 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
264 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
265 pa_tagstruct_puts(t
, "module-device-manager");
266 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
268 for (k
= s
; *k
; k
++) {
272 pa_tagstruct_puts(t
, *k
);
275 pa_pstream_send_tagstruct(c
->pstream
, t
);
276 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_cancel(o
);
283 pa_operation_unref(o
);
287 pa_tagstruct_free(t
);
289 pa_context_set_error(c
, PA_ERR_INVALID
);
293 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
296 pa_context_success_cb_t cb
,
300 pa_operation
*o
= NULL
;
301 pa_tagstruct
*t
= NULL
;
304 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
306 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
307 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
308 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
310 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
312 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
313 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
314 pa_tagstruct_puts(t
, "module-device-manager");
315 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
316 pa_tagstruct_put_boolean(t
, !!enable
);
318 pa_pstream_send_tagstruct(c
->pstream
, t
);
319 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
);
324 pa_operation
*pa_ext_device_manager_subscribe(
327 pa_context_success_cb_t cb
,
335 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
337 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
338 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
339 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
341 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
343 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
344 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
345 pa_tagstruct_puts(t
, "module-device-manager");
346 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
347 pa_tagstruct_put_boolean(t
, enable
);
348 pa_pstream_send_tagstruct(c
->pstream
, t
);
349 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
);
354 void pa_ext_device_manager_set_subscribe_cb(
356 pa_ext_device_manager_subscribe_cb_t cb
,
360 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
362 if (pa_detect_fork())
365 c
->ext_device_manager
.callback
= cb
;
366 c
->ext_device_manager
.userdata
= userdata
;
369 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
373 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
376 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
377 !pa_tagstruct_eof(t
)) {
379 pa_context_fail(c
, PA_ERR_PROTOCOL
);
383 if (subcommand
!= SUBCOMMAND_EVENT
) {
384 pa_context_fail(c
, PA_ERR_PROTOCOL
);
388 if (c
->ext_device_manager
.callback
)
389 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);