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/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-device-manager.h"
43 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 ||
134 pa_tagstruct_gets(t
, &i
.icon
) < 0 ||
135 pa_tagstruct_getu32(t
, &i
.index
) < 0 ||
136 pa_tagstruct_getu32(t
, &i
.n_role_priorities
) < 0) {
138 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
142 if (i
.n_role_priorities
> 0) {
144 i
.role_priorities
= pa_xnew0(pa_ext_device_manager_role_priority_info
, i
.n_role_priorities
+1);
146 for (j
= 0; j
< i
.n_role_priorities
; j
++) {
148 if (pa_tagstruct_gets(t
, &i
.role_priorities
[j
].role
) < 0 ||
149 pa_tagstruct_getu32(t
, &i
.role_priorities
[j
].priority
) < 0) {
151 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
152 pa_xfree(i
.role_priorities
);
157 /* Terminate with an extra NULL entry, just to make sure */
158 i
.role_priorities
[j
].role
= NULL
;
159 i
.role_priorities
[j
].priority
= 0;
163 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
164 cb(o
->context
, &i
, 0, o
->userdata
);
167 pa_xfree(i
.role_priorities
);
172 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
173 cb(o
->context
, NULL
, eol
, o
->userdata
);
177 pa_operation_done(o
);
178 pa_operation_unref(o
);
181 pa_operation
*pa_ext_device_manager_read(
183 pa_ext_device_manager_read_cb_t cb
,
191 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
193 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
194 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
195 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
197 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
199 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
200 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
201 pa_tagstruct_puts(t
, "module-device-manager");
202 pa_tagstruct_putu32(t
, SUBCOMMAND_READ
);
203 pa_pstream_send_tagstruct(c
->pstream
, t
);
204 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
);
209 pa_operation
*pa_ext_device_manager_set_device_description(
212 const char* description
,
213 pa_context_success_cb_t cb
,
217 pa_operation
*o
= NULL
;
218 pa_tagstruct
*t
= NULL
;
221 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
223 pa_assert(description
);
225 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
226 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
227 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
229 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
231 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
232 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
233 pa_tagstruct_puts(t
, "module-device-manager");
234 pa_tagstruct_putu32(t
, SUBCOMMAND_RENAME
);
236 pa_tagstruct_puts(t
, device
);
237 pa_tagstruct_puts(t
, description
);
239 pa_pstream_send_tagstruct(c
->pstream
, t
);
240 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
);
245 pa_operation
*pa_ext_device_manager_delete(
247 const char *const s
[],
248 pa_context_success_cb_t cb
,
252 pa_operation
*o
= NULL
;
253 pa_tagstruct
*t
= NULL
;
254 const char *const *k
;
257 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
260 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
261 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
262 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
264 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
266 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
267 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
268 pa_tagstruct_puts(t
, "module-device-manager");
269 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
271 for (k
= s
; *k
; k
++) {
275 pa_tagstruct_puts(t
, *k
);
278 pa_pstream_send_tagstruct(c
->pstream
, t
);
279 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
);
285 pa_operation_cancel(o
);
286 pa_operation_unref(o
);
290 pa_tagstruct_free(t
);
292 pa_context_set_error(c
, PA_ERR_INVALID
);
296 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
299 pa_context_success_cb_t cb
,
303 pa_operation
*o
= NULL
;
304 pa_tagstruct
*t
= NULL
;
307 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
309 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
310 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
311 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
313 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
315 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
316 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
317 pa_tagstruct_puts(t
, "module-device-manager");
318 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
319 pa_tagstruct_put_boolean(t
, !!enable
);
321 pa_pstream_send_tagstruct(c
->pstream
, t
);
322 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
);
327 pa_operation
*pa_ext_device_manager_reorder_devices_for_role(
330 const char** devices
,
331 pa_context_success_cb_t cb
,
335 pa_operation
*o
= NULL
;
336 pa_tagstruct
*t
= NULL
;
339 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
341 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
342 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
343 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
348 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
350 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
351 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
352 pa_tagstruct_puts(t
, "module-device-manager");
353 pa_tagstruct_putu32(t
, SUBCOMMAND_REORDER
);
354 pa_tagstruct_puts(t
, role
);
356 i
= 0; while (devices
[i
]) i
++;
357 pa_tagstruct_putu32(t
, i
);
361 pa_tagstruct_puts(t
, devices
[i
++]);
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_subscribe(
372 pa_context_success_cb_t cb
,
380 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
382 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
383 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
384 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
386 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
388 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
389 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
390 pa_tagstruct_puts(t
, "module-device-manager");
391 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
392 pa_tagstruct_put_boolean(t
, enable
);
393 pa_pstream_send_tagstruct(c
->pstream
, t
);
394 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
);
399 void pa_ext_device_manager_set_subscribe_cb(
401 pa_ext_device_manager_subscribe_cb_t cb
,
405 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
407 if (pa_detect_fork())
410 c
->ext_device_manager
.callback
= cb
;
411 c
->ext_device_manager
.userdata
= userdata
;
414 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
418 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
421 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
422 !pa_tagstruct_eof(t
)) {
424 pa_context_fail(c
, PA_ERR_PROTOCOL
);
428 if (subcommand
!= SUBCOMMAND_EVENT
) {
429 pa_context_fail(c
, PA_ERR_PROTOCOL
);
433 if (c
->ext_device_manager
.callback
)
434 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);