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>
29 #include <pulse/xmalloc.h>
31 #include <pulsecore/macro.h>
32 #include <pulsecore/pstream-util.h>
35 #include "operation.h"
36 #include "fork-detect.h"
38 #include "ext-device-manager.h"
45 SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
,
51 static void ext_device_manager_test_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
52 pa_operation
*o
= userdata
;
53 uint32_t version
= PA_INVALID_INDEX
;
57 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
62 if (command
!= PA_COMMAND_REPLY
) {
63 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
66 } else if (pa_tagstruct_getu32(t
, &version
) < 0 ||
67 !pa_tagstruct_eof(t
)) {
69 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
74 pa_ext_device_manager_test_cb_t cb
= (pa_ext_device_manager_test_cb_t
) o
->callback
;
75 cb(o
->context
, version
, o
->userdata
);
80 pa_operation_unref(o
);
83 pa_operation
*pa_ext_device_manager_test(
85 pa_ext_device_manager_test_cb_t cb
,
93 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
95 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
96 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
97 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
99 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
101 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
102 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
103 pa_tagstruct_puts(t
, "module-device-manager");
104 pa_tagstruct_putu32(t
, SUBCOMMAND_TEST
);
105 pa_pstream_send_tagstruct(c
->pstream
, t
);
106 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
);
111 static void ext_device_manager_read_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
112 pa_operation
*o
= userdata
;
117 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
122 if (command
!= PA_COMMAND_REPLY
) {
123 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
129 while (!pa_tagstruct_eof(t
)) {
130 pa_ext_device_manager_info i
;
132 memset(&i
, 0, sizeof(i
));
134 if (pa_tagstruct_gets(t
, &i
.name
) < 0 ||
135 pa_tagstruct_gets(t
, &i
.description
) < 0 ||
136 pa_tagstruct_gets(t
, &i
.icon
) < 0 ||
137 pa_tagstruct_getu32(t
, &i
.index
) < 0 ||
138 pa_tagstruct_getu32(t
, &i
.n_role_priorities
) < 0) {
140 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
144 if (i
.n_role_priorities
> 0) {
146 i
.role_priorities
= pa_xnew0(pa_ext_device_manager_role_priority_info
, i
.n_role_priorities
+1);
148 for (j
= 0; j
< i
.n_role_priorities
; j
++) {
150 if (pa_tagstruct_gets(t
, &i
.role_priorities
[j
].role
) < 0 ||
151 pa_tagstruct_getu32(t
, &i
.role_priorities
[j
].priority
) < 0) {
153 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
154 pa_xfree(i
.role_priorities
);
159 /* Terminate with an extra NULL entry, just to make sure */
160 i
.role_priorities
[j
].role
= NULL
;
161 i
.role_priorities
[j
].priority
= 0;
165 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
166 cb(o
->context
, &i
, 0, o
->userdata
);
169 pa_xfree(i
.role_priorities
);
174 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
175 cb(o
->context
, NULL
, eol
, o
->userdata
);
179 pa_operation_done(o
);
180 pa_operation_unref(o
);
183 pa_operation
*pa_ext_device_manager_read(
185 pa_ext_device_manager_read_cb_t cb
,
193 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
195 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
196 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
197 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
199 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
201 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
202 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
203 pa_tagstruct_puts(t
, "module-device-manager");
204 pa_tagstruct_putu32(t
, SUBCOMMAND_READ
);
205 pa_pstream_send_tagstruct(c
->pstream
, t
);
206 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
);
211 pa_operation
*pa_ext_device_manager_set_device_description(
214 const char* description
,
215 pa_context_success_cb_t cb
,
219 pa_operation
*o
= NULL
;
220 pa_tagstruct
*t
= NULL
;
223 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
225 pa_assert(description
);
227 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
228 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
229 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
231 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
233 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
234 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
235 pa_tagstruct_puts(t
, "module-device-manager");
236 pa_tagstruct_putu32(t
, SUBCOMMAND_RENAME
);
238 pa_tagstruct_puts(t
, device
);
239 pa_tagstruct_puts(t
, description
);
241 pa_pstream_send_tagstruct(c
->pstream
, t
);
242 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
);
247 pa_operation
*pa_ext_device_manager_delete(
249 const char *const s
[],
250 pa_context_success_cb_t cb
,
254 pa_operation
*o
= NULL
;
255 pa_tagstruct
*t
= NULL
;
256 const char *const *k
;
259 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
262 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
263 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
264 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
266 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
268 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
269 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
270 pa_tagstruct_puts(t
, "module-device-manager");
271 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
273 for (k
= s
; *k
; k
++) {
277 pa_tagstruct_puts(t
, *k
);
280 pa_pstream_send_tagstruct(c
->pstream
, t
);
281 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
);
287 pa_operation_cancel(o
);
288 pa_operation_unref(o
);
292 pa_tagstruct_free(t
);
294 pa_context_set_error(c
, PA_ERR_INVALID
);
298 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
301 pa_context_success_cb_t cb
,
305 pa_operation
*o
= NULL
;
306 pa_tagstruct
*t
= NULL
;
309 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
311 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
312 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
313 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
315 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
317 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
318 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
319 pa_tagstruct_puts(t
, "module-device-manager");
320 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
321 pa_tagstruct_put_boolean(t
, !!enable
);
323 pa_pstream_send_tagstruct(c
->pstream
, t
);
324 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
);
329 pa_operation
*pa_ext_device_manager_reorder_devices_for_role(
332 const char** devices
,
333 pa_context_success_cb_t cb
,
337 pa_operation
*o
= NULL
;
338 pa_tagstruct
*t
= NULL
;
341 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
343 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
344 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
345 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
350 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
352 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
353 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
354 pa_tagstruct_puts(t
, "module-device-manager");
355 pa_tagstruct_putu32(t
, SUBCOMMAND_REORDER
);
356 pa_tagstruct_puts(t
, role
);
358 i
= 0; while (devices
[i
]) i
++;
359 pa_tagstruct_putu32(t
, i
);
363 pa_tagstruct_puts(t
, devices
[i
++]);
365 pa_pstream_send_tagstruct(c
->pstream
, t
);
366 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
);
371 pa_operation
*pa_ext_device_manager_subscribe(
374 pa_context_success_cb_t cb
,
382 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
384 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
385 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
386 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
388 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
390 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
391 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
392 pa_tagstruct_puts(t
, "module-device-manager");
393 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
394 pa_tagstruct_put_boolean(t
, enable
);
395 pa_pstream_send_tagstruct(c
->pstream
, t
);
396 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
);
401 void pa_ext_device_manager_set_subscribe_cb(
403 pa_ext_device_manager_subscribe_cb_t cb
,
407 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
409 if (pa_detect_fork())
412 c
->ext_device_manager
.callback
= cb
;
413 c
->ext_device_manager
.userdata
= userdata
;
416 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
420 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
423 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
424 !pa_tagstruct_eof(t
)) {
426 pa_context_fail(c
, PA_ERR_PROTOCOL
);
430 if (subcommand
!= SUBCOMMAND_EVENT
) {
431 pa_context_fail(c
, PA_ERR_PROTOCOL
);
435 if (c
->ext_device_manager
.callback
)
436 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);