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>
30 #include <pulse/fork-detect.h>
31 #include <pulse/operation.h>
33 #include <pulsecore/macro.h>
34 #include <pulsecore/pstream-util.h>
37 #include "ext-device-manager.h"
44 SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
,
50 static void ext_device_manager_test_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
51 pa_operation
*o
= userdata
;
52 uint32_t version
= PA_INVALID_INDEX
;
56 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
61 if (command
!= PA_COMMAND_REPLY
) {
62 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
65 } else if (pa_tagstruct_getu32(t
, &version
) < 0 ||
66 !pa_tagstruct_eof(t
)) {
68 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
73 pa_ext_device_manager_test_cb_t cb
= (pa_ext_device_manager_test_cb_t
) o
->callback
;
74 cb(o
->context
, version
, o
->userdata
);
79 pa_operation_unref(o
);
82 pa_operation
*pa_ext_device_manager_test(
84 pa_ext_device_manager_test_cb_t cb
,
92 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
94 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
95 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
96 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
98 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
100 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
101 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
102 pa_tagstruct_puts(t
, "module-device-manager");
103 pa_tagstruct_putu32(t
, SUBCOMMAND_TEST
);
104 pa_pstream_send_tagstruct(c
->pstream
, t
);
105 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
);
110 static void ext_device_manager_read_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
111 pa_operation
*o
= userdata
;
116 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
121 if (command
!= PA_COMMAND_REPLY
) {
122 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
128 while (!pa_tagstruct_eof(t
)) {
129 pa_ext_device_manager_info i
;
131 memset(&i
, 0, sizeof(i
));
133 if (pa_tagstruct_gets(t
, &i
.name
) < 0 ||
134 pa_tagstruct_gets(t
, &i
.description
) < 0 ||
135 pa_tagstruct_gets(t
, &i
.icon
) < 0 ||
136 pa_tagstruct_getu32(t
, &i
.index
) < 0 ||
137 pa_tagstruct_getu32(t
, &i
.n_role_priorities
) < 0) {
139 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
143 if (i
.n_role_priorities
> 0) {
145 i
.role_priorities
= pa_xnew0(pa_ext_device_manager_role_priority_info
, i
.n_role_priorities
+1);
147 for (j
= 0; j
< i
.n_role_priorities
; j
++) {
149 if (pa_tagstruct_gets(t
, &i
.role_priorities
[j
].role
) < 0 ||
150 pa_tagstruct_getu32(t
, &i
.role_priorities
[j
].priority
) < 0) {
152 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
153 pa_xfree(i
.role_priorities
);
158 /* Terminate with an extra NULL entry, just to make sure */
159 i
.role_priorities
[j
].role
= NULL
;
160 i
.role_priorities
[j
].priority
= 0;
164 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
165 cb(o
->context
, &i
, 0, o
->userdata
);
168 pa_xfree(i
.role_priorities
);
173 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
174 cb(o
->context
, NULL
, eol
, o
->userdata
);
178 pa_operation_done(o
);
179 pa_operation_unref(o
);
182 pa_operation
*pa_ext_device_manager_read(
184 pa_ext_device_manager_read_cb_t cb
,
192 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
194 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
195 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
196 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
198 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
200 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
201 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
202 pa_tagstruct_puts(t
, "module-device-manager");
203 pa_tagstruct_putu32(t
, SUBCOMMAND_READ
);
204 pa_pstream_send_tagstruct(c
->pstream
, t
);
205 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
);
210 pa_operation
*pa_ext_device_manager_set_device_description(
213 const char* description
,
214 pa_context_success_cb_t cb
,
218 pa_operation
*o
= NULL
;
219 pa_tagstruct
*t
= NULL
;
222 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
224 pa_assert(description
);
226 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
227 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
228 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
230 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
232 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
233 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
234 pa_tagstruct_puts(t
, "module-device-manager");
235 pa_tagstruct_putu32(t
, SUBCOMMAND_RENAME
);
237 pa_tagstruct_puts(t
, device
);
238 pa_tagstruct_puts(t
, description
);
240 pa_pstream_send_tagstruct(c
->pstream
, t
);
241 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
);
246 pa_operation
*pa_ext_device_manager_delete(
248 const char *const s
[],
249 pa_context_success_cb_t cb
,
253 pa_operation
*o
= NULL
;
254 pa_tagstruct
*t
= NULL
;
255 const char *const *k
;
258 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
261 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
262 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
263 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
265 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
267 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
268 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
269 pa_tagstruct_puts(t
, "module-device-manager");
270 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
272 for (k
= s
; *k
; k
++) {
276 pa_tagstruct_puts(t
, *k
);
279 pa_pstream_send_tagstruct(c
->pstream
, t
);
280 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
);
286 pa_operation_cancel(o
);
287 pa_operation_unref(o
);
291 pa_tagstruct_free(t
);
293 pa_context_set_error(c
, PA_ERR_INVALID
);
297 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
300 pa_context_success_cb_t cb
,
304 pa_operation
*o
= NULL
;
305 pa_tagstruct
*t
= NULL
;
308 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
310 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
311 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
312 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
314 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
316 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
317 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
318 pa_tagstruct_puts(t
, "module-device-manager");
319 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
320 pa_tagstruct_put_boolean(t
, !!enable
);
322 pa_pstream_send_tagstruct(c
->pstream
, t
);
323 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
);
328 pa_operation
*pa_ext_device_manager_reorder_devices_for_role(
331 const char** devices
,
332 pa_context_success_cb_t cb
,
336 pa_operation
*o
= NULL
;
337 pa_tagstruct
*t
= NULL
;
340 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
342 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
343 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
344 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
349 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
351 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
352 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
353 pa_tagstruct_puts(t
, "module-device-manager");
354 pa_tagstruct_putu32(t
, SUBCOMMAND_REORDER
);
355 pa_tagstruct_puts(t
, role
);
357 i
= 0; while (devices
[i
]) i
++;
358 pa_tagstruct_putu32(t
, i
);
362 pa_tagstruct_puts(t
, devices
[i
++]);
364 pa_pstream_send_tagstruct(c
->pstream
, t
);
365 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
);
370 pa_operation
*pa_ext_device_manager_subscribe(
373 pa_context_success_cb_t cb
,
381 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
383 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
384 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
385 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
387 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
389 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
390 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
391 pa_tagstruct_puts(t
, "module-device-manager");
392 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
393 pa_tagstruct_put_boolean(t
, enable
);
394 pa_pstream_send_tagstruct(c
->pstream
, t
);
395 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
);
400 void pa_ext_device_manager_set_subscribe_cb(
402 pa_ext_device_manager_subscribe_cb_t cb
,
406 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
408 if (pa_detect_fork())
411 c
->ext_device_manager
.callback
= cb
;
412 c
->ext_device_manager
.userdata
= userdata
;
415 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
419 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
422 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
423 !pa_tagstruct_eof(t
)) {
425 pa_context_fail(c
, PA_ERR_PROTOCOL
);
429 if (subcommand
!= SUBCOMMAND_EVENT
) {
430 pa_context_fail(c
, PA_ERR_PROTOCOL
);
434 if (c
->ext_device_manager
.callback
)
435 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);