2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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
32 #include <pulse/rtclock.h>
33 #include <pulse/timeval.h>
34 #include <pulse/version.h>
35 #include <pulse/utf8.h>
36 #include <pulse/util.h>
37 #include <pulse/xmalloc.h>
39 #include <pulsecore/native-common.h>
40 #include <pulsecore/packet.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/source-output.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/pstream.h>
45 #include <pulsecore/tagstruct.h>
46 #include <pulsecore/pdispatch.h>
47 #include <pulsecore/pstream-util.h>
48 #include <pulsecore/authkey.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/core-subscribe.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/strlist.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/llist.h>
57 #include <pulsecore/creds.h>
58 #include <pulsecore/core-util.h>
59 #include <pulsecore/ipacl.h>
60 #include <pulsecore/thread-mq.h>
62 #include "protocol-native.h"
64 /* Kick a client if it doesn't authenticate within this time */
65 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
67 /* Don't accept more connection than this */
68 #define MAX_CONNECTIONS 64
70 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
71 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
72 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
73 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
75 struct pa_native_protocol
;
77 typedef struct record_stream
{
80 pa_native_connection
*connection
;
83 pa_source_output
*source_output
;
84 pa_memblockq
*memblockq
;
86 pa_bool_t adjust_latency
:1;
87 pa_bool_t early_requests
:1;
89 pa_buffer_attr buffer_attr
;
91 pa_atomic_t on_the_fly
;
92 pa_usec_t configured_source_latency
;
95 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
96 size_t on_the_fly_snapshot
;
97 pa_usec_t current_monitor_latency
;
98 pa_usec_t current_source_latency
;
101 #define RECORD_STREAM(o) (record_stream_cast(o))
102 PA_DEFINE_PRIVATE_CLASS(record_stream
, pa_msgobject
);
104 typedef struct output_stream
{
108 #define OUTPUT_STREAM(o) (output_stream_cast(o))
109 PA_DEFINE_PRIVATE_CLASS(output_stream
, pa_msgobject
);
111 typedef struct playback_stream
{
112 output_stream parent
;
114 pa_native_connection
*connection
;
117 pa_sink_input
*sink_input
;
118 pa_memblockq
*memblockq
;
120 pa_bool_t adjust_latency
:1;
121 pa_bool_t early_requests
:1;
123 pa_bool_t is_underrun
:1;
124 pa_bool_t drain_request
:1;
129 pa_usec_t configured_sink_latency
;
130 pa_buffer_attr buffer_attr
;
132 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
133 int64_t read_index
, write_index
;
134 size_t render_memblockq_length
;
135 pa_usec_t current_sink_latency
;
136 uint64_t playing_for
, underrun_for
;
139 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
140 PA_DEFINE_PRIVATE_CLASS(playback_stream
, output_stream
);
142 typedef struct upload_stream
{
143 output_stream parent
;
145 pa_native_connection
*connection
;
148 pa_memchunk memchunk
;
151 pa_sample_spec sample_spec
;
152 pa_channel_map channel_map
;
153 pa_proplist
*proplist
;
156 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
157 PA_DEFINE_PRIVATE_CLASS(upload_stream
, output_stream
);
159 struct pa_native_connection
{
161 pa_native_protocol
*protocol
;
162 pa_native_options
*options
;
163 pa_bool_t authorized
:1;
164 pa_bool_t is_local
:1;
168 pa_pdispatch
*pdispatch
;
169 pa_idxset
*record_streams
, *output_streams
;
170 uint32_t rrobin_index
;
171 pa_subscription
*subscription
;
172 pa_time_event
*auth_timeout_event
;
175 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
176 PA_DEFINE_PRIVATE_CLASS(pa_native_connection
, pa_msgobject
);
178 struct pa_native_protocol
{
182 pa_idxset
*connections
;
185 pa_hook hooks
[PA_NATIVE_HOOK_MAX
];
187 pa_hashmap
*extensions
;
191 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
= PA_SOURCE_OUTPUT_MESSAGE_MAX
195 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
196 SINK_INPUT_MESSAGE_DRAIN
, /* disabled prebuf, get playback started. */
197 SINK_INPUT_MESSAGE_FLUSH
,
198 SINK_INPUT_MESSAGE_TRIGGER
,
199 SINK_INPUT_MESSAGE_SEEK
,
200 SINK_INPUT_MESSAGE_PREBUF_FORCE
,
201 SINK_INPUT_MESSAGE_UPDATE_LATENCY
,
202 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
206 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, /* data requested from sink input from the main loop */
207 PLAYBACK_STREAM_MESSAGE_UNDERFLOW
,
208 PLAYBACK_STREAM_MESSAGE_OVERFLOW
,
209 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
,
210 PLAYBACK_STREAM_MESSAGE_STARTED
,
211 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
215 RECORD_STREAM_MESSAGE_POST_DATA
/* data from source output to main loop */
219 CONNECTION_MESSAGE_RELEASE
,
220 CONNECTION_MESSAGE_REVOKE
223 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
224 static void sink_input_kill_cb(pa_sink_input
*i
);
225 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
);
226 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
);
227 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
228 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
229 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
);
230 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
);
232 static void native_connection_send_memblock(pa_native_connection
*c
);
233 static void playback_stream_request_bytes(struct playback_stream
*s
);
235 static void source_output_kill_cb(pa_source_output
*o
);
236 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
237 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
);
238 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
);
239 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
240 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
);
242 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
243 static int source_output_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
245 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
246 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
247 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
248 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
249 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
250 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
251 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
252 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
253 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
254 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
255 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
256 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
257 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
258 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
259 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
260 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
261 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
262 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
263 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
264 static void command_set_volume(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
265 static void command_set_mute(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
266 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
267 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
268 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
269 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
270 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
271 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
272 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
273 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
274 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
275 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
276 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
277 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
278 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
279 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
280 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
281 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
282 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
283 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
285 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
286 [PA_COMMAND_ERROR
] = NULL
,
287 [PA_COMMAND_TIMEOUT
] = NULL
,
288 [PA_COMMAND_REPLY
] = NULL
,
289 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = command_create_playback_stream
,
290 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = command_delete_stream
,
291 [PA_COMMAND_DRAIN_PLAYBACK_STREAM
] = command_drain_playback_stream
,
292 [PA_COMMAND_CREATE_RECORD_STREAM
] = command_create_record_stream
,
293 [PA_COMMAND_DELETE_RECORD_STREAM
] = command_delete_stream
,
294 [PA_COMMAND_AUTH
] = command_auth
,
295 [PA_COMMAND_REQUEST
] = NULL
,
296 [PA_COMMAND_EXIT
] = command_exit
,
297 [PA_COMMAND_SET_CLIENT_NAME
] = command_set_client_name
,
298 [PA_COMMAND_LOOKUP_SINK
] = command_lookup
,
299 [PA_COMMAND_LOOKUP_SOURCE
] = command_lookup
,
300 [PA_COMMAND_STAT
] = command_stat
,
301 [PA_COMMAND_GET_PLAYBACK_LATENCY
] = command_get_playback_latency
,
302 [PA_COMMAND_GET_RECORD_LATENCY
] = command_get_record_latency
,
303 [PA_COMMAND_CREATE_UPLOAD_STREAM
] = command_create_upload_stream
,
304 [PA_COMMAND_DELETE_UPLOAD_STREAM
] = command_delete_stream
,
305 [PA_COMMAND_FINISH_UPLOAD_STREAM
] = command_finish_upload_stream
,
306 [PA_COMMAND_PLAY_SAMPLE
] = command_play_sample
,
307 [PA_COMMAND_REMOVE_SAMPLE
] = command_remove_sample
,
308 [PA_COMMAND_GET_SINK_INFO
] = command_get_info
,
309 [PA_COMMAND_GET_SOURCE_INFO
] = command_get_info
,
310 [PA_COMMAND_GET_CLIENT_INFO
] = command_get_info
,
311 [PA_COMMAND_GET_CARD_INFO
] = command_get_info
,
312 [PA_COMMAND_GET_MODULE_INFO
] = command_get_info
,
313 [PA_COMMAND_GET_SINK_INPUT_INFO
] = command_get_info
,
314 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO
] = command_get_info
,
315 [PA_COMMAND_GET_SAMPLE_INFO
] = command_get_info
,
316 [PA_COMMAND_GET_SINK_INFO_LIST
] = command_get_info_list
,
317 [PA_COMMAND_GET_SOURCE_INFO_LIST
] = command_get_info_list
,
318 [PA_COMMAND_GET_MODULE_INFO_LIST
] = command_get_info_list
,
319 [PA_COMMAND_GET_CLIENT_INFO_LIST
] = command_get_info_list
,
320 [PA_COMMAND_GET_CARD_INFO_LIST
] = command_get_info_list
,
321 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST
] = command_get_info_list
,
322 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
] = command_get_info_list
,
323 [PA_COMMAND_GET_SAMPLE_INFO_LIST
] = command_get_info_list
,
324 [PA_COMMAND_GET_SERVER_INFO
] = command_get_server_info
,
325 [PA_COMMAND_SUBSCRIBE
] = command_subscribe
,
327 [PA_COMMAND_SET_SINK_VOLUME
] = command_set_volume
,
328 [PA_COMMAND_SET_SINK_INPUT_VOLUME
] = command_set_volume
,
329 [PA_COMMAND_SET_SOURCE_VOLUME
] = command_set_volume
,
331 [PA_COMMAND_SET_SINK_MUTE
] = command_set_mute
,
332 [PA_COMMAND_SET_SINK_INPUT_MUTE
] = command_set_mute
,
333 [PA_COMMAND_SET_SOURCE_MUTE
] = command_set_mute
,
335 [PA_COMMAND_SUSPEND_SINK
] = command_suspend
,
336 [PA_COMMAND_SUSPEND_SOURCE
] = command_suspend
,
338 [PA_COMMAND_CORK_PLAYBACK_STREAM
] = command_cork_playback_stream
,
339 [PA_COMMAND_FLUSH_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
340 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
341 [PA_COMMAND_PREBUF_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
343 [PA_COMMAND_CORK_RECORD_STREAM
] = command_cork_record_stream
,
344 [PA_COMMAND_FLUSH_RECORD_STREAM
] = command_flush_record_stream
,
346 [PA_COMMAND_SET_DEFAULT_SINK
] = command_set_default_sink_or_source
,
347 [PA_COMMAND_SET_DEFAULT_SOURCE
] = command_set_default_sink_or_source
,
348 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME
] = command_set_stream_name
,
349 [PA_COMMAND_SET_RECORD_STREAM_NAME
] = command_set_stream_name
,
350 [PA_COMMAND_KILL_CLIENT
] = command_kill
,
351 [PA_COMMAND_KILL_SINK_INPUT
] = command_kill
,
352 [PA_COMMAND_KILL_SOURCE_OUTPUT
] = command_kill
,
353 [PA_COMMAND_LOAD_MODULE
] = command_load_module
,
354 [PA_COMMAND_UNLOAD_MODULE
] = command_unload_module
,
356 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE
] = NULL
,
357 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE
] = NULL
,
358 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE
] = NULL
,
359 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE
] = NULL
,
361 [PA_COMMAND_MOVE_SINK_INPUT
] = command_move_stream
,
362 [PA_COMMAND_MOVE_SOURCE_OUTPUT
] = command_move_stream
,
364 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
365 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
367 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
368 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
370 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
] = command_update_proplist
,
371 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
] = command_update_proplist
,
372 [PA_COMMAND_UPDATE_CLIENT_PROPLIST
] = command_update_proplist
,
374 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
] = command_remove_proplist
,
375 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
] = command_remove_proplist
,
376 [PA_COMMAND_REMOVE_CLIENT_PROPLIST
] = command_remove_proplist
,
378 [PA_COMMAND_SET_CARD_PROFILE
] = command_set_card_profile
,
380 [PA_COMMAND_SET_SINK_PORT
] = command_set_sink_or_source_port
,
381 [PA_COMMAND_SET_SOURCE_PORT
] = command_set_sink_or_source_port
,
383 [PA_COMMAND_EXTENSION
] = command_extension
386 /* structure management */
388 /* Called from main context */
389 static void upload_stream_unlink(upload_stream
*s
) {
395 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
396 s
->connection
= NULL
;
397 upload_stream_unref(s
);
400 /* Called from main context */
401 static void upload_stream_free(pa_object
*o
) {
402 upload_stream
*s
= UPLOAD_STREAM(o
);
405 upload_stream_unlink(s
);
410 pa_proplist_free(s
->proplist
);
412 if (s
->memchunk
.memblock
)
413 pa_memblock_unref(s
->memchunk
.memblock
);
418 /* Called from main context */
419 static upload_stream
* upload_stream_new(
420 pa_native_connection
*c
,
421 const pa_sample_spec
*ss
,
422 const pa_channel_map
*map
,
432 pa_assert(length
> 0);
435 s
= pa_msgobject_new(upload_stream
);
436 s
->parent
.parent
.parent
.free
= upload_stream_free
;
438 s
->sample_spec
= *ss
;
439 s
->channel_map
= *map
;
440 s
->name
= pa_xstrdup(name
);
441 pa_memchunk_reset(&s
->memchunk
);
443 s
->proplist
= pa_proplist_copy(p
);
444 pa_proplist_update(s
->proplist
, PA_UPDATE_MERGE
, c
->client
->proplist
);
446 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
451 /* Called from main context */
452 static void record_stream_unlink(record_stream
*s
) {
458 if (s
->source_output
) {
459 pa_source_output_unlink(s
->source_output
);
460 pa_source_output_unref(s
->source_output
);
461 s
->source_output
= NULL
;
464 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->record_streams
, s
, NULL
) == s
);
465 s
->connection
= NULL
;
466 record_stream_unref(s
);
469 /* Called from main context */
470 static void record_stream_free(pa_object
*o
) {
471 record_stream
*s
= RECORD_STREAM(o
);
474 record_stream_unlink(s
);
476 pa_memblockq_free(s
->memblockq
);
480 /* Called from main context */
481 static int record_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
482 record_stream
*s
= RECORD_STREAM(o
);
483 record_stream_assert_ref(s
);
490 case RECORD_STREAM_MESSAGE_POST_DATA
:
492 /* We try to keep up to date with how many bytes are
493 * currently on the fly */
494 pa_atomic_sub(&s
->on_the_fly
, chunk
->length
);
496 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
497 /* pa_log_warn("Failed to push data into output queue."); */
501 if (!pa_pstream_is_pending(s
->connection
->pstream
))
502 native_connection_send_memblock(s
->connection
);
510 /* Called from main context */
511 static void fix_record_buffer_attr_pre(record_stream
*s
) {
514 pa_usec_t orig_fragsize_usec
, fragsize_usec
, source_usec
;
518 /* This function will be called from the main thread, before as
519 * well as after the source output has been activated using
520 * pa_source_output_put()! That means it may not touch any
521 * ->thread_info data! */
523 frame_size
= pa_frame_size(&s
->source_output
->sample_spec
);
525 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
526 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
527 if (s
->buffer_attr
.maxlength
<= 0)
528 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
530 if (s
->buffer_attr
.fragsize
== (uint32_t) -1)
531 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC
*PA_USEC_PER_MSEC
, &s
->source_output
->sample_spec
);
532 if (s
->buffer_attr
.fragsize
<= 0)
533 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
535 orig_fragsize_usec
= fragsize_usec
= pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &s
->source_output
->sample_spec
);
537 if (s
->early_requests
) {
539 /* In early request mode we need to emulate the classic
540 * fragment-based playback model. We do this setting the source
541 * latency to the fragment size. */
543 source_usec
= fragsize_usec
;
545 } else if (s
->adjust_latency
) {
547 /* So, the user asked us to adjust the latency according to
548 * what the source can provide. Half the latency will be
549 * spent on the hw buffer, half of it in the async buffer
550 * queue we maintain for each client. */
552 source_usec
= fragsize_usec
/2;
556 /* Ok, the user didn't ask us to adjust the latency, hence we
559 source_usec
= (pa_usec_t
) -1;
562 if (source_usec
!= (pa_usec_t
) -1)
563 s
->configured_source_latency
= pa_source_output_set_requested_latency(s
->source_output
, source_usec
);
565 s
->configured_source_latency
= 0;
567 if (s
->early_requests
) {
569 /* Ok, we didn't necessarily get what we were asking for, so
570 * let's tell the user */
572 fragsize_usec
= s
->configured_source_latency
;
574 } else if (s
->adjust_latency
) {
576 /* Now subtract what we actually got */
578 if (fragsize_usec
>= s
->configured_source_latency
*2)
579 fragsize_usec
-= s
->configured_source_latency
;
581 fragsize_usec
= s
->configured_source_latency
;
584 if (pa_usec_to_bytes(orig_fragsize_usec
, &s
->source_output
->sample_spec
) !=
585 pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
))
587 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
);
589 if (s
->buffer_attr
.fragsize
<= 0)
590 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
593 /* Called from main context */
594 static void fix_record_buffer_attr_post(record_stream
*s
) {
599 /* This function will be called from the main thread, before as
600 * well as after the source output has been activated using
601 * pa_source_output_put()! That means it may not touch and
602 * ->thread_info data! */
604 base
= pa_frame_size(&s
->source_output
->sample_spec
);
606 s
->buffer_attr
.fragsize
= (s
->buffer_attr
.fragsize
/base
)*base
;
607 if (s
->buffer_attr
.fragsize
<= 0)
608 s
->buffer_attr
.fragsize
= base
;
610 if (s
->buffer_attr
.fragsize
> s
->buffer_attr
.maxlength
)
611 s
->buffer_attr
.fragsize
= s
->buffer_attr
.maxlength
;
614 /* Called from main context */
615 static record_stream
* record_stream_new(
616 pa_native_connection
*c
,
620 pa_bool_t peak_detect
,
621 pa_buffer_attr
*attr
,
622 pa_source_output_flags_t flags
,
624 pa_bool_t adjust_latency
,
625 pa_sink_input
*direct_on_input
,
626 pa_bool_t early_requests
,
630 pa_source_output
*source_output
= NULL
;
631 pa_source_output_new_data data
;
638 pa_source_output_new_data_init(&data
);
640 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
641 data
.driver
= __FILE__
;
642 data
.module
= c
->options
->module
;
643 data
.client
= c
->client
;
644 data
.source
= source
;
645 data
.direct_on_input
= direct_on_input
;
646 pa_source_output_new_data_set_sample_spec(&data
, ss
);
647 pa_source_output_new_data_set_channel_map(&data
, map
);
649 data
.resample_method
= PA_RESAMPLER_PEAKS
;
652 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
654 pa_source_output_new_data_done(&data
);
659 s
= pa_msgobject_new(record_stream
);
660 s
->parent
.parent
.free
= record_stream_free
;
661 s
->parent
.process_msg
= record_stream_process_msg
;
663 s
->source_output
= source_output
;
664 s
->buffer_attr
= *attr
;
665 s
->adjust_latency
= adjust_latency
;
666 s
->early_requests
= early_requests
;
667 pa_atomic_store(&s
->on_the_fly
, 0);
669 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
670 s
->source_output
->push
= source_output_push_cb
;
671 s
->source_output
->kill
= source_output_kill_cb
;
672 s
->source_output
->get_latency
= source_output_get_latency_cb
;
673 s
->source_output
->moving
= source_output_moving_cb
;
674 s
->source_output
->suspend
= source_output_suspend_cb
;
675 s
->source_output
->send_event
= source_output_send_event_cb
;
676 s
->source_output
->userdata
= s
;
678 fix_record_buffer_attr_pre(s
);
680 s
->memblockq
= pa_memblockq_new(
682 s
->buffer_attr
.maxlength
,
684 pa_frame_size(&source_output
->sample_spec
),
690 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
691 fix_record_buffer_attr_post(s
);
693 *ss
= s
->source_output
->sample_spec
;
694 *map
= s
->source_output
->channel_map
;
696 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
698 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
699 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
700 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
701 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
703 pa_source_output_put(s
->source_output
);
707 /* Called from main context */
708 static void record_stream_send_killed(record_stream
*r
) {
710 record_stream_assert_ref(r
);
712 t
= pa_tagstruct_new(NULL
, 0);
713 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
714 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
715 pa_tagstruct_putu32(t
, r
->index
);
716 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
719 /* Called from main context */
720 static void playback_stream_unlink(playback_stream
*s
) {
727 pa_sink_input_unlink(s
->sink_input
);
728 pa_sink_input_unref(s
->sink_input
);
729 s
->sink_input
= NULL
;
732 if (s
->drain_request
)
733 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
735 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
736 s
->connection
= NULL
;
737 playback_stream_unref(s
);
740 /* Called from main context */
741 static void playback_stream_free(pa_object
* o
) {
742 playback_stream
*s
= PLAYBACK_STREAM(o
);
745 playback_stream_unlink(s
);
747 pa_memblockq_free(s
->memblockq
);
751 /* Called from main context */
752 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
753 playback_stream
*s
= PLAYBACK_STREAM(o
);
754 playback_stream_assert_ref(s
);
761 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
766 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
769 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
773 t
= pa_tagstruct_new(NULL
, 0);
774 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
775 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
776 pa_tagstruct_putu32(t
, s
->index
);
777 pa_tagstruct_putu32(t
, (uint32_t) l
);
778 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
780 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
784 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
787 /* pa_log("signalling underflow"); */
789 /* Report that we're empty */
790 t
= pa_tagstruct_new(NULL
, 0);
791 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
792 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
793 pa_tagstruct_putu32(t
, s
->index
);
794 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
798 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
801 /* Notify the user we're overflowed*/
802 t
= pa_tagstruct_new(NULL
, 0);
803 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
804 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
805 pa_tagstruct_putu32(t
, s
->index
);
806 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
810 case PLAYBACK_STREAM_MESSAGE_STARTED
:
812 if (s
->connection
->version
>= 13) {
815 /* Notify the user we started playback */
816 t
= pa_tagstruct_new(NULL
, 0);
817 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
818 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
819 pa_tagstruct_putu32(t
, s
->index
);
820 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
825 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
826 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
829 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
:
831 s
->buffer_attr
.tlength
= (uint32_t) offset
;
833 if (s
->connection
->version
>= 15) {
836 t
= pa_tagstruct_new(NULL
, 0);
837 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
838 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
839 pa_tagstruct_putu32(t
, s
->index
);
840 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
841 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
842 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
843 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
844 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
845 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
854 /* Called from main context */
855 static void fix_playback_buffer_attr(playback_stream
*s
) {
856 size_t frame_size
, max_prebuf
;
857 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
861 /* This function will be called from the main thread, before as
862 * well as after the sink input has been activated using
863 * pa_sink_input_put()! That means it may not touch any
864 * ->thread_info data, such as the memblockq! */
866 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
868 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
869 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
870 if (s
->buffer_attr
.maxlength
<= 0)
871 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
873 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
874 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
875 if (s
->buffer_attr
.tlength
<= 0)
876 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
878 if (s
->buffer_attr
.minreq
== (uint32_t) -1)
879 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
880 if (s
->buffer_attr
.minreq
<= 0)
881 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
883 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
884 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
886 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
887 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
889 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
890 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
891 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
893 if (s
->early_requests
) {
895 /* In early request mode we need to emulate the classic
896 * fragment-based playback model. We do this setting the sink
897 * latency to the fragment size. */
899 sink_usec
= minreq_usec
;
900 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
902 } else if (s
->adjust_latency
) {
904 /* So, the user asked us to adjust the latency of the stream
905 * buffer according to the what the sink can provide. The
906 * tlength passed in shall be the overall latency. Roughly
907 * half the latency will be spent on the hw buffer, the other
908 * half of it in the async buffer queue we maintain for each
909 * client. In between we'll have a safety space of size
910 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
911 * empty and needs to be filled, then our buffer must have
912 * enough data to fulfill this request immediatly and thus
913 * have at least the same tlength as the size of the hw
914 * buffer. It additionally needs space for 2 times minreq
915 * because if the buffer ran empty and a partial fillup
916 * happens immediately on the next iteration we need to be
917 * able to fulfill it and give the application also minreq
918 * time to fill it up again for the next request Makes 2 times
919 * minreq in plus.. */
921 if (tlength_usec
> minreq_usec
*2)
922 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
926 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
930 /* Ok, the user didn't ask us to adjust the latency, but we
931 * still need to make sure that the parameters from the user
934 if (tlength_usec
> minreq_usec
*2)
935 sink_usec
= (tlength_usec
- minreq_usec
*2);
939 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
942 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
944 if (s
->early_requests
) {
946 /* Ok, we didn't necessarily get what we were asking for, so
947 * let's tell the user */
949 minreq_usec
= s
->configured_sink_latency
;
951 } else if (s
->adjust_latency
) {
953 /* Ok, we didn't necessarily get what we were asking for, so
954 * let's subtract from what we asked for for the remaining
957 if (tlength_usec
>= s
->configured_sink_latency
)
958 tlength_usec
-= s
->configured_sink_latency
;
961 /* FIXME: This is actually larger than necessary, since not all of
962 * the sink latency is actually rewritable. */
963 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
964 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
966 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
967 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
968 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
970 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
971 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
972 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
974 if (s
->buffer_attr
.minreq
<= 0) {
975 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
976 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
979 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
980 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
982 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
984 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
985 s
->buffer_attr
.prebuf
> max_prebuf
)
986 s
->buffer_attr
.prebuf
= max_prebuf
;
989 /* Called from main context */
990 static playback_stream
* playback_stream_new(
991 pa_native_connection
*c
,
1001 pa_sink_input_flags_t flags
,
1003 pa_bool_t adjust_latency
,
1004 pa_bool_t early_requests
,
1007 playback_stream
*s
, *ssync
;
1008 pa_sink_input
*sink_input
= NULL
;
1009 pa_memchunk silence
;
1011 int64_t start_index
;
1012 pa_sink_input_new_data data
;
1020 /* Find syncid group */
1021 for (ssync
= pa_idxset_first(c
->output_streams
, &idx
); ssync
; ssync
= pa_idxset_next(c
->output_streams
, &idx
)) {
1023 if (!playback_stream_isinstance(ssync
))
1026 if (ssync
->syncid
== syncid
)
1030 /* Synced streams must connect to the same sink */
1034 sink
= ssync
->sink_input
->sink
;
1035 else if (sink
!= ssync
->sink_input
->sink
) {
1036 *ret
= PA_ERR_INVALID
;
1041 pa_sink_input_new_data_init(&data
);
1043 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1044 data
.driver
= __FILE__
;
1045 data
.module
= c
->options
->module
;
1046 data
.client
= c
->client
;
1049 data
.save_sink
= TRUE
;
1051 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1052 pa_sink_input_new_data_set_channel_map(&data
, map
);
1054 pa_sink_input_new_data_set_volume(&data
, volume
);
1055 data
.volume_is_absolute
= TRUE
;
1056 data
.save_volume
= TRUE
;
1059 pa_sink_input_new_data_set_muted(&data
, muted
);
1060 data
.save_muted
= TRUE
;
1062 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1065 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1067 pa_sink_input_new_data_done(&data
);
1072 s
= pa_msgobject_new(playback_stream
);
1073 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1074 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1077 s
->sink_input
= sink_input
;
1078 s
->is_underrun
= TRUE
;
1079 s
->drain_request
= FALSE
;
1080 pa_atomic_store(&s
->missing
, 0);
1081 s
->buffer_attr
= *a
;
1082 s
->adjust_latency
= adjust_latency
;
1083 s
->early_requests
= early_requests
;
1085 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1086 s
->sink_input
->pop
= sink_input_pop_cb
;
1087 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1088 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1089 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1090 s
->sink_input
->kill
= sink_input_kill_cb
;
1091 s
->sink_input
->moving
= sink_input_moving_cb
;
1092 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1093 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1094 s
->sink_input
->userdata
= s
;
1096 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1098 fix_playback_buffer_attr(s
);
1100 pa_sink_input_get_silence(sink_input
, &silence
);
1101 s
->memblockq
= pa_memblockq_new(
1103 s
->buffer_attr
.maxlength
,
1104 s
->buffer_attr
.tlength
,
1105 pa_frame_size(&sink_input
->sample_spec
),
1106 s
->buffer_attr
.prebuf
,
1107 s
->buffer_attr
.minreq
,
1110 pa_memblock_unref(silence
.memblock
);
1112 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1114 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1116 *ss
= s
->sink_input
->sample_spec
;
1117 *map
= s
->sink_input
->channel_map
;
1119 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1121 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1122 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1123 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1124 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1125 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1127 pa_sink_input_put(s
->sink_input
);
1131 /* Called from IO context */
1132 static void playback_stream_request_bytes(playback_stream
*s
) {
1134 int previous_missing
;
1136 playback_stream_assert_ref(s
);
1138 m
= pa_memblockq_pop_missing(s
->memblockq
);
1140 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
1141 /* (unsigned long) m, */
1142 /* pa_memblockq_get_tlength(s->memblockq), */
1143 /* pa_memblockq_get_minreq(s->memblockq), */
1144 /* pa_memblockq_get_length(s->memblockq)); */
1149 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1151 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1152 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1154 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1155 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1156 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1159 /* Called from main context */
1160 static void playback_stream_send_killed(playback_stream
*p
) {
1162 playback_stream_assert_ref(p
);
1164 t
= pa_tagstruct_new(NULL
, 0);
1165 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1166 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1167 pa_tagstruct_putu32(t
, p
->index
);
1168 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1171 /* Called from main context */
1172 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1173 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1174 pa_native_connection_assert_ref(c
);
1181 case CONNECTION_MESSAGE_REVOKE
:
1182 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1185 case CONNECTION_MESSAGE_RELEASE
:
1186 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1193 /* Called from main context */
1194 static void native_connection_unlink(pa_native_connection
*c
) {
1203 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1206 pa_native_options_unref(c
->options
);
1208 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1209 record_stream_unlink(r
);
1211 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1212 if (playback_stream_isinstance(o
))
1213 playback_stream_unlink(PLAYBACK_STREAM(o
));
1215 upload_stream_unlink(UPLOAD_STREAM(o
));
1217 if (c
->subscription
)
1218 pa_subscription_free(c
->subscription
);
1221 pa_pstream_unlink(c
->pstream
);
1223 if (c
->auth_timeout_event
) {
1224 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1225 c
->auth_timeout_event
= NULL
;
1228 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1230 pa_native_connection_unref(c
);
1233 /* Called from main context */
1234 static void native_connection_free(pa_object
*o
) {
1235 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1239 native_connection_unlink(c
);
1241 pa_idxset_free(c
->record_streams
, NULL
, NULL
);
1242 pa_idxset_free(c
->output_streams
, NULL
, NULL
);
1244 pa_pdispatch_unref(c
->pdispatch
);
1245 pa_pstream_unref(c
->pstream
);
1246 pa_client_free(c
->client
);
1251 /* Called from main context */
1252 static void native_connection_send_memblock(pa_native_connection
*c
) {
1256 start
= PA_IDXSET_INVALID
;
1260 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1263 if (start
== PA_IDXSET_INVALID
)
1264 start
= c
->rrobin_index
;
1265 else if (start
== c
->rrobin_index
)
1268 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1269 pa_memchunk schunk
= chunk
;
1271 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1272 schunk
.length
= r
->buffer_attr
.fragsize
;
1274 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1276 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1277 pa_memblock_unref(schunk
.memblock
);
1284 /*** sink input callbacks ***/
1286 /* Called from thread context */
1287 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1288 playback_stream_assert_ref(s
);
1290 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1292 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1294 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1296 if (pa_memblockq_is_readable(s
->memblockq
)) {
1298 /* We just ended an underrun, let's ask the sink
1299 * for a complete rewind rewrite */
1301 pa_log_debug("Requesting rewind due to end of underrun.");
1302 pa_sink_input_request_rewind(s
->sink_input
,
1303 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1304 s
->sink_input
->thread_info
.underrun_for
),
1305 FALSE
, TRUE
, FALSE
);
1311 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1313 if (indexw
< indexr
) {
1314 /* OK, the sink already asked for this data, so
1315 * let's have it usk us again */
1317 pa_log_debug("Requesting rewind due to rewrite.");
1318 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1322 playback_stream_request_bytes(s
);
1325 /* Called from thread context */
1326 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1327 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1330 pa_sink_input_assert_ref(i
);
1331 s
= PLAYBACK_STREAM(i
->userdata
);
1332 playback_stream_assert_ref(s
);
1336 case SINK_INPUT_MESSAGE_SEEK
: {
1339 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1341 /* The client side is incapable of accounting correctly
1342 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1343 * able to deal with that. */
1345 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1347 handle_seek(s
, windex
);
1351 case SINK_INPUT_MESSAGE_POST_DATA
: {
1356 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1358 /* pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1360 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1362 if (pa_log_ratelimit())
1363 pa_log_warn("Failed to push data into queue");
1364 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1365 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1368 handle_seek(s
, windex
);
1370 /* pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1375 case SINK_INPUT_MESSAGE_DRAIN
:
1376 case SINK_INPUT_MESSAGE_FLUSH
:
1377 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1378 case SINK_INPUT_MESSAGE_TRIGGER
: {
1381 pa_sink_input
*isync
;
1382 void (*func
)(pa_memblockq
*bq
);
1385 case SINK_INPUT_MESSAGE_FLUSH
:
1386 func
= pa_memblockq_flush_write
;
1389 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1390 func
= pa_memblockq_prebuf_force
;
1393 case SINK_INPUT_MESSAGE_DRAIN
:
1394 case SINK_INPUT_MESSAGE_TRIGGER
:
1395 func
= pa_memblockq_prebuf_disable
;
1399 pa_assert_not_reached();
1402 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1404 handle_seek(s
, windex
);
1406 /* Do the same for all other members in the sync group */
1407 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1408 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1409 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1410 func(ssync
->memblockq
);
1411 handle_seek(ssync
, windex
);
1414 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1415 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1416 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1417 func(ssync
->memblockq
);
1418 handle_seek(ssync
, windex
);
1421 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1422 if (!pa_memblockq_is_readable(s
->memblockq
))
1423 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1425 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1426 s
->drain_request
= TRUE
;
1433 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1434 /* Atomically get a snapshot of all timing parameters... */
1435 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1436 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1437 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1438 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1439 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1440 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1444 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1447 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1449 pa_memblockq_prebuf_force(s
->memblockq
);
1451 handle_seek(s
, windex
);
1453 /* Fall through to the default handler */
1457 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1458 pa_usec_t
*r
= userdata
;
1460 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1462 /* Fall through, the default handler will add in the extra
1463 * latency added by the resampler */
1467 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1468 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1469 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1474 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1477 /* Called from thread context */
1478 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1481 pa_sink_input_assert_ref(i
);
1482 s
= PLAYBACK_STREAM(i
->userdata
);
1483 playback_stream_assert_ref(s
);
1486 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1488 if (pa_memblockq_is_readable(s
->memblockq
))
1489 s
->is_underrun
= FALSE
;
1491 if (!s
->is_underrun
)
1492 pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
)), (unsigned long) pa_memblockq_get_length(s
->memblockq
));
1494 if (s
->drain_request
&& pa_sink_input_safe_to_remove(i
)) {
1495 s
->drain_request
= FALSE
;
1496 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, PA_UINT_TO_PTR(s
->drain_tag
), 0, NULL
, NULL
);
1497 } else if (!s
->is_underrun
)
1498 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, 0, NULL
, NULL
);
1500 s
->is_underrun
= TRUE
;
1502 playback_stream_request_bytes(s
);
1505 /* This call will not fail with prebuf=0, hence we check for
1506 underrun explicitly above */
1507 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1510 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1512 if (i
->thread_info
.underrun_for
> 0)
1513 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1515 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1516 playback_stream_request_bytes(s
);
1521 /* Called from thread context */
1522 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1525 pa_sink_input_assert_ref(i
);
1526 s
= PLAYBACK_STREAM(i
->userdata
);
1527 playback_stream_assert_ref(s
);
1529 /* If we are in an underrun, then we don't rewind */
1530 if (i
->thread_info
.underrun_for
> 0)
1533 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1536 /* Called from thread context */
1537 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1540 pa_sink_input_assert_ref(i
);
1541 s
= PLAYBACK_STREAM(i
->userdata
);
1542 playback_stream_assert_ref(s
);
1544 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1547 /* Called from thread context */
1548 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1550 size_t new_tlength
, old_tlength
;
1552 pa_sink_input_assert_ref(i
);
1553 s
= PLAYBACK_STREAM(i
->userdata
);
1554 playback_stream_assert_ref(s
);
1556 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1557 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1559 if (old_tlength
< new_tlength
) {
1560 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1561 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1562 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1564 if (new_tlength
== old_tlength
)
1565 pa_log_debug("Failed to increase tlength");
1567 pa_log_debug("Notifying client about increased tlength");
1568 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
, NULL
, pa_memblockq_get_tlength(s
->memblockq
), NULL
, NULL
);
1573 /* Called from main context */
1574 static void sink_input_kill_cb(pa_sink_input
*i
) {
1577 pa_sink_input_assert_ref(i
);
1578 s
= PLAYBACK_STREAM(i
->userdata
);
1579 playback_stream_assert_ref(s
);
1581 playback_stream_send_killed(s
);
1582 playback_stream_unlink(s
);
1585 /* Called from main context */
1586 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1590 pa_sink_input_assert_ref(i
);
1591 s
= PLAYBACK_STREAM(i
->userdata
);
1592 playback_stream_assert_ref(s
);
1594 if (s
->connection
->version
< 15)
1597 t
= pa_tagstruct_new(NULL
, 0);
1598 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1599 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1600 pa_tagstruct_putu32(t
, s
->index
);
1601 pa_tagstruct_puts(t
, event
);
1602 pa_tagstruct_put_proplist(t
, pl
);
1603 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1606 /* Called from main context */
1607 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1611 pa_sink_input_assert_ref(i
);
1612 s
= PLAYBACK_STREAM(i
->userdata
);
1613 playback_stream_assert_ref(s
);
1615 if (s
->connection
->version
< 12)
1618 t
= pa_tagstruct_new(NULL
, 0);
1619 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1620 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1621 pa_tagstruct_putu32(t
, s
->index
);
1622 pa_tagstruct_put_boolean(t
, suspend
);
1623 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1626 /* Called from main context */
1627 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1631 pa_sink_input_assert_ref(i
);
1632 s
= PLAYBACK_STREAM(i
->userdata
);
1633 playback_stream_assert_ref(s
);
1638 fix_playback_buffer_attr(s
);
1639 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1640 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1642 if (s
->connection
->version
< 12)
1645 t
= pa_tagstruct_new(NULL
, 0);
1646 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1647 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1648 pa_tagstruct_putu32(t
, s
->index
);
1649 pa_tagstruct_putu32(t
, dest
->index
);
1650 pa_tagstruct_puts(t
, dest
->name
);
1651 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1653 if (s
->connection
->version
>= 13) {
1654 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1655 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1656 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1657 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1658 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1661 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1664 /*** source_output callbacks ***/
1666 /* Called from thread context */
1667 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1668 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1671 pa_source_output_assert_ref(o
);
1672 s
= RECORD_STREAM(o
->userdata
);
1673 record_stream_assert_ref(s
);
1676 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1677 /* Atomically get a snapshot of all timing parameters... */
1678 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1679 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1680 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1684 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1687 /* Called from thread context */
1688 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1691 pa_source_output_assert_ref(o
);
1692 s
= RECORD_STREAM(o
->userdata
);
1693 record_stream_assert_ref(s
);
1696 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1697 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1700 static void source_output_kill_cb(pa_source_output
*o
) {
1703 pa_source_output_assert_ref(o
);
1704 s
= RECORD_STREAM(o
->userdata
);
1705 record_stream_assert_ref(s
);
1707 record_stream_send_killed(s
);
1708 record_stream_unlink(s
);
1711 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1714 pa_source_output_assert_ref(o
);
1715 s
= RECORD_STREAM(o
->userdata
);
1716 record_stream_assert_ref(s
);
1718 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1720 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1723 /* Called from main context */
1724 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1728 pa_source_output_assert_ref(o
);
1729 s
= RECORD_STREAM(o
->userdata
);
1730 record_stream_assert_ref(s
);
1732 if (s
->connection
->version
< 15)
1735 t
= pa_tagstruct_new(NULL
, 0);
1736 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1737 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1738 pa_tagstruct_putu32(t
, s
->index
);
1739 pa_tagstruct_puts(t
, event
);
1740 pa_tagstruct_put_proplist(t
, pl
);
1741 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1744 /* Called from main context */
1745 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1749 pa_source_output_assert_ref(o
);
1750 s
= RECORD_STREAM(o
->userdata
);
1751 record_stream_assert_ref(s
);
1753 if (s
->connection
->version
< 12)
1756 t
= pa_tagstruct_new(NULL
, 0);
1757 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1758 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1759 pa_tagstruct_putu32(t
, s
->index
);
1760 pa_tagstruct_put_boolean(t
, suspend
);
1761 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1764 /* Called from main context */
1765 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1769 pa_source_output_assert_ref(o
);
1770 s
= RECORD_STREAM(o
->userdata
);
1771 record_stream_assert_ref(s
);
1776 fix_record_buffer_attr_pre(s
);
1777 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1778 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1779 fix_record_buffer_attr_post(s
);
1781 if (s
->connection
->version
< 12)
1784 t
= pa_tagstruct_new(NULL
, 0);
1785 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1786 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1787 pa_tagstruct_putu32(t
, s
->index
);
1788 pa_tagstruct_putu32(t
, dest
->index
);
1789 pa_tagstruct_puts(t
, dest
->name
);
1790 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1792 if (s
->connection
->version
>= 13) {
1793 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1794 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1795 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1798 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1801 /*** pdispatch callbacks ***/
1803 static void protocol_error(pa_native_connection
*c
) {
1804 pa_log("protocol error, kicking client");
1805 native_connection_unlink(c
);
1808 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1809 if (!(expression)) { \
1810 pa_pstream_send_error((pstream), (tag), (error)); \
1815 static pa_tagstruct
*reply_new(uint32_t tag
) {
1816 pa_tagstruct
*reply
;
1818 reply
= pa_tagstruct_new(NULL
, 0);
1819 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1820 pa_tagstruct_putu32(reply
, tag
);
1824 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1825 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1827 uint32_t sink_index
, syncid
, missing
;
1828 pa_buffer_attr attr
;
1829 const char *name
= NULL
, *sink_name
;
1832 pa_tagstruct
*reply
;
1833 pa_sink
*sink
= NULL
;
1841 fix_channels
= FALSE
,
1843 variable_rate
= FALSE
,
1845 adjust_latency
= FALSE
,
1846 early_requests
= FALSE
,
1847 dont_inhibit_auto_suspend
= FALSE
,
1849 fail_on_suspend
= FALSE
;
1850 pa_sink_input_flags_t flags
= 0;
1852 pa_bool_t volume_set
= TRUE
;
1853 int ret
= PA_ERR_INVALID
;
1855 pa_native_connection_assert_ref(c
);
1857 memset(&attr
, 0, sizeof(attr
));
1859 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
1862 PA_TAG_SAMPLE_SPEC
, &ss
,
1863 PA_TAG_CHANNEL_MAP
, &map
,
1864 PA_TAG_U32
, &sink_index
,
1865 PA_TAG_STRING
, &sink_name
,
1866 PA_TAG_U32
, &attr
.maxlength
,
1867 PA_TAG_BOOLEAN
, &corked
,
1868 PA_TAG_U32
, &attr
.tlength
,
1869 PA_TAG_U32
, &attr
.prebuf
,
1870 PA_TAG_U32
, &attr
.minreq
,
1871 PA_TAG_U32
, &syncid
,
1872 PA_TAG_CVOLUME
, &volume
,
1873 PA_TAG_INVALID
) < 0) {
1879 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
1880 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
1881 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
1882 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
1883 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
1884 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
1885 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
1886 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
1888 p
= pa_proplist_new();
1891 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
1893 if (c
->version
>= 12) {
1894 /* Since 0.9.8 the user can ask for a couple of additional flags */
1896 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
1897 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
1898 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
1899 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
1900 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
1901 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
1902 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
1905 pa_proplist_free(p
);
1910 if (c
->version
>= 13) {
1912 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
1913 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
1914 pa_tagstruct_get_proplist(t
, p
) < 0) {
1916 pa_proplist_free(p
);
1921 if (c
->version
>= 14) {
1923 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
1924 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
1926 pa_proplist_free(p
);
1931 if (c
->version
>= 15) {
1933 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
1934 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
1935 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
1937 pa_proplist_free(p
);
1942 if (!pa_tagstruct_eof(t
)) {
1944 pa_proplist_free(p
);
1948 if (sink_index
!= PA_INVALID_INDEX
) {
1950 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
1951 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1952 pa_proplist_free(p
);
1956 } else if (sink_name
) {
1958 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
1959 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
1960 pa_proplist_free(p
);
1966 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
1967 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
1968 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
1969 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
1970 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
1971 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
1972 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
1973 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
1974 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
1975 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0);
1977 /* Only since protocol version 15 there's a seperate muted_set
1978 * flag. For older versions we synthesize it here */
1979 muted_set
= muted_set
|| muted
;
1981 s
= playback_stream_new(c
, sink
, &ss
, &map
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, syncid
, &missing
, flags
, p
, adjust_latency
, early_requests
, &ret
);
1982 pa_proplist_free(p
);
1984 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
1986 reply
= reply_new(tag
);
1987 pa_tagstruct_putu32(reply
, s
->index
);
1988 pa_assert(s
->sink_input
);
1989 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
1990 pa_tagstruct_putu32(reply
, missing
);
1992 /* pa_log("initial request is %u", missing); */
1994 if (c
->version
>= 9) {
1995 /* Since 0.9.0 we support sending the buffer metrics back to the client */
1997 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
1998 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
1999 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
2000 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
2003 if (c
->version
>= 12) {
2004 /* Since 0.9.8 we support sending the chosen sample
2005 * spec/channel map/device/suspend status back to the
2008 pa_tagstruct_put_sample_spec(reply
, &ss
);
2009 pa_tagstruct_put_channel_map(reply
, &map
);
2011 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2012 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2014 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2017 if (c
->version
>= 13)
2018 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2020 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2023 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2024 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2027 pa_native_connection_assert_ref(c
);
2030 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2031 !pa_tagstruct_eof(t
)) {
2036 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2040 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2042 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2043 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2047 playback_stream_unlink(s
);
2051 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2053 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2054 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2058 record_stream_unlink(s
);
2062 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2065 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2066 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2070 upload_stream_unlink(s
);
2075 pa_assert_not_reached();
2078 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2081 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2082 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2084 pa_buffer_attr attr
;
2085 uint32_t source_index
;
2086 const char *name
= NULL
, *source_name
;
2089 pa_tagstruct
*reply
;
2090 pa_source
*source
= NULL
;
2097 fix_channels
= FALSE
,
2099 variable_rate
= FALSE
,
2100 adjust_latency
= FALSE
,
2101 peak_detect
= FALSE
,
2102 early_requests
= FALSE
,
2103 dont_inhibit_auto_suspend
= FALSE
,
2104 fail_on_suspend
= FALSE
;
2105 pa_source_output_flags_t flags
= 0;
2107 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2108 pa_sink_input
*direct_on_input
= NULL
;
2109 int ret
= PA_ERR_INVALID
;
2111 pa_native_connection_assert_ref(c
);
2114 memset(&attr
, 0, sizeof(attr
));
2116 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2117 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2118 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2119 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2120 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2121 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2122 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2123 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2128 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2129 CHECK_VALIDITY(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
2130 CHECK_VALIDITY(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
);
2131 CHECK_VALIDITY(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2132 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2133 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2134 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2136 p
= pa_proplist_new();
2139 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2141 if (c
->version
>= 12) {
2142 /* Since 0.9.8 the user can ask for a couple of additional flags */
2144 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2145 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2146 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2147 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2148 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2149 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2150 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2153 pa_proplist_free(p
);
2158 if (c
->version
>= 13) {
2160 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2161 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2162 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2163 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2165 pa_proplist_free(p
);
2170 if (c
->version
>= 14) {
2172 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2174 pa_proplist_free(p
);
2179 if (c
->version
>= 15) {
2181 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2182 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2184 pa_proplist_free(p
);
2189 if (!pa_tagstruct_eof(t
)) {
2191 pa_proplist_free(p
);
2195 if (source_index
!= PA_INVALID_INDEX
) {
2197 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2198 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2199 pa_proplist_free(p
);
2203 } else if (source_name
) {
2205 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2206 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2207 pa_proplist_free(p
);
2212 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2214 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2215 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2216 pa_proplist_free(p
);
2222 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2223 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2224 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2225 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2226 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2227 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2228 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2229 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2230 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2231 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0);
2233 s
= record_stream_new(c
, source
, &ss
, &map
, peak_detect
, &attr
, flags
, p
, adjust_latency
, direct_on_input
, early_requests
, &ret
);
2234 pa_proplist_free(p
);
2236 CHECK_VALIDITY(c
->pstream
, s
, tag
, ret
);
2238 reply
= reply_new(tag
);
2239 pa_tagstruct_putu32(reply
, s
->index
);
2240 pa_assert(s
->source_output
);
2241 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2243 if (c
->version
>= 9) {
2244 /* Since 0.9 we support sending the buffer metrics back to the client */
2246 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2247 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2250 if (c
->version
>= 12) {
2251 /* Since 0.9.8 we support sending the chosen sample
2252 * spec/channel map/device/suspend status back to the
2255 pa_tagstruct_put_sample_spec(reply
, &ss
);
2256 pa_tagstruct_put_channel_map(reply
, &map
);
2258 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2259 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2261 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2264 if (c
->version
>= 13)
2265 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2267 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2270 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2271 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2274 pa_native_connection_assert_ref(c
);
2277 if (!pa_tagstruct_eof(t
)) {
2282 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2283 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2284 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2286 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
)));
2288 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2291 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2292 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2294 pa_tagstruct
*reply
;
2295 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2297 pa_native_connection_assert_ref(c
);
2300 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2301 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2302 !pa_tagstruct_eof(t
)) {
2307 /* Minimum supported version */
2308 if (c
->version
< 8) {
2309 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2313 /* Starting with protocol version 13 the MSB of the version tag
2314 reflects if shm is available for this pa_native_connection or
2316 if (c
->version
>= 13) {
2317 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2318 c
->version
&= 0x7FFFFFFFU
;
2321 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2323 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2325 if (!c
->authorized
) {
2326 pa_bool_t success
= FALSE
;
2329 const pa_creds
*creds
;
2331 if ((creds
= pa_pdispatch_creds(pd
))) {
2332 if (creds
->uid
== getuid())
2334 else if (c
->options
->auth_group
) {
2338 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2339 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2340 else if (gid
== creds
->gid
)
2344 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2345 pa_log_warn("Failed to check group membership.");
2351 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2352 (unsigned long) creds
->uid
,
2353 (unsigned long) creds
->gid
,
2358 if (!success
&& c
->options
->auth_cookie
) {
2361 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2362 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2367 pa_log_warn("Denied access to client with invalid authorization data.");
2368 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2372 c
->authorized
= TRUE
;
2373 if (c
->auth_timeout_event
) {
2374 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2375 c
->auth_timeout_event
= NULL
;
2379 /* Enable shared memory support if possible */
2381 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2384 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2387 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2392 /* Only enable SHM if both sides are owned by the same
2393 * user. This is a security measure because otherwise data
2394 * private to the user might leak. */
2396 const pa_creds
*creds
;
2397 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2402 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2403 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2405 reply
= reply_new(tag
);
2406 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2410 /* SHM support is only enabled after both sides made sure they are the same user. */
2414 ucred
.uid
= getuid();
2415 ucred
.gid
= getgid();
2417 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2420 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2424 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2425 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2426 const char *name
= NULL
;
2428 pa_tagstruct
*reply
;
2430 pa_native_connection_assert_ref(c
);
2433 p
= pa_proplist_new();
2435 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2436 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2437 !pa_tagstruct_eof(t
)) {
2440 pa_proplist_free(p
);
2445 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2446 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2447 pa_proplist_free(p
);
2451 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2452 pa_proplist_free(p
);
2454 reply
= reply_new(tag
);
2456 if (c
->version
>= 13)
2457 pa_tagstruct_putu32(reply
, c
->client
->index
);
2459 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2462 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2463 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2465 uint32_t idx
= PA_IDXSET_INVALID
;
2467 pa_native_connection_assert_ref(c
);
2470 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2471 !pa_tagstruct_eof(t
)) {
2476 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2477 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_LOOKUP_SINK
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
2479 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2481 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2485 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2486 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2487 idx
= source
->index
;
2490 if (idx
== PA_IDXSET_INVALID
)
2491 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2493 pa_tagstruct
*reply
;
2494 reply
= reply_new(tag
);
2495 pa_tagstruct_putu32(reply
, idx
);
2496 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2500 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2501 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2505 pa_native_connection_assert_ref(c
);
2508 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2509 !pa_tagstruct_eof(t
)) {
2514 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2515 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2516 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2517 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2519 pa_asyncmsgq_post(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_DRAIN
, PA_UINT_TO_PTR(tag
), 0, NULL
, NULL
);
2522 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2523 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2524 pa_tagstruct
*reply
;
2525 const pa_mempool_stat
*stat
;
2527 pa_native_connection_assert_ref(c
);
2530 if (!pa_tagstruct_eof(t
)) {
2535 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2537 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2539 reply
= reply_new(tag
);
2540 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2541 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2542 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2543 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2544 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2545 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2548 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2549 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2550 pa_tagstruct
*reply
;
2552 struct timeval tv
, now
;
2555 pa_native_connection_assert_ref(c
);
2558 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2559 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2560 !pa_tagstruct_eof(t
)) {
2565 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2566 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2567 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2568 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2570 /* Get an atomic snapshot of all timing parameters */
2571 pa_assert_se(pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_UPDATE_LATENCY
, s
, 0, NULL
) == 0);
2573 reply
= reply_new(tag
);
2574 pa_tagstruct_put_usec(reply
,
2575 s
->current_sink_latency
+
2576 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2577 pa_tagstruct_put_usec(reply
, 0);
2578 pa_tagstruct_put_boolean(reply
,
2579 s
->playing_for
> 0 &&
2580 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2581 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2582 pa_tagstruct_put_timeval(reply
, &tv
);
2583 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2584 pa_tagstruct_puts64(reply
, s
->write_index
);
2585 pa_tagstruct_puts64(reply
, s
->read_index
);
2587 if (c
->version
>= 13) {
2588 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2589 pa_tagstruct_putu64(reply
, s
->playing_for
);
2592 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2595 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2596 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2597 pa_tagstruct
*reply
;
2599 struct timeval tv
, now
;
2602 pa_native_connection_assert_ref(c
);
2605 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2606 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2607 !pa_tagstruct_eof(t
)) {
2612 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2613 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2614 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2616 /* Get an atomic snapshot of all timing parameters */
2617 pa_assert_se(pa_asyncmsgq_send(s
->source_output
->source
->asyncmsgq
, PA_MSGOBJECT(s
->source_output
), SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
, s
, 0, NULL
) == 0);
2619 reply
= reply_new(tag
);
2620 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2621 pa_tagstruct_put_usec(reply
,
2622 s
->current_source_latency
+
2623 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->sample_spec
));
2624 pa_tagstruct_put_boolean(reply
,
2625 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2626 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2627 pa_tagstruct_put_timeval(reply
, &tv
);
2628 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2629 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2630 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2631 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2634 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2635 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2638 const char *name
= NULL
;
2641 pa_tagstruct
*reply
;
2644 pa_native_connection_assert_ref(c
);
2647 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2648 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2649 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2650 pa_tagstruct_getu32(t
, &length
) < 0) {
2655 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2656 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2657 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2658 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2659 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2660 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2662 p
= pa_proplist_new();
2664 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2665 !pa_tagstruct_eof(t
)) {
2668 pa_proplist_free(p
);
2672 if (c
->version
< 13)
2673 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2675 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2676 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2678 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2679 pa_proplist_free(p
);
2680 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2683 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2684 pa_proplist_free(p
);
2686 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2688 reply
= reply_new(tag
);
2689 pa_tagstruct_putu32(reply
, s
->index
);
2690 pa_tagstruct_putu32(reply
, length
);
2691 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2694 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2695 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2700 pa_native_connection_assert_ref(c
);
2703 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2704 !pa_tagstruct_eof(t
)) {
2709 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2711 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2712 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2713 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2715 if (!s
->memchunk
.memblock
)
2716 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2717 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2718 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2720 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2722 upload_stream_unlink(s
);
2725 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2726 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2727 uint32_t sink_index
;
2730 const char *name
, *sink_name
;
2733 pa_tagstruct
*reply
;
2735 pa_native_connection_assert_ref(c
);
2738 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2740 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
2741 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
2742 pa_tagstruct_getu32(t
, &volume
) < 0 ||
2743 pa_tagstruct_gets(t
, &name
) < 0) {
2748 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
2749 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
2750 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2751 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2753 if (sink_index
!= PA_INVALID_INDEX
)
2754 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
2756 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
2758 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
2760 p
= pa_proplist_new();
2762 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2763 !pa_tagstruct_eof(t
)) {
2765 pa_proplist_free(p
);
2769 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
2771 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
2772 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2773 pa_proplist_free(p
);
2777 pa_proplist_free(p
);
2779 reply
= reply_new(tag
);
2781 if (c
->version
>= 13)
2782 pa_tagstruct_putu32(reply
, idx
);
2784 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2787 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2788 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2791 pa_native_connection_assert_ref(c
);
2794 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2795 !pa_tagstruct_eof(t
)) {
2800 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2801 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2803 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
2804 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2808 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2811 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
2814 pa_assert(original
);
2818 if (c
->version
< 12) {
2819 /* Before protocol version 12 we didn't support S32 samples,
2820 * so we need to lie about this to the client */
2822 if (fixed
->format
== PA_SAMPLE_S32LE
)
2823 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2824 if (fixed
->format
== PA_SAMPLE_S32BE
)
2825 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2828 if (c
->version
< 15) {
2829 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
2830 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2831 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
2832 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
2836 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
2837 pa_sample_spec fixed_ss
;
2840 pa_sink_assert_ref(sink
);
2842 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
2846 PA_TAG_U32
, sink
->index
,
2847 PA_TAG_STRING
, sink
->name
,
2848 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2849 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2850 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
2851 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
2852 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
2853 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
2854 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
2855 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
2856 PA_TAG_USEC
, pa_sink_get_latency(sink
),
2857 PA_TAG_STRING
, sink
->driver
,
2858 PA_TAG_U32
, sink
->flags
,
2861 if (c
->version
>= 13) {
2862 pa_tagstruct_put_proplist(t
, sink
->proplist
);
2863 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
2866 if (c
->version
>= 15) {
2867 pa_tagstruct_put_volume(t
, sink
->base_volume
);
2868 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
2869 pa_log_error("Internal sink state is invalid.");
2870 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
2871 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
2872 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
2875 if (c
->version
>= 16) {
2876 pa_tagstruct_putu32(t
, sink
->ports
? pa_hashmap_size(sink
->ports
) : 0);
2882 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
2883 pa_tagstruct_puts(t
, p
->name
);
2884 pa_tagstruct_puts(t
, p
->description
);
2885 pa_tagstruct_putu32(t
, p
->priority
);
2889 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
2893 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
2894 pa_sample_spec fixed_ss
;
2897 pa_source_assert_ref(source
);
2899 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
2903 PA_TAG_U32
, source
->index
,
2904 PA_TAG_STRING
, source
->name
,
2905 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
2906 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
2907 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
2908 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
2909 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
2910 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
2911 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
2912 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
2913 PA_TAG_USEC
, pa_source_get_latency(source
),
2914 PA_TAG_STRING
, source
->driver
,
2915 PA_TAG_U32
, source
->flags
,
2918 if (c
->version
>= 13) {
2919 pa_tagstruct_put_proplist(t
, source
->proplist
);
2920 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
2923 if (c
->version
>= 15) {
2924 pa_tagstruct_put_volume(t
, source
->base_volume
);
2925 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
2926 pa_log_error("Internal source state is invalid.");
2927 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
2928 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
2929 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
2932 if (c
->version
>= 16) {
2934 pa_tagstruct_putu32(t
, source
->ports
? pa_hashmap_size(source
->ports
) : 0);
2936 if (source
->ports
) {
2940 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
2941 pa_tagstruct_puts(t
, p
->name
);
2942 pa_tagstruct_puts(t
, p
->description
);
2943 pa_tagstruct_putu32(t
, p
->priority
);
2947 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
2951 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
2955 pa_tagstruct_putu32(t
, client
->index
);
2956 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
2957 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
2958 pa_tagstruct_puts(t
, client
->driver
);
2960 if (c
->version
>= 13)
2961 pa_tagstruct_put_proplist(t
, client
->proplist
);
2964 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
2971 pa_tagstruct_putu32(t
, card
->index
);
2972 pa_tagstruct_puts(t
, card
->name
);
2973 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
2974 pa_tagstruct_puts(t
, card
->driver
);
2976 pa_tagstruct_putu32(t
, card
->profiles
? pa_hashmap_size(card
->profiles
) : 0);
2978 if (card
->profiles
) {
2979 while ((p
= pa_hashmap_iterate(card
->profiles
, &state
, NULL
))) {
2980 pa_tagstruct_puts(t
, p
->name
);
2981 pa_tagstruct_puts(t
, p
->description
);
2982 pa_tagstruct_putu32(t
, p
->n_sinks
);
2983 pa_tagstruct_putu32(t
, p
->n_sources
);
2984 pa_tagstruct_putu32(t
, p
->priority
);
2988 pa_tagstruct_puts(t
, card
->active_profile
? card
->active_profile
->name
: NULL
);
2989 pa_tagstruct_put_proplist(t
, card
->proplist
);
2992 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
2996 pa_tagstruct_putu32(t
, module
->index
);
2997 pa_tagstruct_puts(t
, module
->name
);
2998 pa_tagstruct_puts(t
, module
->argument
);
2999 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
3001 if (c
->version
< 15)
3002 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
3004 if (c
->version
>= 15)
3005 pa_tagstruct_put_proplist(t
, module
->proplist
);
3008 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
3009 pa_sample_spec fixed_ss
;
3010 pa_usec_t sink_latency
;
3014 pa_sink_input_assert_ref(s
);
3016 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3018 pa_tagstruct_putu32(t
, s
->index
);
3019 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3020 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3021 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3022 pa_tagstruct_putu32(t
, s
->sink
->index
);
3023 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3024 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3025 pa_tagstruct_put_cvolume(t
, pa_sink_input_get_volume(s
, &v
, TRUE
));
3026 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3027 pa_tagstruct_put_usec(t
, sink_latency
);
3028 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3029 pa_tagstruct_puts(t
, s
->driver
);
3030 if (c
->version
>= 11)
3031 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3032 if (c
->version
>= 13)
3033 pa_tagstruct_put_proplist(t
, s
->proplist
);
3036 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3037 pa_sample_spec fixed_ss
;
3038 pa_usec_t source_latency
;
3041 pa_source_output_assert_ref(s
);
3043 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3045 pa_tagstruct_putu32(t
, s
->index
);
3046 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3047 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3048 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3049 pa_tagstruct_putu32(t
, s
->source
->index
);
3050 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3051 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3052 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3053 pa_tagstruct_put_usec(t
, source_latency
);
3054 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3055 pa_tagstruct_puts(t
, s
->driver
);
3057 if (c
->version
>= 13)
3058 pa_tagstruct_put_proplist(t
, s
->proplist
);
3061 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3062 pa_sample_spec fixed_ss
;
3068 if (e
->memchunk
.memblock
)
3069 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3071 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3073 pa_tagstruct_putu32(t
, e
->index
);
3074 pa_tagstruct_puts(t
, e
->name
);
3076 if (e
->volume_is_set
)
3079 pa_cvolume_init(&v
);
3081 pa_tagstruct_put_cvolume(t
, &v
);
3082 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3083 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3084 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3085 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3086 pa_tagstruct_put_boolean(t
, e
->lazy
);
3087 pa_tagstruct_puts(t
, e
->filename
);
3089 if (c
->version
>= 13)
3090 pa_tagstruct_put_proplist(t
, e
->proplist
);
3093 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3094 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3096 pa_sink
*sink
= NULL
;
3097 pa_source
*source
= NULL
;
3098 pa_client
*client
= NULL
;
3099 pa_card
*card
= NULL
;
3100 pa_module
*module
= NULL
;
3101 pa_sink_input
*si
= NULL
;
3102 pa_source_output
*so
= NULL
;
3103 pa_scache_entry
*sce
= NULL
;
3104 const char *name
= NULL
;
3105 pa_tagstruct
*reply
;
3107 pa_native_connection_assert_ref(c
);
3110 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3111 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3112 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3113 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3114 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3115 pa_tagstruct_gets(t
, &name
) < 0) ||
3116 !pa_tagstruct_eof(t
)) {
3121 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3122 CHECK_VALIDITY(c
->pstream
, !name
||
3123 (command
== PA_COMMAND_GET_SINK_INFO
&&
3124 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3125 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3126 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3127 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3128 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3129 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3130 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3132 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3133 if (idx
!= PA_INVALID_INDEX
)
3134 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3136 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3137 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3138 if (idx
!= PA_INVALID_INDEX
)
3139 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3141 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3142 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3143 if (idx
!= PA_INVALID_INDEX
)
3144 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3146 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3147 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3148 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3149 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3150 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3151 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3152 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3153 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3154 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3156 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3157 if (idx
!= PA_INVALID_INDEX
)
3158 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3160 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3163 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3164 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3168 reply
= reply_new(tag
);
3170 sink_fill_tagstruct(c
, reply
, sink
);
3172 source_fill_tagstruct(c
, reply
, source
);
3174 client_fill_tagstruct(c
, reply
, client
);
3176 card_fill_tagstruct(c
, reply
, card
);
3178 module_fill_tagstruct(c
, reply
, module
);
3180 sink_input_fill_tagstruct(c
, reply
, si
);
3182 source_output_fill_tagstruct(c
, reply
, so
);
3184 scache_fill_tagstruct(c
, reply
, sce
);
3185 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3188 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3189 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3193 pa_tagstruct
*reply
;
3195 pa_native_connection_assert_ref(c
);
3198 if (!pa_tagstruct_eof(t
)) {
3203 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3205 reply
= reply_new(tag
);
3207 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3208 i
= c
->protocol
->core
->sinks
;
3209 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3210 i
= c
->protocol
->core
->sources
;
3211 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3212 i
= c
->protocol
->core
->clients
;
3213 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3214 i
= c
->protocol
->core
->cards
;
3215 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3216 i
= c
->protocol
->core
->modules
;
3217 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3218 i
= c
->protocol
->core
->sink_inputs
;
3219 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3220 i
= c
->protocol
->core
->source_outputs
;
3222 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3223 i
= c
->protocol
->core
->scache
;
3227 for (p
= pa_idxset_first(i
, &idx
); p
; p
= pa_idxset_next(i
, &idx
)) {
3228 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3229 sink_fill_tagstruct(c
, reply
, p
);
3230 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3231 source_fill_tagstruct(c
, reply
, p
);
3232 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3233 client_fill_tagstruct(c
, reply
, p
);
3234 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3235 card_fill_tagstruct(c
, reply
, p
);
3236 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3237 module_fill_tagstruct(c
, reply
, p
);
3238 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3239 sink_input_fill_tagstruct(c
, reply
, p
);
3240 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3241 source_output_fill_tagstruct(c
, reply
, p
);
3243 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3244 scache_fill_tagstruct(c
, reply
, p
);
3249 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3252 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3253 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3254 pa_tagstruct
*reply
;
3256 pa_source
*def_source
;
3257 pa_sample_spec fixed_ss
;
3260 pa_native_connection_assert_ref(c
);
3263 if (!pa_tagstruct_eof(t
)) {
3268 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3270 reply
= reply_new(tag
);
3271 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3272 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3274 u
= pa_get_user_name_malloc();
3275 pa_tagstruct_puts(reply
, u
);
3278 h
= pa_get_host_name_malloc();
3279 pa_tagstruct_puts(reply
, h
);
3282 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3283 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3285 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3286 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3287 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3288 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3290 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3292 if (c
->version
>= 15)
3293 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3295 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3298 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3300 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3302 pa_native_connection_assert_ref(c
);
3304 t
= pa_tagstruct_new(NULL
, 0);
3305 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3306 pa_tagstruct_putu32(t
, (uint32_t) -1);
3307 pa_tagstruct_putu32(t
, e
);
3308 pa_tagstruct_putu32(t
, idx
);
3309 pa_pstream_send_tagstruct(c
->pstream
, t
);
3312 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3313 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3314 pa_subscription_mask_t m
;
3316 pa_native_connection_assert_ref(c
);
3319 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3320 !pa_tagstruct_eof(t
)) {
3325 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3326 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3328 if (c
->subscription
)
3329 pa_subscription_free(c
->subscription
);
3332 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3333 pa_assert(c
->subscription
);
3335 c
->subscription
= NULL
;
3337 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3340 static void command_set_volume(
3347 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3350 pa_sink
*sink
= NULL
;
3351 pa_source
*source
= NULL
;
3352 pa_sink_input
*si
= NULL
;
3353 const char *name
= NULL
;
3354 const char *client_name
;
3356 pa_native_connection_assert_ref(c
);
3359 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3360 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3361 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3362 pa_tagstruct_get_cvolume(t
, &volume
) ||
3363 !pa_tagstruct_eof(t
)) {
3368 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3369 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SET_SINK_VOLUME
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
3370 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3371 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3372 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3373 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3377 case PA_COMMAND_SET_SINK_VOLUME
:
3378 if (idx
!= PA_INVALID_INDEX
)
3379 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3381 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3384 case PA_COMMAND_SET_SOURCE_VOLUME
:
3385 if (idx
!= PA_INVALID_INDEX
)
3386 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3388 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3391 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3392 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3396 pa_assert_not_reached();
3399 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3401 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3404 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3406 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3407 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3408 } else if (source
) {
3409 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3411 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3412 pa_source_set_volume(source
, &volume
, TRUE
);
3414 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3416 pa_log_debug("Client %s changes volume of sink input %s.",
3418 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3419 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3422 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3425 static void command_set_mute(
3432 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3435 pa_sink
*sink
= NULL
;
3436 pa_source
*source
= NULL
;
3437 pa_sink_input
*si
= NULL
;
3438 const char *name
= NULL
, *client_name
;
3440 pa_native_connection_assert_ref(c
);
3443 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3444 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3445 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3446 pa_tagstruct_get_boolean(t
, &mute
) ||
3447 !pa_tagstruct_eof(t
)) {
3452 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3453 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SET_SINK_MUTE
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
3454 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3455 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3456 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3460 case PA_COMMAND_SET_SINK_MUTE
:
3461 if (idx
!= PA_INVALID_INDEX
)
3462 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3464 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3468 case PA_COMMAND_SET_SOURCE_MUTE
:
3469 if (idx
!= PA_INVALID_INDEX
)
3470 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3472 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3476 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3477 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3481 pa_assert_not_reached();
3484 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3486 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3489 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3490 pa_sink_set_mute(sink
, mute
, TRUE
);
3491 } else if (source
) {
3492 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3493 pa_source_set_mute(source
, mute
, TRUE
);
3495 pa_log_debug("Client %s changes mute of sink input %s.",
3497 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3498 pa_sink_input_set_mute(si
, mute
, TRUE
);
3501 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3504 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3505 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3510 pa_native_connection_assert_ref(c
);
3513 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3514 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3515 !pa_tagstruct_eof(t
)) {
3520 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3521 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3522 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3523 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3524 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3526 pa_sink_input_cork(s
->sink_input
, b
);
3529 s
->is_underrun
= TRUE
;
3531 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3534 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3535 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3539 pa_native_connection_assert_ref(c
);
3542 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3543 !pa_tagstruct_eof(t
)) {
3548 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3549 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3550 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3551 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3552 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3555 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3556 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3559 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3560 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3563 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3564 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3568 pa_assert_not_reached();
3571 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3574 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3575 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3580 pa_native_connection_assert_ref(c
);
3583 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3584 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3585 !pa_tagstruct_eof(t
)) {
3590 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3591 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3592 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3594 pa_source_output_cork(s
->source_output
, b
);
3595 pa_memblockq_prebuf_force(s
->memblockq
);
3596 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3599 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3600 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3604 pa_native_connection_assert_ref(c
);
3607 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3608 !pa_tagstruct_eof(t
)) {
3613 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3614 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3615 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3617 pa_memblockq_flush_read(s
->memblockq
);
3618 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3621 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3622 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3625 pa_tagstruct
*reply
;
3627 pa_native_connection_assert_ref(c
);
3630 memset(&a
, 0, sizeof(a
));
3632 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3637 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3639 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
3641 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3643 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3644 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3645 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3647 if (pa_tagstruct_get(
3649 PA_TAG_U32
, &a
.maxlength
,
3650 PA_TAG_U32
, &a
.tlength
,
3651 PA_TAG_U32
, &a
.prebuf
,
3652 PA_TAG_U32
, &a
.minreq
,
3653 PA_TAG_INVALID
) < 0 ||
3654 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3655 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3656 !pa_tagstruct_eof(t
)) {
3661 s
->adjust_latency
= adjust_latency
;
3662 s
->early_requests
= early_requests
;
3665 fix_playback_buffer_attr(s
);
3666 pa_assert_se(pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
, NULL
, 0, NULL
) == 0);
3668 reply
= reply_new(tag
);
3669 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3670 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
3671 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
3672 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
3674 if (c
->version
>= 13)
3675 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
3679 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3680 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
3682 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3683 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3685 if (pa_tagstruct_get(
3687 PA_TAG_U32
, &a
.maxlength
,
3688 PA_TAG_U32
, &a
.fragsize
,
3689 PA_TAG_INVALID
) < 0 ||
3690 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3691 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3692 !pa_tagstruct_eof(t
)) {
3697 s
->adjust_latency
= adjust_latency
;
3698 s
->early_requests
= early_requests
;
3701 fix_record_buffer_attr_pre(s
);
3702 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
3703 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
3704 fix_record_buffer_attr_post(s
);
3706 reply
= reply_new(tag
);
3707 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3708 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
3710 if (c
->version
>= 13)
3711 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
3714 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3717 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3718 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3722 pa_native_connection_assert_ref(c
);
3725 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3726 pa_tagstruct_getu32(t
, &rate
) < 0 ||
3727 !pa_tagstruct_eof(t
)) {
3732 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3733 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
3735 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
3738 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3739 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3740 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3742 pa_sink_input_set_rate(s
->sink_input
, rate
);
3746 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
3748 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3749 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3751 pa_source_output_set_rate(s
->source_output
, rate
);
3754 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3757 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3758 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3763 pa_native_connection_assert_ref(c
);
3766 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3768 p
= pa_proplist_new();
3770 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
3772 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
3773 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3774 !pa_tagstruct_eof(t
)) {
3776 pa_proplist_free(p
);
3782 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3783 pa_tagstruct_getu32(t
, &mode
) < 0 ||
3784 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3785 !pa_tagstruct_eof(t
)) {
3787 pa_proplist_free(p
);
3792 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
3793 pa_proplist_free(p
);
3794 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
3797 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
3800 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3801 if (!s
|| !playback_stream_isinstance(s
)) {
3802 pa_proplist_free(p
);
3803 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3805 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
3807 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
3810 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
3811 pa_proplist_free(p
);
3812 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
3814 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
3817 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
3819 pa_client_update_proplist(c
->client
, mode
, p
);
3822 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3823 pa_proplist_free(p
);
3826 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3827 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3829 unsigned changed
= 0;
3831 pa_strlist
*l
= NULL
;
3833 pa_native_connection_assert_ref(c
);
3836 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3838 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
3840 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3846 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3849 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3850 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3851 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3853 p
= s
->sink_input
->proplist
;
3855 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3858 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3859 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3861 p
= s
->source_output
->proplist
;
3863 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3865 p
= c
->client
->proplist
;
3871 if (pa_tagstruct_gets(t
, &k
) < 0) {
3880 l
= pa_strlist_prepend(l
, k
);
3883 if (!pa_tagstruct_eof(t
)) {
3892 l
= pa_strlist_pop(l
, &z
);
3897 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
3901 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3904 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
3907 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3908 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
3910 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
3913 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3914 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
3917 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
3918 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
3923 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3924 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3927 pa_native_connection_assert_ref(c
);
3930 if (pa_tagstruct_gets(t
, &s
) < 0 ||
3931 !pa_tagstruct_eof(t
)) {
3936 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3937 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
3939 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
3942 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
3943 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
3945 pa_namereg_set_default_source(c
->protocol
->core
, source
);
3948 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
3950 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
3951 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3953 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
3956 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3959 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3960 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3964 pa_native_connection_assert_ref(c
);
3967 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3968 pa_tagstruct_gets(t
, &name
) < 0 ||
3969 !pa_tagstruct_eof(t
)) {
3974 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3975 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
3977 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
3980 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3981 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3982 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3984 pa_sink_input_set_name(s
->sink_input
, name
);
3988 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
3990 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3991 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3993 pa_source_output_set_name(s
->source_output
, name
);
3996 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3999 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4000 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4003 pa_native_connection_assert_ref(c
);
4006 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4007 !pa_tagstruct_eof(t
)) {
4012 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4014 if (command
== PA_COMMAND_KILL_CLIENT
) {
4017 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4018 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4020 pa_native_connection_ref(c
);
4021 pa_client_kill(client
);
4023 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4026 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4027 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4029 pa_native_connection_ref(c
);
4030 pa_sink_input_kill(s
);
4032 pa_source_output
*s
;
4034 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4036 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4037 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4039 pa_native_connection_ref(c
);
4040 pa_source_output_kill(s
);
4043 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4044 pa_native_connection_unref(c
);
4047 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4048 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4050 const char *name
, *argument
;
4051 pa_tagstruct
*reply
;
4053 pa_native_connection_assert_ref(c
);
4056 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4057 pa_tagstruct_gets(t
, &argument
) < 0 ||
4058 !pa_tagstruct_eof(t
)) {
4063 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4064 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4065 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4067 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4068 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4072 reply
= reply_new(tag
);
4073 pa_tagstruct_putu32(reply
, m
->index
);
4074 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4077 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4078 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4082 pa_native_connection_assert_ref(c
);
4085 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4086 !pa_tagstruct_eof(t
)) {
4091 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4092 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4093 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4095 pa_module_unload_request(m
, FALSE
);
4096 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4099 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4100 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4101 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4102 const char *name_device
= NULL
;
4104 pa_native_connection_assert_ref(c
);
4107 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4108 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4109 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4110 !pa_tagstruct_eof(t
)) {
4115 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4116 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4118 CHECK_VALIDITY(c
->pstream
, !name_device
|| pa_namereg_is_valid_name_or_wildcard(name_device
, command
== PA_COMMAND_MOVE_SINK_INPUT
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
4119 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4120 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4121 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4123 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4124 pa_sink_input
*si
= NULL
;
4125 pa_sink
*sink
= NULL
;
4127 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4129 if (idx_device
!= PA_INVALID_INDEX
)
4130 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4132 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4134 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4136 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4137 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4141 pa_source_output
*so
= NULL
;
4144 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4146 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4148 if (idx_device
!= PA_INVALID_INDEX
)
4149 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4151 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4153 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4155 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4156 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4161 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4164 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4165 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4166 uint32_t idx
= PA_INVALID_INDEX
;
4167 const char *name
= NULL
;
4170 pa_native_connection_assert_ref(c
);
4173 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4174 pa_tagstruct_gets(t
, &name
) < 0 ||
4175 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4176 !pa_tagstruct_eof(t
)) {
4181 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4182 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SUSPEND_SINK
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
) || *name
== 0, tag
, PA_ERR_INVALID
);
4183 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4184 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4185 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4187 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4189 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4191 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4193 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4194 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4198 pa_sink
*sink
= NULL
;
4200 if (idx
!= PA_INVALID_INDEX
)
4201 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4203 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4205 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4207 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4208 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4214 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4216 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4218 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4220 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4221 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4228 if (idx
!= PA_INVALID_INDEX
)
4229 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4231 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4233 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4235 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4236 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4242 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4245 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4246 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4247 uint32_t idx
= PA_INVALID_INDEX
;
4248 const char *name
= NULL
;
4250 pa_native_protocol_ext_cb_t cb
;
4252 pa_native_connection_assert_ref(c
);
4255 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4256 pa_tagstruct_gets(t
, &name
) < 0) {
4261 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4262 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4263 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4264 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4265 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4267 if (idx
!= PA_INVALID_INDEX
)
4268 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4270 for (m
= pa_idxset_first(c
->protocol
->core
->modules
, &idx
); m
; m
= pa_idxset_next(c
->protocol
->core
->modules
, &idx
))
4271 if (strcmp(name
, m
->name
) == 0)
4275 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4276 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4278 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4279 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4281 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4285 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4286 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4287 uint32_t idx
= PA_INVALID_INDEX
;
4288 const char *name
= NULL
, *profile
= NULL
;
4289 pa_card
*card
= NULL
;
4292 pa_native_connection_assert_ref(c
);
4295 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4296 pa_tagstruct_gets(t
, &name
) < 0 ||
4297 pa_tagstruct_gets(t
, &profile
) < 0 ||
4298 !pa_tagstruct_eof(t
)) {
4303 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4304 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4305 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4306 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4307 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4309 if (idx
!= PA_INVALID_INDEX
)
4310 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4312 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4314 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4316 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4317 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4321 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4324 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4325 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4326 uint32_t idx
= PA_INVALID_INDEX
;
4327 const char *name
= NULL
, *port
= NULL
;
4330 pa_native_connection_assert_ref(c
);
4333 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4334 pa_tagstruct_gets(t
, &name
) < 0 ||
4335 pa_tagstruct_gets(t
, &port
) < 0 ||
4336 !pa_tagstruct_eof(t
)) {
4341 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4342 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name_or_wildcard(name
, command
== PA_COMMAND_SET_SINK_PORT
? PA_NAMEREG_SINK
: PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
);
4343 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4344 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4345 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4347 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4350 if (idx
!= PA_INVALID_INDEX
)
4351 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4353 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4355 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4357 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4358 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4364 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4366 if (idx
!= PA_INVALID_INDEX
)
4367 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4369 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4371 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4373 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4374 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4379 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4382 /*** pstream callbacks ***/
4384 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4385 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4389 pa_native_connection_assert_ref(c
);
4391 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4392 pa_log("invalid packet.");
4393 native_connection_unlink(c
);
4397 static void pstream_memblock_callback(pa_pstream
*p
, uint32_t channel
, int64_t offset
, pa_seek_mode_t seek
, const pa_memchunk
*chunk
, void *userdata
) {
4398 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4399 output_stream
*stream
;
4403 pa_native_connection_assert_ref(c
);
4405 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4406 pa_log_debug("Client sent block for invalid stream.");
4411 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4413 if (playback_stream_isinstance(stream
)) {
4414 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4416 if (chunk
->memblock
) {
4417 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4418 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_SEEK
, PA_UINT_TO_PTR(seek
), offset
, NULL
, NULL
);
4420 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4422 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_SEEK
, PA_UINT_TO_PTR(seek
), offset
+chunk
->length
, NULL
, NULL
);
4425 upload_stream
*u
= UPLOAD_STREAM(stream
);
4428 if (!u
->memchunk
.memblock
) {
4429 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4430 u
->memchunk
= *chunk
;
4431 pa_memblock_ref(u
->memchunk
.memblock
);
4434 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4435 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4439 pa_assert(u
->memchunk
.memblock
);
4442 if (l
> chunk
->length
)
4447 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4449 if (chunk
->memblock
) {
4451 src
= pa_memblock_acquire(chunk
->memblock
);
4453 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4454 (uint8_t*) src
+ chunk
->index
, l
);
4456 pa_memblock_release(chunk
->memblock
);
4458 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4460 pa_memblock_release(u
->memchunk
.memblock
);
4462 u
->memchunk
.length
+= l
;
4468 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4469 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4472 pa_native_connection_assert_ref(c
);
4474 native_connection_unlink(c
);
4475 pa_log_info("Connection died.");
4478 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4479 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4482 pa_native_connection_assert_ref(c
);
4484 native_connection_send_memblock(c
);
4487 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4490 if (!(q
= pa_thread_mq_get()))
4491 pa_pstream_send_revoke(p
, block_id
);
4493 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4496 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4499 if (!(q
= pa_thread_mq_get()))
4500 pa_pstream_send_release(p
, block_id
);
4502 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4505 /*** client callbacks ***/
4507 static void client_kill_cb(pa_client
*c
) {
4510 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4511 pa_log_info("Connection killed.");
4514 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4516 pa_native_connection
*c
;
4519 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4520 pa_native_connection_assert_ref(c
);
4522 if (c
->version
< 15)
4525 t
= pa_tagstruct_new(NULL
, 0);
4526 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4527 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4528 pa_tagstruct_puts(t
, event
);
4529 pa_tagstruct_put_proplist(t
, pl
);
4530 pa_pstream_send_tagstruct(c
->pstream
, t
);
4533 /*** module entry points ***/
4535 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4536 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4539 pa_native_connection_assert_ref(c
);
4540 pa_assert(c
->auth_timeout_event
== e
);
4542 if (!c
->authorized
) {
4543 native_connection_unlink(c
);
4544 pa_log_info("Connection terminated due to authentication timeout.");
4548 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4549 pa_native_connection
*c
;
4552 pa_client_new_data data
;
4558 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4559 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4560 pa_iochannel_free(io
);
4564 pa_client_new_data_init(&data
);
4565 data
.module
= o
->module
;
4566 data
.driver
= __FILE__
;
4567 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4568 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4569 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4570 client
= pa_client_new(p
->core
, &data
);
4571 pa_client_new_data_done(&data
);
4576 c
= pa_msgobject_new(pa_native_connection
);
4577 c
->parent
.parent
.free
= native_connection_free
;
4578 c
->parent
.process_msg
= native_connection_process_msg
;
4580 c
->options
= pa_native_options_ref(o
);
4581 c
->authorized
= FALSE
;
4583 if (o
->auth_anonymous
) {
4584 pa_log_info("Client authenticated anonymously.");
4585 c
->authorized
= TRUE
;
4588 if (!c
->authorized
&&
4590 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
4592 pa_log_info("Client authenticated by IP ACL.");
4593 c
->authorized
= TRUE
;
4597 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
4599 c
->auth_timeout_event
= NULL
;
4601 c
->is_local
= pa_iochannel_socket_is_local(io
);
4605 c
->client
->kill
= client_kill_cb
;
4606 c
->client
->send_event
= client_send_event_cb
;
4607 c
->client
->userdata
= c
;
4609 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
4610 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
4611 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
4612 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
4613 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
4614 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
4615 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
4617 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
4619 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
4620 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
4622 c
->rrobin_index
= PA_IDXSET_INVALID
;
4623 c
->subscription
= NULL
;
4625 pa_idxset_put(p
->connections
, c
, NULL
);
4628 if (pa_iochannel_creds_supported(io
))
4629 pa_iochannel_creds_enable(io
);
4632 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
4635 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
4636 pa_native_connection
*c
;
4642 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
4643 if (c
->options
->module
== m
)
4644 native_connection_unlink(c
);
4647 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
4648 pa_native_protocol
*p
;
4653 p
= pa_xnew(pa_native_protocol
, 1);
4656 p
->connections
= pa_idxset_new(NULL
, NULL
);
4660 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
4662 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4663 pa_hook_init(&p
->hooks
[h
], p
);
4665 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
4670 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
4671 pa_native_protocol
*p
;
4673 if ((p
= pa_shared_get(c
, "native-protocol")))
4674 return pa_native_protocol_ref(p
);
4676 return native_protocol_new(c
);
4679 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
4681 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4688 void pa_native_protocol_unref(pa_native_protocol
*p
) {
4689 pa_native_connection
*c
;
4693 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4695 if (PA_REFCNT_DEC(p
) > 0)
4698 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
4699 native_connection_unlink(c
);
4701 pa_idxset_free(p
->connections
, NULL
, NULL
);
4703 pa_strlist_free(p
->servers
);
4705 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4706 pa_hook_done(&p
->hooks
[h
]);
4708 pa_hashmap_free(p
->extensions
, NULL
, NULL
);
4710 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
4715 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
4717 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4720 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
4722 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4725 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
4727 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4730 p
->servers
= pa_strlist_remove(p
->servers
, name
);
4732 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4735 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
4737 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4742 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
4744 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4749 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
4751 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4754 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
4756 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
4760 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
4762 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4765 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
4768 pa_native_options
* pa_native_options_new(void) {
4769 pa_native_options
*o
;
4771 o
= pa_xnew0(pa_native_options
, 1);
4777 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
4779 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4786 void pa_native_options_unref(pa_native_options
*o
) {
4788 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4790 if (PA_REFCNT_DEC(o
) > 0)
4793 pa_xfree(o
->auth_group
);
4796 pa_ip_acl_free(o
->auth_ip_acl
);
4799 pa_auth_cookie_unref(o
->auth_cookie
);
4804 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
4809 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4812 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
4813 pa_log("auth-anonymous= expects a boolean argument.");
4818 if (pa_modargs_get_value_boolean(ma
, "auth-group-enabled", &enabled
) < 0) {
4819 pa_log("auth-group-enabled= expects a boolean argument.");
4823 pa_xfree(o
->auth_group
);
4824 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
4828 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4831 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
4834 if (!(ipa
= pa_ip_acl_new(acl
))) {
4835 pa_log("Failed to parse IP ACL '%s'", acl
);
4840 pa_ip_acl_free(o
->auth_ip_acl
);
4842 o
->auth_ip_acl
= ipa
;
4846 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
4847 pa_log("auth-cookie-enabled= expects a boolean argument.");
4852 pa_auth_cookie_unref(o
->auth_cookie
);
4857 /* The new name for this is 'auth-cookie', for compat reasons
4858 * we check the old name too */
4859 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
4860 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
4861 cn
= PA_NATIVE_COOKIE_FILE
;
4863 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, PA_NATIVE_COOKIE_LENGTH
)))
4867 o
->auth_cookie
= NULL
;
4872 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
4873 pa_native_connection_assert_ref(c
);
4878 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
4879 pa_native_connection_assert_ref(c
);