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
;
133 memset(&i
, 0, sizeof(i
));
136 if (pa_tagstruct_gets(t
, &i
.name
) < 0 ||
137 pa_tagstruct_gets(t
, &i
.description
) < 0 ||
138 pa_tagstruct_gets(t
, &i
.icon
) < 0 ||
139 pa_tagstruct_get_boolean(t
, &available
) < 0 ||
140 pa_tagstruct_getu32(t
, &i
.n_role_priorities
) < 0) {
142 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
145 i
.available
= (uint8_t)available
;
147 if (i
.n_role_priorities
> 0) {
149 i
.role_priorities
= pa_xnew0(pa_ext_device_manager_role_priority_info
, i
.n_role_priorities
+1);
151 for (j
= 0; j
< i
.n_role_priorities
; j
++) {
153 if (pa_tagstruct_gets(t
, &i
.role_priorities
[j
].role
) < 0 ||
154 pa_tagstruct_getu32(t
, &i
.role_priorities
[j
].priority
) < 0) {
156 pa_context_fail(o
->context
, PA_ERR_PROTOCOL
);
157 pa_xfree(i
.role_priorities
);
162 /* Terminate with an extra NULL entry, just to make sure */
163 i
.role_priorities
[j
].role
= NULL
;
164 i
.role_priorities
[j
].priority
= 0;
168 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
169 cb(o
->context
, &i
, 0, o
->userdata
);
172 pa_xfree(i
.role_priorities
);
177 pa_ext_device_manager_read_cb_t cb
= (pa_ext_device_manager_read_cb_t
) o
->callback
;
178 cb(o
->context
, NULL
, eol
, o
->userdata
);
182 pa_operation_done(o
);
183 pa_operation_unref(o
);
186 pa_operation
*pa_ext_device_manager_read(
188 pa_ext_device_manager_read_cb_t cb
,
196 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
198 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
199 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
200 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
202 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
204 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
205 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
206 pa_tagstruct_puts(t
, "module-device-manager");
207 pa_tagstruct_putu32(t
, SUBCOMMAND_READ
);
208 pa_pstream_send_tagstruct(c
->pstream
, t
);
209 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
);
214 pa_operation
*pa_ext_device_manager_set_device_description(
217 const char* description
,
218 pa_context_success_cb_t cb
,
222 pa_operation
*o
= NULL
;
223 pa_tagstruct
*t
= NULL
;
226 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
228 pa_assert(description
);
230 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
231 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
232 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
234 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
236 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
237 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
238 pa_tagstruct_puts(t
, "module-device-manager");
239 pa_tagstruct_putu32(t
, SUBCOMMAND_RENAME
);
241 pa_tagstruct_puts(t
, device
);
242 pa_tagstruct_puts(t
, description
);
244 pa_pstream_send_tagstruct(c
->pstream
, t
);
245 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
);
250 pa_operation
*pa_ext_device_manager_delete(
252 const char *const s
[],
253 pa_context_success_cb_t cb
,
257 pa_operation
*o
= NULL
;
258 pa_tagstruct
*t
= NULL
;
259 const char *const *k
;
262 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
265 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
266 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
267 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
269 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
271 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
272 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
273 pa_tagstruct_puts(t
, "module-device-manager");
274 pa_tagstruct_putu32(t
, SUBCOMMAND_DELETE
);
276 for (k
= s
; *k
; k
++) {
280 pa_tagstruct_puts(t
, *k
);
283 pa_pstream_send_tagstruct(c
->pstream
, t
);
284 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
);
290 pa_operation_cancel(o
);
291 pa_operation_unref(o
);
295 pa_tagstruct_free(t
);
297 pa_context_set_error(c
, PA_ERR_INVALID
);
301 pa_operation
*pa_ext_device_manager_enable_role_device_priority_routing(
304 pa_context_success_cb_t cb
,
308 pa_operation
*o
= NULL
;
309 pa_tagstruct
*t
= NULL
;
312 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
314 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
315 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
316 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
318 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
320 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
321 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
322 pa_tagstruct_puts(t
, "module-device-manager");
323 pa_tagstruct_putu32(t
, SUBCOMMAND_ROLE_DEVICE_PRIORITY_ROUTING
);
324 pa_tagstruct_put_boolean(t
, !!enable
);
326 pa_pstream_send_tagstruct(c
->pstream
, t
);
327 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
);
332 pa_operation
*pa_ext_device_manager_reorder_devices_for_role(
335 const char** devices
,
336 pa_context_success_cb_t cb
,
340 pa_operation
*o
= NULL
;
341 pa_tagstruct
*t
= NULL
;
344 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
346 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
347 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
348 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
353 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
355 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
356 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
357 pa_tagstruct_puts(t
, "module-device-manager");
358 pa_tagstruct_putu32(t
, SUBCOMMAND_REORDER
);
359 pa_tagstruct_puts(t
, role
);
361 i
= 0; while (devices
[i
]) i
++;
362 pa_tagstruct_putu32(t
, i
);
366 pa_tagstruct_puts(t
, devices
[i
++]);
368 pa_pstream_send_tagstruct(c
->pstream
, t
);
369 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
);
374 pa_operation
*pa_ext_device_manager_subscribe(
377 pa_context_success_cb_t cb
,
385 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
387 PA_CHECK_VALIDITY_RETURN_NULL(c
, !pa_detect_fork(), PA_ERR_FORKED
);
388 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->state
== PA_CONTEXT_READY
, PA_ERR_BADSTATE
);
389 PA_CHECK_VALIDITY_RETURN_NULL(c
, c
->version
>= 14, PA_ERR_NOTSUPPORTED
);
391 o
= pa_operation_new(c
, NULL
, (pa_operation_cb_t
) cb
, userdata
);
393 t
= pa_tagstruct_command(c
, PA_COMMAND_EXTENSION
, &tag
);
394 pa_tagstruct_putu32(t
, PA_INVALID_INDEX
);
395 pa_tagstruct_puts(t
, "module-device-manager");
396 pa_tagstruct_putu32(t
, SUBCOMMAND_SUBSCRIBE
);
397 pa_tagstruct_put_boolean(t
, enable
);
398 pa_pstream_send_tagstruct(c
->pstream
, t
);
399 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
);
404 void pa_ext_device_manager_set_subscribe_cb(
406 pa_ext_device_manager_subscribe_cb_t cb
,
410 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
412 if (pa_detect_fork())
415 c
->ext_device_manager
.callback
= cb
;
416 c
->ext_device_manager
.userdata
= userdata
;
419 void pa_ext_device_manager_command(pa_context
*c
, uint32_t tag
, pa_tagstruct
*t
) {
423 pa_assert(PA_REFCNT_VALUE(c
) >= 1);
426 if (pa_tagstruct_getu32(t
, &subcommand
) < 0 ||
427 !pa_tagstruct_eof(t
)) {
429 pa_context_fail(c
, PA_ERR_PROTOCOL
);
433 if (subcommand
!= SUBCOMMAND_EVENT
) {
434 pa_context_fail(c
, PA_ERR_PROTOCOL
);
438 if (c
->ext_device_manager
.callback
)
439 c
->ext_device_manager
.callback(c
, c
->ext_device_manager
.userdata
);