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>
38 #include <pulse/internal.h>
40 #include <pulsecore/native-common.h>
41 #include <pulsecore/packet.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/source-output.h>
44 #include <pulsecore/sink-input.h>
45 #include <pulsecore/pstream.h>
46 #include <pulsecore/tagstruct.h>
47 #include <pulsecore/pdispatch.h>
48 #include <pulsecore/pstream-util.h>
49 #include <pulsecore/authkey.h>
50 #include <pulsecore/namereg.h>
51 #include <pulsecore/core-scache.h>
52 #include <pulsecore/core-subscribe.h>
53 #include <pulsecore/log.h>
54 #include <pulsecore/strlist.h>
55 #include <pulsecore/shared.h>
56 #include <pulsecore/sample-util.h>
57 #include <pulsecore/llist.h>
58 #include <pulsecore/creds.h>
59 #include <pulsecore/core-util.h>
60 #include <pulsecore/ipacl.h>
61 #include <pulsecore/thread-mq.h>
63 #include "protocol-native.h"
65 /* Kick a client if it doesn't authenticate within this time */
66 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
68 /* Don't accept more connection than this */
69 #define MAX_CONNECTIONS 64
71 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
72 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
73 #define DEFAULT_PROCESS_MSEC 20 /* 20ms */
74 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
76 struct pa_native_protocol
;
78 typedef struct record_stream
{
81 pa_native_connection
*connection
;
84 pa_source_output
*source_output
;
85 pa_memblockq
*memblockq
;
87 pa_bool_t adjust_latency
:1;
88 pa_bool_t early_requests
:1;
90 /* Requested buffer attributes */
91 pa_buffer_attr buffer_attr_req
;
92 /* Fixed-up and adjusted buffer attributes */
93 pa_buffer_attr buffer_attr
;
95 pa_atomic_t on_the_fly
;
96 pa_usec_t configured_source_latency
;
99 /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
100 size_t on_the_fly_snapshot
;
101 pa_usec_t current_monitor_latency
;
102 pa_usec_t current_source_latency
;
105 #define RECORD_STREAM(o) (record_stream_cast(o))
106 PA_DEFINE_PRIVATE_CLASS(record_stream
, pa_msgobject
);
108 typedef struct output_stream
{
112 #define OUTPUT_STREAM(o) (output_stream_cast(o))
113 PA_DEFINE_PRIVATE_CLASS(output_stream
, pa_msgobject
);
115 typedef struct playback_stream
{
116 output_stream parent
;
118 pa_native_connection
*connection
;
121 pa_sink_input
*sink_input
;
122 pa_memblockq
*memblockq
;
124 pa_bool_t adjust_latency
:1;
125 pa_bool_t early_requests
:1;
127 pa_bool_t is_underrun
:1;
128 pa_bool_t drain_request
:1;
132 /* Optimization to avoid too many rewinds with a lot of small blocks */
133 pa_atomic_t seek_or_post_in_queue
;
137 pa_usec_t configured_sink_latency
;
138 /* Requested buffer attributes */
139 pa_buffer_attr buffer_attr_req
;
140 /* Fixed-up and adjusted buffer attributes */
141 pa_buffer_attr buffer_attr
;
143 /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
144 int64_t read_index
, write_index
;
145 size_t render_memblockq_length
;
146 pa_usec_t current_sink_latency
;
147 uint64_t playing_for
, underrun_for
;
150 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
151 PA_DEFINE_PRIVATE_CLASS(playback_stream
, output_stream
);
153 typedef struct upload_stream
{
154 output_stream parent
;
156 pa_native_connection
*connection
;
159 pa_memchunk memchunk
;
162 pa_sample_spec sample_spec
;
163 pa_channel_map channel_map
;
164 pa_proplist
*proplist
;
167 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
168 PA_DEFINE_PRIVATE_CLASS(upload_stream
, output_stream
);
170 struct pa_native_connection
{
172 pa_native_protocol
*protocol
;
173 pa_native_options
*options
;
174 pa_bool_t authorized
:1;
175 pa_bool_t is_local
:1;
179 pa_pdispatch
*pdispatch
;
180 pa_idxset
*record_streams
, *output_streams
;
181 uint32_t rrobin_index
;
182 pa_subscription
*subscription
;
183 pa_time_event
*auth_timeout_event
;
186 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
187 PA_DEFINE_PRIVATE_CLASS(pa_native_connection
, pa_msgobject
);
189 struct pa_native_protocol
{
193 pa_idxset
*connections
;
196 pa_hook hooks
[PA_NATIVE_HOOK_MAX
];
198 pa_hashmap
*extensions
;
202 SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
= PA_SOURCE_OUTPUT_MESSAGE_MAX
206 SINK_INPUT_MESSAGE_POST_DATA
= PA_SINK_INPUT_MESSAGE_MAX
, /* data from main loop to sink input */
207 SINK_INPUT_MESSAGE_DRAIN
, /* disabled prebuf, get playback started. */
208 SINK_INPUT_MESSAGE_FLUSH
,
209 SINK_INPUT_MESSAGE_TRIGGER
,
210 SINK_INPUT_MESSAGE_SEEK
,
211 SINK_INPUT_MESSAGE_PREBUF_FORCE
,
212 SINK_INPUT_MESSAGE_UPDATE_LATENCY
,
213 SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
217 PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, /* data requested from sink input from the main loop */
218 PLAYBACK_STREAM_MESSAGE_UNDERFLOW
,
219 PLAYBACK_STREAM_MESSAGE_OVERFLOW
,
220 PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
,
221 PLAYBACK_STREAM_MESSAGE_STARTED
,
222 PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
226 RECORD_STREAM_MESSAGE_POST_DATA
/* data from source output to main loop */
230 CONNECTION_MESSAGE_RELEASE
,
231 CONNECTION_MESSAGE_REVOKE
234 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
235 static void sink_input_kill_cb(pa_sink_input
*i
);
236 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
);
237 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
);
238 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
239 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
240 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
);
241 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
);
243 static void native_connection_send_memblock(pa_native_connection
*c
);
244 static void playback_stream_request_bytes(struct playback_stream
*s
);
246 static void source_output_kill_cb(pa_source_output
*o
);
247 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
248 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
);
249 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
);
250 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
251 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
);
253 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
254 static int source_output_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
256 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
257 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
258 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
259 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
260 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
261 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
262 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
263 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
264 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
265 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
266 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
267 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
268 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
269 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
270 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
271 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
272 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
273 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
274 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
275 static void command_set_volume(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
276 static void command_set_mute(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
277 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
278 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
279 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
280 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
281 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
282 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
283 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
284 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
285 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
286 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
287 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
288 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
289 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
290 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
291 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
292 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
293 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
294 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
296 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
297 [PA_COMMAND_ERROR
] = NULL
,
298 [PA_COMMAND_TIMEOUT
] = NULL
,
299 [PA_COMMAND_REPLY
] = NULL
,
300 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = command_create_playback_stream
,
301 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = command_delete_stream
,
302 [PA_COMMAND_DRAIN_PLAYBACK_STREAM
] = command_drain_playback_stream
,
303 [PA_COMMAND_CREATE_RECORD_STREAM
] = command_create_record_stream
,
304 [PA_COMMAND_DELETE_RECORD_STREAM
] = command_delete_stream
,
305 [PA_COMMAND_AUTH
] = command_auth
,
306 [PA_COMMAND_REQUEST
] = NULL
,
307 [PA_COMMAND_EXIT
] = command_exit
,
308 [PA_COMMAND_SET_CLIENT_NAME
] = command_set_client_name
,
309 [PA_COMMAND_LOOKUP_SINK
] = command_lookup
,
310 [PA_COMMAND_LOOKUP_SOURCE
] = command_lookup
,
311 [PA_COMMAND_STAT
] = command_stat
,
312 [PA_COMMAND_GET_PLAYBACK_LATENCY
] = command_get_playback_latency
,
313 [PA_COMMAND_GET_RECORD_LATENCY
] = command_get_record_latency
,
314 [PA_COMMAND_CREATE_UPLOAD_STREAM
] = command_create_upload_stream
,
315 [PA_COMMAND_DELETE_UPLOAD_STREAM
] = command_delete_stream
,
316 [PA_COMMAND_FINISH_UPLOAD_STREAM
] = command_finish_upload_stream
,
317 [PA_COMMAND_PLAY_SAMPLE
] = command_play_sample
,
318 [PA_COMMAND_REMOVE_SAMPLE
] = command_remove_sample
,
319 [PA_COMMAND_GET_SINK_INFO
] = command_get_info
,
320 [PA_COMMAND_GET_SOURCE_INFO
] = command_get_info
,
321 [PA_COMMAND_GET_CLIENT_INFO
] = command_get_info
,
322 [PA_COMMAND_GET_CARD_INFO
] = command_get_info
,
323 [PA_COMMAND_GET_MODULE_INFO
] = command_get_info
,
324 [PA_COMMAND_GET_SINK_INPUT_INFO
] = command_get_info
,
325 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO
] = command_get_info
,
326 [PA_COMMAND_GET_SAMPLE_INFO
] = command_get_info
,
327 [PA_COMMAND_GET_SINK_INFO_LIST
] = command_get_info_list
,
328 [PA_COMMAND_GET_SOURCE_INFO_LIST
] = command_get_info_list
,
329 [PA_COMMAND_GET_MODULE_INFO_LIST
] = command_get_info_list
,
330 [PA_COMMAND_GET_CLIENT_INFO_LIST
] = command_get_info_list
,
331 [PA_COMMAND_GET_CARD_INFO_LIST
] = command_get_info_list
,
332 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST
] = command_get_info_list
,
333 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
] = command_get_info_list
,
334 [PA_COMMAND_GET_SAMPLE_INFO_LIST
] = command_get_info_list
,
335 [PA_COMMAND_GET_SERVER_INFO
] = command_get_server_info
,
336 [PA_COMMAND_SUBSCRIBE
] = command_subscribe
,
338 [PA_COMMAND_SET_SINK_VOLUME
] = command_set_volume
,
339 [PA_COMMAND_SET_SINK_INPUT_VOLUME
] = command_set_volume
,
340 [PA_COMMAND_SET_SOURCE_VOLUME
] = command_set_volume
,
342 [PA_COMMAND_SET_SINK_MUTE
] = command_set_mute
,
343 [PA_COMMAND_SET_SINK_INPUT_MUTE
] = command_set_mute
,
344 [PA_COMMAND_SET_SOURCE_MUTE
] = command_set_mute
,
346 [PA_COMMAND_SUSPEND_SINK
] = command_suspend
,
347 [PA_COMMAND_SUSPEND_SOURCE
] = command_suspend
,
349 [PA_COMMAND_CORK_PLAYBACK_STREAM
] = command_cork_playback_stream
,
350 [PA_COMMAND_FLUSH_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
351 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
352 [PA_COMMAND_PREBUF_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
354 [PA_COMMAND_CORK_RECORD_STREAM
] = command_cork_record_stream
,
355 [PA_COMMAND_FLUSH_RECORD_STREAM
] = command_flush_record_stream
,
357 [PA_COMMAND_SET_DEFAULT_SINK
] = command_set_default_sink_or_source
,
358 [PA_COMMAND_SET_DEFAULT_SOURCE
] = command_set_default_sink_or_source
,
359 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME
] = command_set_stream_name
,
360 [PA_COMMAND_SET_RECORD_STREAM_NAME
] = command_set_stream_name
,
361 [PA_COMMAND_KILL_CLIENT
] = command_kill
,
362 [PA_COMMAND_KILL_SINK_INPUT
] = command_kill
,
363 [PA_COMMAND_KILL_SOURCE_OUTPUT
] = command_kill
,
364 [PA_COMMAND_LOAD_MODULE
] = command_load_module
,
365 [PA_COMMAND_UNLOAD_MODULE
] = command_unload_module
,
367 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE
] = NULL
,
368 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE
] = NULL
,
369 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE
] = NULL
,
370 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE
] = NULL
,
372 [PA_COMMAND_MOVE_SINK_INPUT
] = command_move_stream
,
373 [PA_COMMAND_MOVE_SOURCE_OUTPUT
] = command_move_stream
,
375 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
376 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
378 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
379 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
381 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
] = command_update_proplist
,
382 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
] = command_update_proplist
,
383 [PA_COMMAND_UPDATE_CLIENT_PROPLIST
] = command_update_proplist
,
385 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
] = command_remove_proplist
,
386 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
] = command_remove_proplist
,
387 [PA_COMMAND_REMOVE_CLIENT_PROPLIST
] = command_remove_proplist
,
389 [PA_COMMAND_SET_CARD_PROFILE
] = command_set_card_profile
,
391 [PA_COMMAND_SET_SINK_PORT
] = command_set_sink_or_source_port
,
392 [PA_COMMAND_SET_SOURCE_PORT
] = command_set_sink_or_source_port
,
394 [PA_COMMAND_EXTENSION
] = command_extension
397 /* structure management */
399 /* Called from main context */
400 static void upload_stream_unlink(upload_stream
*s
) {
406 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
407 s
->connection
= NULL
;
408 upload_stream_unref(s
);
411 /* Called from main context */
412 static void upload_stream_free(pa_object
*o
) {
413 upload_stream
*s
= UPLOAD_STREAM(o
);
416 upload_stream_unlink(s
);
421 pa_proplist_free(s
->proplist
);
423 if (s
->memchunk
.memblock
)
424 pa_memblock_unref(s
->memchunk
.memblock
);
429 /* Called from main context */
430 static upload_stream
* upload_stream_new(
431 pa_native_connection
*c
,
432 const pa_sample_spec
*ss
,
433 const pa_channel_map
*map
,
443 pa_assert(length
> 0);
446 s
= pa_msgobject_new(upload_stream
);
447 s
->parent
.parent
.parent
.free
= upload_stream_free
;
449 s
->sample_spec
= *ss
;
450 s
->channel_map
= *map
;
451 s
->name
= pa_xstrdup(name
);
452 pa_memchunk_reset(&s
->memchunk
);
454 s
->proplist
= pa_proplist_copy(p
);
455 pa_proplist_update(s
->proplist
, PA_UPDATE_MERGE
, c
->client
->proplist
);
457 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
462 /* Called from main context */
463 static void record_stream_unlink(record_stream
*s
) {
469 if (s
->source_output
) {
470 pa_source_output_unlink(s
->source_output
);
471 pa_source_output_unref(s
->source_output
);
472 s
->source_output
= NULL
;
475 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->record_streams
, s
, NULL
) == s
);
476 s
->connection
= NULL
;
477 record_stream_unref(s
);
480 /* Called from main context */
481 static void record_stream_free(pa_object
*o
) {
482 record_stream
*s
= RECORD_STREAM(o
);
485 record_stream_unlink(s
);
487 pa_memblockq_free(s
->memblockq
);
491 /* Called from main context */
492 static int record_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
493 record_stream
*s
= RECORD_STREAM(o
);
494 record_stream_assert_ref(s
);
501 case RECORD_STREAM_MESSAGE_POST_DATA
:
503 /* We try to keep up to date with how many bytes are
504 * currently on the fly */
505 pa_atomic_sub(&s
->on_the_fly
, chunk
->length
);
507 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
508 /* pa_log_warn("Failed to push data into output queue."); */
512 if (!pa_pstream_is_pending(s
->connection
->pstream
))
513 native_connection_send_memblock(s
->connection
);
521 /* Called from main context */
522 static void fix_record_buffer_attr_pre(record_stream
*s
) {
525 pa_usec_t orig_fragsize_usec
, fragsize_usec
, source_usec
;
529 /* This function will be called from the main thread, before as
530 * well as after the source output has been activated using
531 * pa_source_output_put()! That means it may not touch any
532 * ->thread_info data! */
534 frame_size
= pa_frame_size(&s
->source_output
->sample_spec
);
535 s
->buffer_attr
= s
->buffer_attr_req
;
537 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
538 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
539 if (s
->buffer_attr
.maxlength
<= 0)
540 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
542 if (s
->buffer_attr
.fragsize
== (uint32_t) -1)
543 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC
*PA_USEC_PER_MSEC
, &s
->source_output
->sample_spec
);
544 if (s
->buffer_attr
.fragsize
<= 0)
545 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
547 orig_fragsize_usec
= fragsize_usec
= pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &s
->source_output
->sample_spec
);
549 if (s
->early_requests
) {
551 /* In early request mode we need to emulate the classic
552 * fragment-based playback model. We do this setting the source
553 * latency to the fragment size. */
555 source_usec
= fragsize_usec
;
557 } else if (s
->adjust_latency
) {
559 /* So, the user asked us to adjust the latency according to
560 * what the source can provide. Half the latency will be
561 * spent on the hw buffer, half of it in the async buffer
562 * queue we maintain for each client. */
564 source_usec
= fragsize_usec
/2;
568 /* Ok, the user didn't ask us to adjust the latency, hence we
571 source_usec
= (pa_usec_t
) -1;
574 if (source_usec
!= (pa_usec_t
) -1)
575 s
->configured_source_latency
= pa_source_output_set_requested_latency(s
->source_output
, source_usec
);
577 s
->configured_source_latency
= 0;
579 if (s
->early_requests
) {
581 /* Ok, we didn't necessarily get what we were asking for, so
582 * let's tell the user */
584 fragsize_usec
= s
->configured_source_latency
;
586 } else if (s
->adjust_latency
) {
588 /* Now subtract what we actually got */
590 if (fragsize_usec
>= s
->configured_source_latency
*2)
591 fragsize_usec
-= s
->configured_source_latency
;
593 fragsize_usec
= s
->configured_source_latency
;
596 if (pa_usec_to_bytes(orig_fragsize_usec
, &s
->source_output
->sample_spec
) !=
597 pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
))
599 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
);
601 if (s
->buffer_attr
.fragsize
<= 0)
602 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
605 /* Called from main context */
606 static void fix_record_buffer_attr_post(record_stream
*s
) {
611 /* This function will be called from the main thread, before as
612 * well as after the source output has been activated using
613 * pa_source_output_put()! That means it may not touch and
614 * ->thread_info data! */
616 base
= pa_frame_size(&s
->source_output
->sample_spec
);
618 s
->buffer_attr
.fragsize
= (s
->buffer_attr
.fragsize
/base
)*base
;
619 if (s
->buffer_attr
.fragsize
<= 0)
620 s
->buffer_attr
.fragsize
= base
;
622 if (s
->buffer_attr
.fragsize
> s
->buffer_attr
.maxlength
)
623 s
->buffer_attr
.fragsize
= s
->buffer_attr
.maxlength
;
626 /* Called from main context */
627 static record_stream
* record_stream_new(
628 pa_native_connection
*c
,
633 pa_buffer_attr
*attr
,
634 pa_source_output_flags_t flags
,
636 pa_bool_t adjust_latency
,
637 pa_bool_t early_requests
,
638 pa_bool_t peak_detect
,
639 pa_sink_input
*direct_on_input
,
643 pa_source_output
*source_output
= NULL
;
644 pa_source_output_new_data data
;
651 pa_source_output_new_data_init(&data
);
653 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
654 data
.driver
= __FILE__
;
655 data
.module
= c
->options
->module
;
656 data
.client
= c
->client
;
658 pa_source_output_new_data_set_source(&data
, source
, TRUE
);
659 if (pa_sample_spec_valid(ss
))
660 pa_source_output_new_data_set_sample_spec(&data
, ss
);
661 if (pa_channel_map_valid(map
))
662 pa_source_output_new_data_set_channel_map(&data
, map
);
664 pa_source_output_new_data_set_formats(&data
, formats
);
665 data
.direct_on_input
= direct_on_input
;
667 data
.resample_method
= PA_RESAMPLER_PEAKS
;
670 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
672 pa_source_output_new_data_done(&data
);
677 s
= pa_msgobject_new(record_stream
);
678 s
->parent
.parent
.free
= record_stream_free
;
679 s
->parent
.process_msg
= record_stream_process_msg
;
681 s
->source_output
= source_output
;
682 s
->buffer_attr_req
= *attr
;
683 s
->adjust_latency
= adjust_latency
;
684 s
->early_requests
= early_requests
;
685 pa_atomic_store(&s
->on_the_fly
, 0);
687 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
688 s
->source_output
->push
= source_output_push_cb
;
689 s
->source_output
->kill
= source_output_kill_cb
;
690 s
->source_output
->get_latency
= source_output_get_latency_cb
;
691 s
->source_output
->moving
= source_output_moving_cb
;
692 s
->source_output
->suspend
= source_output_suspend_cb
;
693 s
->source_output
->send_event
= source_output_send_event_cb
;
694 s
->source_output
->userdata
= s
;
696 fix_record_buffer_attr_pre(s
);
698 s
->memblockq
= pa_memblockq_new(
700 s
->buffer_attr
.maxlength
,
702 pa_frame_size(&source_output
->sample_spec
),
708 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
709 fix_record_buffer_attr_post(s
);
711 *ss
= s
->source_output
->sample_spec
;
712 *map
= s
->source_output
->channel_map
;
714 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
716 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
717 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
718 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
719 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
721 pa_source_output_put(s
->source_output
);
725 /* Called from main context */
726 static void record_stream_send_killed(record_stream
*r
) {
728 record_stream_assert_ref(r
);
730 t
= pa_tagstruct_new(NULL
, 0);
731 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
732 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
733 pa_tagstruct_putu32(t
, r
->index
);
734 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
737 /* Called from main context */
738 static void playback_stream_unlink(playback_stream
*s
) {
745 pa_sink_input_unlink(s
->sink_input
);
746 pa_sink_input_unref(s
->sink_input
);
747 s
->sink_input
= NULL
;
750 if (s
->drain_request
)
751 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
753 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
754 s
->connection
= NULL
;
755 playback_stream_unref(s
);
758 /* Called from main context */
759 static void playback_stream_free(pa_object
* o
) {
760 playback_stream
*s
= PLAYBACK_STREAM(o
);
763 playback_stream_unlink(s
);
765 pa_memblockq_free(s
->memblockq
);
769 /* Called from main context */
770 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
771 playback_stream
*s
= PLAYBACK_STREAM(o
);
772 playback_stream_assert_ref(s
);
779 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
784 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
787 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
791 t
= pa_tagstruct_new(NULL
, 0);
792 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
793 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
794 pa_tagstruct_putu32(t
, s
->index
);
795 pa_tagstruct_putu32(t
, (uint32_t) l
);
796 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
798 /* pa_log("Requesting %lu bytes", (unsigned long) l); */
802 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
805 /* pa_log("signalling underflow"); */
807 /* Report that we're empty */
808 t
= pa_tagstruct_new(NULL
, 0);
809 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
810 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
811 pa_tagstruct_putu32(t
, s
->index
);
812 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
816 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
819 /* Notify the user we're overflowed*/
820 t
= pa_tagstruct_new(NULL
, 0);
821 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
822 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
823 pa_tagstruct_putu32(t
, s
->index
);
824 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
828 case PLAYBACK_STREAM_MESSAGE_STARTED
:
830 if (s
->connection
->version
>= 13) {
833 /* Notify the user we started playback */
834 t
= pa_tagstruct_new(NULL
, 0);
835 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
836 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
837 pa_tagstruct_putu32(t
, s
->index
);
838 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
843 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
844 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
847 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
:
849 s
->buffer_attr
.tlength
= (uint32_t) offset
;
851 if (s
->connection
->version
>= 15) {
854 t
= pa_tagstruct_new(NULL
, 0);
855 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
856 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
857 pa_tagstruct_putu32(t
, s
->index
);
858 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
859 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
860 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
861 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
862 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
863 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
872 /* Called from main context */
873 static void fix_playback_buffer_attr(playback_stream
*s
) {
874 size_t frame_size
, max_prebuf
;
875 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
879 /* pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes", */
880 /* (long) s->buffer_attr.maxlength, */
881 /* (long) s->buffer_attr.tlength, */
882 /* (long) s->buffer_attr.minreq, */
883 /* (long) s->buffer_attr.prebuf); */
885 /* pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms", */
886 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
887 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
888 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
889 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC)); */
891 /* This function will be called from the main thread, before as
892 * well as after the sink input has been activated using
893 * pa_sink_input_put()! That means it may not touch any
894 * ->thread_info data, such as the memblockq! */
896 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
897 s
->buffer_attr
= s
->buffer_attr_req
;
899 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
900 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
901 if (s
->buffer_attr
.maxlength
<= 0)
902 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
904 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
905 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
906 if (s
->buffer_attr
.tlength
<= 0)
907 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
909 if (s
->buffer_attr
.minreq
== (uint32_t) -1)
910 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
911 if (s
->buffer_attr
.minreq
<= 0)
912 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
914 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
915 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
917 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
918 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
920 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
921 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
922 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
924 if (s
->early_requests
) {
926 /* In early request mode we need to emulate the classic
927 * fragment-based playback model. We do this setting the sink
928 * latency to the fragment size. */
930 sink_usec
= minreq_usec
;
931 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
933 } else if (s
->adjust_latency
) {
935 /* So, the user asked us to adjust the latency of the stream
936 * buffer according to the what the sink can provide. The
937 * tlength passed in shall be the overall latency. Roughly
938 * half the latency will be spent on the hw buffer, the other
939 * half of it in the async buffer queue we maintain for each
940 * client. In between we'll have a safety space of size
941 * 2*minreq. Why the 2*minreq? When the hw buffer is completey
942 * empty and needs to be filled, then our buffer must have
943 * enough data to fulfill this request immediatly and thus
944 * have at least the same tlength as the size of the hw
945 * buffer. It additionally needs space for 2 times minreq
946 * because if the buffer ran empty and a partial fillup
947 * happens immediately on the next iteration we need to be
948 * able to fulfill it and give the application also minreq
949 * time to fill it up again for the next request Makes 2 times
950 * minreq in plus.. */
952 if (tlength_usec
> minreq_usec
*2)
953 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
957 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
961 /* Ok, the user didn't ask us to adjust the latency, but we
962 * still need to make sure that the parameters from the user
965 if (tlength_usec
> minreq_usec
*2)
966 sink_usec
= (tlength_usec
- minreq_usec
*2);
970 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
973 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
975 if (s
->early_requests
) {
977 /* Ok, we didn't necessarily get what we were asking for, so
978 * let's tell the user */
980 minreq_usec
= s
->configured_sink_latency
;
982 } else if (s
->adjust_latency
) {
984 /* Ok, we didn't necessarily get what we were asking for, so
985 * let's subtract from what we asked for for the remaining
988 if (tlength_usec
>= s
->configured_sink_latency
)
989 tlength_usec
-= s
->configured_sink_latency
;
992 /* FIXME: This is actually larger than necessary, since not all of
993 * the sink latency is actually rewritable. */
994 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
995 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
997 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
998 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
999 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
1001 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
1002 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
1003 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
1005 if (s
->buffer_attr
.minreq
<= 0) {
1006 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
1007 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
1010 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
1011 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
1013 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
1015 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
1016 s
->buffer_attr
.prebuf
> max_prebuf
)
1017 s
->buffer_attr
.prebuf
= max_prebuf
;
1019 /* pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms", */
1020 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.maxlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
1021 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
1022 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC), */
1023 /* (unsigned long) (pa_bytes_to_usec(s->buffer_attr.prebuf, &s->sink_input->sample_spec) / PA_USEC_PER_MSEC)); */
1026 /* Called from main context */
1027 static playback_stream
* playback_stream_new(
1028 pa_native_connection
*c
,
1031 pa_channel_map
*map
,
1036 pa_bool_t muted_set
,
1037 pa_sink_input_flags_t flags
,
1039 pa_bool_t adjust_latency
,
1040 pa_bool_t early_requests
,
1041 pa_bool_t relative_volume
,
1046 /* Note: This function takes ownership of the 'formats' param, so we need
1047 * to take extra care to not leak it */
1049 playback_stream
*s
, *ssync
;
1050 pa_sink_input
*sink_input
= NULL
;
1051 pa_memchunk silence
;
1053 int64_t start_index
;
1054 pa_sink_input_new_data data
;
1062 /* Find syncid group */
1063 PA_IDXSET_FOREACH(ssync
, c
->output_streams
, idx
) {
1065 if (!playback_stream_isinstance(ssync
))
1068 if (ssync
->syncid
== syncid
)
1072 /* Synced streams must connect to the same sink */
1076 sink
= ssync
->sink_input
->sink
;
1077 else if (sink
!= ssync
->sink_input
->sink
) {
1078 *ret
= PA_ERR_INVALID
;
1083 pa_sink_input_new_data_init(&data
);
1085 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1086 data
.driver
= __FILE__
;
1087 data
.module
= c
->options
->module
;
1088 data
.client
= c
->client
;
1090 pa_sink_input_new_data_set_sink(&data
, sink
, TRUE
);
1091 if (pa_sample_spec_valid(ss
))
1092 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1093 if (pa_channel_map_valid(map
))
1094 pa_sink_input_new_data_set_channel_map(&data
, map
);
1096 pa_sink_input_new_data_set_formats(&data
, formats
);
1097 /* Ownership transferred to new_data, so we don't free it ourseleves */
1101 pa_sink_input_new_data_set_volume(&data
, volume
);
1102 data
.volume_is_absolute
= !relative_volume
;
1103 data
.save_volume
= TRUE
;
1106 pa_sink_input_new_data_set_muted(&data
, muted
);
1107 data
.save_muted
= TRUE
;
1109 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1112 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1114 pa_sink_input_new_data_done(&data
);
1119 s
= pa_msgobject_new(playback_stream
);
1120 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1121 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1124 s
->sink_input
= sink_input
;
1125 s
->is_underrun
= TRUE
;
1126 s
->drain_request
= FALSE
;
1127 pa_atomic_store(&s
->missing
, 0);
1128 s
->buffer_attr_req
= *a
;
1129 s
->adjust_latency
= adjust_latency
;
1130 s
->early_requests
= early_requests
;
1131 pa_atomic_store(&s
->seek_or_post_in_queue
, 0);
1132 s
->seek_windex
= -1;
1134 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1135 s
->sink_input
->pop
= sink_input_pop_cb
;
1136 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1137 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1138 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1139 s
->sink_input
->kill
= sink_input_kill_cb
;
1140 s
->sink_input
->moving
= sink_input_moving_cb
;
1141 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1142 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1143 s
->sink_input
->userdata
= s
;
1145 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1147 fix_playback_buffer_attr(s
);
1149 pa_sink_input_get_silence(sink_input
, &silence
);
1150 s
->memblockq
= pa_memblockq_new(
1152 s
->buffer_attr
.maxlength
,
1153 s
->buffer_attr
.tlength
,
1154 pa_frame_size(&sink_input
->sample_spec
),
1155 s
->buffer_attr
.prebuf
,
1156 s
->buffer_attr
.minreq
,
1159 pa_memblock_unref(silence
.memblock
);
1161 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1163 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1165 /* pa_log("missing original: %li", (long int) *missing); */
1167 *ss
= s
->sink_input
->sample_spec
;
1168 *map
= s
->sink_input
->channel_map
;
1170 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1172 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1173 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1174 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1175 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1176 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1178 pa_sink_input_put(s
->sink_input
);
1182 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
1187 /* Called from IO context */
1188 static void playback_stream_request_bytes(playback_stream
*s
) {
1190 int previous_missing
;
1192 playback_stream_assert_ref(s
);
1194 m
= pa_memblockq_pop_missing(s
->memblockq
);
1196 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1197 /* (unsigned long) m, */
1198 /* pa_memblockq_get_tlength(s->memblockq), */
1199 /* pa_memblockq_get_minreq(s->memblockq), */
1200 /* pa_memblockq_get_length(s->memblockq), */
1201 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1206 /* pa_log("request_bytes(%lu)", (unsigned long) m); */
1208 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1209 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1211 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1212 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1213 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1216 /* Called from main context */
1217 static void playback_stream_send_killed(playback_stream
*p
) {
1219 playback_stream_assert_ref(p
);
1221 t
= pa_tagstruct_new(NULL
, 0);
1222 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1223 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1224 pa_tagstruct_putu32(t
, p
->index
);
1225 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1228 /* Called from main context */
1229 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1230 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1231 pa_native_connection_assert_ref(c
);
1238 case CONNECTION_MESSAGE_REVOKE
:
1239 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1242 case CONNECTION_MESSAGE_RELEASE
:
1243 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1250 /* Called from main context */
1251 static void native_connection_unlink(pa_native_connection
*c
) {
1260 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1263 pa_native_options_unref(c
->options
);
1265 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1266 record_stream_unlink(r
);
1268 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1269 if (playback_stream_isinstance(o
))
1270 playback_stream_unlink(PLAYBACK_STREAM(o
));
1272 upload_stream_unlink(UPLOAD_STREAM(o
));
1274 if (c
->subscription
)
1275 pa_subscription_free(c
->subscription
);
1278 pa_pstream_unlink(c
->pstream
);
1280 if (c
->auth_timeout_event
) {
1281 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1282 c
->auth_timeout_event
= NULL
;
1285 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1287 pa_native_connection_unref(c
);
1290 /* Called from main context */
1291 static void native_connection_free(pa_object
*o
) {
1292 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1296 native_connection_unlink(c
);
1298 pa_idxset_free(c
->record_streams
, NULL
, NULL
);
1299 pa_idxset_free(c
->output_streams
, NULL
, NULL
);
1301 pa_pdispatch_unref(c
->pdispatch
);
1302 pa_pstream_unref(c
->pstream
);
1303 pa_client_free(c
->client
);
1308 /* Called from main context */
1309 static void native_connection_send_memblock(pa_native_connection
*c
) {
1313 start
= PA_IDXSET_INVALID
;
1317 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1320 if (start
== PA_IDXSET_INVALID
)
1321 start
= c
->rrobin_index
;
1322 else if (start
== c
->rrobin_index
)
1325 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1326 pa_memchunk schunk
= chunk
;
1328 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1329 schunk
.length
= r
->buffer_attr
.fragsize
;
1331 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1333 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1334 pa_memblock_unref(schunk
.memblock
);
1341 /*** sink input callbacks ***/
1343 /* Called from thread context */
1344 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1345 playback_stream_assert_ref(s
);
1347 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1349 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1351 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1353 if (pa_memblockq_is_readable(s
->memblockq
)) {
1355 /* We just ended an underrun, let's ask the sink
1356 * for a complete rewind rewrite */
1358 pa_log_debug("Requesting rewind due to end of underrun.");
1359 pa_sink_input_request_rewind(s
->sink_input
,
1360 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1361 s
->sink_input
->thread_info
.underrun_for
),
1362 FALSE
, TRUE
, FALSE
);
1368 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1370 if (indexw
< indexr
) {
1371 /* OK, the sink already asked for this data, so
1372 * let's have it usk us again */
1374 pa_log_debug("Requesting rewind due to rewrite.");
1375 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1379 playback_stream_request_bytes(s
);
1382 static void flush_write_no_account(pa_memblockq
*q
) {
1383 pa_memblockq_flush_write(q
, FALSE
);
1386 /* Called from thread context */
1387 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1388 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1391 pa_sink_input_assert_ref(i
);
1392 s
= PLAYBACK_STREAM(i
->userdata
);
1393 playback_stream_assert_ref(s
);
1397 case SINK_INPUT_MESSAGE_SEEK
:
1398 case SINK_INPUT_MESSAGE_POST_DATA
: {
1399 int64_t windex
= pa_memblockq_get_write_index(s
->memblockq
);
1401 if (code
== SINK_INPUT_MESSAGE_SEEK
) {
1402 /* The client side is incapable of accounting correctly
1403 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1404 * able to deal with that. */
1406 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1407 windex
= PA_MIN(windex
, pa_memblockq_get_write_index(s
->memblockq
));
1410 if (chunk
&& pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1411 if (pa_log_ratelimit(PA_LOG_WARN
))
1412 pa_log_warn("Failed to push data into queue");
1413 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1414 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1417 /* If more data is in queue, we rewind later instead. */
1418 if (s
->seek_windex
!= -1)
1419 windex
= PA_MIN(windex
, s
->seek_windex
);
1420 if (pa_atomic_dec(&s
->seek_or_post_in_queue
) > 1)
1421 s
->seek_windex
= windex
;
1423 s
->seek_windex
= -1;
1424 handle_seek(s
, windex
);
1429 case SINK_INPUT_MESSAGE_DRAIN
:
1430 case SINK_INPUT_MESSAGE_FLUSH
:
1431 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1432 case SINK_INPUT_MESSAGE_TRIGGER
: {
1435 pa_sink_input
*isync
;
1436 void (*func
)(pa_memblockq
*bq
);
1439 case SINK_INPUT_MESSAGE_FLUSH
:
1440 func
= flush_write_no_account
;
1443 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1444 func
= pa_memblockq_prebuf_force
;
1447 case SINK_INPUT_MESSAGE_DRAIN
:
1448 case SINK_INPUT_MESSAGE_TRIGGER
:
1449 func
= pa_memblockq_prebuf_disable
;
1453 pa_assert_not_reached();
1456 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1458 handle_seek(s
, windex
);
1460 /* Do the same for all other members in the sync group */
1461 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1462 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1463 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1464 func(ssync
->memblockq
);
1465 handle_seek(ssync
, windex
);
1468 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1469 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1470 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1471 func(ssync
->memblockq
);
1472 handle_seek(ssync
, windex
);
1475 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1476 if (!pa_memblockq_is_readable(s
->memblockq
))
1477 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1479 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1480 s
->drain_request
= TRUE
;
1487 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1488 /* Atomically get a snapshot of all timing parameters... */
1489 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1490 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1491 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1492 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1493 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1494 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1498 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1501 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1503 pa_memblockq_prebuf_force(s
->memblockq
);
1505 handle_seek(s
, windex
);
1507 /* Fall through to the default handler */
1511 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1512 pa_usec_t
*r
= userdata
;
1514 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1516 /* Fall through, the default handler will add in the extra
1517 * latency added by the resampler */
1521 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1522 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1523 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1528 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1531 /* Called from thread context */
1532 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1535 pa_sink_input_assert_ref(i
);
1536 s
= PLAYBACK_STREAM(i
->userdata
);
1537 playback_stream_assert_ref(s
);
1540 /* pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1542 if (pa_memblockq_is_readable(s
->memblockq
))
1543 s
->is_underrun
= FALSE
;
1545 if (!s
->is_underrun
)
1546 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
));
1548 if (s
->drain_request
&& pa_sink_input_safe_to_remove(i
)) {
1549 s
->drain_request
= FALSE
;
1550 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
);
1551 } else if (!s
->is_underrun
)
1552 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, 0, NULL
, NULL
);
1554 s
->is_underrun
= TRUE
;
1556 playback_stream_request_bytes(s
);
1559 /* This call will not fail with prebuf=0, hence we check for
1560 underrun explicitly above */
1561 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1564 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1566 if (i
->thread_info
.underrun_for
> 0)
1567 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1569 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1570 playback_stream_request_bytes(s
);
1575 /* Called from thread context */
1576 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1579 pa_sink_input_assert_ref(i
);
1580 s
= PLAYBACK_STREAM(i
->userdata
);
1581 playback_stream_assert_ref(s
);
1583 /* If we are in an underrun, then we don't rewind */
1584 if (i
->thread_info
.underrun_for
> 0)
1587 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1590 /* Called from thread context */
1591 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1594 pa_sink_input_assert_ref(i
);
1595 s
= PLAYBACK_STREAM(i
->userdata
);
1596 playback_stream_assert_ref(s
);
1598 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1601 /* Called from thread context */
1602 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1604 size_t new_tlength
, old_tlength
;
1606 pa_sink_input_assert_ref(i
);
1607 s
= PLAYBACK_STREAM(i
->userdata
);
1608 playback_stream_assert_ref(s
);
1610 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1611 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1613 if (old_tlength
< new_tlength
) {
1614 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1615 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1616 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1618 if (new_tlength
== old_tlength
)
1619 pa_log_debug("Failed to increase tlength");
1621 pa_log_debug("Notifying client about increased tlength");
1622 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
);
1627 /* Called from main context */
1628 static void sink_input_kill_cb(pa_sink_input
*i
) {
1631 pa_sink_input_assert_ref(i
);
1632 s
= PLAYBACK_STREAM(i
->userdata
);
1633 playback_stream_assert_ref(s
);
1635 playback_stream_send_killed(s
);
1636 playback_stream_unlink(s
);
1639 /* Called from main context */
1640 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1644 pa_sink_input_assert_ref(i
);
1645 s
= PLAYBACK_STREAM(i
->userdata
);
1646 playback_stream_assert_ref(s
);
1648 if (s
->connection
->version
< 15)
1651 t
= pa_tagstruct_new(NULL
, 0);
1652 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1653 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1654 pa_tagstruct_putu32(t
, s
->index
);
1655 pa_tagstruct_puts(t
, event
);
1656 pa_tagstruct_put_proplist(t
, pl
);
1657 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1660 /* Called from main context */
1661 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1665 pa_sink_input_assert_ref(i
);
1666 s
= PLAYBACK_STREAM(i
->userdata
);
1667 playback_stream_assert_ref(s
);
1669 if (s
->connection
->version
< 12)
1672 t
= pa_tagstruct_new(NULL
, 0);
1673 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1674 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1675 pa_tagstruct_putu32(t
, s
->index
);
1676 pa_tagstruct_put_boolean(t
, suspend
);
1677 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1680 /* Called from main context */
1681 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1685 pa_sink_input_assert_ref(i
);
1686 s
= PLAYBACK_STREAM(i
->userdata
);
1687 playback_stream_assert_ref(s
);
1692 fix_playback_buffer_attr(s
);
1693 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1694 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1696 if (s
->connection
->version
< 12)
1699 t
= pa_tagstruct_new(NULL
, 0);
1700 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1701 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1702 pa_tagstruct_putu32(t
, s
->index
);
1703 pa_tagstruct_putu32(t
, dest
->index
);
1704 pa_tagstruct_puts(t
, dest
->name
);
1705 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1707 if (s
->connection
->version
>= 13) {
1708 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1709 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1710 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1711 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1712 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1715 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1718 /*** source_output callbacks ***/
1720 /* Called from thread context */
1721 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1722 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1725 pa_source_output_assert_ref(o
);
1726 s
= RECORD_STREAM(o
->userdata
);
1727 record_stream_assert_ref(s
);
1730 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1731 /* Atomically get a snapshot of all timing parameters... */
1732 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1733 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1734 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1738 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1741 /* Called from thread context */
1742 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1745 pa_source_output_assert_ref(o
);
1746 s
= RECORD_STREAM(o
->userdata
);
1747 record_stream_assert_ref(s
);
1750 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1751 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1754 static void source_output_kill_cb(pa_source_output
*o
) {
1757 pa_source_output_assert_ref(o
);
1758 s
= RECORD_STREAM(o
->userdata
);
1759 record_stream_assert_ref(s
);
1761 record_stream_send_killed(s
);
1762 record_stream_unlink(s
);
1765 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1768 pa_source_output_assert_ref(o
);
1769 s
= RECORD_STREAM(o
->userdata
);
1770 record_stream_assert_ref(s
);
1772 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1774 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1777 /* Called from main context */
1778 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1782 pa_source_output_assert_ref(o
);
1783 s
= RECORD_STREAM(o
->userdata
);
1784 record_stream_assert_ref(s
);
1786 if (s
->connection
->version
< 15)
1789 t
= pa_tagstruct_new(NULL
, 0);
1790 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1791 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1792 pa_tagstruct_putu32(t
, s
->index
);
1793 pa_tagstruct_puts(t
, event
);
1794 pa_tagstruct_put_proplist(t
, pl
);
1795 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1798 /* Called from main context */
1799 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1803 pa_source_output_assert_ref(o
);
1804 s
= RECORD_STREAM(o
->userdata
);
1805 record_stream_assert_ref(s
);
1807 if (s
->connection
->version
< 12)
1810 t
= pa_tagstruct_new(NULL
, 0);
1811 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1812 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1813 pa_tagstruct_putu32(t
, s
->index
);
1814 pa_tagstruct_put_boolean(t
, suspend
);
1815 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1818 /* Called from main context */
1819 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1823 pa_source_output_assert_ref(o
);
1824 s
= RECORD_STREAM(o
->userdata
);
1825 record_stream_assert_ref(s
);
1830 fix_record_buffer_attr_pre(s
);
1831 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1832 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1833 fix_record_buffer_attr_post(s
);
1835 if (s
->connection
->version
< 12)
1838 t
= pa_tagstruct_new(NULL
, 0);
1839 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1840 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1841 pa_tagstruct_putu32(t
, s
->index
);
1842 pa_tagstruct_putu32(t
, dest
->index
);
1843 pa_tagstruct_puts(t
, dest
->name
);
1844 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1846 if (s
->connection
->version
>= 13) {
1847 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1848 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1849 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1852 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1855 /*** pdispatch callbacks ***/
1857 static void protocol_error(pa_native_connection
*c
) {
1858 pa_log("protocol error, kicking client");
1859 native_connection_unlink(c
);
1862 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1863 if (!(expression)) { \
1864 pa_pstream_send_error((pstream), (tag), (error)); \
1869 #define CHECK_VALIDITY_GOTO(pstream, expression, tag, error, label) do { \
1870 if (!(expression)) { \
1871 pa_pstream_send_error((pstream), (tag), (error)); \
1876 static pa_tagstruct
*reply_new(uint32_t tag
) {
1877 pa_tagstruct
*reply
;
1879 reply
= pa_tagstruct_new(NULL
, 0);
1880 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1881 pa_tagstruct_putu32(reply
, tag
);
1885 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1886 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1888 uint32_t sink_index
, syncid
, missing
;
1889 pa_buffer_attr attr
;
1890 const char *name
= NULL
, *sink_name
;
1893 pa_tagstruct
*reply
;
1894 pa_sink
*sink
= NULL
;
1902 fix_channels
= FALSE
,
1904 variable_rate
= FALSE
,
1906 adjust_latency
= FALSE
,
1907 early_requests
= FALSE
,
1908 dont_inhibit_auto_suspend
= FALSE
,
1911 fail_on_suspend
= FALSE
,
1912 relative_volume
= FALSE
,
1913 passthrough
= FALSE
;
1915 pa_sink_input_flags_t flags
= 0;
1916 pa_proplist
*p
= NULL
;
1917 int ret
= PA_ERR_INVALID
;
1918 uint8_t n_formats
= 0;
1919 pa_format_info
*format
;
1920 pa_idxset
*formats
= NULL
;
1923 pa_native_connection_assert_ref(c
);
1925 memset(&attr
, 0, sizeof(attr
));
1927 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
1930 PA_TAG_SAMPLE_SPEC
, &ss
,
1931 PA_TAG_CHANNEL_MAP
, &map
,
1932 PA_TAG_U32
, &sink_index
,
1933 PA_TAG_STRING
, &sink_name
,
1934 PA_TAG_U32
, &attr
.maxlength
,
1935 PA_TAG_BOOLEAN
, &corked
,
1936 PA_TAG_U32
, &attr
.tlength
,
1937 PA_TAG_U32
, &attr
.prebuf
,
1938 PA_TAG_U32
, &attr
.minreq
,
1939 PA_TAG_U32
, &syncid
,
1940 PA_TAG_CVOLUME
, &volume
,
1941 PA_TAG_INVALID
) < 0) {
1947 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
1948 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
, finish
);
1949 CHECK_VALIDITY_GOTO(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
, finish
);
1950 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
1951 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
1953 p
= pa_proplist_new();
1956 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
1958 if (c
->version
>= 12) {
1959 /* Since 0.9.8 the user can ask for a couple of additional flags */
1961 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
1962 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
1963 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
1964 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
1965 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
1966 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
1967 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
1974 if (c
->version
>= 13) {
1976 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
1977 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
1978 pa_tagstruct_get_proplist(t
, p
) < 0) {
1985 if (c
->version
>= 14) {
1987 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
1988 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
1995 if (c
->version
>= 15) {
1997 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
1998 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
1999 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2006 if (c
->version
>= 17) {
2008 if (pa_tagstruct_get_boolean(t
, &relative_volume
) < 0) {
2015 if (c
->version
>= 18) {
2017 if (pa_tagstruct_get_boolean(t
, &passthrough
) < 0 ) {
2023 if (c
->version
>= 21) {
2025 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2031 formats
= pa_idxset_new(NULL
, NULL
);
2033 for (i
= 0; i
< n_formats
; i
++) {
2034 format
= pa_format_info_new();
2035 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2039 pa_idxset_put(formats
, format
, NULL
);
2043 if (n_formats
== 0) {
2044 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2045 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2046 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2048 PA_IDXSET_FOREACH(format
, formats
, i
) {
2049 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2053 if (!pa_tagstruct_eof(t
)) {
2058 if (sink_index
!= PA_INVALID_INDEX
) {
2060 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
2061 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2065 } else if (sink_name
) {
2067 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
2068 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2074 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
2075 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
2076 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
2077 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
2078 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
2079 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
2080 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
2081 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
2082 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2083 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0) |
2084 (passthrough
? PA_SINK_INPUT_PASSTHROUGH
: 0);
2086 /* Only since protocol version 15 there's a seperate muted_set
2087 * flag. For older versions we synthesize it here */
2088 muted_set
= muted_set
|| muted
;
2090 s
= playback_stream_new(c
, sink
, &ss
, &map
, formats
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, flags
, p
, adjust_latency
, early_requests
, relative_volume
, syncid
, &missing
, &ret
);
2091 /* We no longer own the formats idxset */
2094 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2096 reply
= reply_new(tag
);
2097 pa_tagstruct_putu32(reply
, s
->index
);
2098 pa_assert(s
->sink_input
);
2099 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
2100 pa_tagstruct_putu32(reply
, missing
);
2102 /* pa_log("initial request is %u", missing); */
2104 if (c
->version
>= 9) {
2105 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2107 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2108 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
2109 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
2110 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
2113 if (c
->version
>= 12) {
2114 /* Since 0.9.8 we support sending the chosen sample
2115 * spec/channel map/device/suspend status back to the
2118 pa_tagstruct_put_sample_spec(reply
, &ss
);
2119 pa_tagstruct_put_channel_map(reply
, &map
);
2121 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2122 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2124 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2127 if (c
->version
>= 13)
2128 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2130 if (c
->version
>= 21) {
2131 /* Send back the format we negotiated */
2132 if (s
->sink_input
->format
)
2133 pa_tagstruct_put_format_info(reply
, s
->sink_input
->format
);
2135 pa_format_info
*f
= pa_format_info_new();
2136 pa_tagstruct_put_format_info(reply
, f
);
2137 pa_format_info_free(f
);
2141 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2145 pa_proplist_free(p
);
2147 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
2150 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2151 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2154 pa_native_connection_assert_ref(c
);
2157 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2158 !pa_tagstruct_eof(t
)) {
2163 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2167 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2169 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2170 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2174 playback_stream_unlink(s
);
2178 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2180 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2181 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2185 record_stream_unlink(s
);
2189 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2192 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2193 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2197 upload_stream_unlink(s
);
2202 pa_assert_not_reached();
2205 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2208 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2209 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2211 pa_buffer_attr attr
;
2212 uint32_t source_index
;
2213 const char *name
= NULL
, *source_name
;
2216 pa_tagstruct
*reply
;
2217 pa_source
*source
= NULL
;
2224 fix_channels
= FALSE
,
2226 variable_rate
= FALSE
,
2227 adjust_latency
= FALSE
,
2228 peak_detect
= FALSE
,
2229 early_requests
= FALSE
,
2230 dont_inhibit_auto_suspend
= FALSE
,
2231 fail_on_suspend
= FALSE
,
2232 passthrough
= FALSE
;
2234 pa_source_output_flags_t flags
= 0;
2235 pa_proplist
*p
= NULL
;
2236 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2237 pa_sink_input
*direct_on_input
= NULL
;
2238 int ret
= PA_ERR_INVALID
;
2239 uint8_t n_formats
= 0;
2240 pa_format_info
*format
;
2241 pa_idxset
*formats
= NULL
;
2244 pa_native_connection_assert_ref(c
);
2247 memset(&attr
, 0, sizeof(attr
));
2249 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2250 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2251 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2252 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2253 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2254 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2255 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2256 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2262 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
2263 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
, finish
);
2264 CHECK_VALIDITY_GOTO(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
, finish
);
2265 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
2267 p
= pa_proplist_new();
2270 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2272 if (c
->version
>= 12) {
2273 /* Since 0.9.8 the user can ask for a couple of additional flags */
2275 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2276 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2277 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2278 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2279 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2280 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2281 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2288 if (c
->version
>= 13) {
2290 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2291 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2292 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2293 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2300 if (c
->version
>= 14) {
2302 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2308 if (c
->version
>= 15) {
2310 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2311 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2318 if (c
->version
>= 22) {
2320 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2326 formats
= pa_idxset_new(NULL
, NULL
);
2328 for (i
= 0; i
< n_formats
; i
++) {
2329 format
= pa_format_info_new();
2330 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2334 pa_idxset_put(formats
, format
, NULL
);
2338 if (n_formats
== 0) {
2339 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2340 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2342 PA_IDXSET_FOREACH(format
, formats
, i
) {
2343 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2348 if (!pa_tagstruct_eof(t
)) {
2353 if (source_index
!= PA_INVALID_INDEX
) {
2355 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2356 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2360 } else if (source_name
) {
2362 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2363 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2368 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2370 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2371 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2377 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2378 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2379 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2380 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2381 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2382 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2383 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2384 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2385 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2386 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0) |
2387 (passthrough
? PA_SOURCE_OUTPUT_PASSTHROUGH
: 0);
2389 s
= record_stream_new(c
, source
, &ss
, &map
, formats
, &attr
, flags
, p
, adjust_latency
, early_requests
, peak_detect
, direct_on_input
, &ret
);
2391 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2393 reply
= reply_new(tag
);
2394 pa_tagstruct_putu32(reply
, s
->index
);
2395 pa_assert(s
->source_output
);
2396 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2398 if (c
->version
>= 9) {
2399 /* Since 0.9 we support sending the buffer metrics back to the client */
2401 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2402 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2405 if (c
->version
>= 12) {
2406 /* Since 0.9.8 we support sending the chosen sample
2407 * spec/channel map/device/suspend status back to the
2410 pa_tagstruct_put_sample_spec(reply
, &ss
);
2411 pa_tagstruct_put_channel_map(reply
, &map
);
2413 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2414 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2416 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2419 if (c
->version
>= 13)
2420 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2422 if (c
->version
>= 22) {
2423 /* Send back the format we negotiated */
2424 if (s
->source_output
->format
)
2425 pa_tagstruct_put_format_info(reply
, s
->source_output
->format
);
2427 pa_format_info
*f
= pa_format_info_new();
2428 pa_tagstruct_put_format_info(reply
, f
);
2429 pa_format_info_free(f
);
2433 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2437 pa_proplist_free(p
);
2439 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
2442 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2443 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2446 pa_native_connection_assert_ref(c
);
2449 if (!pa_tagstruct_eof(t
)) {
2454 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2455 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2456 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2458 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
)));
2460 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2463 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2464 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2466 pa_tagstruct
*reply
;
2467 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2469 pa_native_connection_assert_ref(c
);
2472 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2473 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2474 !pa_tagstruct_eof(t
)) {
2479 /* Minimum supported version */
2480 if (c
->version
< 8) {
2481 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2485 /* Starting with protocol version 13 the MSB of the version tag
2486 reflects if shm is available for this pa_native_connection or
2488 if (c
->version
>= 13) {
2489 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2490 c
->version
&= 0x7FFFFFFFU
;
2493 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2495 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2497 if (!c
->authorized
) {
2498 pa_bool_t success
= FALSE
;
2501 const pa_creds
*creds
;
2503 if ((creds
= pa_pdispatch_creds(pd
))) {
2504 if (creds
->uid
== getuid())
2506 else if (c
->options
->auth_group
) {
2510 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2511 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2512 else if (gid
== creds
->gid
)
2516 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2517 pa_log_warn("Failed to check group membership.");
2523 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2524 (unsigned long) creds
->uid
,
2525 (unsigned long) creds
->gid
,
2530 if (!success
&& c
->options
->auth_cookie
) {
2533 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2534 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2539 pa_log_warn("Denied access to client with invalid authorization data.");
2540 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2544 c
->authorized
= TRUE
;
2545 if (c
->auth_timeout_event
) {
2546 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2547 c
->auth_timeout_event
= NULL
;
2551 /* Enable shared memory support if possible */
2553 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2556 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2559 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2564 /* Only enable SHM if both sides are owned by the same
2565 * user. This is a security measure because otherwise data
2566 * private to the user might leak. */
2568 const pa_creds
*creds
;
2569 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2574 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2575 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2577 reply
= reply_new(tag
);
2578 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2582 /* SHM support is only enabled after both sides made sure they are the same user. */
2586 ucred
.uid
= getuid();
2587 ucred
.gid
= getgid();
2589 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2592 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2596 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2597 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2598 const char *name
= NULL
;
2600 pa_tagstruct
*reply
;
2602 pa_native_connection_assert_ref(c
);
2605 p
= pa_proplist_new();
2607 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2608 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2609 !pa_tagstruct_eof(t
)) {
2612 pa_proplist_free(p
);
2617 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2618 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2619 pa_proplist_free(p
);
2623 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2624 pa_proplist_free(p
);
2626 reply
= reply_new(tag
);
2628 if (c
->version
>= 13)
2629 pa_tagstruct_putu32(reply
, c
->client
->index
);
2631 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2634 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2635 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2637 uint32_t idx
= PA_IDXSET_INVALID
;
2639 pa_native_connection_assert_ref(c
);
2642 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2643 !pa_tagstruct_eof(t
)) {
2648 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2649 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
);
2651 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2653 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2657 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2658 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2659 idx
= source
->index
;
2662 if (idx
== PA_IDXSET_INVALID
)
2663 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2665 pa_tagstruct
*reply
;
2666 reply
= reply_new(tag
);
2667 pa_tagstruct_putu32(reply
, idx
);
2668 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2672 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2673 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2677 pa_native_connection_assert_ref(c
);
2680 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2681 !pa_tagstruct_eof(t
)) {
2686 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2687 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2688 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2689 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2691 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
);
2694 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2695 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2696 pa_tagstruct
*reply
;
2697 const pa_mempool_stat
*stat
;
2699 pa_native_connection_assert_ref(c
);
2702 if (!pa_tagstruct_eof(t
)) {
2707 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2709 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2711 reply
= reply_new(tag
);
2712 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2713 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2714 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2715 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2716 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2717 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2720 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2721 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2722 pa_tagstruct
*reply
;
2724 struct timeval tv
, now
;
2727 pa_native_connection_assert_ref(c
);
2730 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2731 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2732 !pa_tagstruct_eof(t
)) {
2737 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2738 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2739 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2740 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2742 /* Get an atomic snapshot of all timing parameters */
2743 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);
2745 reply
= reply_new(tag
);
2746 pa_tagstruct_put_usec(reply
,
2747 s
->current_sink_latency
+
2748 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2749 pa_tagstruct_put_usec(reply
, 0);
2750 pa_tagstruct_put_boolean(reply
,
2751 s
->playing_for
> 0 &&
2752 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2753 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2754 pa_tagstruct_put_timeval(reply
, &tv
);
2755 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2756 pa_tagstruct_puts64(reply
, s
->write_index
);
2757 pa_tagstruct_puts64(reply
, s
->read_index
);
2759 if (c
->version
>= 13) {
2760 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2761 pa_tagstruct_putu64(reply
, s
->playing_for
);
2764 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2767 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2768 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2769 pa_tagstruct
*reply
;
2771 struct timeval tv
, now
;
2774 pa_native_connection_assert_ref(c
);
2777 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2778 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2779 !pa_tagstruct_eof(t
)) {
2784 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2785 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2786 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2788 /* Get an atomic snapshot of all timing parameters */
2789 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);
2791 reply
= reply_new(tag
);
2792 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2793 pa_tagstruct_put_usec(reply
,
2794 s
->current_source_latency
+
2795 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->source
->sample_spec
));
2796 pa_tagstruct_put_boolean(reply
,
2797 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2798 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2799 pa_tagstruct_put_timeval(reply
, &tv
);
2800 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2801 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2802 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2803 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2806 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2807 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2810 const char *name
= NULL
;
2813 pa_tagstruct
*reply
;
2816 pa_native_connection_assert_ref(c
);
2819 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2820 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2821 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2822 pa_tagstruct_getu32(t
, &length
) < 0) {
2827 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2828 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2829 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2830 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2831 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2832 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2834 p
= pa_proplist_new();
2836 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2837 !pa_tagstruct_eof(t
)) {
2840 pa_proplist_free(p
);
2844 if (c
->version
< 13)
2845 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2847 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2848 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2850 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2851 pa_proplist_free(p
);
2852 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2855 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2856 pa_proplist_free(p
);
2858 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2860 reply
= reply_new(tag
);
2861 pa_tagstruct_putu32(reply
, s
->index
);
2862 pa_tagstruct_putu32(reply
, length
);
2863 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2866 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2867 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2872 pa_native_connection_assert_ref(c
);
2875 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2876 !pa_tagstruct_eof(t
)) {
2881 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2883 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2884 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2885 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2887 if (!s
->memchunk
.memblock
)
2888 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2889 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2890 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2892 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2894 upload_stream_unlink(s
);
2897 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2898 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2899 uint32_t sink_index
;
2902 const char *name
, *sink_name
;
2905 pa_tagstruct
*reply
;
2907 pa_native_connection_assert_ref(c
);
2910 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2912 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
2913 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
2914 pa_tagstruct_getu32(t
, &volume
) < 0 ||
2915 pa_tagstruct_gets(t
, &name
) < 0) {
2920 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
2921 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
2922 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2923 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2925 if (sink_index
!= PA_INVALID_INDEX
)
2926 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
2928 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
2930 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
2932 p
= pa_proplist_new();
2934 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2935 !pa_tagstruct_eof(t
)) {
2937 pa_proplist_free(p
);
2941 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
2943 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
2944 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2945 pa_proplist_free(p
);
2949 pa_proplist_free(p
);
2951 reply
= reply_new(tag
);
2953 if (c
->version
>= 13)
2954 pa_tagstruct_putu32(reply
, idx
);
2956 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2959 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2960 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2963 pa_native_connection_assert_ref(c
);
2966 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2967 !pa_tagstruct_eof(t
)) {
2972 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2973 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2975 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
2976 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2980 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2983 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
2986 pa_assert(original
);
2990 if (c
->version
< 12) {
2991 /* Before protocol version 12 we didn't support S32 samples,
2992 * so we need to lie about this to the client */
2994 if (fixed
->format
== PA_SAMPLE_S32LE
)
2995 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
2996 if (fixed
->format
== PA_SAMPLE_S32BE
)
2997 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3000 if (c
->version
< 15) {
3001 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
3002 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3003 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
3004 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3008 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
3009 pa_sample_spec fixed_ss
;
3012 pa_sink_assert_ref(sink
);
3014 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
3018 PA_TAG_U32
, sink
->index
,
3019 PA_TAG_STRING
, sink
->name
,
3020 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3021 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3022 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
3023 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
3024 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
3025 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
3026 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
3027 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
3028 PA_TAG_USEC
, pa_sink_get_latency(sink
),
3029 PA_TAG_STRING
, sink
->driver
,
3030 PA_TAG_U32
, sink
->flags
& ~PA_SINK_SHARE_VOLUME_WITH_MASTER
,
3033 if (c
->version
>= 13) {
3034 pa_tagstruct_put_proplist(t
, sink
->proplist
);
3035 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
3038 if (c
->version
>= 15) {
3039 pa_tagstruct_put_volume(t
, sink
->base_volume
);
3040 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
3041 pa_log_error("Internal sink state is invalid.");
3042 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
3043 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
3044 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
3047 if (c
->version
>= 16) {
3048 pa_tagstruct_putu32(t
, sink
->ports
? pa_hashmap_size(sink
->ports
) : 0);
3054 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
3055 pa_tagstruct_puts(t
, p
->name
);
3056 pa_tagstruct_puts(t
, p
->description
);
3057 pa_tagstruct_putu32(t
, p
->priority
);
3061 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
3064 if (c
->version
>= 21) {
3067 pa_idxset
*formats
= pa_sink_get_formats(sink
);
3069 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3070 PA_IDXSET_FOREACH(f
, formats
, i
) {
3071 pa_tagstruct_put_format_info(t
, f
);
3074 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
3078 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
3079 pa_sample_spec fixed_ss
;
3082 pa_source_assert_ref(source
);
3084 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
3088 PA_TAG_U32
, source
->index
,
3089 PA_TAG_STRING
, source
->name
,
3090 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3091 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3092 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
3093 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
3094 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
3095 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
3096 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
3097 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
3098 PA_TAG_USEC
, pa_source_get_latency(source
),
3099 PA_TAG_STRING
, source
->driver
,
3100 PA_TAG_U32
, source
->flags
,
3103 if (c
->version
>= 13) {
3104 pa_tagstruct_put_proplist(t
, source
->proplist
);
3105 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
3108 if (c
->version
>= 15) {
3109 pa_tagstruct_put_volume(t
, source
->base_volume
);
3110 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
3111 pa_log_error("Internal source state is invalid.");
3112 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
3113 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
3114 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
3117 if (c
->version
>= 16) {
3119 pa_tagstruct_putu32(t
, source
->ports
? pa_hashmap_size(source
->ports
) : 0);
3121 if (source
->ports
) {
3125 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
3126 pa_tagstruct_puts(t
, p
->name
);
3127 pa_tagstruct_puts(t
, p
->description
);
3128 pa_tagstruct_putu32(t
, p
->priority
);
3132 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
3136 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
3140 pa_tagstruct_putu32(t
, client
->index
);
3141 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
3142 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
3143 pa_tagstruct_puts(t
, client
->driver
);
3145 if (c
->version
>= 13)
3146 pa_tagstruct_put_proplist(t
, client
->proplist
);
3149 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
3156 pa_tagstruct_putu32(t
, card
->index
);
3157 pa_tagstruct_puts(t
, card
->name
);
3158 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
3159 pa_tagstruct_puts(t
, card
->driver
);
3161 pa_tagstruct_putu32(t
, card
->profiles
? pa_hashmap_size(card
->profiles
) : 0);
3163 if (card
->profiles
) {
3164 while ((p
= pa_hashmap_iterate(card
->profiles
, &state
, NULL
))) {
3165 pa_tagstruct_puts(t
, p
->name
);
3166 pa_tagstruct_puts(t
, p
->description
);
3167 pa_tagstruct_putu32(t
, p
->n_sinks
);
3168 pa_tagstruct_putu32(t
, p
->n_sources
);
3169 pa_tagstruct_putu32(t
, p
->priority
);
3173 pa_tagstruct_puts(t
, card
->active_profile
? card
->active_profile
->name
: NULL
);
3174 pa_tagstruct_put_proplist(t
, card
->proplist
);
3177 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
3181 pa_tagstruct_putu32(t
, module
->index
);
3182 pa_tagstruct_puts(t
, module
->name
);
3183 pa_tagstruct_puts(t
, module
->argument
);
3184 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
3186 if (c
->version
< 15)
3187 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
3189 if (c
->version
>= 15)
3190 pa_tagstruct_put_proplist(t
, module
->proplist
);
3193 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
3194 pa_sample_spec fixed_ss
;
3195 pa_usec_t sink_latency
;
3197 pa_bool_t has_volume
= FALSE
;
3200 pa_sink_input_assert_ref(s
);
3202 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3204 has_volume
= pa_sink_input_is_volume_readable(s
);
3206 pa_sink_input_get_volume(s
, &v
, TRUE
);
3208 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3210 pa_tagstruct_putu32(t
, s
->index
);
3211 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3212 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3213 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3214 pa_tagstruct_putu32(t
, s
->sink
->index
);
3215 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3216 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3217 pa_tagstruct_put_cvolume(t
, &v
);
3218 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3219 pa_tagstruct_put_usec(t
, sink_latency
);
3220 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3221 pa_tagstruct_puts(t
, s
->driver
);
3222 if (c
->version
>= 11)
3223 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3224 if (c
->version
>= 13)
3225 pa_tagstruct_put_proplist(t
, s
->proplist
);
3226 if (c
->version
>= 19)
3227 pa_tagstruct_put_boolean(t
, (pa_sink_input_get_state(s
) == PA_SINK_INPUT_CORKED
));
3228 if (c
->version
>= 20) {
3229 pa_tagstruct_put_boolean(t
, has_volume
);
3230 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3232 if (c
->version
>= 21)
3233 pa_tagstruct_put_format_info(t
, s
->format
);
3236 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3237 pa_sample_spec fixed_ss
;
3238 pa_usec_t source_latency
;
3241 pa_source_output_assert_ref(s
);
3243 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3245 pa_tagstruct_putu32(t
, s
->index
);
3246 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3247 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3248 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3249 pa_tagstruct_putu32(t
, s
->source
->index
);
3250 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3251 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3252 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3253 pa_tagstruct_put_usec(t
, source_latency
);
3254 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3255 pa_tagstruct_puts(t
, s
->driver
);
3256 if (c
->version
>= 13)
3257 pa_tagstruct_put_proplist(t
, s
->proplist
);
3258 if (c
->version
>= 19)
3259 pa_tagstruct_put_boolean(t
, (pa_source_output_get_state(s
) == PA_SOURCE_OUTPUT_CORKED
));
3262 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3263 pa_sample_spec fixed_ss
;
3269 if (e
->memchunk
.memblock
)
3270 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3272 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3274 pa_tagstruct_putu32(t
, e
->index
);
3275 pa_tagstruct_puts(t
, e
->name
);
3277 if (e
->volume_is_set
)
3280 pa_cvolume_init(&v
);
3282 pa_tagstruct_put_cvolume(t
, &v
);
3283 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3284 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3285 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3286 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3287 pa_tagstruct_put_boolean(t
, e
->lazy
);
3288 pa_tagstruct_puts(t
, e
->filename
);
3290 if (c
->version
>= 13)
3291 pa_tagstruct_put_proplist(t
, e
->proplist
);
3294 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3295 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3297 pa_sink
*sink
= NULL
;
3298 pa_source
*source
= NULL
;
3299 pa_client
*client
= NULL
;
3300 pa_card
*card
= NULL
;
3301 pa_module
*module
= NULL
;
3302 pa_sink_input
*si
= NULL
;
3303 pa_source_output
*so
= NULL
;
3304 pa_scache_entry
*sce
= NULL
;
3305 const char *name
= NULL
;
3306 pa_tagstruct
*reply
;
3308 pa_native_connection_assert_ref(c
);
3311 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3312 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3313 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3314 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3315 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3316 pa_tagstruct_gets(t
, &name
) < 0) ||
3317 !pa_tagstruct_eof(t
)) {
3322 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3323 CHECK_VALIDITY(c
->pstream
, !name
||
3324 (command
== PA_COMMAND_GET_SINK_INFO
&&
3325 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3326 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3327 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3328 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3329 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3330 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3331 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3333 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3334 if (idx
!= PA_INVALID_INDEX
)
3335 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3337 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3338 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3339 if (idx
!= PA_INVALID_INDEX
)
3340 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3342 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3343 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3344 if (idx
!= PA_INVALID_INDEX
)
3345 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3347 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3348 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3349 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3350 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3351 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3352 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3353 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3354 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3355 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3357 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3358 if (idx
!= PA_INVALID_INDEX
)
3359 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3361 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3364 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3365 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3369 reply
= reply_new(tag
);
3371 sink_fill_tagstruct(c
, reply
, sink
);
3373 source_fill_tagstruct(c
, reply
, source
);
3375 client_fill_tagstruct(c
, reply
, client
);
3377 card_fill_tagstruct(c
, reply
, card
);
3379 module_fill_tagstruct(c
, reply
, module
);
3381 sink_input_fill_tagstruct(c
, reply
, si
);
3383 source_output_fill_tagstruct(c
, reply
, so
);
3385 scache_fill_tagstruct(c
, reply
, sce
);
3386 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3389 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3390 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3394 pa_tagstruct
*reply
;
3396 pa_native_connection_assert_ref(c
);
3399 if (!pa_tagstruct_eof(t
)) {
3404 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3406 reply
= reply_new(tag
);
3408 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3409 i
= c
->protocol
->core
->sinks
;
3410 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3411 i
= c
->protocol
->core
->sources
;
3412 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3413 i
= c
->protocol
->core
->clients
;
3414 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3415 i
= c
->protocol
->core
->cards
;
3416 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3417 i
= c
->protocol
->core
->modules
;
3418 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3419 i
= c
->protocol
->core
->sink_inputs
;
3420 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3421 i
= c
->protocol
->core
->source_outputs
;
3423 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3424 i
= c
->protocol
->core
->scache
;
3428 for (p
= pa_idxset_first(i
, &idx
); p
; p
= pa_idxset_next(i
, &idx
)) {
3429 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3430 sink_fill_tagstruct(c
, reply
, p
);
3431 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3432 source_fill_tagstruct(c
, reply
, p
);
3433 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3434 client_fill_tagstruct(c
, reply
, p
);
3435 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3436 card_fill_tagstruct(c
, reply
, p
);
3437 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3438 module_fill_tagstruct(c
, reply
, p
);
3439 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3440 sink_input_fill_tagstruct(c
, reply
, p
);
3441 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3442 source_output_fill_tagstruct(c
, reply
, p
);
3444 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3445 scache_fill_tagstruct(c
, reply
, p
);
3450 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3453 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3454 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3455 pa_tagstruct
*reply
;
3457 pa_source
*def_source
;
3458 pa_sample_spec fixed_ss
;
3461 pa_native_connection_assert_ref(c
);
3464 if (!pa_tagstruct_eof(t
)) {
3469 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3471 reply
= reply_new(tag
);
3472 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3473 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3475 u
= pa_get_user_name_malloc();
3476 pa_tagstruct_puts(reply
, u
);
3479 h
= pa_get_host_name_malloc();
3480 pa_tagstruct_puts(reply
, h
);
3483 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3484 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3486 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3487 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3488 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3489 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3491 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3493 if (c
->version
>= 15)
3494 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3496 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3499 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3501 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3503 pa_native_connection_assert_ref(c
);
3505 t
= pa_tagstruct_new(NULL
, 0);
3506 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3507 pa_tagstruct_putu32(t
, (uint32_t) -1);
3508 pa_tagstruct_putu32(t
, e
);
3509 pa_tagstruct_putu32(t
, idx
);
3510 pa_pstream_send_tagstruct(c
->pstream
, t
);
3513 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3514 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3515 pa_subscription_mask_t m
;
3517 pa_native_connection_assert_ref(c
);
3520 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3521 !pa_tagstruct_eof(t
)) {
3526 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3527 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3529 if (c
->subscription
)
3530 pa_subscription_free(c
->subscription
);
3533 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3534 pa_assert(c
->subscription
);
3536 c
->subscription
= NULL
;
3538 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3541 static void command_set_volume(
3548 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3551 pa_sink
*sink
= NULL
;
3552 pa_source
*source
= NULL
;
3553 pa_sink_input
*si
= NULL
;
3554 const char *name
= NULL
;
3555 const char *client_name
;
3557 pa_native_connection_assert_ref(c
);
3560 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3561 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3562 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3563 pa_tagstruct_get_cvolume(t
, &volume
) ||
3564 !pa_tagstruct_eof(t
)) {
3569 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3570 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
);
3571 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3572 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3573 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3574 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3578 case PA_COMMAND_SET_SINK_VOLUME
:
3579 if (idx
!= PA_INVALID_INDEX
)
3580 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3582 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3585 case PA_COMMAND_SET_SOURCE_VOLUME
:
3586 if (idx
!= PA_INVALID_INDEX
)
3587 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3589 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3592 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3593 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3597 pa_assert_not_reached();
3600 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3602 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3605 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3607 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3608 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3609 } else if (source
) {
3610 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3612 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3613 pa_source_set_volume(source
, &volume
, TRUE
);
3615 CHECK_VALIDITY(c
->pstream
, si
->volume_writable
, tag
, PA_ERR_BADSTATE
);
3616 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3618 pa_log_debug("Client %s changes volume of sink input %s.",
3620 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3621 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3624 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3627 static void command_set_mute(
3634 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3637 pa_sink
*sink
= NULL
;
3638 pa_source
*source
= NULL
;
3639 pa_sink_input
*si
= NULL
;
3640 const char *name
= NULL
, *client_name
;
3642 pa_native_connection_assert_ref(c
);
3645 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3646 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3647 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3648 pa_tagstruct_get_boolean(t
, &mute
) ||
3649 !pa_tagstruct_eof(t
)) {
3654 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3655 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
);
3656 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3657 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3658 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3662 case PA_COMMAND_SET_SINK_MUTE
:
3663 if (idx
!= PA_INVALID_INDEX
)
3664 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3666 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3670 case PA_COMMAND_SET_SOURCE_MUTE
:
3671 if (idx
!= PA_INVALID_INDEX
)
3672 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3674 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3678 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3679 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3683 pa_assert_not_reached();
3686 CHECK_VALIDITY(c
->pstream
, si
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3688 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3691 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3692 pa_sink_set_mute(sink
, mute
, TRUE
);
3693 } else if (source
) {
3694 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3695 pa_source_set_mute(source
, mute
, TRUE
);
3697 pa_log_debug("Client %s changes mute of sink input %s.",
3699 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3700 pa_sink_input_set_mute(si
, mute
, TRUE
);
3703 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3706 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3707 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3712 pa_native_connection_assert_ref(c
);
3715 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3716 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3717 !pa_tagstruct_eof(t
)) {
3722 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3723 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3724 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3725 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3726 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3728 pa_sink_input_cork(s
->sink_input
, b
);
3731 s
->is_underrun
= TRUE
;
3733 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3736 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3737 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3741 pa_native_connection_assert_ref(c
);
3744 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3745 !pa_tagstruct_eof(t
)) {
3750 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3751 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3752 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3753 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3754 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3757 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3758 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3761 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3762 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3765 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3766 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3770 pa_assert_not_reached();
3773 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3776 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3777 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3782 pa_native_connection_assert_ref(c
);
3785 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3786 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3787 !pa_tagstruct_eof(t
)) {
3792 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3793 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3794 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3796 pa_source_output_cork(s
->source_output
, b
);
3797 pa_memblockq_prebuf_force(s
->memblockq
);
3798 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3801 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3802 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3806 pa_native_connection_assert_ref(c
);
3809 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3810 !pa_tagstruct_eof(t
)) {
3815 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3816 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3817 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3819 pa_memblockq_flush_read(s
->memblockq
);
3820 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3823 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3824 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3827 pa_tagstruct
*reply
;
3829 pa_native_connection_assert_ref(c
);
3832 memset(&a
, 0, sizeof(a
));
3834 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3839 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3841 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
3843 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3845 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3846 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3847 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3849 if (pa_tagstruct_get(
3851 PA_TAG_U32
, &a
.maxlength
,
3852 PA_TAG_U32
, &a
.tlength
,
3853 PA_TAG_U32
, &a
.prebuf
,
3854 PA_TAG_U32
, &a
.minreq
,
3855 PA_TAG_INVALID
) < 0 ||
3856 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3857 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3858 !pa_tagstruct_eof(t
)) {
3863 s
->adjust_latency
= adjust_latency
;
3864 s
->early_requests
= early_requests
;
3865 s
->buffer_attr_req
= a
;
3867 fix_playback_buffer_attr(s
);
3868 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);
3870 reply
= reply_new(tag
);
3871 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3872 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
3873 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
3874 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
3876 if (c
->version
>= 13)
3877 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
3881 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3882 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
3884 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3885 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3887 if (pa_tagstruct_get(
3889 PA_TAG_U32
, &a
.maxlength
,
3890 PA_TAG_U32
, &a
.fragsize
,
3891 PA_TAG_INVALID
) < 0 ||
3892 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
3893 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
3894 !pa_tagstruct_eof(t
)) {
3899 s
->adjust_latency
= adjust_latency
;
3900 s
->early_requests
= early_requests
;
3901 s
->buffer_attr_req
= a
;
3903 fix_record_buffer_attr_pre(s
);
3904 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
3905 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
3906 fix_record_buffer_attr_post(s
);
3908 reply
= reply_new(tag
);
3909 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
3910 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
3912 if (c
->version
>= 13)
3913 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
3916 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3919 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3920 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3924 pa_native_connection_assert_ref(c
);
3927 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3928 pa_tagstruct_getu32(t
, &rate
) < 0 ||
3929 !pa_tagstruct_eof(t
)) {
3934 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3935 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
3937 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
3940 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3941 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3942 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3944 pa_sink_input_set_rate(s
->sink_input
, rate
);
3948 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
3950 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3951 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3953 pa_source_output_set_rate(s
->source_output
, rate
);
3956 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3959 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3960 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3965 pa_native_connection_assert_ref(c
);
3968 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3970 p
= pa_proplist_new();
3972 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
3974 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
3975 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3976 !pa_tagstruct_eof(t
)) {
3978 pa_proplist_free(p
);
3984 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3985 pa_tagstruct_getu32(t
, &mode
) < 0 ||
3986 pa_tagstruct_get_proplist(t
, p
) < 0 ||
3987 !pa_tagstruct_eof(t
)) {
3989 pa_proplist_free(p
);
3994 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
3995 pa_proplist_free(p
);
3996 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
3999 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
4002 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4003 if (!s
|| !playback_stream_isinstance(s
)) {
4004 pa_proplist_free(p
);
4005 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4007 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
4009 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
4012 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
4013 pa_proplist_free(p
);
4014 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4016 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
4019 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
4021 pa_client_update_proplist(c
->client
, mode
, p
);
4024 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4025 pa_proplist_free(p
);
4028 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4029 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4031 unsigned changed
= 0;
4033 pa_strlist
*l
= NULL
;
4035 pa_native_connection_assert_ref(c
);
4038 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4040 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
4042 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
4048 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4051 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4052 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4053 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4055 p
= s
->sink_input
->proplist
;
4057 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4060 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4061 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4063 p
= s
->source_output
->proplist
;
4065 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4067 p
= c
->client
->proplist
;
4073 if (pa_tagstruct_gets(t
, &k
) < 0) {
4082 l
= pa_strlist_prepend(l
, k
);
4085 if (!pa_tagstruct_eof(t
)) {
4094 l
= pa_strlist_pop(l
, &z
);
4099 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
4103 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4106 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4109 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4110 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
4112 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4115 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4116 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
4119 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4120 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
4125 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4126 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4129 pa_native_connection_assert_ref(c
);
4132 if (pa_tagstruct_gets(t
, &s
) < 0 ||
4133 !pa_tagstruct_eof(t
)) {
4138 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4139 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
4141 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
4144 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
4145 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4147 pa_namereg_set_default_source(c
->protocol
->core
, source
);
4150 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
4152 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
4153 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4155 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
4158 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4161 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4162 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4166 pa_native_connection_assert_ref(c
);
4169 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4170 pa_tagstruct_gets(t
, &name
) < 0 ||
4171 !pa_tagstruct_eof(t
)) {
4176 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4177 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4179 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
4182 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4183 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4184 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4186 pa_sink_input_set_name(s
->sink_input
, name
);
4190 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
4192 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4193 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4195 pa_source_output_set_name(s
->source_output
, name
);
4198 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4201 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4202 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4205 pa_native_connection_assert_ref(c
);
4208 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4209 !pa_tagstruct_eof(t
)) {
4214 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4216 if (command
== PA_COMMAND_KILL_CLIENT
) {
4219 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4220 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4222 pa_native_connection_ref(c
);
4223 pa_client_kill(client
);
4225 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4228 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4229 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4231 pa_native_connection_ref(c
);
4232 pa_sink_input_kill(s
);
4234 pa_source_output
*s
;
4236 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4238 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4239 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4241 pa_native_connection_ref(c
);
4242 pa_source_output_kill(s
);
4245 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4246 pa_native_connection_unref(c
);
4249 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4250 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4252 const char *name
, *argument
;
4253 pa_tagstruct
*reply
;
4255 pa_native_connection_assert_ref(c
);
4258 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4259 pa_tagstruct_gets(t
, &argument
) < 0 ||
4260 !pa_tagstruct_eof(t
)) {
4265 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4266 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4267 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4269 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4270 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4274 reply
= reply_new(tag
);
4275 pa_tagstruct_putu32(reply
, m
->index
);
4276 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4279 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4280 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4284 pa_native_connection_assert_ref(c
);
4287 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4288 !pa_tagstruct_eof(t
)) {
4293 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4294 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4295 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4297 pa_module_unload_request(m
, FALSE
);
4298 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4301 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4302 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4303 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4304 const char *name_device
= NULL
;
4306 pa_native_connection_assert_ref(c
);
4309 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4310 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4311 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4312 !pa_tagstruct_eof(t
)) {
4317 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4318 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4320 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
);
4321 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4322 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4323 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4325 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4326 pa_sink_input
*si
= NULL
;
4327 pa_sink
*sink
= NULL
;
4329 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4331 if (idx_device
!= PA_INVALID_INDEX
)
4332 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4334 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4336 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4338 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4339 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4343 pa_source_output
*so
= NULL
;
4346 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4348 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4350 if (idx_device
!= PA_INVALID_INDEX
)
4351 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4353 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4355 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4357 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4358 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4363 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4366 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4367 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4368 uint32_t idx
= PA_INVALID_INDEX
;
4369 const char *name
= NULL
;
4372 pa_native_connection_assert_ref(c
);
4375 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4376 pa_tagstruct_gets(t
, &name
) < 0 ||
4377 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4378 !pa_tagstruct_eof(t
)) {
4383 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4384 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
);
4385 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4386 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4387 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4389 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4391 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4393 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4395 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4396 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4400 pa_sink
*sink
= NULL
;
4402 if (idx
!= PA_INVALID_INDEX
)
4403 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4405 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4407 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4409 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4410 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4416 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4418 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4420 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4422 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4423 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4430 if (idx
!= PA_INVALID_INDEX
)
4431 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4433 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4435 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4437 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4438 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4444 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4447 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4448 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4449 uint32_t idx
= PA_INVALID_INDEX
;
4450 const char *name
= NULL
;
4452 pa_native_protocol_ext_cb_t cb
;
4454 pa_native_connection_assert_ref(c
);
4457 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4458 pa_tagstruct_gets(t
, &name
) < 0) {
4463 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4464 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4465 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4466 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4467 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4469 if (idx
!= PA_INVALID_INDEX
)
4470 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4472 for (m
= pa_idxset_first(c
->protocol
->core
->modules
, &idx
); m
; m
= pa_idxset_next(c
->protocol
->core
->modules
, &idx
))
4473 if (strcmp(name
, m
->name
) == 0)
4477 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4478 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4480 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4481 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4483 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4487 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4488 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4489 uint32_t idx
= PA_INVALID_INDEX
;
4490 const char *name
= NULL
, *profile
= NULL
;
4491 pa_card
*card
= NULL
;
4494 pa_native_connection_assert_ref(c
);
4497 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4498 pa_tagstruct_gets(t
, &name
) < 0 ||
4499 pa_tagstruct_gets(t
, &profile
) < 0 ||
4500 !pa_tagstruct_eof(t
)) {
4505 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4506 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4507 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4508 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4509 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4511 if (idx
!= PA_INVALID_INDEX
)
4512 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4514 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4516 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4518 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4519 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4523 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4526 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4527 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4528 uint32_t idx
= PA_INVALID_INDEX
;
4529 const char *name
= NULL
, *port
= NULL
;
4532 pa_native_connection_assert_ref(c
);
4535 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4536 pa_tagstruct_gets(t
, &name
) < 0 ||
4537 pa_tagstruct_gets(t
, &port
) < 0 ||
4538 !pa_tagstruct_eof(t
)) {
4543 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4544 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
);
4545 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4546 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4547 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4549 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4552 if (idx
!= PA_INVALID_INDEX
)
4553 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4555 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4557 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4559 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4560 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4566 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4568 if (idx
!= PA_INVALID_INDEX
)
4569 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4571 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4573 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4575 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4576 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4581 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4584 /*** pstream callbacks ***/
4586 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4587 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4591 pa_native_connection_assert_ref(c
);
4593 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4594 pa_log("invalid packet.");
4595 native_connection_unlink(c
);
4599 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
) {
4600 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4601 output_stream
*stream
;
4605 pa_native_connection_assert_ref(c
);
4607 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4608 pa_log_debug("Client sent block for invalid stream.");
4613 /* pa_log("got %lu bytes", (unsigned long) chunk->length); */
4615 if (playback_stream_isinstance(stream
)) {
4616 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4618 pa_atomic_inc(&ps
->seek_or_post_in_queue
);
4619 if (chunk
->memblock
) {
4620 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4621 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_SEEK
, PA_UINT_TO_PTR(seek
), offset
, chunk
, NULL
);
4623 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4625 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
);
4628 upload_stream
*u
= UPLOAD_STREAM(stream
);
4631 if (!u
->memchunk
.memblock
) {
4632 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4633 u
->memchunk
= *chunk
;
4634 pa_memblock_ref(u
->memchunk
.memblock
);
4637 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4638 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4642 pa_assert(u
->memchunk
.memblock
);
4645 if (l
> chunk
->length
)
4650 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4652 if (chunk
->memblock
) {
4654 src
= pa_memblock_acquire(chunk
->memblock
);
4656 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4657 (uint8_t*) src
+ chunk
->index
, l
);
4659 pa_memblock_release(chunk
->memblock
);
4661 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4663 pa_memblock_release(u
->memchunk
.memblock
);
4665 u
->memchunk
.length
+= l
;
4671 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4672 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4675 pa_native_connection_assert_ref(c
);
4677 native_connection_unlink(c
);
4678 pa_log_info("Connection died.");
4681 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4682 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4685 pa_native_connection_assert_ref(c
);
4687 native_connection_send_memblock(c
);
4690 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4693 if (!(q
= pa_thread_mq_get()))
4694 pa_pstream_send_revoke(p
, block_id
);
4696 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4699 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4702 if (!(q
= pa_thread_mq_get()))
4703 pa_pstream_send_release(p
, block_id
);
4705 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4708 /*** client callbacks ***/
4710 static void client_kill_cb(pa_client
*c
) {
4713 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4714 pa_log_info("Connection killed.");
4717 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4719 pa_native_connection
*c
;
4722 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4723 pa_native_connection_assert_ref(c
);
4725 if (c
->version
< 15)
4728 t
= pa_tagstruct_new(NULL
, 0);
4729 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4730 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4731 pa_tagstruct_puts(t
, event
);
4732 pa_tagstruct_put_proplist(t
, pl
);
4733 pa_pstream_send_tagstruct(c
->pstream
, t
);
4736 /*** module entry points ***/
4738 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4739 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4742 pa_native_connection_assert_ref(c
);
4743 pa_assert(c
->auth_timeout_event
== e
);
4745 if (!c
->authorized
) {
4746 native_connection_unlink(c
);
4747 pa_log_info("Connection terminated due to authentication timeout.");
4751 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4752 pa_native_connection
*c
;
4755 pa_client_new_data data
;
4761 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4762 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4763 pa_iochannel_free(io
);
4767 pa_client_new_data_init(&data
);
4768 data
.module
= o
->module
;
4769 data
.driver
= __FILE__
;
4770 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4771 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4772 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4773 client
= pa_client_new(p
->core
, &data
);
4774 pa_client_new_data_done(&data
);
4779 c
= pa_msgobject_new(pa_native_connection
);
4780 c
->parent
.parent
.free
= native_connection_free
;
4781 c
->parent
.process_msg
= native_connection_process_msg
;
4783 c
->options
= pa_native_options_ref(o
);
4784 c
->authorized
= FALSE
;
4786 if (o
->auth_anonymous
) {
4787 pa_log_info("Client authenticated anonymously.");
4788 c
->authorized
= TRUE
;
4791 if (!c
->authorized
&&
4793 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
4795 pa_log_info("Client authenticated by IP ACL.");
4796 c
->authorized
= TRUE
;
4800 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
4802 c
->auth_timeout_event
= NULL
;
4804 c
->is_local
= pa_iochannel_socket_is_local(io
);
4808 c
->client
->kill
= client_kill_cb
;
4809 c
->client
->send_event
= client_send_event_cb
;
4810 c
->client
->userdata
= c
;
4812 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
4813 pa_pstream_set_recieve_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
4814 pa_pstream_set_recieve_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
4815 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
4816 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
4817 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
4818 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
4820 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
4822 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
4823 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
4825 c
->rrobin_index
= PA_IDXSET_INVALID
;
4826 c
->subscription
= NULL
;
4828 pa_idxset_put(p
->connections
, c
, NULL
);
4831 if (pa_iochannel_creds_supported(io
))
4832 pa_iochannel_creds_enable(io
);
4835 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
4838 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
4839 pa_native_connection
*c
;
4845 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
4846 if (c
->options
->module
== m
)
4847 native_connection_unlink(c
);
4850 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
4851 pa_native_protocol
*p
;
4856 p
= pa_xnew(pa_native_protocol
, 1);
4859 p
->connections
= pa_idxset_new(NULL
, NULL
);
4863 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
4865 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4866 pa_hook_init(&p
->hooks
[h
], p
);
4868 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
4873 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
4874 pa_native_protocol
*p
;
4876 if ((p
= pa_shared_get(c
, "native-protocol")))
4877 return pa_native_protocol_ref(p
);
4879 return native_protocol_new(c
);
4882 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
4884 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4891 void pa_native_protocol_unref(pa_native_protocol
*p
) {
4892 pa_native_connection
*c
;
4896 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4898 if (PA_REFCNT_DEC(p
) > 0)
4901 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
4902 native_connection_unlink(c
);
4904 pa_idxset_free(p
->connections
, NULL
, NULL
);
4906 pa_strlist_free(p
->servers
);
4908 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
4909 pa_hook_done(&p
->hooks
[h
]);
4911 pa_hashmap_free(p
->extensions
, NULL
, NULL
);
4913 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
4918 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
4920 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4923 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
4925 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4928 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
4930 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4933 p
->servers
= pa_strlist_remove(p
->servers
, name
);
4935 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
4938 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
4940 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4945 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
4947 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4952 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
4954 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4957 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
4959 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
4963 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
4965 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
4968 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
4971 pa_native_options
* pa_native_options_new(void) {
4972 pa_native_options
*o
;
4974 o
= pa_xnew0(pa_native_options
, 1);
4980 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
4982 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4989 void pa_native_options_unref(pa_native_options
*o
) {
4991 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
4993 if (PA_REFCNT_DEC(o
) > 0)
4996 pa_xfree(o
->auth_group
);
4999 pa_ip_acl_free(o
->auth_ip_acl
);
5002 pa_auth_cookie_unref(o
->auth_cookie
);
5007 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
5012 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5015 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
5016 pa_log("auth-anonymous= expects a boolean argument.");
5021 if (pa_modargs_get_value_boolean(ma
, "auth-group-enabled", &enabled
) < 0) {
5022 pa_log("auth-group-enabled= expects a boolean argument.");
5026 pa_xfree(o
->auth_group
);
5027 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
5031 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
5034 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
5037 if (!(ipa
= pa_ip_acl_new(acl
))) {
5038 pa_log("Failed to parse IP ACL '%s'", acl
);
5043 pa_ip_acl_free(o
->auth_ip_acl
);
5045 o
->auth_ip_acl
= ipa
;
5049 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
5050 pa_log("auth-cookie-enabled= expects a boolean argument.");
5055 pa_auth_cookie_unref(o
->auth_cookie
);
5060 /* The new name for this is 'auth-cookie', for compat reasons
5061 * we check the old name too */
5062 if (!(cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
)))
5063 if (!(cn
= pa_modargs_get_value(ma
, "cookie", NULL
)))
5064 cn
= PA_NATIVE_COOKIE_FILE
;
5066 if (!(o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, PA_NATIVE_COOKIE_LENGTH
)))
5070 o
->auth_cookie
= NULL
;
5075 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
5076 pa_native_connection_assert_ref(c
);
5081 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
5082 pa_native_connection_assert_ref(c
);