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
,
46 SUBCOMMAND_PREFER_DEVICE
,
47 SUBCOMMAND_DEFER_DEVICE
,
52 static void ext_device_manager_test_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
53 pa_operation
*o
= userdata
;
54 uint32_t version
= PA_INVALID_INDEX
;
58 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
63 if (command
!= PA_COMMAND_REPLY
) {
64 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
67 } else if (pa_tagstruct_getu32(t
, &version
) < 0 ||
68 !pa_tagstruct_eof(t
)) {
70 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
75 pa_ext_device_manager_test_cb_t cb
= (pa_ext_device_manager_test_cb_t
) o
->callback
;
76 cb(o
->context
, version
, o
->userdata
);
81 pa_operation_unref(o
);
84 pa_operation
*pa_ext_device_manager_test(
86 pa_ext_device_manager_test_cb_t cb
,
94 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
96 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
97 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
98 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
100 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
102 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
103 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
104 pa_tagstruct_puts(t
, "module-device-manager");
105 pa_tagstruct_putu32(t
, SUBCOMMAND_TEST
);
106 pa_pstream_send_tagstruct(c
->pstream
, t
);
107 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
);
112 static void ext_device_manager_read_cb(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
113 pa_operation
*o
= userdata
;
118 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
123 if (command
!= PA_COMMAND_REPLY
) {
124 if (pa_context_handle_error(o
->context
, command
, t
, FALSE
) < 0)
130 while (!pa_tagstruct_eof(t
)) {
131 pa_ext_device_manager_info i
;
134 memset(&i
, 0, sizeof(i
));
137 if (pa_tagstruct_gets(t
, &i
.name
) < 0 ||
138 pa_tagstruct_gets(t
, &i
.description
) < 0 ||
139 pa_tagstruct_gets(t
, &i
.icon
) < 0 ||
140 pa_tagstruct_get_boolean(t
, &available
) < 0 ||
141 pa_tagstruct_getu32(t
, &i
.n_role_priorities
) < 0) {
143 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
146 i
.available
= (uint8_t)available
;
148 if (i
.n_role_priorities
> 0) {
150 i
.role_priorities
= pa_xnew0(pa_ext_device_manager_role_priority_info
, i
.n_role_priorities
+1);
152 for (j
= 0; j
< i
.n_role_priorities
; j
++) {
154 if (pa_tagstruct_gets(t
, &i
.role_priorities
[j
].role
) < 0 ||
155 pa_tagstruct_getu32(t
, &i
.role_priorities
[j
].priority
) < 0) {
157 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
158 pa_xfree(i
.role_priorities
);
163 /* Terminate with an extra NULL entry, just to make sure */
164 i
.role_priorities
[j
].role
= NULL
;
165 i
.role_priorities
[j
].priority
= 0;
169 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
170 cb(o
->context
, &i
, 0, o
->userdata
);
173 pa_xfree(i
.role_priorities
);
178 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
179 cb(o
->context
, NULL
, eol
, o
->userdata
);
183 pa_operation_done(o
);
184 pa_operation_unref(o
);
187 pa_operation
*pa_ext_device_manager_read(
189 pa_ext_device_manager_read_cb_t cb
,
197 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
199 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
200 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
201 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
203 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
205 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
206 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
207 pa_tagstruct_puts(t
, "module-device-manager");
208 pa_tagstruct_putu32(t
, SUBCOMMAND_READ
);
209 pa_pstream_send_tagstruct(c
->pstream
, t
);
210 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
);
215 pa_operation
*pa_ext_device_manager_set_device_description(
218 const char* description
,
219 pa_context_success_cb_t cb
,
223 pa_operation
*o
= NULL
;
224 pa_tagstruct
*t
= NULL
;
227 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
229 pa_assert(description
);
231 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
232 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
233 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
235 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
237 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
238 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
239 pa_tagstruct_puts(t
, "module-device-manager");
240 pa_tagstruct_putu32(t
, SUBCOMMAND_RENAME
);
242 pa_tagstruct_puts(t
, device
);
243 pa_tagstruct_puts(t
, description
);
245 pa_pstream_send_tagstruct(c
->pstream
, t
);
246 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
);
251 pa_operation
*pa_ext_device_manager_delete(
253 const char *const s
[],
254 pa_context_success_cb_t cb
,
258 pa_operation
*o
= NULL
;
259 pa_tagstruct
*t
= NULL
;
260 const char *const *k
;
263 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
266 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
267 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
268 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
270 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
272 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
273 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
274 pa_tagstruct_puts(t
, "module-device-manager");
275 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
277 for (k
= s
; *k
; k
++) {
281 pa_tagstruct_puts(t
, *k
);
284 pa_pstream_send_tagstruct(c
->pstream
, t
);
285 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
);
291 pa_operation_cancel(o
);
292 pa_operation_unref(o
);
296 pa_tagstruct_free(t
);
298 pa_context_set_error(c
, PA_ERR_INVALID
);
302 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
305 pa_context_success_cb_t cb
,
309 pa_operation
*o
= NULL
;
310 pa_tagstruct
*t
= NULL
;
313 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
315 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
316 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
317 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
319 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
321 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
322 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
323 pa_tagstruct_puts(t
, "module-device-manager");
324 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
325 pa_tagstruct_put_boolean(t
, !!enable
);
327 pa_pstream_send_tagstruct(c
->pstream
, t
);
328 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
);
333 pa_operation
*pa_ext_device_manager_prefer_device(
337 pa_context_success_cb_t cb
,
341 pa_operation
*o
= NULL
;
342 pa_tagstruct
*t
= NULL
;
345 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
347 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
348 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
349 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
354 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
356 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
357 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
358 pa_tagstruct_puts(t
, "module-device-manager");
359 pa_tagstruct_putu32(t
, SUBCOMMAND_PREFER_DEVICE
);
360 pa_tagstruct_puts(t
, role
);
361 pa_tagstruct_puts(t
, device
);
363 pa_pstream_send_tagstruct(c
->pstream
, t
);
364 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
);
369 pa_operation
*pa_ext_device_manager_defer_device(
373 pa_context_success_cb_t cb
,
377 pa_operation
*o
= NULL
;
378 pa_tagstruct
*t
= NULL
;
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
);
390 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
392 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
393 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
394 pa_tagstruct_puts(t
, "module-device-manager");
395 pa_tagstruct_putu32(t
, SUBCOMMAND_DEFER_DEVICE
);
396 pa_tagstruct_puts(t
, role
);
397 pa_tagstruct_puts(t
, device
);
399 pa_pstream_send_tagstruct(c
->pstream
, t
);
400 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
);
405 pa_operation
*pa_ext_device_manager_subscribe(
408 pa_context_success_cb_t cb
,
416 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
418 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
419 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
420 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
422 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
424 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
425 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
426 pa_tagstruct_puts(t
, "module-device-manager");
427 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
428 pa_tagstruct_put_boolean(t
, enable
);
429 pa_pstream_send_tagstruct(c
->pstream
, t
);
430 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
);
435 void pa_ext_device_manager_set_subscribe_cb(
437 pa_ext_device_manager_subscribe_cb_t cb
,
441 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
443 if (pa_detect_fork())
446 c
->ext_device_manager
.callback
= cb
;
447 c
->ext_device_manager
.userdata
= userdata
;
450 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
454 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
457 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
458 !pa_tagstruct_eof(t
)) {
460 pa_context_fail(c
, PA_ERR_PROTOCOL
);
464 if (subcommand
!= SUBCOMMAND_EVENT
) {
465 pa_context_fail(c
, PA_ERR_PROTOCOL
);
469 if (c
->ext_device_manager
.callback
)
470 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);