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/namereg.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/core-subscribe.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/strlist.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/creds.h>
57 #include <pulsecore/core-util.h>
58 #include <pulsecore/ipacl.h>
59 #include <pulsecore/thread-mq.h>
61 #include "protocol-native.h"
63 /* #define PROTOCOL_NATIVE_DEBUG */
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
);
295 static void command_set_port_latency_offset(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
297 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
298 [PA_COMMAND_ERROR
] = NULL
,
299 [PA_COMMAND_TIMEOUT
] = NULL
,
300 [PA_COMMAND_REPLY
] = NULL
,
301 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = command_create_playback_stream
,
302 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = command_delete_stream
,
303 [PA_COMMAND_DRAIN_PLAYBACK_STREAM
] = command_drain_playback_stream
,
304 [PA_COMMAND_CREATE_RECORD_STREAM
] = command_create_record_stream
,
305 [PA_COMMAND_DELETE_RECORD_STREAM
] = command_delete_stream
,
306 [PA_COMMAND_AUTH
] = command_auth
,
307 [PA_COMMAND_REQUEST
] = NULL
,
308 [PA_COMMAND_EXIT
] = command_exit
,
309 [PA_COMMAND_SET_CLIENT_NAME
] = command_set_client_name
,
310 [PA_COMMAND_LOOKUP_SINK
] = command_lookup
,
311 [PA_COMMAND_LOOKUP_SOURCE
] = command_lookup
,
312 [PA_COMMAND_STAT
] = command_stat
,
313 [PA_COMMAND_GET_PLAYBACK_LATENCY
] = command_get_playback_latency
,
314 [PA_COMMAND_GET_RECORD_LATENCY
] = command_get_record_latency
,
315 [PA_COMMAND_CREATE_UPLOAD_STREAM
] = command_create_upload_stream
,
316 [PA_COMMAND_DELETE_UPLOAD_STREAM
] = command_delete_stream
,
317 [PA_COMMAND_FINISH_UPLOAD_STREAM
] = command_finish_upload_stream
,
318 [PA_COMMAND_PLAY_SAMPLE
] = command_play_sample
,
319 [PA_COMMAND_REMOVE_SAMPLE
] = command_remove_sample
,
320 [PA_COMMAND_GET_SINK_INFO
] = command_get_info
,
321 [PA_COMMAND_GET_SOURCE_INFO
] = command_get_info
,
322 [PA_COMMAND_GET_CLIENT_INFO
] = command_get_info
,
323 [PA_COMMAND_GET_CARD_INFO
] = command_get_info
,
324 [PA_COMMAND_GET_MODULE_INFO
] = command_get_info
,
325 [PA_COMMAND_GET_SINK_INPUT_INFO
] = command_get_info
,
326 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO
] = command_get_info
,
327 [PA_COMMAND_GET_SAMPLE_INFO
] = command_get_info
,
328 [PA_COMMAND_GET_SINK_INFO_LIST
] = command_get_info_list
,
329 [PA_COMMAND_GET_SOURCE_INFO_LIST
] = command_get_info_list
,
330 [PA_COMMAND_GET_MODULE_INFO_LIST
] = command_get_info_list
,
331 [PA_COMMAND_GET_CLIENT_INFO_LIST
] = command_get_info_list
,
332 [PA_COMMAND_GET_CARD_INFO_LIST
] = command_get_info_list
,
333 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST
] = command_get_info_list
,
334 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
] = command_get_info_list
,
335 [PA_COMMAND_GET_SAMPLE_INFO_LIST
] = command_get_info_list
,
336 [PA_COMMAND_GET_SERVER_INFO
] = command_get_server_info
,
337 [PA_COMMAND_SUBSCRIBE
] = command_subscribe
,
339 [PA_COMMAND_SET_SINK_VOLUME
] = command_set_volume
,
340 [PA_COMMAND_SET_SINK_INPUT_VOLUME
] = command_set_volume
,
341 [PA_COMMAND_SET_SOURCE_VOLUME
] = command_set_volume
,
342 [PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME
] = command_set_volume
,
344 [PA_COMMAND_SET_SINK_MUTE
] = command_set_mute
,
345 [PA_COMMAND_SET_SINK_INPUT_MUTE
] = command_set_mute
,
346 [PA_COMMAND_SET_SOURCE_MUTE
] = command_set_mute
,
347 [PA_COMMAND_SET_SOURCE_OUTPUT_MUTE
] = command_set_mute
,
349 [PA_COMMAND_SUSPEND_SINK
] = command_suspend
,
350 [PA_COMMAND_SUSPEND_SOURCE
] = command_suspend
,
352 [PA_COMMAND_CORK_PLAYBACK_STREAM
] = command_cork_playback_stream
,
353 [PA_COMMAND_FLUSH_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
354 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
355 [PA_COMMAND_PREBUF_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
357 [PA_COMMAND_CORK_RECORD_STREAM
] = command_cork_record_stream
,
358 [PA_COMMAND_FLUSH_RECORD_STREAM
] = command_flush_record_stream
,
360 [PA_COMMAND_SET_DEFAULT_SINK
] = command_set_default_sink_or_source
,
361 [PA_COMMAND_SET_DEFAULT_SOURCE
] = command_set_default_sink_or_source
,
362 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME
] = command_set_stream_name
,
363 [PA_COMMAND_SET_RECORD_STREAM_NAME
] = command_set_stream_name
,
364 [PA_COMMAND_KILL_CLIENT
] = command_kill
,
365 [PA_COMMAND_KILL_SINK_INPUT
] = command_kill
,
366 [PA_COMMAND_KILL_SOURCE_OUTPUT
] = command_kill
,
367 [PA_COMMAND_LOAD_MODULE
] = command_load_module
,
368 [PA_COMMAND_UNLOAD_MODULE
] = command_unload_module
,
370 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE
] = NULL
,
371 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE
] = NULL
,
372 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE
] = NULL
,
373 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE
] = NULL
,
375 [PA_COMMAND_MOVE_SINK_INPUT
] = command_move_stream
,
376 [PA_COMMAND_MOVE_SOURCE_OUTPUT
] = command_move_stream
,
378 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
379 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
381 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
382 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
384 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
] = command_update_proplist
,
385 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
] = command_update_proplist
,
386 [PA_COMMAND_UPDATE_CLIENT_PROPLIST
] = command_update_proplist
,
388 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
] = command_remove_proplist
,
389 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
] = command_remove_proplist
,
390 [PA_COMMAND_REMOVE_CLIENT_PROPLIST
] = command_remove_proplist
,
392 [PA_COMMAND_SET_CARD_PROFILE
] = command_set_card_profile
,
394 [PA_COMMAND_SET_SINK_PORT
] = command_set_sink_or_source_port
,
395 [PA_COMMAND_SET_SOURCE_PORT
] = command_set_sink_or_source_port
,
397 [PA_COMMAND_SET_PORT_LATENCY_OFFSET
] = command_set_port_latency_offset
,
399 [PA_COMMAND_EXTENSION
] = command_extension
402 /* structure management */
404 /* Called from main context */
405 static void upload_stream_unlink(upload_stream
*s
) {
411 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
412 s
->connection
= NULL
;
413 upload_stream_unref(s
);
416 /* Called from main context */
417 static void upload_stream_free(pa_object
*o
) {
418 upload_stream
*s
= UPLOAD_STREAM(o
);
421 upload_stream_unlink(s
);
426 pa_proplist_free(s
->proplist
);
428 if (s
->memchunk
.memblock
)
429 pa_memblock_unref(s
->memchunk
.memblock
);
434 /* Called from main context */
435 static upload_stream
* upload_stream_new(
436 pa_native_connection
*c
,
437 const pa_sample_spec
*ss
,
438 const pa_channel_map
*map
,
448 pa_assert(length
> 0);
451 s
= pa_msgobject_new(upload_stream
);
452 s
->parent
.parent
.parent
.free
= upload_stream_free
;
454 s
->sample_spec
= *ss
;
455 s
->channel_map
= *map
;
456 s
->name
= pa_xstrdup(name
);
457 pa_memchunk_reset(&s
->memchunk
);
459 s
->proplist
= pa_proplist_copy(p
);
460 pa_proplist_update(s
->proplist
, PA_UPDATE_MERGE
, c
->client
->proplist
);
462 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
467 /* Called from main context */
468 static void record_stream_unlink(record_stream
*s
) {
474 if (s
->source_output
) {
475 pa_source_output_unlink(s
->source_output
);
476 pa_source_output_unref(s
->source_output
);
477 s
->source_output
= NULL
;
480 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->record_streams
, s
, NULL
) == s
);
481 s
->connection
= NULL
;
482 record_stream_unref(s
);
485 /* Called from main context */
486 static void record_stream_free(pa_object
*o
) {
487 record_stream
*s
= RECORD_STREAM(o
);
490 record_stream_unlink(s
);
492 pa_memblockq_free(s
->memblockq
);
496 /* Called from main context */
497 static int record_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
498 record_stream
*s
= RECORD_STREAM(o
);
499 record_stream_assert_ref(s
);
506 case RECORD_STREAM_MESSAGE_POST_DATA
:
508 /* We try to keep up to date with how many bytes are
509 * currently on the fly */
510 pa_atomic_sub(&s
->on_the_fly
, chunk
->length
);
512 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
513 /* pa_log_warn("Failed to push data into output queue."); */
517 if (!pa_pstream_is_pending(s
->connection
->pstream
))
518 native_connection_send_memblock(s
->connection
);
526 /* Called from main context */
527 static void fix_record_buffer_attr_pre(record_stream
*s
) {
530 pa_usec_t orig_fragsize_usec
, fragsize_usec
, source_usec
;
534 /* This function will be called from the main thread, before as
535 * well as after the source output has been activated using
536 * pa_source_output_put()! That means it may not touch any
537 * ->thread_info data! */
539 frame_size
= pa_frame_size(&s
->source_output
->sample_spec
);
540 s
->buffer_attr
= s
->buffer_attr_req
;
542 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
543 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
544 if (s
->buffer_attr
.maxlength
<= 0)
545 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
547 if (s
->buffer_attr
.fragsize
== (uint32_t) -1)
548 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC
*PA_USEC_PER_MSEC
, &s
->source_output
->sample_spec
);
549 if (s
->buffer_attr
.fragsize
<= 0)
550 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
552 orig_fragsize_usec
= fragsize_usec
= pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &s
->source_output
->sample_spec
);
554 if (s
->early_requests
) {
556 /* In early request mode we need to emulate the classic
557 * fragment-based playback model. We do this setting the source
558 * latency to the fragment size. */
560 source_usec
= fragsize_usec
;
562 } else if (s
->adjust_latency
) {
564 /* So, the user asked us to adjust the latency according to
565 * what the source can provide. Half the latency will be
566 * spent on the hw buffer, half of it in the async buffer
567 * queue we maintain for each client. */
569 source_usec
= fragsize_usec
/2;
573 /* Ok, the user didn't ask us to adjust the latency, hence we
576 source_usec
= (pa_usec_t
) -1;
579 if (source_usec
!= (pa_usec_t
) -1)
580 s
->configured_source_latency
= pa_source_output_set_requested_latency(s
->source_output
, source_usec
);
582 s
->configured_source_latency
= 0;
584 if (s
->early_requests
) {
586 /* Ok, we didn't necessarily get what we were asking for, so
587 * let's tell the user */
589 fragsize_usec
= s
->configured_source_latency
;
591 } else if (s
->adjust_latency
) {
593 /* Now subtract what we actually got */
595 if (fragsize_usec
>= s
->configured_source_latency
*2)
596 fragsize_usec
-= s
->configured_source_latency
;
598 fragsize_usec
= s
->configured_source_latency
;
601 if (pa_usec_to_bytes(orig_fragsize_usec
, &s
->source_output
->sample_spec
) !=
602 pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
))
604 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
);
606 if (s
->buffer_attr
.fragsize
<= 0)
607 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
610 /* Called from main context */
611 static void fix_record_buffer_attr_post(record_stream
*s
) {
616 /* This function will be called from the main thread, before as
617 * well as after the source output has been activated using
618 * pa_source_output_put()! That means it may not touch and
619 * ->thread_info data! */
621 base
= pa_frame_size(&s
->source_output
->sample_spec
);
623 s
->buffer_attr
.fragsize
= (s
->buffer_attr
.fragsize
/base
)*base
;
624 if (s
->buffer_attr
.fragsize
<= 0)
625 s
->buffer_attr
.fragsize
= base
;
627 if (s
->buffer_attr
.fragsize
> s
->buffer_attr
.maxlength
)
628 s
->buffer_attr
.fragsize
= s
->buffer_attr
.maxlength
;
631 /* Called from main context */
632 static record_stream
* record_stream_new(
633 pa_native_connection
*c
,
638 pa_buffer_attr
*attr
,
642 pa_source_output_flags_t flags
,
644 pa_bool_t adjust_latency
,
645 pa_bool_t early_requests
,
646 pa_bool_t relative_volume
,
647 pa_bool_t peak_detect
,
648 pa_sink_input
*direct_on_input
,
652 pa_source_output
*source_output
= NULL
;
653 pa_source_output_new_data data
;
654 char *memblockq_name
;
661 pa_source_output_new_data_init(&data
);
663 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
664 data
.driver
= __FILE__
;
665 data
.module
= c
->options
->module
;
666 data
.client
= c
->client
;
668 pa_source_output_new_data_set_source(&data
, source
, FALSE
);
669 if (pa_sample_spec_valid(ss
))
670 pa_source_output_new_data_set_sample_spec(&data
, ss
);
671 if (pa_channel_map_valid(map
))
672 pa_source_output_new_data_set_channel_map(&data
, map
);
674 pa_source_output_new_data_set_formats(&data
, formats
);
675 data
.direct_on_input
= direct_on_input
;
677 pa_source_output_new_data_set_volume(&data
, volume
);
678 data
.volume_is_absolute
= !relative_volume
;
679 data
.save_volume
= FALSE
;
682 pa_source_output_new_data_set_muted(&data
, muted
);
683 data
.save_muted
= FALSE
;
686 data
.resample_method
= PA_RESAMPLER_PEAKS
;
689 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
691 pa_source_output_new_data_done(&data
);
696 s
= pa_msgobject_new(record_stream
);
697 s
->parent
.parent
.free
= record_stream_free
;
698 s
->parent
.process_msg
= record_stream_process_msg
;
700 s
->source_output
= source_output
;
701 s
->buffer_attr_req
= *attr
;
702 s
->adjust_latency
= adjust_latency
;
703 s
->early_requests
= early_requests
;
704 pa_atomic_store(&s
->on_the_fly
, 0);
706 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
707 s
->source_output
->push
= source_output_push_cb
;
708 s
->source_output
->kill
= source_output_kill_cb
;
709 s
->source_output
->get_latency
= source_output_get_latency_cb
;
710 s
->source_output
->moving
= source_output_moving_cb
;
711 s
->source_output
->suspend
= source_output_suspend_cb
;
712 s
->source_output
->send_event
= source_output_send_event_cb
;
713 s
->source_output
->userdata
= s
;
715 fix_record_buffer_attr_pre(s
);
717 memblockq_name
= pa_sprintf_malloc("native protocol record stream memblockq [%u]", s
->source_output
->index
);
718 s
->memblockq
= pa_memblockq_new(
721 s
->buffer_attr
.maxlength
,
723 &source_output
->sample_spec
,
728 pa_xfree(memblockq_name
);
730 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
731 fix_record_buffer_attr_post(s
);
733 *ss
= s
->source_output
->sample_spec
;
734 *map
= s
->source_output
->channel_map
;
736 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
738 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
739 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
740 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
741 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
743 pa_source_output_put(s
->source_output
);
747 /* Called from main context */
748 static void record_stream_send_killed(record_stream
*r
) {
750 record_stream_assert_ref(r
);
752 t
= pa_tagstruct_new(NULL
, 0);
753 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
754 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
755 pa_tagstruct_putu32(t
, r
->index
);
756 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
759 /* Called from main context */
760 static void playback_stream_unlink(playback_stream
*s
) {
767 pa_sink_input_unlink(s
->sink_input
);
768 pa_sink_input_unref(s
->sink_input
);
769 s
->sink_input
= NULL
;
772 if (s
->drain_request
)
773 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
775 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
776 s
->connection
= NULL
;
777 playback_stream_unref(s
);
780 /* Called from main context */
781 static void playback_stream_free(pa_object
* o
) {
782 playback_stream
*s
= PLAYBACK_STREAM(o
);
785 playback_stream_unlink(s
);
787 pa_memblockq_free(s
->memblockq
);
791 /* Called from main context */
792 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
793 playback_stream
*s
= PLAYBACK_STREAM(o
);
794 playback_stream_assert_ref(s
);
801 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
806 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
809 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
813 t
= pa_tagstruct_new(NULL
, 0);
814 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
815 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
816 pa_tagstruct_putu32(t
, s
->index
);
817 pa_tagstruct_putu32(t
, (uint32_t) l
);
818 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
820 #ifdef PROTOCOL_NATIVE_DEBUG
821 pa_log("Requesting %lu bytes", (unsigned long) l
);
826 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
829 #ifdef PROTOCOL_NATIVE_DEBUG
830 pa_log("signalling underflow");
833 /* Report that we're empty */
834 t
= pa_tagstruct_new(NULL
, 0);
835 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
836 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
837 pa_tagstruct_putu32(t
, s
->index
);
838 if (s
->connection
->version
>= 23)
839 pa_tagstruct_puts64(t
, offset
);
840 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
844 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
847 /* Notify the user we're overflowed*/
848 t
= pa_tagstruct_new(NULL
, 0);
849 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
850 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
851 pa_tagstruct_putu32(t
, s
->index
);
852 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
856 case PLAYBACK_STREAM_MESSAGE_STARTED
:
858 if (s
->connection
->version
>= 13) {
861 /* Notify the user we started playback */
862 t
= pa_tagstruct_new(NULL
, 0);
863 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
864 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
865 pa_tagstruct_putu32(t
, s
->index
);
866 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
871 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
872 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
875 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
:
877 s
->buffer_attr
.tlength
= (uint32_t) offset
;
879 if (s
->connection
->version
>= 15) {
882 t
= pa_tagstruct_new(NULL
, 0);
883 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
884 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
885 pa_tagstruct_putu32(t
, s
->index
);
886 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
887 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
888 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
889 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
890 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
891 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
900 /* Called from main context */
901 static void fix_playback_buffer_attr(playback_stream
*s
) {
902 size_t frame_size
, max_prebuf
;
903 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
907 #ifdef PROTOCOL_NATIVE_DEBUG
908 pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes",
909 (long) s
->buffer_attr
.maxlength
,
910 (long) s
->buffer_attr
.tlength
,
911 (long) s
->buffer_attr
.minreq
,
912 (long) s
->buffer_attr
.prebuf
);
914 pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
915 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.maxlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
916 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
917 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
918 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.prebuf
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
));
921 /* This function will be called from the main thread, before as
922 * well as after the sink input has been activated using
923 * pa_sink_input_put()! That means it may not touch any
924 * ->thread_info data, such as the memblockq! */
926 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
927 s
->buffer_attr
= s
->buffer_attr_req
;
929 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
930 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
931 if (s
->buffer_attr
.maxlength
<= 0)
932 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
934 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
935 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
936 if (s
->buffer_attr
.tlength
<= 0)
937 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
939 if (s
->buffer_attr
.minreq
== (uint32_t) -1)
940 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
941 if (s
->buffer_attr
.minreq
<= 0)
942 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
944 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
945 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
947 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
948 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
950 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
951 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
952 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
954 if (s
->early_requests
) {
956 /* In early request mode we need to emulate the classic
957 * fragment-based playback model. We do this setting the sink
958 * latency to the fragment size. */
960 sink_usec
= minreq_usec
;
961 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
963 } else if (s
->adjust_latency
) {
965 /* So, the user asked us to adjust the latency of the stream
966 * buffer according to the what the sink can provide. The
967 * tlength passed in shall be the overall latency. Roughly
968 * half the latency will be spent on the hw buffer, the other
969 * half of it in the async buffer queue we maintain for each
970 * client. In between we'll have a safety space of size
971 * 2*minreq. Why the 2*minreq? When the hw buffer is completely
972 * empty and needs to be filled, then our buffer must have
973 * enough data to fulfill this request immediately and thus
974 * have at least the same tlength as the size of the hw
975 * buffer. It additionally needs space for 2 times minreq
976 * because if the buffer ran empty and a partial fillup
977 * happens immediately on the next iteration we need to be
978 * able to fulfill it and give the application also minreq
979 * time to fill it up again for the next request Makes 2 times
980 * minreq in plus.. */
982 if (tlength_usec
> minreq_usec
*2)
983 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
987 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
991 /* Ok, the user didn't ask us to adjust the latency, but we
992 * still need to make sure that the parameters from the user
995 if (tlength_usec
> minreq_usec
*2)
996 sink_usec
= (tlength_usec
- minreq_usec
*2);
1000 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
1003 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
1005 if (s
->early_requests
) {
1007 /* Ok, we didn't necessarily get what we were asking for, so
1008 * let's tell the user */
1010 minreq_usec
= s
->configured_sink_latency
;
1012 } else if (s
->adjust_latency
) {
1014 /* Ok, we didn't necessarily get what we were asking for, so
1015 * let's subtract from what we asked for for the remaining
1018 if (tlength_usec
>= s
->configured_sink_latency
)
1019 tlength_usec
-= s
->configured_sink_latency
;
1022 pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
1023 (double) sink_usec
/ PA_USEC_PER_MSEC
,
1024 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1026 /* FIXME: This is actually larger than necessary, since not all of
1027 * the sink latency is actually rewritable. */
1028 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
1029 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
1031 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
1032 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
1033 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
1035 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
1036 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
1037 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
1039 if (s
->buffer_attr
.minreq
<= 0) {
1040 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
1041 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
1044 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
1045 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
1047 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
1049 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
1050 s
->buffer_attr
.prebuf
> max_prebuf
)
1051 s
->buffer_attr
.prebuf
= max_prebuf
;
1053 #ifdef PROTOCOL_NATIVE_DEBUG
1054 pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
1055 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.maxlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1056 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1057 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1058 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.prebuf
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
));
1062 /* Called from main context */
1063 static playback_stream
* playback_stream_new(
1064 pa_native_connection
*c
,
1067 pa_channel_map
*map
,
1072 pa_bool_t muted_set
,
1073 pa_sink_input_flags_t flags
,
1075 pa_bool_t adjust_latency
,
1076 pa_bool_t early_requests
,
1077 pa_bool_t relative_volume
,
1082 /* Note: This function takes ownership of the 'formats' param, so we need
1083 * to take extra care to not leak it */
1085 playback_stream
*ssync
;
1086 playback_stream
*s
= NULL
;
1087 pa_sink_input
*sink_input
= NULL
;
1088 pa_memchunk silence
;
1090 int64_t start_index
;
1091 pa_sink_input_new_data data
;
1092 char *memblockq_name
;
1100 /* Find syncid group */
1101 PA_IDXSET_FOREACH(ssync
, c
->output_streams
, idx
) {
1103 if (!playback_stream_isinstance(ssync
))
1106 if (ssync
->syncid
== syncid
)
1110 /* Synced streams must connect to the same sink */
1114 sink
= ssync
->sink_input
->sink
;
1115 else if (sink
!= ssync
->sink_input
->sink
) {
1116 *ret
= PA_ERR_INVALID
;
1121 pa_sink_input_new_data_init(&data
);
1123 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1124 data
.driver
= __FILE__
;
1125 data
.module
= c
->options
->module
;
1126 data
.client
= c
->client
;
1128 pa_sink_input_new_data_set_sink(&data
, sink
, FALSE
);
1129 if (pa_sample_spec_valid(ss
))
1130 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1131 if (pa_channel_map_valid(map
))
1132 pa_sink_input_new_data_set_channel_map(&data
, map
);
1134 pa_sink_input_new_data_set_formats(&data
, formats
);
1135 /* Ownership transferred to new_data, so we don't free it ourselves */
1139 pa_sink_input_new_data_set_volume(&data
, volume
);
1140 data
.volume_is_absolute
= !relative_volume
;
1141 data
.save_volume
= FALSE
;
1144 pa_sink_input_new_data_set_muted(&data
, muted
);
1145 data
.save_muted
= FALSE
;
1147 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1150 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1152 pa_sink_input_new_data_done(&data
);
1157 s
= pa_msgobject_new(playback_stream
);
1158 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1159 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1162 s
->sink_input
= sink_input
;
1163 s
->is_underrun
= TRUE
;
1164 s
->drain_request
= FALSE
;
1165 pa_atomic_store(&s
->missing
, 0);
1166 s
->buffer_attr_req
= *a
;
1167 s
->adjust_latency
= adjust_latency
;
1168 s
->early_requests
= early_requests
;
1169 pa_atomic_store(&s
->seek_or_post_in_queue
, 0);
1170 s
->seek_windex
= -1;
1172 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1173 s
->sink_input
->pop
= sink_input_pop_cb
;
1174 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1175 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1176 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1177 s
->sink_input
->kill
= sink_input_kill_cb
;
1178 s
->sink_input
->moving
= sink_input_moving_cb
;
1179 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1180 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1181 s
->sink_input
->userdata
= s
;
1183 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1185 fix_playback_buffer_attr(s
);
1187 pa_sink_input_get_silence(sink_input
, &silence
);
1188 memblockq_name
= pa_sprintf_malloc("native protocol playback stream memblockq [%u]", s
->sink_input
->index
);
1189 s
->memblockq
= pa_memblockq_new(
1192 s
->buffer_attr
.maxlength
,
1193 s
->buffer_attr
.tlength
,
1194 &sink_input
->sample_spec
,
1195 s
->buffer_attr
.prebuf
,
1196 s
->buffer_attr
.minreq
,
1199 pa_xfree(memblockq_name
);
1200 pa_memblock_unref(silence
.memblock
);
1202 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1204 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1206 #ifdef PROTOCOL_NATIVE_DEBUG
1207 pa_log("missing original: %li", (long int) *missing
);
1210 *ss
= s
->sink_input
->sample_spec
;
1211 *map
= s
->sink_input
->channel_map
;
1213 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1215 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1216 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1217 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1218 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1219 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1221 pa_sink_input_put(s
->sink_input
);
1225 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
1230 /* Called from IO context */
1231 static void playback_stream_request_bytes(playback_stream
*s
) {
1233 int previous_missing
;
1235 playback_stream_assert_ref(s
);
1237 m
= pa_memblockq_pop_missing(s
->memblockq
);
1239 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1240 /* (unsigned long) m, */
1241 /* pa_memblockq_get_tlength(s->memblockq), */
1242 /* pa_memblockq_get_minreq(s->memblockq), */
1243 /* pa_memblockq_get_length(s->memblockq), */
1244 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1249 #ifdef PROTOCOL_NATIVE_DEBUG
1250 pa_log("request_bytes(%lu)", (unsigned long) m
);
1253 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1254 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1256 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1257 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1258 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1261 /* Called from main context */
1262 static void playback_stream_send_killed(playback_stream
*p
) {
1264 playback_stream_assert_ref(p
);
1266 t
= pa_tagstruct_new(NULL
, 0);
1267 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1268 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1269 pa_tagstruct_putu32(t
, p
->index
);
1270 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1273 /* Called from main context */
1274 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1275 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1276 pa_native_connection_assert_ref(c
);
1283 case CONNECTION_MESSAGE_REVOKE
:
1284 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1287 case CONNECTION_MESSAGE_RELEASE
:
1288 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1295 /* Called from main context */
1296 static void native_connection_unlink(pa_native_connection
*c
) {
1305 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1308 pa_native_options_unref(c
->options
);
1310 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1311 record_stream_unlink(r
);
1313 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1314 if (playback_stream_isinstance(o
))
1315 playback_stream_unlink(PLAYBACK_STREAM(o
));
1317 upload_stream_unlink(UPLOAD_STREAM(o
));
1319 if (c
->subscription
)
1320 pa_subscription_free(c
->subscription
);
1323 pa_pstream_unlink(c
->pstream
);
1325 if (c
->auth_timeout_event
) {
1326 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1327 c
->auth_timeout_event
= NULL
;
1330 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1332 pa_native_connection_unref(c
);
1335 /* Called from main context */
1336 static void native_connection_free(pa_object
*o
) {
1337 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1341 native_connection_unlink(c
);
1343 pa_idxset_free(c
->record_streams
, NULL
, NULL
);
1344 pa_idxset_free(c
->output_streams
, NULL
, NULL
);
1346 pa_pdispatch_unref(c
->pdispatch
);
1347 pa_pstream_unref(c
->pstream
);
1348 pa_client_free(c
->client
);
1353 /* Called from main context */
1354 static void native_connection_send_memblock(pa_native_connection
*c
) {
1358 start
= PA_IDXSET_INVALID
;
1362 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1365 if (start
== PA_IDXSET_INVALID
)
1366 start
= c
->rrobin_index
;
1367 else if (start
== c
->rrobin_index
)
1370 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1371 pa_memchunk schunk
= chunk
;
1373 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1374 schunk
.length
= r
->buffer_attr
.fragsize
;
1376 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1378 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1379 pa_memblock_unref(schunk
.memblock
);
1386 /*** sink input callbacks ***/
1388 /* Called from thread context */
1389 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1390 playback_stream_assert_ref(s
);
1392 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1394 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1396 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1398 if (pa_memblockq_is_readable(s
->memblockq
)) {
1400 /* We just ended an underrun, let's ask the sink
1401 * for a complete rewind rewrite */
1403 pa_log_debug("Requesting rewind due to end of underrun.");
1404 pa_sink_input_request_rewind(s
->sink_input
,
1405 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1406 s
->sink_input
->thread_info
.underrun_for
),
1407 FALSE
, TRUE
, FALSE
);
1413 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1415 if (indexw
< indexr
) {
1416 /* OK, the sink already asked for this data, so
1417 * let's have it ask us again */
1419 pa_log_debug("Requesting rewind due to rewrite.");
1420 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1424 playback_stream_request_bytes(s
);
1427 static void flush_write_no_account(pa_memblockq
*q
) {
1428 pa_memblockq_flush_write(q
, FALSE
);
1431 /* Called from thread context */
1432 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1433 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1436 pa_sink_input_assert_ref(i
);
1437 s
= PLAYBACK_STREAM(i
->userdata
);
1438 playback_stream_assert_ref(s
);
1442 case SINK_INPUT_MESSAGE_SEEK
:
1443 case SINK_INPUT_MESSAGE_POST_DATA
: {
1444 int64_t windex
= pa_memblockq_get_write_index(s
->memblockq
);
1446 if (code
== SINK_INPUT_MESSAGE_SEEK
) {
1447 /* The client side is incapable of accounting correctly
1448 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1449 * able to deal with that. */
1451 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1452 windex
= PA_MIN(windex
, pa_memblockq_get_write_index(s
->memblockq
));
1455 if (chunk
&& pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1456 if (pa_log_ratelimit(PA_LOG_WARN
))
1457 pa_log_warn("Failed to push data into queue");
1458 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1459 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1462 /* If more data is in queue, we rewind later instead. */
1463 if (s
->seek_windex
!= -1)
1464 windex
= PA_MIN(windex
, s
->seek_windex
);
1465 if (pa_atomic_dec(&s
->seek_or_post_in_queue
) > 1)
1466 s
->seek_windex
= windex
;
1468 s
->seek_windex
= -1;
1469 handle_seek(s
, windex
);
1474 case SINK_INPUT_MESSAGE_DRAIN
:
1475 case SINK_INPUT_MESSAGE_FLUSH
:
1476 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1477 case SINK_INPUT_MESSAGE_TRIGGER
: {
1480 pa_sink_input
*isync
;
1481 void (*func
)(pa_memblockq
*bq
);
1484 case SINK_INPUT_MESSAGE_FLUSH
:
1485 func
= flush_write_no_account
;
1488 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1489 func
= pa_memblockq_prebuf_force
;
1492 case SINK_INPUT_MESSAGE_DRAIN
:
1493 case SINK_INPUT_MESSAGE_TRIGGER
:
1494 func
= pa_memblockq_prebuf_disable
;
1498 pa_assert_not_reached();
1501 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1503 handle_seek(s
, windex
);
1505 /* Do the same for all other members in the sync group */
1506 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1507 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1508 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1509 func(ssync
->memblockq
);
1510 handle_seek(ssync
, windex
);
1513 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1514 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1515 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1516 func(ssync
->memblockq
);
1517 handle_seek(ssync
, windex
);
1520 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1521 if (!pa_memblockq_is_readable(s
->memblockq
))
1522 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1524 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1525 s
->drain_request
= TRUE
;
1532 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1533 /* Atomically get a snapshot of all timing parameters... */
1534 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1535 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1536 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1537 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1538 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1539 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1543 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1546 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1548 pa_memblockq_prebuf_force(s
->memblockq
);
1550 handle_seek(s
, windex
);
1552 /* Fall through to the default handler */
1556 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1557 pa_usec_t
*r
= userdata
;
1559 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1561 /* Fall through, the default handler will add in the extra
1562 * latency added by the resampler */
1566 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1567 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1568 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1573 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1576 /* Called from thread context */
1577 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1580 pa_sink_input_assert_ref(i
);
1581 s
= PLAYBACK_STREAM(i
->userdata
);
1582 playback_stream_assert_ref(s
);
1585 #ifdef PROTOCOL_NATIVE_DEBUG
1586 pa_log("%s, pop(): %lu", pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
), (unsigned long) pa_memblockq_get_length(s
->memblockq
));
1589 if (pa_memblockq_is_readable(s
->memblockq
))
1590 s
->is_underrun
= FALSE
;
1592 if (!s
->is_underrun
)
1593 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
));
1595 if (s
->drain_request
&& pa_sink_input_safe_to_remove(i
)) {
1596 s
->drain_request
= FALSE
;
1597 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
);
1598 } else if (!s
->is_underrun
)
1599 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_UNDERFLOW
, NULL
, pa_memblockq_get_read_index(s
->memblockq
), NULL
, NULL
);
1601 s
->is_underrun
= TRUE
;
1603 playback_stream_request_bytes(s
);
1606 /* This call will not fail with prebuf=0, hence we check for
1607 underrun explicitly above */
1608 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1611 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1613 if (i
->thread_info
.underrun_for
> 0)
1614 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1616 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1617 playback_stream_request_bytes(s
);
1622 /* Called from thread context */
1623 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1626 pa_sink_input_assert_ref(i
);
1627 s
= PLAYBACK_STREAM(i
->userdata
);
1628 playback_stream_assert_ref(s
);
1630 /* If we are in an underrun, then we don't rewind */
1631 if (i
->thread_info
.underrun_for
> 0)
1634 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1637 /* Called from thread context */
1638 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1641 pa_sink_input_assert_ref(i
);
1642 s
= PLAYBACK_STREAM(i
->userdata
);
1643 playback_stream_assert_ref(s
);
1645 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1648 /* Called from thread context */
1649 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1651 size_t new_tlength
, old_tlength
;
1653 pa_sink_input_assert_ref(i
);
1654 s
= PLAYBACK_STREAM(i
->userdata
);
1655 playback_stream_assert_ref(s
);
1657 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1658 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1660 if (old_tlength
< new_tlength
) {
1661 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1662 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1663 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1665 if (new_tlength
== old_tlength
)
1666 pa_log_debug("Failed to increase tlength");
1668 pa_log_debug("Notifying client about increased tlength");
1669 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
);
1674 /* Called from main context */
1675 static void sink_input_kill_cb(pa_sink_input
*i
) {
1678 pa_sink_input_assert_ref(i
);
1679 s
= PLAYBACK_STREAM(i
->userdata
);
1680 playback_stream_assert_ref(s
);
1682 playback_stream_send_killed(s
);
1683 playback_stream_unlink(s
);
1686 /* Called from main context */
1687 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1691 pa_sink_input_assert_ref(i
);
1692 s
= PLAYBACK_STREAM(i
->userdata
);
1693 playback_stream_assert_ref(s
);
1695 if (s
->connection
->version
< 15)
1698 t
= pa_tagstruct_new(NULL
, 0);
1699 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1700 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1701 pa_tagstruct_putu32(t
, s
->index
);
1702 pa_tagstruct_puts(t
, event
);
1703 pa_tagstruct_put_proplist(t
, pl
);
1704 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1707 /* Called from main context */
1708 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1712 pa_sink_input_assert_ref(i
);
1713 s
= PLAYBACK_STREAM(i
->userdata
);
1714 playback_stream_assert_ref(s
);
1716 if (s
->connection
->version
< 12)
1719 t
= pa_tagstruct_new(NULL
, 0);
1720 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1721 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1722 pa_tagstruct_putu32(t
, s
->index
);
1723 pa_tagstruct_put_boolean(t
, suspend
);
1724 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1727 /* Called from main context */
1728 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1732 pa_sink_input_assert_ref(i
);
1733 s
= PLAYBACK_STREAM(i
->userdata
);
1734 playback_stream_assert_ref(s
);
1739 fix_playback_buffer_attr(s
);
1740 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1741 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1743 if (s
->connection
->version
< 12)
1746 t
= pa_tagstruct_new(NULL
, 0);
1747 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1748 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1749 pa_tagstruct_putu32(t
, s
->index
);
1750 pa_tagstruct_putu32(t
, dest
->index
);
1751 pa_tagstruct_puts(t
, dest
->name
);
1752 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1754 if (s
->connection
->version
>= 13) {
1755 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1756 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1757 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1758 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1759 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1762 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1765 /*** source_output callbacks ***/
1767 /* Called from thread context */
1768 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1769 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1772 pa_source_output_assert_ref(o
);
1773 s
= RECORD_STREAM(o
->userdata
);
1774 record_stream_assert_ref(s
);
1777 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1778 /* Atomically get a snapshot of all timing parameters... */
1779 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1780 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1781 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1785 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1788 /* Called from thread context */
1789 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1792 pa_source_output_assert_ref(o
);
1793 s
= RECORD_STREAM(o
->userdata
);
1794 record_stream_assert_ref(s
);
1797 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1798 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1801 static void source_output_kill_cb(pa_source_output
*o
) {
1804 pa_source_output_assert_ref(o
);
1805 s
= RECORD_STREAM(o
->userdata
);
1806 record_stream_assert_ref(s
);
1808 record_stream_send_killed(s
);
1809 record_stream_unlink(s
);
1812 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1815 pa_source_output_assert_ref(o
);
1816 s
= RECORD_STREAM(o
->userdata
);
1817 record_stream_assert_ref(s
);
1819 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1821 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1824 /* Called from main context */
1825 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1829 pa_source_output_assert_ref(o
);
1830 s
= RECORD_STREAM(o
->userdata
);
1831 record_stream_assert_ref(s
);
1833 if (s
->connection
->version
< 15)
1836 t
= pa_tagstruct_new(NULL
, 0);
1837 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1838 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1839 pa_tagstruct_putu32(t
, s
->index
);
1840 pa_tagstruct_puts(t
, event
);
1841 pa_tagstruct_put_proplist(t
, pl
);
1842 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1845 /* Called from main context */
1846 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1850 pa_source_output_assert_ref(o
);
1851 s
= RECORD_STREAM(o
->userdata
);
1852 record_stream_assert_ref(s
);
1854 if (s
->connection
->version
< 12)
1857 t
= pa_tagstruct_new(NULL
, 0);
1858 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1859 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1860 pa_tagstruct_putu32(t
, s
->index
);
1861 pa_tagstruct_put_boolean(t
, suspend
);
1862 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1865 /* Called from main context */
1866 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1870 pa_source_output_assert_ref(o
);
1871 s
= RECORD_STREAM(o
->userdata
);
1872 record_stream_assert_ref(s
);
1877 fix_record_buffer_attr_pre(s
);
1878 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1879 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1880 fix_record_buffer_attr_post(s
);
1882 if (s
->connection
->version
< 12)
1885 t
= pa_tagstruct_new(NULL
, 0);
1886 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1887 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1888 pa_tagstruct_putu32(t
, s
->index
);
1889 pa_tagstruct_putu32(t
, dest
->index
);
1890 pa_tagstruct_puts(t
, dest
->name
);
1891 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1893 if (s
->connection
->version
>= 13) {
1894 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1895 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1896 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1899 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1902 /*** pdispatch callbacks ***/
1904 static void protocol_error(pa_native_connection
*c
) {
1905 pa_log("protocol error, kicking client");
1906 native_connection_unlink(c
);
1909 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1910 if (!(expression)) { \
1911 pa_pstream_send_error((pstream), (tag), (error)); \
1916 #define CHECK_VALIDITY_GOTO(pstream, expression, tag, error, label) do { \
1917 if (!(expression)) { \
1918 pa_pstream_send_error((pstream), (tag), (error)); \
1923 static pa_tagstruct
*reply_new(uint32_t tag
) {
1924 pa_tagstruct
*reply
;
1926 reply
= pa_tagstruct_new(NULL
, 0);
1927 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1928 pa_tagstruct_putu32(reply
, tag
);
1932 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1933 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1935 uint32_t sink_index
, syncid
, missing
= 0;
1936 pa_buffer_attr attr
;
1937 const char *name
= NULL
, *sink_name
;
1940 pa_tagstruct
*reply
;
1941 pa_sink
*sink
= NULL
;
1949 fix_channels
= FALSE
,
1951 variable_rate
= FALSE
,
1953 adjust_latency
= FALSE
,
1954 early_requests
= FALSE
,
1955 dont_inhibit_auto_suspend
= FALSE
,
1958 fail_on_suspend
= FALSE
,
1959 relative_volume
= FALSE
,
1960 passthrough
= FALSE
;
1962 pa_sink_input_flags_t flags
= 0;
1963 pa_proplist
*p
= NULL
;
1964 int ret
= PA_ERR_INVALID
;
1965 uint8_t n_formats
= 0;
1966 pa_format_info
*format
;
1967 pa_idxset
*formats
= NULL
;
1970 pa_native_connection_assert_ref(c
);
1972 memset(&attr
, 0, sizeof(attr
));
1974 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
1977 PA_TAG_SAMPLE_SPEC
, &ss
,
1978 PA_TAG_CHANNEL_MAP
, &map
,
1979 PA_TAG_U32
, &sink_index
,
1980 PA_TAG_STRING
, &sink_name
,
1981 PA_TAG_U32
, &attr
.maxlength
,
1982 PA_TAG_BOOLEAN
, &corked
,
1983 PA_TAG_U32
, &attr
.tlength
,
1984 PA_TAG_U32
, &attr
.prebuf
,
1985 PA_TAG_U32
, &attr
.minreq
,
1986 PA_TAG_U32
, &syncid
,
1987 PA_TAG_CVOLUME
, &volume
,
1988 PA_TAG_INVALID
) < 0) {
1994 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
1995 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
, finish
);
1996 CHECK_VALIDITY_GOTO(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
, finish
);
1997 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
1998 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
2000 p
= pa_proplist_new();
2003 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2005 if (c
->version
>= 12) {
2006 /* Since 0.9.8 the user can ask for a couple of additional flags */
2008 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2009 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2010 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2011 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2012 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2013 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2014 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2021 if (c
->version
>= 13) {
2023 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
2024 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2025 pa_tagstruct_get_proplist(t
, p
) < 0) {
2032 if (c
->version
>= 14) {
2034 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
2035 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2042 if (c
->version
>= 15) {
2044 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
2045 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2046 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2053 if (c
->version
>= 17) {
2055 if (pa_tagstruct_get_boolean(t
, &relative_volume
) < 0) {
2062 if (c
->version
>= 18) {
2064 if (pa_tagstruct_get_boolean(t
, &passthrough
) < 0 ) {
2070 if (c
->version
>= 21) {
2072 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2078 formats
= pa_idxset_new(NULL
, NULL
);
2080 for (i
= 0; i
< n_formats
; i
++) {
2081 format
= pa_format_info_new();
2082 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2086 pa_idxset_put(formats
, format
, NULL
);
2090 if (n_formats
== 0) {
2091 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2092 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2093 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2095 PA_IDXSET_FOREACH(format
, formats
, i
) {
2096 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2100 if (!pa_tagstruct_eof(t
)) {
2105 if (sink_index
!= PA_INVALID_INDEX
) {
2107 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
2108 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2112 } else if (sink_name
) {
2114 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
2115 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2121 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
2122 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
2123 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
2124 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
2125 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
2126 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
2127 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
2128 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
2129 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2130 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0) |
2131 (passthrough
? PA_SINK_INPUT_PASSTHROUGH
: 0);
2133 /* Only since protocol version 15 there's a separate muted_set
2134 * flag. For older versions we synthesize it here */
2135 muted_set
= muted_set
|| muted
;
2137 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
);
2138 /* We no longer own the formats idxset */
2141 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2143 reply
= reply_new(tag
);
2144 pa_tagstruct_putu32(reply
, s
->index
);
2145 pa_assert(s
->sink_input
);
2146 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
2147 pa_tagstruct_putu32(reply
, missing
);
2149 #ifdef PROTOCOL_NATIVE_DEBUG
2150 pa_log("initial request is %u", missing
);
2153 if (c
->version
>= 9) {
2154 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2156 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2157 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
2158 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
2159 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
2162 if (c
->version
>= 12) {
2163 /* Since 0.9.8 we support sending the chosen sample
2164 * spec/channel map/device/suspend status back to the
2167 pa_tagstruct_put_sample_spec(reply
, &ss
);
2168 pa_tagstruct_put_channel_map(reply
, &map
);
2170 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2171 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2173 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2176 if (c
->version
>= 13)
2177 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2179 if (c
->version
>= 21) {
2180 /* Send back the format we negotiated */
2181 if (s
->sink_input
->format
)
2182 pa_tagstruct_put_format_info(reply
, s
->sink_input
->format
);
2184 pa_format_info
*f
= pa_format_info_new();
2185 pa_tagstruct_put_format_info(reply
, f
);
2186 pa_format_info_free(f
);
2190 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2194 pa_proplist_free(p
);
2196 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
2199 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2200 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2203 pa_native_connection_assert_ref(c
);
2206 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2207 !pa_tagstruct_eof(t
)) {
2212 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2216 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2218 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2219 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2223 playback_stream_unlink(s
);
2227 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2229 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2230 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2234 record_stream_unlink(s
);
2238 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2241 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2242 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2246 upload_stream_unlink(s
);
2251 pa_assert_not_reached();
2254 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2257 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2258 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2260 pa_buffer_attr attr
;
2261 uint32_t source_index
;
2262 const char *name
= NULL
, *source_name
;
2265 pa_tagstruct
*reply
;
2266 pa_source
*source
= NULL
;
2274 fix_channels
= FALSE
,
2276 variable_rate
= FALSE
,
2278 adjust_latency
= FALSE
,
2279 peak_detect
= FALSE
,
2280 early_requests
= FALSE
,
2281 dont_inhibit_auto_suspend
= FALSE
,
2284 fail_on_suspend
= FALSE
,
2285 relative_volume
= FALSE
,
2286 passthrough
= FALSE
;
2288 pa_source_output_flags_t flags
= 0;
2289 pa_proplist
*p
= NULL
;
2290 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2291 pa_sink_input
*direct_on_input
= NULL
;
2292 int ret
= PA_ERR_INVALID
;
2293 uint8_t n_formats
= 0;
2294 pa_format_info
*format
;
2295 pa_idxset
*formats
= NULL
;
2298 pa_native_connection_assert_ref(c
);
2301 memset(&attr
, 0, sizeof(attr
));
2303 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2304 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2305 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2306 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2307 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2308 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2309 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2310 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2316 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
2317 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
, finish
);
2318 CHECK_VALIDITY_GOTO(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
, finish
);
2319 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
2321 p
= pa_proplist_new();
2324 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2326 if (c
->version
>= 12) {
2327 /* Since 0.9.8 the user can ask for a couple of additional flags */
2329 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2330 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2331 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2332 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2333 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2334 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2335 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2342 if (c
->version
>= 13) {
2344 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2345 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2346 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2347 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2354 if (c
->version
>= 14) {
2356 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2362 if (c
->version
>= 15) {
2364 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2365 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2372 if (c
->version
>= 22) {
2373 /* For newer client versions (with per-source-output volumes), we try
2374 * to make the behaviour for playback and record streams the same. */
2377 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2383 formats
= pa_idxset_new(NULL
, NULL
);
2385 for (i
= 0; i
< n_formats
; i
++) {
2386 format
= pa_format_info_new();
2387 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2391 pa_idxset_put(formats
, format
, NULL
);
2394 if (pa_tagstruct_get_cvolume(t
, &volume
) < 0 ||
2395 pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
2396 pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
2397 pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
2398 pa_tagstruct_get_boolean(t
, &relative_volume
) < 0 ||
2399 pa_tagstruct_get_boolean(t
, &passthrough
) < 0) {
2405 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
2408 if (n_formats
== 0) {
2409 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2410 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2411 CHECK_VALIDITY_GOTO(c
->pstream
, c
->version
< 22 || (volume
.channels
== ss
.channels
), tag
, PA_ERR_INVALID
, finish
);
2412 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2414 PA_IDXSET_FOREACH(format
, formats
, i
) {
2415 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2420 if (!pa_tagstruct_eof(t
)) {
2425 if (source_index
!= PA_INVALID_INDEX
) {
2427 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2428 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2432 } else if (source_name
) {
2434 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2435 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2440 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2442 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2443 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2449 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2450 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2451 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2452 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2453 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2454 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2455 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2456 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2457 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2458 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0) |
2459 (passthrough
? PA_SOURCE_OUTPUT_PASSTHROUGH
: 0);
2461 s
= record_stream_new(c
, source
, &ss
, &map
, formats
, &attr
, volume_set
? &volume
: NULL
, muted
, muted_set
, flags
, p
, adjust_latency
, early_requests
, relative_volume
, peak_detect
, direct_on_input
, &ret
);
2463 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2465 reply
= reply_new(tag
);
2466 pa_tagstruct_putu32(reply
, s
->index
);
2467 pa_assert(s
->source_output
);
2468 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2470 if (c
->version
>= 9) {
2471 /* Since 0.9 we support sending the buffer metrics back to the client */
2473 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2474 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2477 if (c
->version
>= 12) {
2478 /* Since 0.9.8 we support sending the chosen sample
2479 * spec/channel map/device/suspend status back to the
2482 pa_tagstruct_put_sample_spec(reply
, &ss
);
2483 pa_tagstruct_put_channel_map(reply
, &map
);
2485 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2486 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2488 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2491 if (c
->version
>= 13)
2492 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2494 if (c
->version
>= 22) {
2495 /* Send back the format we negotiated */
2496 if (s
->source_output
->format
)
2497 pa_tagstruct_put_format_info(reply
, s
->source_output
->format
);
2499 pa_format_info
*f
= pa_format_info_new();
2500 pa_tagstruct_put_format_info(reply
, f
);
2501 pa_format_info_free(f
);
2505 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2509 pa_proplist_free(p
);
2511 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
2514 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2515 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2518 pa_native_connection_assert_ref(c
);
2521 if (!pa_tagstruct_eof(t
)) {
2526 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2527 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2528 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2530 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
)));
2532 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2535 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2536 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2538 pa_tagstruct
*reply
;
2539 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2541 pa_native_connection_assert_ref(c
);
2544 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2545 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2546 !pa_tagstruct_eof(t
)) {
2551 /* Minimum supported version */
2552 if (c
->version
< 8) {
2553 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2557 /* Starting with protocol version 13 the MSB of the version tag
2558 reflects if shm is available for this pa_native_connection or
2560 if (c
->version
>= 13) {
2561 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2562 c
->version
&= 0x7FFFFFFFU
;
2565 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2567 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2569 if (!c
->authorized
) {
2570 pa_bool_t success
= FALSE
;
2573 const pa_creds
*creds
;
2575 if ((creds
= pa_pdispatch_creds(pd
))) {
2576 if (creds
->uid
== getuid())
2578 else if (c
->options
->auth_group
) {
2582 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2583 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2584 else if (gid
== creds
->gid
)
2588 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2589 pa_log_warn("Failed to check group membership.");
2595 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2596 (unsigned long) creds
->uid
,
2597 (unsigned long) creds
->gid
,
2602 if (!success
&& c
->options
->auth_cookie
) {
2605 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2606 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2611 pa_log_warn("Denied access to client with invalid authorization data.");
2612 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2616 c
->authorized
= TRUE
;
2617 if (c
->auth_timeout_event
) {
2618 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2619 c
->auth_timeout_event
= NULL
;
2623 /* Enable shared memory support if possible */
2625 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2628 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2631 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2636 /* Only enable SHM if both sides are owned by the same
2637 * user. This is a security measure because otherwise data
2638 * private to the user might leak. */
2640 const pa_creds
*creds
;
2641 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2646 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2647 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2649 reply
= reply_new(tag
);
2650 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2654 /* SHM support is only enabled after both sides made sure they are the same user. */
2658 ucred
.uid
= getuid();
2659 ucred
.gid
= getgid();
2661 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2664 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2668 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2669 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2670 const char *name
= NULL
;
2672 pa_tagstruct
*reply
;
2674 pa_native_connection_assert_ref(c
);
2677 p
= pa_proplist_new();
2679 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2680 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2681 !pa_tagstruct_eof(t
)) {
2684 pa_proplist_free(p
);
2689 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2690 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2691 pa_proplist_free(p
);
2695 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2696 pa_proplist_free(p
);
2698 reply
= reply_new(tag
);
2700 if (c
->version
>= 13)
2701 pa_tagstruct_putu32(reply
, c
->client
->index
);
2703 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2706 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2707 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2709 uint32_t idx
= PA_IDXSET_INVALID
;
2711 pa_native_connection_assert_ref(c
);
2714 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2715 !pa_tagstruct_eof(t
)) {
2720 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2721 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
);
2723 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2725 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2729 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2730 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2731 idx
= source
->index
;
2734 if (idx
== PA_IDXSET_INVALID
)
2735 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2737 pa_tagstruct
*reply
;
2738 reply
= reply_new(tag
);
2739 pa_tagstruct_putu32(reply
, idx
);
2740 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2744 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2745 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2749 pa_native_connection_assert_ref(c
);
2752 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2753 !pa_tagstruct_eof(t
)) {
2758 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2759 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2760 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2761 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2763 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
);
2766 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2767 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2768 pa_tagstruct
*reply
;
2769 const pa_mempool_stat
*stat
;
2771 pa_native_connection_assert_ref(c
);
2774 if (!pa_tagstruct_eof(t
)) {
2779 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2781 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2783 reply
= reply_new(tag
);
2784 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2785 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2786 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2787 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2788 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2789 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2792 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2793 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2794 pa_tagstruct
*reply
;
2796 struct timeval tv
, now
;
2799 pa_native_connection_assert_ref(c
);
2802 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2803 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2804 !pa_tagstruct_eof(t
)) {
2809 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2810 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2811 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2812 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2814 /* Get an atomic snapshot of all timing parameters */
2815 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);
2817 reply
= reply_new(tag
);
2818 pa_tagstruct_put_usec(reply
,
2819 s
->current_sink_latency
+
2820 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2821 pa_tagstruct_put_usec(reply
, 0);
2822 pa_tagstruct_put_boolean(reply
,
2823 s
->playing_for
> 0 &&
2824 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2825 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2826 pa_tagstruct_put_timeval(reply
, &tv
);
2827 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2828 pa_tagstruct_puts64(reply
, s
->write_index
);
2829 pa_tagstruct_puts64(reply
, s
->read_index
);
2831 if (c
->version
>= 13) {
2832 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2833 pa_tagstruct_putu64(reply
, s
->playing_for
);
2836 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2839 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2840 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2841 pa_tagstruct
*reply
;
2843 struct timeval tv
, now
;
2846 pa_native_connection_assert_ref(c
);
2849 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2850 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2851 !pa_tagstruct_eof(t
)) {
2856 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2857 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2858 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2860 /* Get an atomic snapshot of all timing parameters */
2861 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);
2863 reply
= reply_new(tag
);
2864 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2865 pa_tagstruct_put_usec(reply
,
2866 s
->current_source_latency
+
2867 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->source
->sample_spec
));
2868 pa_tagstruct_put_boolean(reply
,
2869 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2870 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2871 pa_tagstruct_put_timeval(reply
, &tv
);
2872 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2873 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2874 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2875 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2878 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2879 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2882 const char *name
= NULL
;
2885 pa_tagstruct
*reply
;
2888 pa_native_connection_assert_ref(c
);
2891 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2892 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2893 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2894 pa_tagstruct_getu32(t
, &length
) < 0) {
2899 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2900 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2901 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2902 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2903 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2904 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2906 p
= pa_proplist_new();
2908 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2909 !pa_tagstruct_eof(t
)) {
2912 pa_proplist_free(p
);
2916 if (c
->version
< 13)
2917 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2919 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2920 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2922 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2923 pa_proplist_free(p
);
2924 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2927 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2928 pa_proplist_free(p
);
2930 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2932 reply
= reply_new(tag
);
2933 pa_tagstruct_putu32(reply
, s
->index
);
2934 pa_tagstruct_putu32(reply
, length
);
2935 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2938 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2939 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2944 pa_native_connection_assert_ref(c
);
2947 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2948 !pa_tagstruct_eof(t
)) {
2953 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2955 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2956 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2957 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2959 if (!s
->memchunk
.memblock
)
2960 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2961 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2962 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2964 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2966 upload_stream_unlink(s
);
2969 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2970 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2971 uint32_t sink_index
;
2974 const char *name
, *sink_name
;
2977 pa_tagstruct
*reply
;
2979 pa_native_connection_assert_ref(c
);
2982 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2984 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
2985 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
2986 pa_tagstruct_getu32(t
, &volume
) < 0 ||
2987 pa_tagstruct_gets(t
, &name
) < 0) {
2992 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
2993 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
2994 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
2995 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
2997 if (sink_index
!= PA_INVALID_INDEX
)
2998 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
3000 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
3002 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3004 p
= pa_proplist_new();
3006 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
3007 !pa_tagstruct_eof(t
)) {
3009 pa_proplist_free(p
);
3013 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
3015 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
3016 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3017 pa_proplist_free(p
);
3021 pa_proplist_free(p
);
3023 reply
= reply_new(tag
);
3025 if (c
->version
>= 13)
3026 pa_tagstruct_putu32(reply
, idx
);
3028 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3031 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3032 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3035 pa_native_connection_assert_ref(c
);
3038 if (pa_tagstruct_gets(t
, &name
) < 0 ||
3039 !pa_tagstruct_eof(t
)) {
3044 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3045 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3047 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
3048 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3052 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3055 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
3058 pa_assert(original
);
3062 if (c
->version
< 12) {
3063 /* Before protocol version 12 we didn't support S32 samples,
3064 * so we need to lie about this to the client */
3066 if (fixed
->format
== PA_SAMPLE_S32LE
)
3067 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3068 if (fixed
->format
== PA_SAMPLE_S32BE
)
3069 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3072 if (c
->version
< 15) {
3073 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
3074 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3075 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
3076 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3080 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
3081 pa_sample_spec fixed_ss
;
3084 pa_sink_assert_ref(sink
);
3086 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
3090 PA_TAG_U32
, sink
->index
,
3091 PA_TAG_STRING
, sink
->name
,
3092 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3093 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3094 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
3095 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
3096 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
3097 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
3098 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
3099 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
3100 PA_TAG_USEC
, pa_sink_get_latency(sink
),
3101 PA_TAG_STRING
, sink
->driver
,
3102 PA_TAG_U32
, sink
->flags
& PA_SINK_CLIENT_FLAGS_MASK
,
3105 if (c
->version
>= 13) {
3106 pa_tagstruct_put_proplist(t
, sink
->proplist
);
3107 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
3110 if (c
->version
>= 15) {
3111 pa_tagstruct_put_volume(t
, sink
->base_volume
);
3112 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
3113 pa_log_error("Internal sink state is invalid.");
3114 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
3115 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
3116 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
3119 if (c
->version
>= 16) {
3123 pa_tagstruct_putu32(t
, pa_hashmap_size(sink
->ports
));
3125 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
3126 pa_tagstruct_puts(t
, p
->name
);
3127 pa_tagstruct_puts(t
, p
->description
);
3128 pa_tagstruct_putu32(t
, p
->priority
);
3129 if (c
->version
>= 24)
3130 pa_tagstruct_putu32(t
, p
->available
);
3133 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
3136 if (c
->version
>= 21) {
3139 pa_idxset
*formats
= pa_sink_get_formats(sink
);
3141 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3142 PA_IDXSET_FOREACH(f
, formats
, i
) {
3143 pa_tagstruct_put_format_info(t
, f
);
3146 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
3150 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
3151 pa_sample_spec fixed_ss
;
3154 pa_source_assert_ref(source
);
3156 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
3160 PA_TAG_U32
, source
->index
,
3161 PA_TAG_STRING
, source
->name
,
3162 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3163 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3164 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
3165 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
3166 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
3167 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
3168 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
3169 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
3170 PA_TAG_USEC
, pa_source_get_latency(source
),
3171 PA_TAG_STRING
, source
->driver
,
3172 PA_TAG_U32
, source
->flags
& PA_SOURCE_CLIENT_FLAGS_MASK
,
3175 if (c
->version
>= 13) {
3176 pa_tagstruct_put_proplist(t
, source
->proplist
);
3177 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
3180 if (c
->version
>= 15) {
3181 pa_tagstruct_put_volume(t
, source
->base_volume
);
3182 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
3183 pa_log_error("Internal source state is invalid.");
3184 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
3185 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
3186 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
3189 if (c
->version
>= 16) {
3193 pa_tagstruct_putu32(t
, pa_hashmap_size(source
->ports
));
3195 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
3196 pa_tagstruct_puts(t
, p
->name
);
3197 pa_tagstruct_puts(t
, p
->description
);
3198 pa_tagstruct_putu32(t
, p
->priority
);
3199 if (c
->version
>= 24)
3200 pa_tagstruct_putu32(t
, p
->available
);
3203 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
3206 if (c
->version
>= 22) {
3209 pa_idxset
*formats
= pa_source_get_formats(source
);
3211 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3212 PA_IDXSET_FOREACH(f
, formats
, i
) {
3213 pa_tagstruct_put_format_info(t
, f
);
3216 pa_idxset_free(formats
, (pa_free2_cb_t
) pa_format_info_free2
, NULL
);
3220 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
3224 pa_tagstruct_putu32(t
, client
->index
);
3225 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
3226 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
3227 pa_tagstruct_puts(t
, client
->driver
);
3229 if (c
->version
>= 13)
3230 pa_tagstruct_put_proplist(t
, client
->proplist
);
3233 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
3236 pa_device_port
*port
;
3241 pa_tagstruct_putu32(t
, card
->index
);
3242 pa_tagstruct_puts(t
, card
->name
);
3243 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
3244 pa_tagstruct_puts(t
, card
->driver
);
3246 pa_tagstruct_putu32(t
, pa_hashmap_size(card
->profiles
));
3248 PA_HASHMAP_FOREACH(p
, card
->profiles
, state
) {
3249 pa_tagstruct_puts(t
, p
->name
);
3250 pa_tagstruct_puts(t
, p
->description
);
3251 pa_tagstruct_putu32(t
, p
->n_sinks
);
3252 pa_tagstruct_putu32(t
, p
->n_sources
);
3253 pa_tagstruct_putu32(t
, p
->priority
);
3256 pa_tagstruct_puts(t
, card
->active_profile
->name
);
3257 pa_tagstruct_put_proplist(t
, card
->proplist
);
3259 if (c
->version
< 26)
3262 pa_tagstruct_putu32(t
, pa_hashmap_size(card
->ports
));
3264 PA_HASHMAP_FOREACH(port
, card
->ports
, state
) {
3267 pa_tagstruct_puts(t
, port
->name
);
3268 pa_tagstruct_puts(t
, port
->description
);
3269 pa_tagstruct_putu32(t
, port
->priority
);
3270 pa_tagstruct_putu32(t
, port
->available
);
3271 pa_tagstruct_putu8(t
, /* FIXME: port->direction */ (port
->is_input
? PA_DIRECTION_INPUT
: 0) | (port
->is_output
? PA_DIRECTION_OUTPUT
: 0));
3272 pa_tagstruct_put_proplist(t
, port
->proplist
);
3274 pa_tagstruct_putu32(t
, pa_hashmap_size(port
->profiles
));
3276 PA_HASHMAP_FOREACH(p
, port
->profiles
, state2
)
3277 pa_tagstruct_puts(t
, p
->name
);
3279 if (c
->version
>= 27)
3280 pa_tagstruct_puts64(t
, port
->latency_offset
);
3284 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
3288 pa_tagstruct_putu32(t
, module
->index
);
3289 pa_tagstruct_puts(t
, module
->name
);
3290 pa_tagstruct_puts(t
, module
->argument
);
3291 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
3293 if (c
->version
< 15)
3294 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
3296 if (c
->version
>= 15)
3297 pa_tagstruct_put_proplist(t
, module
->proplist
);
3300 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
3301 pa_sample_spec fixed_ss
;
3302 pa_usec_t sink_latency
;
3304 pa_bool_t has_volume
= FALSE
;
3307 pa_sink_input_assert_ref(s
);
3309 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3311 has_volume
= pa_sink_input_is_volume_readable(s
);
3313 pa_sink_input_get_volume(s
, &v
, TRUE
);
3315 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3317 pa_tagstruct_putu32(t
, s
->index
);
3318 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3319 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3320 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3321 pa_tagstruct_putu32(t
, s
->sink
->index
);
3322 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3323 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3324 pa_tagstruct_put_cvolume(t
, &v
);
3325 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3326 pa_tagstruct_put_usec(t
, sink_latency
);
3327 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3328 pa_tagstruct_puts(t
, s
->driver
);
3329 if (c
->version
>= 11)
3330 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3331 if (c
->version
>= 13)
3332 pa_tagstruct_put_proplist(t
, s
->proplist
);
3333 if (c
->version
>= 19)
3334 pa_tagstruct_put_boolean(t
, (pa_sink_input_get_state(s
) == PA_SINK_INPUT_CORKED
));
3335 if (c
->version
>= 20) {
3336 pa_tagstruct_put_boolean(t
, has_volume
);
3337 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3339 if (c
->version
>= 21)
3340 pa_tagstruct_put_format_info(t
, s
->format
);
3343 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3344 pa_sample_spec fixed_ss
;
3345 pa_usec_t source_latency
;
3347 pa_bool_t has_volume
= FALSE
;
3350 pa_source_output_assert_ref(s
);
3352 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3354 has_volume
= pa_source_output_is_volume_readable(s
);
3356 pa_source_output_get_volume(s
, &v
, TRUE
);
3358 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3360 pa_tagstruct_putu32(t
, s
->index
);
3361 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3362 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3363 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3364 pa_tagstruct_putu32(t
, s
->source
->index
);
3365 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3366 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3367 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3368 pa_tagstruct_put_usec(t
, source_latency
);
3369 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3370 pa_tagstruct_puts(t
, s
->driver
);
3371 if (c
->version
>= 13)
3372 pa_tagstruct_put_proplist(t
, s
->proplist
);
3373 if (c
->version
>= 19)
3374 pa_tagstruct_put_boolean(t
, (pa_source_output_get_state(s
) == PA_SOURCE_OUTPUT_CORKED
));
3375 if (c
->version
>= 22) {
3376 pa_tagstruct_put_cvolume(t
, &v
);
3377 pa_tagstruct_put_boolean(t
, pa_source_output_get_mute(s
));
3378 pa_tagstruct_put_boolean(t
, has_volume
);
3379 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3380 pa_tagstruct_put_format_info(t
, s
->format
);
3384 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3385 pa_sample_spec fixed_ss
;
3391 if (e
->memchunk
.memblock
)
3392 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3394 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3396 pa_tagstruct_putu32(t
, e
->index
);
3397 pa_tagstruct_puts(t
, e
->name
);
3399 if (e
->volume_is_set
)
3402 pa_cvolume_init(&v
);
3404 pa_tagstruct_put_cvolume(t
, &v
);
3405 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3406 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3407 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3408 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3409 pa_tagstruct_put_boolean(t
, e
->lazy
);
3410 pa_tagstruct_puts(t
, e
->filename
);
3412 if (c
->version
>= 13)
3413 pa_tagstruct_put_proplist(t
, e
->proplist
);
3416 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3417 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3419 pa_sink
*sink
= NULL
;
3420 pa_source
*source
= NULL
;
3421 pa_client
*client
= NULL
;
3422 pa_card
*card
= NULL
;
3423 pa_module
*module
= NULL
;
3424 pa_sink_input
*si
= NULL
;
3425 pa_source_output
*so
= NULL
;
3426 pa_scache_entry
*sce
= NULL
;
3427 const char *name
= NULL
;
3428 pa_tagstruct
*reply
;
3430 pa_native_connection_assert_ref(c
);
3433 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3434 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3435 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3436 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3437 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3438 pa_tagstruct_gets(t
, &name
) < 0) ||
3439 !pa_tagstruct_eof(t
)) {
3444 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3445 CHECK_VALIDITY(c
->pstream
, !name
||
3446 (command
== PA_COMMAND_GET_SINK_INFO
&&
3447 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3448 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3449 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3450 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3451 CHECK_VALIDITY(c
->pstream
, command
== PA_COMMAND_GET_SINK_INFO
||
3452 command
== PA_COMMAND_GET_SOURCE_INFO
||
3453 (idx
!= PA_INVALID_INDEX
|| name
), tag
, PA_ERR_INVALID
);
3454 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3455 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3457 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3458 if (idx
!= PA_INVALID_INDEX
)
3459 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3461 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3462 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3463 if (idx
!= PA_INVALID_INDEX
)
3464 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3466 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3467 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3468 if (idx
!= PA_INVALID_INDEX
)
3469 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3471 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3472 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3473 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3474 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3475 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3476 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3477 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3478 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3479 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3481 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3482 if (idx
!= PA_INVALID_INDEX
)
3483 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3485 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3488 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3489 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3493 reply
= reply_new(tag
);
3495 sink_fill_tagstruct(c
, reply
, sink
);
3497 source_fill_tagstruct(c
, reply
, source
);
3499 client_fill_tagstruct(c
, reply
, client
);
3501 card_fill_tagstruct(c
, reply
, card
);
3503 module_fill_tagstruct(c
, reply
, module
);
3505 sink_input_fill_tagstruct(c
, reply
, si
);
3507 source_output_fill_tagstruct(c
, reply
, so
);
3509 scache_fill_tagstruct(c
, reply
, sce
);
3510 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3513 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3514 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3518 pa_tagstruct
*reply
;
3520 pa_native_connection_assert_ref(c
);
3523 if (!pa_tagstruct_eof(t
)) {
3528 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3530 reply
= reply_new(tag
);
3532 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3533 i
= c
->protocol
->core
->sinks
;
3534 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3535 i
= c
->protocol
->core
->sources
;
3536 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3537 i
= c
->protocol
->core
->clients
;
3538 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3539 i
= c
->protocol
->core
->cards
;
3540 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3541 i
= c
->protocol
->core
->modules
;
3542 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3543 i
= c
->protocol
->core
->sink_inputs
;
3544 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3545 i
= c
->protocol
->core
->source_outputs
;
3547 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3548 i
= c
->protocol
->core
->scache
;
3552 PA_IDXSET_FOREACH(p
, i
, idx
) {
3553 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3554 sink_fill_tagstruct(c
, reply
, p
);
3555 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3556 source_fill_tagstruct(c
, reply
, p
);
3557 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3558 client_fill_tagstruct(c
, reply
, p
);
3559 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3560 card_fill_tagstruct(c
, reply
, p
);
3561 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3562 module_fill_tagstruct(c
, reply
, p
);
3563 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3564 sink_input_fill_tagstruct(c
, reply
, p
);
3565 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3566 source_output_fill_tagstruct(c
, reply
, p
);
3568 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3569 scache_fill_tagstruct(c
, reply
, p
);
3574 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3577 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3578 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3579 pa_tagstruct
*reply
;
3581 pa_source
*def_source
;
3582 pa_sample_spec fixed_ss
;
3585 pa_native_connection_assert_ref(c
);
3588 if (!pa_tagstruct_eof(t
)) {
3593 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3595 reply
= reply_new(tag
);
3596 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3597 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3599 u
= pa_get_user_name_malloc();
3600 pa_tagstruct_puts(reply
, u
);
3603 h
= pa_get_host_name_malloc();
3604 pa_tagstruct_puts(reply
, h
);
3607 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3608 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3610 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3611 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3612 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3613 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3615 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3617 if (c
->version
>= 15)
3618 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3620 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3623 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3625 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3627 pa_native_connection_assert_ref(c
);
3629 t
= pa_tagstruct_new(NULL
, 0);
3630 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3631 pa_tagstruct_putu32(t
, (uint32_t) -1);
3632 pa_tagstruct_putu32(t
, e
);
3633 pa_tagstruct_putu32(t
, idx
);
3634 pa_pstream_send_tagstruct(c
->pstream
, t
);
3637 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3638 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3639 pa_subscription_mask_t m
;
3641 pa_native_connection_assert_ref(c
);
3644 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3645 !pa_tagstruct_eof(t
)) {
3650 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3651 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3653 if (c
->subscription
)
3654 pa_subscription_free(c
->subscription
);
3657 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3658 pa_assert(c
->subscription
);
3660 c
->subscription
= NULL
;
3662 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3665 static void command_set_volume(
3672 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3675 pa_sink
*sink
= NULL
;
3676 pa_source
*source
= NULL
;
3677 pa_sink_input
*si
= NULL
;
3678 pa_source_output
*so
= NULL
;
3679 const char *name
= NULL
;
3680 const char *client_name
;
3682 pa_native_connection_assert_ref(c
);
3685 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3686 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3687 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3688 pa_tagstruct_get_cvolume(t
, &volume
) ||
3689 !pa_tagstruct_eof(t
)) {
3694 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3695 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
);
3696 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3697 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3698 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3699 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3703 case PA_COMMAND_SET_SINK_VOLUME
:
3704 if (idx
!= PA_INVALID_INDEX
)
3705 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3707 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3710 case PA_COMMAND_SET_SOURCE_VOLUME
:
3711 if (idx
!= PA_INVALID_INDEX
)
3712 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3714 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3717 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3718 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3721 case PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME
:
3722 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3726 pa_assert_not_reached();
3729 CHECK_VALIDITY(c
->pstream
, si
|| so
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3731 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3734 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3736 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3737 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3738 } else if (source
) {
3739 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3741 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3742 pa_source_set_volume(source
, &volume
, TRUE
, TRUE
);
3744 CHECK_VALIDITY(c
->pstream
, si
->volume_writable
, tag
, PA_ERR_BADSTATE
);
3745 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3747 pa_log_debug("Client %s changes volume of sink input %s.",
3749 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3750 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3752 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &so
->sample_spec
), tag
, PA_ERR_INVALID
);
3754 pa_log_debug("Client %s changes volume of source output %s.",
3756 pa_strnull(pa_proplist_gets(so
->proplist
, PA_PROP_MEDIA_NAME
)));
3757 pa_source_output_set_volume(so
, &volume
, TRUE
, TRUE
);
3760 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3763 static void command_set_mute(
3770 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3773 pa_sink
*sink
= NULL
;
3774 pa_source
*source
= NULL
;
3775 pa_sink_input
*si
= NULL
;
3776 pa_source_output
*so
= NULL
;
3777 const char *name
= NULL
, *client_name
;
3779 pa_native_connection_assert_ref(c
);
3782 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3783 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3784 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3785 pa_tagstruct_get_boolean(t
, &mute
) ||
3786 !pa_tagstruct_eof(t
)) {
3791 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3792 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
);
3793 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3794 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3795 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3799 case PA_COMMAND_SET_SINK_MUTE
:
3800 if (idx
!= PA_INVALID_INDEX
)
3801 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3803 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3807 case PA_COMMAND_SET_SOURCE_MUTE
:
3808 if (idx
!= PA_INVALID_INDEX
)
3809 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3811 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3815 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3816 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3819 case PA_COMMAND_SET_SOURCE_OUTPUT_MUTE
:
3820 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3824 pa_assert_not_reached();
3827 CHECK_VALIDITY(c
->pstream
, si
|| so
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3829 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3832 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3833 pa_sink_set_mute(sink
, mute
, TRUE
);
3834 } else if (source
) {
3835 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3836 pa_source_set_mute(source
, mute
, TRUE
);
3838 pa_log_debug("Client %s changes mute of sink input %s.",
3840 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3841 pa_sink_input_set_mute(si
, mute
, TRUE
);
3843 pa_log_debug("Client %s changes mute of source output %s.",
3845 pa_strnull(pa_proplist_gets(so
->proplist
, PA_PROP_MEDIA_NAME
)));
3846 pa_source_output_set_mute(so
, mute
, TRUE
);
3849 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3852 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3853 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3858 pa_native_connection_assert_ref(c
);
3861 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3862 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3863 !pa_tagstruct_eof(t
)) {
3868 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3869 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3870 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3871 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3872 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3874 pa_sink_input_cork(s
->sink_input
, b
);
3877 s
->is_underrun
= TRUE
;
3879 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3882 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3883 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3887 pa_native_connection_assert_ref(c
);
3890 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3891 !pa_tagstruct_eof(t
)) {
3896 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3897 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3898 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3899 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3900 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3903 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3904 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3907 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3908 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3911 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3912 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3916 pa_assert_not_reached();
3919 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3922 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3923 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3928 pa_native_connection_assert_ref(c
);
3931 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3932 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3933 !pa_tagstruct_eof(t
)) {
3938 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3939 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3940 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3942 pa_source_output_cork(s
->source_output
, b
);
3943 pa_memblockq_prebuf_force(s
->memblockq
);
3944 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3947 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3948 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3952 pa_native_connection_assert_ref(c
);
3955 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3956 !pa_tagstruct_eof(t
)) {
3961 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3962 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3963 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3965 pa_memblockq_flush_read(s
->memblockq
);
3966 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3969 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3970 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3973 pa_tagstruct
*reply
;
3975 pa_native_connection_assert_ref(c
);
3978 memset(&a
, 0, sizeof(a
));
3980 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
3985 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3987 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
3989 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
3991 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3992 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3993 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3995 if (pa_tagstruct_get(
3997 PA_TAG_U32
, &a
.maxlength
,
3998 PA_TAG_U32
, &a
.tlength
,
3999 PA_TAG_U32
, &a
.prebuf
,
4000 PA_TAG_U32
, &a
.minreq
,
4001 PA_TAG_INVALID
) < 0 ||
4002 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
4003 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
4004 !pa_tagstruct_eof(t
)) {
4009 s
->adjust_latency
= adjust_latency
;
4010 s
->early_requests
= early_requests
;
4011 s
->buffer_attr_req
= a
;
4013 fix_playback_buffer_attr(s
);
4014 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);
4016 reply
= reply_new(tag
);
4017 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
4018 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
4019 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
4020 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
4022 if (c
->version
>= 13)
4023 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
4027 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
4028 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
4030 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4031 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4033 if (pa_tagstruct_get(
4035 PA_TAG_U32
, &a
.maxlength
,
4036 PA_TAG_U32
, &a
.fragsize
,
4037 PA_TAG_INVALID
) < 0 ||
4038 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
4039 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
4040 !pa_tagstruct_eof(t
)) {
4045 s
->adjust_latency
= adjust_latency
;
4046 s
->early_requests
= early_requests
;
4047 s
->buffer_attr_req
= a
;
4049 fix_record_buffer_attr_pre(s
);
4050 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
4051 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
4052 fix_record_buffer_attr_post(s
);
4054 reply
= reply_new(tag
);
4055 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
4056 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
4058 if (c
->version
>= 13)
4059 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
4062 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4065 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4066 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4070 pa_native_connection_assert_ref(c
);
4073 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4074 pa_tagstruct_getu32(t
, &rate
) < 0 ||
4075 !pa_tagstruct_eof(t
)) {
4080 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4081 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
4083 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
4086 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4087 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4088 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4090 pa_sink_input_set_rate(s
->sink_input
, rate
);
4094 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
4096 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4097 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4099 pa_source_output_set_rate(s
->source_output
, rate
);
4102 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4105 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4106 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4111 pa_native_connection_assert_ref(c
);
4114 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4116 p
= pa_proplist_new();
4118 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
4120 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
4121 pa_tagstruct_get_proplist(t
, p
) < 0 ||
4122 !pa_tagstruct_eof(t
)) {
4124 pa_proplist_free(p
);
4130 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4131 pa_tagstruct_getu32(t
, &mode
) < 0 ||
4132 pa_tagstruct_get_proplist(t
, p
) < 0 ||
4133 !pa_tagstruct_eof(t
)) {
4135 pa_proplist_free(p
);
4140 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
4141 pa_proplist_free(p
);
4142 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
4145 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
4148 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4149 if (!s
|| !playback_stream_isinstance(s
)) {
4150 pa_proplist_free(p
);
4151 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4153 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
4155 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
4158 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
4159 pa_proplist_free(p
);
4160 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4162 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
4165 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
4167 pa_client_update_proplist(c
->client
, mode
, p
);
4170 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4171 pa_proplist_free(p
);
4174 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4175 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4177 unsigned changed
= 0;
4179 pa_strlist
*l
= NULL
;
4181 pa_native_connection_assert_ref(c
);
4184 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4186 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
4188 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
4194 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4197 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4198 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4199 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4201 p
= s
->sink_input
->proplist
;
4203 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4206 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4207 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4209 p
= s
->source_output
->proplist
;
4211 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4213 p
= c
->client
->proplist
;
4219 if (pa_tagstruct_gets(t
, &k
) < 0) {
4228 l
= pa_strlist_prepend(l
, k
);
4231 if (!pa_tagstruct_eof(t
)) {
4240 l
= pa_strlist_pop(l
, &z
);
4245 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
4249 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4252 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4255 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4256 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
4258 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4261 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4262 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
4265 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4266 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
4271 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4272 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4275 pa_native_connection_assert_ref(c
);
4278 if (pa_tagstruct_gets(t
, &s
) < 0 ||
4279 !pa_tagstruct_eof(t
)) {
4284 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4285 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
4287 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
4290 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
4291 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4293 pa_namereg_set_default_source(c
->protocol
->core
, source
);
4296 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
4298 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
4299 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4301 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
4304 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4307 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4308 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4312 pa_native_connection_assert_ref(c
);
4315 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4316 pa_tagstruct_gets(t
, &name
) < 0 ||
4317 !pa_tagstruct_eof(t
)) {
4322 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4323 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4325 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
4328 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4329 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4330 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4332 pa_sink_input_set_name(s
->sink_input
, name
);
4336 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
4338 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4339 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4341 pa_source_output_set_name(s
->source_output
, name
);
4344 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4347 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4348 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4351 pa_native_connection_assert_ref(c
);
4354 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4355 !pa_tagstruct_eof(t
)) {
4360 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4362 if (command
== PA_COMMAND_KILL_CLIENT
) {
4365 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4366 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4368 pa_native_connection_ref(c
);
4369 pa_client_kill(client
);
4371 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4374 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4375 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4377 pa_native_connection_ref(c
);
4378 pa_sink_input_kill(s
);
4380 pa_source_output
*s
;
4382 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4384 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4385 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4387 pa_native_connection_ref(c
);
4388 pa_source_output_kill(s
);
4391 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4392 pa_native_connection_unref(c
);
4395 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4396 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4398 const char *name
, *argument
;
4399 pa_tagstruct
*reply
;
4401 pa_native_connection_assert_ref(c
);
4404 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4405 pa_tagstruct_gets(t
, &argument
) < 0 ||
4406 !pa_tagstruct_eof(t
)) {
4411 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4412 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4413 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4415 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4416 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4420 reply
= reply_new(tag
);
4421 pa_tagstruct_putu32(reply
, m
->index
);
4422 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4425 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4426 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4430 pa_native_connection_assert_ref(c
);
4433 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4434 !pa_tagstruct_eof(t
)) {
4439 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4440 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4441 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4443 pa_module_unload_request(m
, FALSE
);
4444 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4447 static void command_move_stream(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
, idx_device
= PA_INVALID_INDEX
;
4450 const char *name_device
= NULL
;
4452 pa_native_connection_assert_ref(c
);
4455 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4456 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4457 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4458 !pa_tagstruct_eof(t
)) {
4463 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4464 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4466 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
);
4467 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4468 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4469 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4471 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4472 pa_sink_input
*si
= NULL
;
4473 pa_sink
*sink
= NULL
;
4475 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4477 if (idx_device
!= PA_INVALID_INDEX
)
4478 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4480 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4482 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4484 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4485 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4489 pa_source_output
*so
= NULL
;
4492 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4494 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4496 if (idx_device
!= PA_INVALID_INDEX
)
4497 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4499 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4501 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4503 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4504 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4509 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4512 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4513 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4514 uint32_t idx
= PA_INVALID_INDEX
;
4515 const char *name
= NULL
;
4518 pa_native_connection_assert_ref(c
);
4521 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4522 pa_tagstruct_gets(t
, &name
) < 0 ||
4523 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4524 !pa_tagstruct_eof(t
)) {
4529 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4530 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
);
4531 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4532 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4533 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4535 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4537 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4539 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4541 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4542 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4546 pa_sink
*sink
= NULL
;
4548 if (idx
!= PA_INVALID_INDEX
)
4549 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4551 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4553 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4555 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4556 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4562 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4564 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4566 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4568 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4569 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4576 if (idx
!= PA_INVALID_INDEX
)
4577 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4579 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4581 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4583 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4584 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4590 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4593 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4594 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4595 uint32_t idx
= PA_INVALID_INDEX
;
4596 const char *name
= NULL
;
4598 pa_native_protocol_ext_cb_t cb
;
4600 pa_native_connection_assert_ref(c
);
4603 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4604 pa_tagstruct_gets(t
, &name
) < 0) {
4609 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4610 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4611 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4612 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4613 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4615 if (idx
!= PA_INVALID_INDEX
)
4616 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4618 PA_IDXSET_FOREACH(m
, c
->protocol
->core
->modules
, idx
)
4619 if (pa_streq(name
, m
->name
))
4622 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4623 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4625 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4626 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4628 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4632 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4633 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4634 uint32_t idx
= PA_INVALID_INDEX
;
4635 const char *name
= NULL
, *profile
= NULL
;
4636 pa_card
*card
= NULL
;
4639 pa_native_connection_assert_ref(c
);
4642 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4643 pa_tagstruct_gets(t
, &name
) < 0 ||
4644 pa_tagstruct_gets(t
, &profile
) < 0 ||
4645 !pa_tagstruct_eof(t
)) {
4650 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4651 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4652 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4653 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4654 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4656 if (idx
!= PA_INVALID_INDEX
)
4657 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4659 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4661 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4663 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4664 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4668 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4671 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4672 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4673 uint32_t idx
= PA_INVALID_INDEX
;
4674 const char *name
= NULL
, *port
= NULL
;
4677 pa_native_connection_assert_ref(c
);
4680 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4681 pa_tagstruct_gets(t
, &name
) < 0 ||
4682 pa_tagstruct_gets(t
, &port
) < 0 ||
4683 !pa_tagstruct_eof(t
)) {
4688 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4689 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
);
4690 CHECK_VALIDITY(c
->pstream
, (idx
!= PA_INVALID_INDEX
) ^ (name
!= NULL
), tag
, PA_ERR_INVALID
);
4691 CHECK_VALIDITY(c
->pstream
, port
, tag
, PA_ERR_INVALID
);
4693 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4696 if (idx
!= PA_INVALID_INDEX
)
4697 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4699 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4701 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4703 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4704 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4710 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4712 if (idx
!= PA_INVALID_INDEX
)
4713 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4715 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4717 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4719 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4720 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4725 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4728 static void command_set_port_latency_offset(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4729 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4730 const char *port_name
, *card_name
;
4731 uint32_t idx
= PA_INVALID_INDEX
;
4733 pa_card
*card
= NULL
;
4734 pa_device_port
*port
= NULL
;
4736 pa_native_connection_assert_ref(c
);
4739 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4740 pa_tagstruct_gets(t
, &card_name
) < 0 ||
4741 pa_tagstruct_gets(t
, &port_name
) < 0 ||
4742 pa_tagstruct_gets64(t
, &offset
) < 0 ||
4743 !pa_tagstruct_eof(t
)) {
4747 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4748 CHECK_VALIDITY(c
->pstream
, !card_name
|| pa_namereg_is_valid_name(card_name
), tag
, PA_ERR_INVALID
);
4749 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| card_name
, tag
, PA_ERR_INVALID
);
4750 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !card_name
, tag
, PA_ERR_INVALID
);
4751 CHECK_VALIDITY(c
->pstream
, port_name
, tag
, PA_ERR_INVALID
);
4753 if (idx
!= PA_INVALID_INDEX
)
4754 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4756 card
= pa_namereg_get(c
->protocol
->core
, card_name
, PA_NAMEREG_CARD
);
4758 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4760 port
= pa_hashmap_get(card
->ports
, port_name
);
4761 CHECK_VALIDITY(c
->pstream
, port
, tag
, PA_ERR_NOENTITY
);
4763 pa_device_port_set_latency_offset(port
, offset
);
4765 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4768 /*** pstream callbacks ***/
4770 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4771 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4775 pa_native_connection_assert_ref(c
);
4777 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4778 pa_log("invalid packet.");
4779 native_connection_unlink(c
);
4783 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
) {
4784 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4785 output_stream
*stream
;
4789 pa_native_connection_assert_ref(c
);
4791 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4792 pa_log_debug("Client sent block for invalid stream.");
4797 #ifdef PROTOCOL_NATIVE_DEBUG
4798 pa_log("got %lu bytes from client", (unsigned long) chunk
->length
);
4801 if (playback_stream_isinstance(stream
)) {
4802 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4804 pa_atomic_inc(&ps
->seek_or_post_in_queue
);
4805 if (chunk
->memblock
) {
4806 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4807 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
);
4809 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4811 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
);
4814 upload_stream
*u
= UPLOAD_STREAM(stream
);
4817 if (!u
->memchunk
.memblock
) {
4818 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4819 u
->memchunk
= *chunk
;
4820 pa_memblock_ref(u
->memchunk
.memblock
);
4823 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4824 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4828 pa_assert(u
->memchunk
.memblock
);
4831 if (l
> chunk
->length
)
4836 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4838 if (chunk
->memblock
) {
4840 src
= pa_memblock_acquire(chunk
->memblock
);
4842 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4843 (uint8_t*) src
+ chunk
->index
, l
);
4845 pa_memblock_release(chunk
->memblock
);
4847 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4849 pa_memblock_release(u
->memchunk
.memblock
);
4851 u
->memchunk
.length
+= l
;
4857 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4858 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4861 pa_native_connection_assert_ref(c
);
4863 native_connection_unlink(c
);
4864 pa_log_info("Connection died.");
4867 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4868 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4871 pa_native_connection_assert_ref(c
);
4873 native_connection_send_memblock(c
);
4876 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4879 if (!(q
= pa_thread_mq_get()))
4880 pa_pstream_send_revoke(p
, block_id
);
4882 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4885 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4888 if (!(q
= pa_thread_mq_get()))
4889 pa_pstream_send_release(p
, block_id
);
4891 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4894 /*** client callbacks ***/
4896 static void client_kill_cb(pa_client
*c
) {
4899 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4900 pa_log_info("Connection killed.");
4903 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4905 pa_native_connection
*c
;
4908 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4909 pa_native_connection_assert_ref(c
);
4911 if (c
->version
< 15)
4914 t
= pa_tagstruct_new(NULL
, 0);
4915 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4916 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4917 pa_tagstruct_puts(t
, event
);
4918 pa_tagstruct_put_proplist(t
, pl
);
4919 pa_pstream_send_tagstruct(c
->pstream
, t
);
4922 /*** module entry points ***/
4924 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4925 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4928 pa_native_connection_assert_ref(c
);
4929 pa_assert(c
->auth_timeout_event
== e
);
4931 if (!c
->authorized
) {
4932 native_connection_unlink(c
);
4933 pa_log_info("Connection terminated due to authentication timeout.");
4937 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4938 pa_native_connection
*c
;
4941 pa_client_new_data data
;
4947 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4948 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4949 pa_iochannel_free(io
);
4953 pa_client_new_data_init(&data
);
4954 data
.module
= o
->module
;
4955 data
.driver
= __FILE__
;
4956 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4957 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4958 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4959 client
= pa_client_new(p
->core
, &data
);
4960 pa_client_new_data_done(&data
);
4965 c
= pa_msgobject_new(pa_native_connection
);
4966 c
->parent
.parent
.free
= native_connection_free
;
4967 c
->parent
.process_msg
= native_connection_process_msg
;
4969 c
->options
= pa_native_options_ref(o
);
4970 c
->authorized
= FALSE
;
4972 if (o
->auth_anonymous
) {
4973 pa_log_info("Client authenticated anonymously.");
4974 c
->authorized
= TRUE
;
4977 if (!c
->authorized
&&
4979 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
4981 pa_log_info("Client authenticated by IP ACL.");
4982 c
->authorized
= TRUE
;
4986 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
4988 c
->auth_timeout_event
= NULL
;
4990 c
->is_local
= pa_iochannel_socket_is_local(io
);
4994 c
->client
->kill
= client_kill_cb
;
4995 c
->client
->send_event
= client_send_event_cb
;
4996 c
->client
->userdata
= c
;
4998 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
4999 pa_pstream_set_receive_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
5000 pa_pstream_set_receive_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
5001 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
5002 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
5003 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
5004 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
5006 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
5008 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
5009 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
5011 c
->rrobin_index
= PA_IDXSET_INVALID
;
5012 c
->subscription
= NULL
;
5014 pa_idxset_put(p
->connections
, c
, NULL
);
5017 if (pa_iochannel_creds_supported(io
))
5018 pa_iochannel_creds_enable(io
);
5021 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
5024 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
5025 pa_native_connection
*c
;
5031 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
5032 if (c
->options
->module
== m
)
5033 native_connection_unlink(c
);
5036 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
5037 pa_native_protocol
*p
;
5042 p
= pa_xnew(pa_native_protocol
, 1);
5045 p
->connections
= pa_idxset_new(NULL
, NULL
);
5049 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
5051 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
5052 pa_hook_init(&p
->hooks
[h
], p
);
5054 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
5059 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
5060 pa_native_protocol
*p
;
5062 if ((p
= pa_shared_get(c
, "native-protocol")))
5063 return pa_native_protocol_ref(p
);
5065 return native_protocol_new(c
);
5068 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
5070 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5077 void pa_native_protocol_unref(pa_native_protocol
*p
) {
5078 pa_native_connection
*c
;
5082 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5084 if (PA_REFCNT_DEC(p
) > 0)
5087 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
5088 native_connection_unlink(c
);
5090 pa_idxset_free(p
->connections
, NULL
, NULL
);
5092 pa_strlist_free(p
->servers
);
5094 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
5095 pa_hook_done(&p
->hooks
[h
]);
5097 pa_hashmap_free(p
->extensions
, NULL
, NULL
);
5099 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
5104 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
5106 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5109 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
5111 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
5114 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
5116 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5119 p
->servers
= pa_strlist_remove(p
->servers
, name
);
5121 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
5124 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
5126 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5131 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
5133 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5138 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
5140 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5143 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
5145 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
5149 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
5151 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5154 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
5157 pa_native_options
* pa_native_options_new(void) {
5158 pa_native_options
*o
;
5160 o
= pa_xnew0(pa_native_options
, 1);
5166 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
5168 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5175 void pa_native_options_unref(pa_native_options
*o
) {
5177 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5179 if (PA_REFCNT_DEC(o
) > 0)
5182 pa_xfree(o
->auth_group
);
5185 pa_ip_acl_free(o
->auth_ip_acl
);
5188 pa_auth_cookie_unref(o
->auth_cookie
);
5193 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
5198 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5201 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
5202 pa_log("auth-anonymous= expects a boolean argument.");
5207 if (pa_modargs_get_value_boolean(ma
, "auth-group-enable", &enabled
) < 0) {
5208 pa_log("auth-group-enable= expects a boolean argument.");
5212 pa_xfree(o
->auth_group
);
5213 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
5217 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
5220 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
5223 if (!(ipa
= pa_ip_acl_new(acl
))) {
5224 pa_log("Failed to parse IP ACL '%s'", acl
);
5229 pa_ip_acl_free(o
->auth_ip_acl
);
5231 o
->auth_ip_acl
= ipa
;
5235 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
5236 pa_log("auth-cookie-enabled= expects a boolean argument.");
5241 pa_auth_cookie_unref(o
->auth_cookie
);
5246 /* The new name for this is 'auth-cookie', for compat reasons
5247 * we check the old name too */
5248 cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
);
5250 cn
= pa_modargs_get_value(ma
, "cookie", NULL
);
5253 o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, TRUE
, PA_NATIVE_COOKIE_LENGTH
);
5255 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE
, FALSE
, PA_NATIVE_COOKIE_LENGTH
);
5256 if (!o
->auth_cookie
) {
5257 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE_FALLBACK
, FALSE
, PA_NATIVE_COOKIE_LENGTH
);
5259 if (!o
->auth_cookie
)
5260 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE
, TRUE
, PA_NATIVE_COOKIE_LENGTH
);
5264 if (!o
->auth_cookie
)
5268 o
->auth_cookie
= NULL
;
5273 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
5274 pa_native_connection_assert_ref(c
);
5279 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
5280 pa_native_connection_assert_ref(c
);