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 bool sink_input_process_underrun_cb(pa_sink_input
*i
);
235 static int sink_input_pop_cb(pa_sink_input
*i
, size_t length
, pa_memchunk
*chunk
);
236 static void sink_input_kill_cb(pa_sink_input
*i
);
237 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
);
238 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
);
239 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
240 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
);
241 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
);
242 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
);
244 static void native_connection_send_memblock(pa_native_connection
*c
);
245 static void playback_stream_request_bytes(struct playback_stream
*s
);
247 static void source_output_kill_cb(pa_source_output
*o
);
248 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
);
249 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
);
250 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
);
251 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
);
252 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
);
254 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
255 static int source_output_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
);
257 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
258 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
259 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
260 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
261 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
262 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
263 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
264 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
265 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
266 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
267 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
268 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
269 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
270 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
271 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
272 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
273 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
274 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
275 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
276 static void command_set_volume(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
277 static void command_set_mute(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
278 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
279 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
280 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
281 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
282 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
283 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
284 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
285 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
286 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
287 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
288 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
289 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
290 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
291 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
292 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
293 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
294 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
295 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
296 static void command_set_port_latency_offset(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
);
298 static const pa_pdispatch_cb_t command_table
[PA_COMMAND_MAX
] = {
299 [PA_COMMAND_ERROR
] = NULL
,
300 [PA_COMMAND_TIMEOUT
] = NULL
,
301 [PA_COMMAND_REPLY
] = NULL
,
302 [PA_COMMAND_CREATE_PLAYBACK_STREAM
] = command_create_playback_stream
,
303 [PA_COMMAND_DELETE_PLAYBACK_STREAM
] = command_delete_stream
,
304 [PA_COMMAND_DRAIN_PLAYBACK_STREAM
] = command_drain_playback_stream
,
305 [PA_COMMAND_CREATE_RECORD_STREAM
] = command_create_record_stream
,
306 [PA_COMMAND_DELETE_RECORD_STREAM
] = command_delete_stream
,
307 [PA_COMMAND_AUTH
] = command_auth
,
308 [PA_COMMAND_REQUEST
] = NULL
,
309 [PA_COMMAND_EXIT
] = command_exit
,
310 [PA_COMMAND_SET_CLIENT_NAME
] = command_set_client_name
,
311 [PA_COMMAND_LOOKUP_SINK
] = command_lookup
,
312 [PA_COMMAND_LOOKUP_SOURCE
] = command_lookup
,
313 [PA_COMMAND_STAT
] = command_stat
,
314 [PA_COMMAND_GET_PLAYBACK_LATENCY
] = command_get_playback_latency
,
315 [PA_COMMAND_GET_RECORD_LATENCY
] = command_get_record_latency
,
316 [PA_COMMAND_CREATE_UPLOAD_STREAM
] = command_create_upload_stream
,
317 [PA_COMMAND_DELETE_UPLOAD_STREAM
] = command_delete_stream
,
318 [PA_COMMAND_FINISH_UPLOAD_STREAM
] = command_finish_upload_stream
,
319 [PA_COMMAND_PLAY_SAMPLE
] = command_play_sample
,
320 [PA_COMMAND_REMOVE_SAMPLE
] = command_remove_sample
,
321 [PA_COMMAND_GET_SINK_INFO
] = command_get_info
,
322 [PA_COMMAND_GET_SOURCE_INFO
] = command_get_info
,
323 [PA_COMMAND_GET_CLIENT_INFO
] = command_get_info
,
324 [PA_COMMAND_GET_CARD_INFO
] = command_get_info
,
325 [PA_COMMAND_GET_MODULE_INFO
] = command_get_info
,
326 [PA_COMMAND_GET_SINK_INPUT_INFO
] = command_get_info
,
327 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO
] = command_get_info
,
328 [PA_COMMAND_GET_SAMPLE_INFO
] = command_get_info
,
329 [PA_COMMAND_GET_SINK_INFO_LIST
] = command_get_info_list
,
330 [PA_COMMAND_GET_SOURCE_INFO_LIST
] = command_get_info_list
,
331 [PA_COMMAND_GET_MODULE_INFO_LIST
] = command_get_info_list
,
332 [PA_COMMAND_GET_CLIENT_INFO_LIST
] = command_get_info_list
,
333 [PA_COMMAND_GET_CARD_INFO_LIST
] = command_get_info_list
,
334 [PA_COMMAND_GET_SINK_INPUT_INFO_LIST
] = command_get_info_list
,
335 [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
] = command_get_info_list
,
336 [PA_COMMAND_GET_SAMPLE_INFO_LIST
] = command_get_info_list
,
337 [PA_COMMAND_GET_SERVER_INFO
] = command_get_server_info
,
338 [PA_COMMAND_SUBSCRIBE
] = command_subscribe
,
340 [PA_COMMAND_SET_SINK_VOLUME
] = command_set_volume
,
341 [PA_COMMAND_SET_SINK_INPUT_VOLUME
] = command_set_volume
,
342 [PA_COMMAND_SET_SOURCE_VOLUME
] = command_set_volume
,
343 [PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME
] = command_set_volume
,
345 [PA_COMMAND_SET_SINK_MUTE
] = command_set_mute
,
346 [PA_COMMAND_SET_SINK_INPUT_MUTE
] = command_set_mute
,
347 [PA_COMMAND_SET_SOURCE_MUTE
] = command_set_mute
,
348 [PA_COMMAND_SET_SOURCE_OUTPUT_MUTE
] = command_set_mute
,
350 [PA_COMMAND_SUSPEND_SINK
] = command_suspend
,
351 [PA_COMMAND_SUSPEND_SOURCE
] = command_suspend
,
353 [PA_COMMAND_CORK_PLAYBACK_STREAM
] = command_cork_playback_stream
,
354 [PA_COMMAND_FLUSH_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
355 [PA_COMMAND_TRIGGER_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
356 [PA_COMMAND_PREBUF_PLAYBACK_STREAM
] = command_trigger_or_flush_or_prebuf_playback_stream
,
358 [PA_COMMAND_CORK_RECORD_STREAM
] = command_cork_record_stream
,
359 [PA_COMMAND_FLUSH_RECORD_STREAM
] = command_flush_record_stream
,
361 [PA_COMMAND_SET_DEFAULT_SINK
] = command_set_default_sink_or_source
,
362 [PA_COMMAND_SET_DEFAULT_SOURCE
] = command_set_default_sink_or_source
,
363 [PA_COMMAND_SET_PLAYBACK_STREAM_NAME
] = command_set_stream_name
,
364 [PA_COMMAND_SET_RECORD_STREAM_NAME
] = command_set_stream_name
,
365 [PA_COMMAND_KILL_CLIENT
] = command_kill
,
366 [PA_COMMAND_KILL_SINK_INPUT
] = command_kill
,
367 [PA_COMMAND_KILL_SOURCE_OUTPUT
] = command_kill
,
368 [PA_COMMAND_LOAD_MODULE
] = command_load_module
,
369 [PA_COMMAND_UNLOAD_MODULE
] = command_unload_module
,
371 [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE
] = NULL
,
372 [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE
] = NULL
,
373 [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE
] = NULL
,
374 [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE
] = NULL
,
376 [PA_COMMAND_MOVE_SINK_INPUT
] = command_move_stream
,
377 [PA_COMMAND_MOVE_SOURCE_OUTPUT
] = command_move_stream
,
379 [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
380 [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
] = command_set_stream_buffer_attr
,
382 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
383 [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
] = command_update_stream_sample_rate
,
385 [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
] = command_update_proplist
,
386 [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
] = command_update_proplist
,
387 [PA_COMMAND_UPDATE_CLIENT_PROPLIST
] = command_update_proplist
,
389 [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
] = command_remove_proplist
,
390 [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
] = command_remove_proplist
,
391 [PA_COMMAND_REMOVE_CLIENT_PROPLIST
] = command_remove_proplist
,
393 [PA_COMMAND_SET_CARD_PROFILE
] = command_set_card_profile
,
395 [PA_COMMAND_SET_SINK_PORT
] = command_set_sink_or_source_port
,
396 [PA_COMMAND_SET_SOURCE_PORT
] = command_set_sink_or_source_port
,
398 [PA_COMMAND_SET_PORT_LATENCY_OFFSET
] = command_set_port_latency_offset
,
400 [PA_COMMAND_EXTENSION
] = command_extension
403 /* structure management */
405 /* Called from main context */
406 static void upload_stream_unlink(upload_stream
*s
) {
412 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
413 s
->connection
= NULL
;
414 upload_stream_unref(s
);
417 /* Called from main context */
418 static void upload_stream_free(pa_object
*o
) {
419 upload_stream
*s
= UPLOAD_STREAM(o
);
422 upload_stream_unlink(s
);
427 pa_proplist_free(s
->proplist
);
429 if (s
->memchunk
.memblock
)
430 pa_memblock_unref(s
->memchunk
.memblock
);
435 /* Called from main context */
436 static upload_stream
* upload_stream_new(
437 pa_native_connection
*c
,
438 const pa_sample_spec
*ss
,
439 const pa_channel_map
*map
,
449 pa_assert(length
> 0);
452 s
= pa_msgobject_new(upload_stream
);
453 s
->parent
.parent
.parent
.free
= upload_stream_free
;
455 s
->sample_spec
= *ss
;
456 s
->channel_map
= *map
;
457 s
->name
= pa_xstrdup(name
);
458 pa_memchunk_reset(&s
->memchunk
);
460 s
->proplist
= pa_proplist_copy(p
);
461 pa_proplist_update(s
->proplist
, PA_UPDATE_MERGE
, c
->client
->proplist
);
463 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
468 /* Called from main context */
469 static void record_stream_unlink(record_stream
*s
) {
475 if (s
->source_output
) {
476 pa_source_output_unlink(s
->source_output
);
477 pa_source_output_unref(s
->source_output
);
478 s
->source_output
= NULL
;
481 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->record_streams
, s
, NULL
) == s
);
482 s
->connection
= NULL
;
483 record_stream_unref(s
);
486 /* Called from main context */
487 static void record_stream_free(pa_object
*o
) {
488 record_stream
*s
= RECORD_STREAM(o
);
491 record_stream_unlink(s
);
493 pa_memblockq_free(s
->memblockq
);
497 /* Called from main context */
498 static int record_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
499 record_stream
*s
= RECORD_STREAM(o
);
500 record_stream_assert_ref(s
);
507 case RECORD_STREAM_MESSAGE_POST_DATA
:
509 /* We try to keep up to date with how many bytes are
510 * currently on the fly */
511 pa_atomic_sub(&s
->on_the_fly
, chunk
->length
);
513 if (pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
514 /* pa_log_warn("Failed to push data into output queue."); */
518 if (!pa_pstream_is_pending(s
->connection
->pstream
))
519 native_connection_send_memblock(s
->connection
);
527 /* Called from main context */
528 static void fix_record_buffer_attr_pre(record_stream
*s
) {
531 pa_usec_t orig_fragsize_usec
, fragsize_usec
, source_usec
;
535 /* This function will be called from the main thread, before as
536 * well as after the source output has been activated using
537 * pa_source_output_put()! That means it may not touch any
538 * ->thread_info data! */
540 frame_size
= pa_frame_size(&s
->source_output
->sample_spec
);
541 s
->buffer_attr
= s
->buffer_attr_req
;
543 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
544 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
545 if (s
->buffer_attr
.maxlength
<= 0)
546 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
548 if (s
->buffer_attr
.fragsize
== (uint32_t) -1)
549 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC
*PA_USEC_PER_MSEC
, &s
->source_output
->sample_spec
);
550 if (s
->buffer_attr
.fragsize
<= 0)
551 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
553 orig_fragsize_usec
= fragsize_usec
= pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &s
->source_output
->sample_spec
);
555 if (s
->early_requests
) {
557 /* In early request mode we need to emulate the classic
558 * fragment-based playback model. We do this setting the source
559 * latency to the fragment size. */
561 source_usec
= fragsize_usec
;
563 } else if (s
->adjust_latency
) {
565 /* So, the user asked us to adjust the latency according to
566 * what the source can provide. Half the latency will be
567 * spent on the hw buffer, half of it in the async buffer
568 * queue we maintain for each client. */
570 source_usec
= fragsize_usec
/2;
574 /* Ok, the user didn't ask us to adjust the latency, hence we
577 source_usec
= (pa_usec_t
) -1;
580 if (source_usec
!= (pa_usec_t
) -1)
581 s
->configured_source_latency
= pa_source_output_set_requested_latency(s
->source_output
, source_usec
);
583 s
->configured_source_latency
= 0;
585 if (s
->early_requests
) {
587 /* Ok, we didn't necessarily get what we were asking for, so
588 * let's tell the user */
590 fragsize_usec
= s
->configured_source_latency
;
592 } else if (s
->adjust_latency
) {
594 /* Now subtract what we actually got */
596 if (fragsize_usec
>= s
->configured_source_latency
*2)
597 fragsize_usec
-= s
->configured_source_latency
;
599 fragsize_usec
= s
->configured_source_latency
;
602 if (pa_usec_to_bytes(orig_fragsize_usec
, &s
->source_output
->sample_spec
) !=
603 pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
))
605 s
->buffer_attr
.fragsize
= (uint32_t) pa_usec_to_bytes(fragsize_usec
, &s
->source_output
->sample_spec
);
607 if (s
->buffer_attr
.fragsize
<= 0)
608 s
->buffer_attr
.fragsize
= (uint32_t) frame_size
;
611 /* Called from main context */
612 static void fix_record_buffer_attr_post(record_stream
*s
) {
617 /* This function will be called from the main thread, before as
618 * well as after the source output has been activated using
619 * pa_source_output_put()! That means it may not touch and
620 * ->thread_info data! */
622 base
= pa_frame_size(&s
->source_output
->sample_spec
);
624 s
->buffer_attr
.fragsize
= (s
->buffer_attr
.fragsize
/base
)*base
;
625 if (s
->buffer_attr
.fragsize
<= 0)
626 s
->buffer_attr
.fragsize
= base
;
628 if (s
->buffer_attr
.fragsize
> s
->buffer_attr
.maxlength
)
629 s
->buffer_attr
.fragsize
= s
->buffer_attr
.maxlength
;
632 /* Called from main context */
633 static record_stream
* record_stream_new(
634 pa_native_connection
*c
,
639 pa_buffer_attr
*attr
,
643 pa_source_output_flags_t flags
,
645 pa_bool_t adjust_latency
,
646 pa_bool_t early_requests
,
647 pa_bool_t relative_volume
,
648 pa_bool_t peak_detect
,
649 pa_sink_input
*direct_on_input
,
653 pa_source_output
*source_output
= NULL
;
654 pa_source_output_new_data data
;
655 char *memblockq_name
;
662 pa_source_output_new_data_init(&data
);
664 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
665 data
.driver
= __FILE__
;
666 data
.module
= c
->options
->module
;
667 data
.client
= c
->client
;
669 pa_source_output_new_data_set_source(&data
, source
, FALSE
);
670 if (pa_sample_spec_valid(ss
))
671 pa_source_output_new_data_set_sample_spec(&data
, ss
);
672 if (pa_channel_map_valid(map
))
673 pa_source_output_new_data_set_channel_map(&data
, map
);
675 pa_source_output_new_data_set_formats(&data
, formats
);
676 data
.direct_on_input
= direct_on_input
;
678 pa_source_output_new_data_set_volume(&data
, volume
);
679 data
.volume_is_absolute
= !relative_volume
;
680 data
.save_volume
= FALSE
;
683 pa_source_output_new_data_set_muted(&data
, muted
);
684 data
.save_muted
= FALSE
;
687 data
.resample_method
= PA_RESAMPLER_PEAKS
;
690 *ret
= -pa_source_output_new(&source_output
, c
->protocol
->core
, &data
);
692 pa_source_output_new_data_done(&data
);
697 s
= pa_msgobject_new(record_stream
);
698 s
->parent
.parent
.free
= record_stream_free
;
699 s
->parent
.process_msg
= record_stream_process_msg
;
701 s
->source_output
= source_output
;
702 s
->buffer_attr_req
= *attr
;
703 s
->adjust_latency
= adjust_latency
;
704 s
->early_requests
= early_requests
;
705 pa_atomic_store(&s
->on_the_fly
, 0);
707 s
->source_output
->parent
.process_msg
= source_output_process_msg
;
708 s
->source_output
->push
= source_output_push_cb
;
709 s
->source_output
->kill
= source_output_kill_cb
;
710 s
->source_output
->get_latency
= source_output_get_latency_cb
;
711 s
->source_output
->moving
= source_output_moving_cb
;
712 s
->source_output
->suspend
= source_output_suspend_cb
;
713 s
->source_output
->send_event
= source_output_send_event_cb
;
714 s
->source_output
->userdata
= s
;
716 fix_record_buffer_attr_pre(s
);
718 memblockq_name
= pa_sprintf_malloc("native protocol record stream memblockq [%u]", s
->source_output
->index
);
719 s
->memblockq
= pa_memblockq_new(
722 s
->buffer_attr
.maxlength
,
724 &source_output
->sample_spec
,
729 pa_xfree(memblockq_name
);
731 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
732 fix_record_buffer_attr_post(s
);
734 *ss
= s
->source_output
->sample_spec
;
735 *map
= s
->source_output
->channel_map
;
737 pa_idxset_put(c
->record_streams
, s
, &s
->index
);
739 pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
740 ((double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) + (double) s
->configured_source_latency
) / PA_USEC_PER_MSEC
,
741 (double) pa_bytes_to_usec(s
->buffer_attr
.fragsize
, &source_output
->sample_spec
) / PA_USEC_PER_MSEC
,
742 (double) s
->configured_source_latency
/ PA_USEC_PER_MSEC
);
744 pa_source_output_put(s
->source_output
);
748 /* Called from main context */
749 static void record_stream_send_killed(record_stream
*r
) {
751 record_stream_assert_ref(r
);
753 t
= pa_tagstruct_new(NULL
, 0);
754 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_KILLED
);
755 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
756 pa_tagstruct_putu32(t
, r
->index
);
757 pa_pstream_send_tagstruct(r
->connection
->pstream
, t
);
760 /* Called from main context */
761 static void playback_stream_unlink(playback_stream
*s
) {
768 pa_sink_input_unlink(s
->sink_input
);
769 pa_sink_input_unref(s
->sink_input
);
770 s
->sink_input
= NULL
;
773 if (s
->drain_request
)
774 pa_pstream_send_error(s
->connection
->pstream
, s
->drain_tag
, PA_ERR_NOENTITY
);
776 pa_assert_se(pa_idxset_remove_by_data(s
->connection
->output_streams
, s
, NULL
) == s
);
777 s
->connection
= NULL
;
778 playback_stream_unref(s
);
781 /* Called from main context */
782 static void playback_stream_free(pa_object
* o
) {
783 playback_stream
*s
= PLAYBACK_STREAM(o
);
786 playback_stream_unlink(s
);
788 pa_memblockq_free(s
->memblockq
);
792 /* Called from main context */
793 static int playback_stream_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
794 playback_stream
*s
= PLAYBACK_STREAM(o
);
795 playback_stream_assert_ref(s
);
802 case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
: {
807 if ((l
= pa_atomic_load(&s
->missing
)) <= 0)
810 if (pa_atomic_cmpxchg(&s
->missing
, l
, 0))
814 t
= pa_tagstruct_new(NULL
, 0);
815 pa_tagstruct_putu32(t
, PA_COMMAND_REQUEST
);
816 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
817 pa_tagstruct_putu32(t
, s
->index
);
818 pa_tagstruct_putu32(t
, (uint32_t) l
);
819 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
821 #ifdef PROTOCOL_NATIVE_DEBUG
822 pa_log("Requesting %lu bytes", (unsigned long) l
);
827 case PLAYBACK_STREAM_MESSAGE_UNDERFLOW
: {
830 #ifdef PROTOCOL_NATIVE_DEBUG
831 pa_log("signalling underflow");
834 /* Report that we're empty */
835 t
= pa_tagstruct_new(NULL
, 0);
836 pa_tagstruct_putu32(t
, PA_COMMAND_UNDERFLOW
);
837 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
838 pa_tagstruct_putu32(t
, s
->index
);
839 if (s
->connection
->version
>= 23)
840 pa_tagstruct_puts64(t
, offset
);
841 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
845 case PLAYBACK_STREAM_MESSAGE_OVERFLOW
: {
848 /* Notify the user we're overflowed*/
849 t
= pa_tagstruct_new(NULL
, 0);
850 pa_tagstruct_putu32(t
, PA_COMMAND_OVERFLOW
);
851 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
852 pa_tagstruct_putu32(t
, s
->index
);
853 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
857 case PLAYBACK_STREAM_MESSAGE_STARTED
:
859 if (s
->connection
->version
>= 13) {
862 /* Notify the user we started playback */
863 t
= pa_tagstruct_new(NULL
, 0);
864 pa_tagstruct_putu32(t
, PA_COMMAND_STARTED
);
865 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
866 pa_tagstruct_putu32(t
, s
->index
);
867 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
872 case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
:
873 pa_pstream_send_simple_ack(s
->connection
->pstream
, PA_PTR_TO_UINT(userdata
));
876 case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
:
878 s
->buffer_attr
.tlength
= (uint32_t) offset
;
880 if (s
->connection
->version
>= 15) {
883 t
= pa_tagstruct_new(NULL
, 0);
884 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED
);
885 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
886 pa_tagstruct_putu32(t
, s
->index
);
887 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
888 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
889 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
890 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
891 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
892 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
901 /* Called from main context */
902 static void fix_playback_buffer_attr(playback_stream
*s
) {
903 size_t frame_size
, max_prebuf
;
904 pa_usec_t orig_tlength_usec
, tlength_usec
, orig_minreq_usec
, minreq_usec
, sink_usec
;
908 #ifdef PROTOCOL_NATIVE_DEBUG
909 pa_log("Client requested: maxlength=%li bytes tlength=%li bytes minreq=%li bytes prebuf=%li bytes",
910 (long) s
->buffer_attr_req
.maxlength
,
911 (long) s
->buffer_attr_req
.tlength
,
912 (long) s
->buffer_attr_req
.minreq
,
913 (long) s
->buffer_attr_req
.prebuf
);
915 pa_log("Client requested: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
916 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.maxlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
917 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.tlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
918 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.minreq
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
919 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr_req
.prebuf
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
));
922 /* This function will be called from the main thread, before as
923 * well as after the sink input has been activated using
924 * pa_sink_input_put()! That means it may not touch any
925 * ->thread_info data, such as the memblockq! */
927 frame_size
= pa_frame_size(&s
->sink_input
->sample_spec
);
928 s
->buffer_attr
= s
->buffer_attr_req
;
930 if (s
->buffer_attr
.maxlength
== (uint32_t) -1 || s
->buffer_attr
.maxlength
> MAX_MEMBLOCKQ_LENGTH
)
931 s
->buffer_attr
.maxlength
= MAX_MEMBLOCKQ_LENGTH
;
932 if (s
->buffer_attr
.maxlength
<= 0)
933 s
->buffer_attr
.maxlength
= (uint32_t) frame_size
;
935 if (s
->buffer_attr
.tlength
== (uint32_t) -1)
936 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
937 if (s
->buffer_attr
.tlength
<= 0)
938 s
->buffer_attr
.tlength
= (uint32_t) frame_size
;
939 if (s
->buffer_attr
.tlength
> s
->buffer_attr
.maxlength
)
940 s
->buffer_attr
.tlength
= s
->buffer_attr
.maxlength
;
942 if (s
->buffer_attr
.minreq
== (uint32_t) -1) {
943 uint32_t process
= (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC
*PA_USEC_PER_MSEC
, &s
->sink_input
->sample_spec
);
944 /* With low-latency, tlength/4 gives a decent default in all of traditional, adjust latency and early request modes. */
945 uint32_t m
= s
->buffer_attr
.tlength
/ 4;
948 s
->buffer_attr
.minreq
= PA_MIN(process
, m
);
950 if (s
->buffer_attr
.minreq
<= 0)
951 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
953 if (s
->buffer_attr
.tlength
< s
->buffer_attr
.minreq
+frame_size
)
954 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
+(uint32_t) frame_size
;
956 orig_tlength_usec
= tlength_usec
= pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
);
957 orig_minreq_usec
= minreq_usec
= pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
);
959 pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
960 (double) tlength_usec
/ PA_USEC_PER_MSEC
,
961 (double) minreq_usec
/ PA_USEC_PER_MSEC
);
963 if (s
->early_requests
) {
965 /* In early request mode we need to emulate the classic
966 * fragment-based playback model. We do this setting the sink
967 * latency to the fragment size. */
969 sink_usec
= minreq_usec
;
970 pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
972 } else if (s
->adjust_latency
) {
974 /* So, the user asked us to adjust the latency of the stream
975 * buffer according to the what the sink can provide. The
976 * tlength passed in shall be the overall latency. Roughly
977 * half the latency will be spent on the hw buffer, the other
978 * half of it in the async buffer queue we maintain for each
979 * client. In between we'll have a safety space of size
980 * 2*minreq. Why the 2*minreq? When the hw buffer is completely
981 * empty and needs to be filled, then our buffer must have
982 * enough data to fulfill this request immediately and thus
983 * have at least the same tlength as the size of the hw
984 * buffer. It additionally needs space for 2 times minreq
985 * because if the buffer ran empty and a partial fillup
986 * happens immediately on the next iteration we need to be
987 * able to fulfill it and give the application also minreq
988 * time to fill it up again for the next request Makes 2 times
989 * minreq in plus.. */
991 if (tlength_usec
> minreq_usec
*2)
992 sink_usec
= (tlength_usec
- minreq_usec
*2)/2;
996 pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
1000 /* Ok, the user didn't ask us to adjust the latency, but we
1001 * still need to make sure that the parameters from the user
1004 if (tlength_usec
> minreq_usec
*2)
1005 sink_usec
= (tlength_usec
- minreq_usec
*2);
1009 pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
1012 s
->configured_sink_latency
= pa_sink_input_set_requested_latency(s
->sink_input
, sink_usec
);
1014 if (s
->early_requests
) {
1016 /* Ok, we didn't necessarily get what we were asking for, so
1017 * let's tell the user */
1019 minreq_usec
= s
->configured_sink_latency
;
1021 } else if (s
->adjust_latency
) {
1023 /* Ok, we didn't necessarily get what we were asking for, so
1024 * let's subtract from what we asked for for the remaining
1027 if (tlength_usec
>= s
->configured_sink_latency
)
1028 tlength_usec
-= s
->configured_sink_latency
;
1031 pa_log_debug("Requested latency=%0.2f ms, Received latency=%0.2f ms",
1032 (double) sink_usec
/ PA_USEC_PER_MSEC
,
1033 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1035 /* FIXME: This is actually larger than necessary, since not all of
1036 * the sink latency is actually rewritable. */
1037 if (tlength_usec
< s
->configured_sink_latency
+ 2*minreq_usec
)
1038 tlength_usec
= s
->configured_sink_latency
+ 2*minreq_usec
;
1040 if (pa_usec_to_bytes_round_up(orig_tlength_usec
, &s
->sink_input
->sample_spec
) !=
1041 pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
))
1042 s
->buffer_attr
.tlength
= (uint32_t) pa_usec_to_bytes_round_up(tlength_usec
, &s
->sink_input
->sample_spec
);
1044 if (pa_usec_to_bytes(orig_minreq_usec
, &s
->sink_input
->sample_spec
) !=
1045 pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
))
1046 s
->buffer_attr
.minreq
= (uint32_t) pa_usec_to_bytes(minreq_usec
, &s
->sink_input
->sample_spec
);
1048 if (s
->buffer_attr
.minreq
<= 0) {
1049 s
->buffer_attr
.minreq
= (uint32_t) frame_size
;
1050 s
->buffer_attr
.tlength
+= (uint32_t) frame_size
*2;
1053 if (s
->buffer_attr
.tlength
<= s
->buffer_attr
.minreq
)
1054 s
->buffer_attr
.tlength
= s
->buffer_attr
.minreq
*2 + (uint32_t) frame_size
;
1056 max_prebuf
= s
->buffer_attr
.tlength
+ (uint32_t)frame_size
- s
->buffer_attr
.minreq
;
1058 if (s
->buffer_attr
.prebuf
== (uint32_t) -1 ||
1059 s
->buffer_attr
.prebuf
> max_prebuf
)
1060 s
->buffer_attr
.prebuf
= max_prebuf
;
1062 #ifdef PROTOCOL_NATIVE_DEBUG
1063 pa_log("Client accepted: maxlength=%lu ms tlength=%lu ms minreq=%lu ms prebuf=%lu ms",
1064 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.maxlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1065 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.tlength
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1066 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.minreq
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
),
1067 (unsigned long) (pa_bytes_to_usec(s
->buffer_attr
.prebuf
, &s
->sink_input
->sample_spec
) / PA_USEC_PER_MSEC
));
1071 /* Called from main context */
1072 static playback_stream
* playback_stream_new(
1073 pa_native_connection
*c
,
1076 pa_channel_map
*map
,
1081 pa_bool_t muted_set
,
1082 pa_sink_input_flags_t flags
,
1084 pa_bool_t adjust_latency
,
1085 pa_bool_t early_requests
,
1086 pa_bool_t relative_volume
,
1091 /* Note: This function takes ownership of the 'formats' param, so we need
1092 * to take extra care to not leak it */
1094 playback_stream
*ssync
;
1095 playback_stream
*s
= NULL
;
1096 pa_sink_input
*sink_input
= NULL
;
1097 pa_memchunk silence
;
1099 int64_t start_index
;
1100 pa_sink_input_new_data data
;
1101 char *memblockq_name
;
1109 /* Find syncid group */
1110 PA_IDXSET_FOREACH(ssync
, c
->output_streams
, idx
) {
1112 if (!playback_stream_isinstance(ssync
))
1115 if (ssync
->syncid
== syncid
)
1119 /* Synced streams must connect to the same sink */
1123 sink
= ssync
->sink_input
->sink
;
1124 else if (sink
!= ssync
->sink_input
->sink
) {
1125 *ret
= PA_ERR_INVALID
;
1130 pa_sink_input_new_data_init(&data
);
1132 pa_proplist_update(data
.proplist
, PA_UPDATE_REPLACE
, p
);
1133 data
.driver
= __FILE__
;
1134 data
.module
= c
->options
->module
;
1135 data
.client
= c
->client
;
1137 pa_sink_input_new_data_set_sink(&data
, sink
, FALSE
);
1138 if (pa_sample_spec_valid(ss
))
1139 pa_sink_input_new_data_set_sample_spec(&data
, ss
);
1140 if (pa_channel_map_valid(map
))
1141 pa_sink_input_new_data_set_channel_map(&data
, map
);
1143 pa_sink_input_new_data_set_formats(&data
, formats
);
1144 /* Ownership transferred to new_data, so we don't free it ourselves */
1148 pa_sink_input_new_data_set_volume(&data
, volume
);
1149 data
.volume_is_absolute
= !relative_volume
;
1150 data
.save_volume
= FALSE
;
1153 pa_sink_input_new_data_set_muted(&data
, muted
);
1154 data
.save_muted
= FALSE
;
1156 data
.sync_base
= ssync
? ssync
->sink_input
: NULL
;
1159 *ret
= -pa_sink_input_new(&sink_input
, c
->protocol
->core
, &data
);
1161 pa_sink_input_new_data_done(&data
);
1166 s
= pa_msgobject_new(playback_stream
);
1167 s
->parent
.parent
.parent
.free
= playback_stream_free
;
1168 s
->parent
.parent
.process_msg
= playback_stream_process_msg
;
1171 s
->sink_input
= sink_input
;
1172 s
->is_underrun
= TRUE
;
1173 s
->drain_request
= FALSE
;
1174 pa_atomic_store(&s
->missing
, 0);
1175 s
->buffer_attr_req
= *a
;
1176 s
->adjust_latency
= adjust_latency
;
1177 s
->early_requests
= early_requests
;
1178 pa_atomic_store(&s
->seek_or_post_in_queue
, 0);
1179 s
->seek_windex
= -1;
1181 s
->sink_input
->parent
.process_msg
= sink_input_process_msg
;
1182 s
->sink_input
->pop
= sink_input_pop_cb
;
1183 s
->sink_input
->process_underrun
= sink_input_process_underrun_cb
;
1184 s
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1185 s
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1186 s
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1187 s
->sink_input
->kill
= sink_input_kill_cb
;
1188 s
->sink_input
->moving
= sink_input_moving_cb
;
1189 s
->sink_input
->suspend
= sink_input_suspend_cb
;
1190 s
->sink_input
->send_event
= sink_input_send_event_cb
;
1191 s
->sink_input
->userdata
= s
;
1193 start_index
= ssync
? pa_memblockq_get_read_index(ssync
->memblockq
) : 0;
1195 fix_playback_buffer_attr(s
);
1197 pa_sink_input_get_silence(sink_input
, &silence
);
1198 memblockq_name
= pa_sprintf_malloc("native protocol playback stream memblockq [%u]", s
->sink_input
->index
);
1199 s
->memblockq
= pa_memblockq_new(
1202 s
->buffer_attr
.maxlength
,
1203 s
->buffer_attr
.tlength
,
1204 &sink_input
->sample_spec
,
1205 s
->buffer_attr
.prebuf
,
1206 s
->buffer_attr
.minreq
,
1209 pa_xfree(memblockq_name
);
1210 pa_memblock_unref(silence
.memblock
);
1212 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1214 *missing
= (uint32_t) pa_memblockq_pop_missing(s
->memblockq
);
1216 #ifdef PROTOCOL_NATIVE_DEBUG
1217 pa_log("missing original: %li", (long int) *missing
);
1220 *ss
= s
->sink_input
->sample_spec
;
1221 *map
= s
->sink_input
->channel_map
;
1223 pa_idxset_put(c
->output_streams
, s
, &s
->index
);
1225 pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1226 ((double) pa_bytes_to_usec(s
->buffer_attr
.tlength
, &sink_input
->sample_spec
) + (double) s
->configured_sink_latency
) / PA_USEC_PER_MSEC
,
1227 (double) pa_bytes_to_usec(s
->buffer_attr
.tlength
-s
->buffer_attr
.minreq
*2, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1228 (double) pa_bytes_to_usec(s
->buffer_attr
.minreq
, &sink_input
->sample_spec
) / PA_USEC_PER_MSEC
,
1229 (double) s
->configured_sink_latency
/ PA_USEC_PER_MSEC
);
1231 pa_sink_input_put(s
->sink_input
);
1235 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
1240 /* Called from IO context */
1241 static void playback_stream_request_bytes(playback_stream
*s
) {
1243 int previous_missing
;
1245 playback_stream_assert_ref(s
);
1247 m
= pa_memblockq_pop_missing(s
->memblockq
);
1249 /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
1250 /* (unsigned long) m, */
1251 /* pa_memblockq_get_tlength(s->memblockq), */
1252 /* pa_memblockq_get_minreq(s->memblockq), */
1253 /* pa_memblockq_get_length(s->memblockq), */
1254 /* (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
1259 #ifdef PROTOCOL_NATIVE_DEBUG
1260 pa_log("request_bytes(%lu)", (unsigned long) m
);
1263 previous_missing
= pa_atomic_add(&s
->missing
, (int) m
);
1264 minreq
= pa_memblockq_get_minreq(s
->memblockq
);
1266 if (pa_memblockq_prebuf_active(s
->memblockq
) ||
1267 (previous_missing
< (int) minreq
&& previous_missing
+ (int) m
>= (int) minreq
))
1268 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA
, NULL
, 0, NULL
, NULL
);
1271 /* Called from main context */
1272 static void playback_stream_send_killed(playback_stream
*p
) {
1274 playback_stream_assert_ref(p
);
1276 t
= pa_tagstruct_new(NULL
, 0);
1277 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_KILLED
);
1278 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1279 pa_tagstruct_putu32(t
, p
->index
);
1280 pa_pstream_send_tagstruct(p
->connection
->pstream
, t
);
1283 /* Called from main context */
1284 static int native_connection_process_msg(pa_msgobject
*o
, int code
, void*userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1285 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1286 pa_native_connection_assert_ref(c
);
1293 case CONNECTION_MESSAGE_REVOKE
:
1294 pa_pstream_send_revoke(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1297 case CONNECTION_MESSAGE_RELEASE
:
1298 pa_pstream_send_release(c
->pstream
, PA_PTR_TO_UINT(userdata
));
1305 /* Called from main context */
1306 static void native_connection_unlink(pa_native_connection
*c
) {
1315 pa_hook_fire(&c
->protocol
->hooks
[PA_NATIVE_HOOK_CONNECTION_UNLINK
], c
);
1318 pa_native_options_unref(c
->options
);
1320 while ((r
= pa_idxset_first(c
->record_streams
, NULL
)))
1321 record_stream_unlink(r
);
1323 while ((o
= pa_idxset_first(c
->output_streams
, NULL
)))
1324 if (playback_stream_isinstance(o
))
1325 playback_stream_unlink(PLAYBACK_STREAM(o
));
1327 upload_stream_unlink(UPLOAD_STREAM(o
));
1329 if (c
->subscription
)
1330 pa_subscription_free(c
->subscription
);
1333 pa_pstream_unlink(c
->pstream
);
1335 if (c
->auth_timeout_event
) {
1336 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
1337 c
->auth_timeout_event
= NULL
;
1340 pa_assert_se(pa_idxset_remove_by_data(c
->protocol
->connections
, c
, NULL
) == c
);
1342 pa_native_connection_unref(c
);
1345 /* Called from main context */
1346 static void native_connection_free(pa_object
*o
) {
1347 pa_native_connection
*c
= PA_NATIVE_CONNECTION(o
);
1351 native_connection_unlink(c
);
1353 pa_idxset_free(c
->record_streams
, NULL
);
1354 pa_idxset_free(c
->output_streams
, NULL
);
1356 pa_pdispatch_unref(c
->pdispatch
);
1357 pa_pstream_unref(c
->pstream
);
1358 pa_client_free(c
->client
);
1363 /* Called from main context */
1364 static void native_connection_send_memblock(pa_native_connection
*c
) {
1368 start
= PA_IDXSET_INVALID
;
1372 if (!(r
= RECORD_STREAM(pa_idxset_rrobin(c
->record_streams
, &c
->rrobin_index
))))
1375 if (start
== PA_IDXSET_INVALID
)
1376 start
= c
->rrobin_index
;
1377 else if (start
== c
->rrobin_index
)
1380 if (pa_memblockq_peek(r
->memblockq
, &chunk
) >= 0) {
1381 pa_memchunk schunk
= chunk
;
1383 if (schunk
.length
> r
->buffer_attr
.fragsize
)
1384 schunk
.length
= r
->buffer_attr
.fragsize
;
1386 pa_pstream_send_memblock(c
->pstream
, r
->index
, 0, PA_SEEK_RELATIVE
, &schunk
);
1388 pa_memblockq_drop(r
->memblockq
, schunk
.length
);
1389 pa_memblock_unref(schunk
.memblock
);
1396 /*** sink input callbacks ***/
1398 /* Called from thread context */
1399 static void handle_seek(playback_stream
*s
, int64_t indexw
) {
1400 playback_stream_assert_ref(s
);
1402 /* pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1404 if (s
->sink_input
->thread_info
.underrun_for
> 0) {
1406 /* pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1408 if (pa_memblockq_is_readable(s
->memblockq
)) {
1410 /* We just ended an underrun, let's ask the sink
1411 * for a complete rewind rewrite */
1413 pa_log_debug("Requesting rewind due to end of underrun.");
1414 pa_sink_input_request_rewind(s
->sink_input
,
1415 (size_t) (s
->sink_input
->thread_info
.underrun_for
== (uint64_t) -1 ? 0 :
1416 s
->sink_input
->thread_info
.underrun_for
),
1417 FALSE
, TRUE
, FALSE
);
1423 indexr
= pa_memblockq_get_read_index(s
->memblockq
);
1425 if (indexw
< indexr
) {
1426 /* OK, the sink already asked for this data, so
1427 * let's have it ask us again */
1429 pa_log_debug("Requesting rewind due to rewrite.");
1430 pa_sink_input_request_rewind(s
->sink_input
, (size_t) (indexr
- indexw
), TRUE
, FALSE
, FALSE
);
1434 playback_stream_request_bytes(s
);
1437 static void flush_write_no_account(pa_memblockq
*q
) {
1438 pa_memblockq_flush_write(q
, FALSE
);
1441 /* Called from thread context */
1442 static int sink_input_process_msg(pa_msgobject
*o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1443 pa_sink_input
*i
= PA_SINK_INPUT(o
);
1446 pa_sink_input_assert_ref(i
);
1447 s
= PLAYBACK_STREAM(i
->userdata
);
1448 playback_stream_assert_ref(s
);
1452 case SINK_INPUT_MESSAGE_SEEK
:
1453 case SINK_INPUT_MESSAGE_POST_DATA
: {
1454 int64_t windex
= pa_memblockq_get_write_index(s
->memblockq
);
1456 if (code
== SINK_INPUT_MESSAGE_SEEK
) {
1457 /* The client side is incapable of accounting correctly
1458 * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1459 * able to deal with that. */
1461 pa_memblockq_seek(s
->memblockq
, offset
, PA_PTR_TO_UINT(userdata
), PA_PTR_TO_UINT(userdata
) == PA_SEEK_RELATIVE
);
1462 windex
= PA_MIN(windex
, pa_memblockq_get_write_index(s
->memblockq
));
1465 if (chunk
&& pa_memblockq_push_align(s
->memblockq
, chunk
) < 0) {
1466 if (pa_log_ratelimit(PA_LOG_WARN
))
1467 pa_log_warn("Failed to push data into queue");
1468 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_OVERFLOW
, NULL
, 0, NULL
, NULL
);
1469 pa_memblockq_seek(s
->memblockq
, (int64_t) chunk
->length
, PA_SEEK_RELATIVE
, TRUE
);
1472 /* If more data is in queue, we rewind later instead. */
1473 if (s
->seek_windex
!= -1)
1474 windex
= PA_MIN(windex
, s
->seek_windex
);
1475 if (pa_atomic_dec(&s
->seek_or_post_in_queue
) > 1)
1476 s
->seek_windex
= windex
;
1478 s
->seek_windex
= -1;
1479 handle_seek(s
, windex
);
1484 case SINK_INPUT_MESSAGE_DRAIN
:
1485 case SINK_INPUT_MESSAGE_FLUSH
:
1486 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1487 case SINK_INPUT_MESSAGE_TRIGGER
: {
1490 pa_sink_input
*isync
;
1491 void (*func
)(pa_memblockq
*bq
);
1494 case SINK_INPUT_MESSAGE_FLUSH
:
1495 func
= flush_write_no_account
;
1498 case SINK_INPUT_MESSAGE_PREBUF_FORCE
:
1499 func
= pa_memblockq_prebuf_force
;
1502 case SINK_INPUT_MESSAGE_DRAIN
:
1503 case SINK_INPUT_MESSAGE_TRIGGER
:
1504 func
= pa_memblockq_prebuf_disable
;
1508 pa_assert_not_reached();
1511 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1513 handle_seek(s
, windex
);
1515 /* Do the same for all other members in the sync group */
1516 for (isync
= i
->sync_prev
; isync
; isync
= isync
->sync_prev
) {
1517 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1518 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1519 func(ssync
->memblockq
);
1520 handle_seek(ssync
, windex
);
1523 for (isync
= i
->sync_next
; isync
; isync
= isync
->sync_next
) {
1524 playback_stream
*ssync
= PLAYBACK_STREAM(isync
->userdata
);
1525 windex
= pa_memblockq_get_write_index(ssync
->memblockq
);
1526 func(ssync
->memblockq
);
1527 handle_seek(ssync
, windex
);
1530 if (code
== SINK_INPUT_MESSAGE_DRAIN
) {
1531 if (!pa_memblockq_is_readable(s
->memblockq
))
1532 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK
, userdata
, 0, NULL
, NULL
);
1534 s
->drain_tag
= PA_PTR_TO_UINT(userdata
);
1535 s
->drain_request
= TRUE
;
1542 case SINK_INPUT_MESSAGE_UPDATE_LATENCY
:
1543 /* Atomically get a snapshot of all timing parameters... */
1544 s
->read_index
= pa_memblockq_get_read_index(s
->memblockq
);
1545 s
->write_index
= pa_memblockq_get_write_index(s
->memblockq
);
1546 s
->render_memblockq_length
= pa_memblockq_get_length(s
->sink_input
->thread_info
.render_memblockq
);
1547 s
->current_sink_latency
= pa_sink_get_latency_within_thread(s
->sink_input
->sink
);
1548 s
->underrun_for
= s
->sink_input
->thread_info
.underrun_for
;
1549 s
->playing_for
= s
->sink_input
->thread_info
.playing_for
;
1553 case PA_SINK_INPUT_MESSAGE_SET_STATE
: {
1556 windex
= pa_memblockq_get_write_index(s
->memblockq
);
1558 pa_memblockq_prebuf_force(s
->memblockq
);
1560 handle_seek(s
, windex
);
1562 /* Fall through to the default handler */
1566 case PA_SINK_INPUT_MESSAGE_GET_LATENCY
: {
1567 pa_usec_t
*r
= userdata
;
1569 *r
= pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &i
->sample_spec
);
1571 /* Fall through, the default handler will add in the extra
1572 * latency added by the resampler */
1576 case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
: {
1577 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1578 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1583 return pa_sink_input_process_msg(o
, code
, userdata
, offset
, chunk
);
1587 static bool handle_input_underrun(playback_stream
*s
, bool force
)
1591 if (pa_memblockq_is_readable(s
->memblockq
))
1594 if (!s
->is_underrun
)
1595 pa_log_debug("%s %s of '%s'", force
? "Actual" : "Implicit",
1596 s
->drain_request
? "drain" : "underrun", pa_strnull(pa_proplist_gets(s
->sink_input
->proplist
, PA_PROP_MEDIA_NAME
)));
1598 send_drain
= s
->drain_request
&& (force
|| pa_sink_input_safe_to_remove(s
->sink_input
));
1601 s
->drain_request
= false;
1602 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
);
1603 pa_log_debug("Drain acknowledged of '%s'", pa_strnull(pa_proplist_gets(s
->sink_input
->proplist
, PA_PROP_MEDIA_NAME
)));
1604 } else if (!s
->is_underrun
) {
1605 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
);
1607 s
->is_underrun
= true;
1608 playback_stream_request_bytes(s
);
1612 /* Called from thread context */
1613 static bool sink_input_process_underrun_cb(pa_sink_input
*i
) {
1616 pa_sink_input_assert_ref(i
);
1617 s
= PLAYBACK_STREAM(i
->userdata
);
1618 playback_stream_assert_ref(s
);
1620 return handle_input_underrun(s
, true);
1624 /* Called from thread context */
1625 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
1628 pa_sink_input_assert_ref(i
);
1629 s
= PLAYBACK_STREAM(i
->userdata
);
1630 playback_stream_assert_ref(s
);
1633 #ifdef PROTOCOL_NATIVE_DEBUG
1634 pa_log("%s, pop(): %lu", pa_proplist_gets(i
->proplist
, PA_PROP_MEDIA_NAME
), (unsigned long) pa_memblockq_get_length(s
->memblockq
));
1637 if (!handle_input_underrun(s
, false))
1638 s
->is_underrun
= false;
1640 /* This call will not fail with prebuf=0, hence we check for
1641 underrun explicitly in handle_input_underrun */
1642 if (pa_memblockq_peek(s
->memblockq
, chunk
) < 0)
1645 chunk
->length
= PA_MIN(nbytes
, chunk
->length
);
1647 if (i
->thread_info
.underrun_for
> 0)
1648 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), PLAYBACK_STREAM_MESSAGE_STARTED
, NULL
, 0, NULL
, NULL
);
1650 pa_memblockq_drop(s
->memblockq
, chunk
->length
);
1651 playback_stream_request_bytes(s
);
1656 /* Called from thread context */
1657 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1660 pa_sink_input_assert_ref(i
);
1661 s
= PLAYBACK_STREAM(i
->userdata
);
1662 playback_stream_assert_ref(s
);
1664 /* If we are in an underrun, then we don't rewind */
1665 if (i
->thread_info
.underrun_for
> 0)
1668 pa_memblockq_rewind(s
->memblockq
, nbytes
);
1671 /* Called from thread context */
1672 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
1675 pa_sink_input_assert_ref(i
);
1676 s
= PLAYBACK_STREAM(i
->userdata
);
1677 playback_stream_assert_ref(s
);
1679 pa_memblockq_set_maxrewind(s
->memblockq
, nbytes
);
1682 /* Called from thread context */
1683 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
1685 size_t new_tlength
, old_tlength
;
1687 pa_sink_input_assert_ref(i
);
1688 s
= PLAYBACK_STREAM(i
->userdata
);
1689 playback_stream_assert_ref(s
);
1691 old_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1692 new_tlength
= nbytes
+2*pa_memblockq_get_minreq(s
->memblockq
);
1694 if (old_tlength
< new_tlength
) {
1695 pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength
, new_tlength
);
1696 pa_memblockq_set_tlength(s
->memblockq
, new_tlength
);
1697 new_tlength
= pa_memblockq_get_tlength(s
->memblockq
);
1699 if (new_tlength
== old_tlength
)
1700 pa_log_debug("Failed to increase tlength");
1702 pa_log_debug("Notifying client about increased tlength");
1703 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
);
1708 /* Called from main context */
1709 static void sink_input_kill_cb(pa_sink_input
*i
) {
1712 pa_sink_input_assert_ref(i
);
1713 s
= PLAYBACK_STREAM(i
->userdata
);
1714 playback_stream_assert_ref(s
);
1716 playback_stream_send_killed(s
);
1717 playback_stream_unlink(s
);
1720 /* Called from main context */
1721 static void sink_input_send_event_cb(pa_sink_input
*i
, const char *event
, pa_proplist
*pl
) {
1725 pa_sink_input_assert_ref(i
);
1726 s
= PLAYBACK_STREAM(i
->userdata
);
1727 playback_stream_assert_ref(s
);
1729 if (s
->connection
->version
< 15)
1732 t
= pa_tagstruct_new(NULL
, 0);
1733 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_EVENT
);
1734 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1735 pa_tagstruct_putu32(t
, s
->index
);
1736 pa_tagstruct_puts(t
, event
);
1737 pa_tagstruct_put_proplist(t
, pl
);
1738 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1741 /* Called from main context */
1742 static void sink_input_suspend_cb(pa_sink_input
*i
, pa_bool_t suspend
) {
1746 pa_sink_input_assert_ref(i
);
1747 s
= PLAYBACK_STREAM(i
->userdata
);
1748 playback_stream_assert_ref(s
);
1750 if (s
->connection
->version
< 12)
1753 t
= pa_tagstruct_new(NULL
, 0);
1754 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED
);
1755 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1756 pa_tagstruct_putu32(t
, s
->index
);
1757 pa_tagstruct_put_boolean(t
, suspend
);
1758 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1761 /* Called from main context */
1762 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1766 pa_sink_input_assert_ref(i
);
1767 s
= PLAYBACK_STREAM(i
->userdata
);
1768 playback_stream_assert_ref(s
);
1773 fix_playback_buffer_attr(s
);
1774 pa_memblockq_apply_attr(s
->memblockq
, &s
->buffer_attr
);
1775 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1777 if (s
->connection
->version
< 12)
1780 t
= pa_tagstruct_new(NULL
, 0);
1781 pa_tagstruct_putu32(t
, PA_COMMAND_PLAYBACK_STREAM_MOVED
);
1782 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1783 pa_tagstruct_putu32(t
, s
->index
);
1784 pa_tagstruct_putu32(t
, dest
->index
);
1785 pa_tagstruct_puts(t
, dest
->name
);
1786 pa_tagstruct_put_boolean(t
, pa_sink_get_state(dest
) == PA_SINK_SUSPENDED
);
1788 if (s
->connection
->version
>= 13) {
1789 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1790 pa_tagstruct_putu32(t
, s
->buffer_attr
.tlength
);
1791 pa_tagstruct_putu32(t
, s
->buffer_attr
.prebuf
);
1792 pa_tagstruct_putu32(t
, s
->buffer_attr
.minreq
);
1793 pa_tagstruct_put_usec(t
, s
->configured_sink_latency
);
1796 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1799 /*** source_output callbacks ***/
1801 /* Called from thread context */
1802 static int source_output_process_msg(pa_msgobject
*_o
, int code
, void *userdata
, int64_t offset
, pa_memchunk
*chunk
) {
1803 pa_source_output
*o
= PA_SOURCE_OUTPUT(_o
);
1806 pa_source_output_assert_ref(o
);
1807 s
= RECORD_STREAM(o
->userdata
);
1808 record_stream_assert_ref(s
);
1811 case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY
:
1812 /* Atomically get a snapshot of all timing parameters... */
1813 s
->current_monitor_latency
= o
->source
->monitor_of
? pa_sink_get_latency_within_thread(o
->source
->monitor_of
) : 0;
1814 s
->current_source_latency
= pa_source_get_latency_within_thread(o
->source
);
1815 s
->on_the_fly_snapshot
= pa_atomic_load(&s
->on_the_fly
);
1819 return pa_source_output_process_msg(_o
, code
, userdata
, offset
, chunk
);
1822 /* Called from thread context */
1823 static void source_output_push_cb(pa_source_output
*o
, const pa_memchunk
*chunk
) {
1826 pa_source_output_assert_ref(o
);
1827 s
= RECORD_STREAM(o
->userdata
);
1828 record_stream_assert_ref(s
);
1831 pa_atomic_add(&s
->on_the_fly
, chunk
->length
);
1832 pa_asyncmsgq_post(pa_thread_mq_get()->outq
, PA_MSGOBJECT(s
), RECORD_STREAM_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
1835 static void source_output_kill_cb(pa_source_output
*o
) {
1838 pa_source_output_assert_ref(o
);
1839 s
= RECORD_STREAM(o
->userdata
);
1840 record_stream_assert_ref(s
);
1842 record_stream_send_killed(s
);
1843 record_stream_unlink(s
);
1846 static pa_usec_t
source_output_get_latency_cb(pa_source_output
*o
) {
1849 pa_source_output_assert_ref(o
);
1850 s
= RECORD_STREAM(o
->userdata
);
1851 record_stream_assert_ref(s
);
1853 /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1855 return pa_bytes_to_usec(pa_memblockq_get_length(s
->memblockq
), &o
->sample_spec
);
1858 /* Called from main context */
1859 static void source_output_send_event_cb(pa_source_output
*o
, const char *event
, pa_proplist
*pl
) {
1863 pa_source_output_assert_ref(o
);
1864 s
= RECORD_STREAM(o
->userdata
);
1865 record_stream_assert_ref(s
);
1867 if (s
->connection
->version
< 15)
1870 t
= pa_tagstruct_new(NULL
, 0);
1871 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_EVENT
);
1872 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1873 pa_tagstruct_putu32(t
, s
->index
);
1874 pa_tagstruct_puts(t
, event
);
1875 pa_tagstruct_put_proplist(t
, pl
);
1876 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1879 /* Called from main context */
1880 static void source_output_suspend_cb(pa_source_output
*o
, pa_bool_t suspend
) {
1884 pa_source_output_assert_ref(o
);
1885 s
= RECORD_STREAM(o
->userdata
);
1886 record_stream_assert_ref(s
);
1888 if (s
->connection
->version
< 12)
1891 t
= pa_tagstruct_new(NULL
, 0);
1892 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_SUSPENDED
);
1893 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1894 pa_tagstruct_putu32(t
, s
->index
);
1895 pa_tagstruct_put_boolean(t
, suspend
);
1896 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1899 /* Called from main context */
1900 static void source_output_moving_cb(pa_source_output
*o
, pa_source
*dest
) {
1904 pa_source_output_assert_ref(o
);
1905 s
= RECORD_STREAM(o
->userdata
);
1906 record_stream_assert_ref(s
);
1911 fix_record_buffer_attr_pre(s
);
1912 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
1913 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
1914 fix_record_buffer_attr_post(s
);
1916 if (s
->connection
->version
< 12)
1919 t
= pa_tagstruct_new(NULL
, 0);
1920 pa_tagstruct_putu32(t
, PA_COMMAND_RECORD_STREAM_MOVED
);
1921 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
1922 pa_tagstruct_putu32(t
, s
->index
);
1923 pa_tagstruct_putu32(t
, dest
->index
);
1924 pa_tagstruct_puts(t
, dest
->name
);
1925 pa_tagstruct_put_boolean(t
, pa_source_get_state(dest
) == PA_SOURCE_SUSPENDED
);
1927 if (s
->connection
->version
>= 13) {
1928 pa_tagstruct_putu32(t
, s
->buffer_attr
.maxlength
);
1929 pa_tagstruct_putu32(t
, s
->buffer_attr
.fragsize
);
1930 pa_tagstruct_put_usec(t
, s
->configured_source_latency
);
1933 pa_pstream_send_tagstruct(s
->connection
->pstream
, t
);
1936 /*** pdispatch callbacks ***/
1938 static void protocol_error(pa_native_connection
*c
) {
1939 pa_log("protocol error, kicking client");
1940 native_connection_unlink(c
);
1943 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1944 if (!(expression)) { \
1945 pa_pstream_send_error((pstream), (tag), (error)); \
1950 #define CHECK_VALIDITY_GOTO(pstream, expression, tag, error, label) do { \
1951 if (!(expression)) { \
1952 pa_pstream_send_error((pstream), (tag), (error)); \
1957 static pa_tagstruct
*reply_new(uint32_t tag
) {
1958 pa_tagstruct
*reply
;
1960 reply
= pa_tagstruct_new(NULL
, 0);
1961 pa_tagstruct_putu32(reply
, PA_COMMAND_REPLY
);
1962 pa_tagstruct_putu32(reply
, tag
);
1966 static void command_create_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
1967 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
1969 uint32_t sink_index
, syncid
, missing
= 0;
1970 pa_buffer_attr attr
;
1971 const char *name
= NULL
, *sink_name
;
1974 pa_tagstruct
*reply
;
1975 pa_sink
*sink
= NULL
;
1983 fix_channels
= FALSE
,
1985 variable_rate
= FALSE
,
1987 adjust_latency
= FALSE
,
1988 early_requests
= FALSE
,
1989 dont_inhibit_auto_suspend
= FALSE
,
1992 fail_on_suspend
= FALSE
,
1993 relative_volume
= FALSE
,
1994 passthrough
= FALSE
;
1996 pa_sink_input_flags_t flags
= 0;
1997 pa_proplist
*p
= NULL
;
1998 int ret
= PA_ERR_INVALID
;
1999 uint8_t n_formats
= 0;
2000 pa_format_info
*format
;
2001 pa_idxset
*formats
= NULL
;
2004 pa_native_connection_assert_ref(c
);
2006 memset(&attr
, 0, sizeof(attr
));
2008 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2011 PA_TAG_SAMPLE_SPEC
, &ss
,
2012 PA_TAG_CHANNEL_MAP
, &map
,
2013 PA_TAG_U32
, &sink_index
,
2014 PA_TAG_STRING
, &sink_name
,
2015 PA_TAG_U32
, &attr
.maxlength
,
2016 PA_TAG_BOOLEAN
, &corked
,
2017 PA_TAG_U32
, &attr
.tlength
,
2018 PA_TAG_U32
, &attr
.prebuf
,
2019 PA_TAG_U32
, &attr
.minreq
,
2020 PA_TAG_U32
, &syncid
,
2021 PA_TAG_CVOLUME
, &volume
,
2022 PA_TAG_INVALID
) < 0) {
2028 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
2029 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
, finish
);
2030 CHECK_VALIDITY_GOTO(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
, finish
);
2031 CHECK_VALIDITY_GOTO(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
2032 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
2034 p
= pa_proplist_new();
2037 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2039 if (c
->version
>= 12) {
2040 /* Since 0.9.8 the user can ask for a couple of additional flags */
2042 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2043 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2044 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2045 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2046 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2047 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2048 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2055 if (c
->version
>= 13) {
2057 if (pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
2058 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2059 pa_tagstruct_get_proplist(t
, p
) < 0) {
2066 if (c
->version
>= 14) {
2068 if (pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
2069 pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2076 if (c
->version
>= 15) {
2078 if (pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
2079 pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2080 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2087 if (c
->version
>= 17) {
2089 if (pa_tagstruct_get_boolean(t
, &relative_volume
) < 0) {
2096 if (c
->version
>= 18) {
2098 if (pa_tagstruct_get_boolean(t
, &passthrough
) < 0 ) {
2104 if (c
->version
>= 21) {
2106 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2112 formats
= pa_idxset_new(NULL
, NULL
);
2114 for (i
= 0; i
< n_formats
; i
++) {
2115 format
= pa_format_info_new();
2116 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2120 pa_idxset_put(formats
, format
, NULL
);
2124 if (n_formats
== 0) {
2125 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2126 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
&& volume
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2127 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2129 PA_IDXSET_FOREACH(format
, formats
, i
) {
2130 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2134 if (!pa_tagstruct_eof(t
)) {
2139 if (sink_index
!= PA_INVALID_INDEX
) {
2141 if (!(sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
))) {
2142 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2146 } else if (sink_name
) {
2148 if (!(sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
))) {
2149 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2155 (corked
? PA_SINK_INPUT_START_CORKED
: 0) |
2156 (no_remap
? PA_SINK_INPUT_NO_REMAP
: 0) |
2157 (no_remix
? PA_SINK_INPUT_NO_REMIX
: 0) |
2158 (fix_format
? PA_SINK_INPUT_FIX_FORMAT
: 0) |
2159 (fix_rate
? PA_SINK_INPUT_FIX_RATE
: 0) |
2160 (fix_channels
? PA_SINK_INPUT_FIX_CHANNELS
: 0) |
2161 (no_move
? PA_SINK_INPUT_DONT_MOVE
: 0) |
2162 (variable_rate
? PA_SINK_INPUT_VARIABLE_RATE
: 0) |
2163 (dont_inhibit_auto_suspend
? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2164 (fail_on_suspend
? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND
|PA_SINK_INPUT_KILL_ON_SUSPEND
: 0) |
2165 (passthrough
? PA_SINK_INPUT_PASSTHROUGH
: 0);
2167 /* Only since protocol version 15 there's a separate muted_set
2168 * flag. For older versions we synthesize it here */
2169 muted_set
= muted_set
|| muted
;
2171 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
);
2172 /* We no longer own the formats idxset */
2175 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2177 reply
= reply_new(tag
);
2178 pa_tagstruct_putu32(reply
, s
->index
);
2179 pa_assert(s
->sink_input
);
2180 pa_tagstruct_putu32(reply
, s
->sink_input
->index
);
2181 pa_tagstruct_putu32(reply
, missing
);
2183 #ifdef PROTOCOL_NATIVE_DEBUG
2184 pa_log("initial request is %u", missing
);
2187 if (c
->version
>= 9) {
2188 /* Since 0.9.0 we support sending the buffer metrics back to the client */
2190 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2191 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.tlength
);
2192 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.prebuf
);
2193 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.minreq
);
2196 if (c
->version
>= 12) {
2197 /* Since 0.9.8 we support sending the chosen sample
2198 * spec/channel map/device/suspend status back to the
2201 pa_tagstruct_put_sample_spec(reply
, &ss
);
2202 pa_tagstruct_put_channel_map(reply
, &map
);
2204 pa_tagstruct_putu32(reply
, s
->sink_input
->sink
->index
);
2205 pa_tagstruct_puts(reply
, s
->sink_input
->sink
->name
);
2207 pa_tagstruct_put_boolean(reply
, pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_SUSPENDED
);
2210 if (c
->version
>= 13)
2211 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
2213 if (c
->version
>= 21) {
2214 /* Send back the format we negotiated */
2215 if (s
->sink_input
->format
)
2216 pa_tagstruct_put_format_info(reply
, s
->sink_input
->format
);
2218 pa_format_info
*f
= pa_format_info_new();
2219 pa_tagstruct_put_format_info(reply
, f
);
2220 pa_format_info_free(f
);
2224 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2228 pa_proplist_free(p
);
2230 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
2233 static void command_delete_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2234 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2237 pa_native_connection_assert_ref(c
);
2240 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2241 !pa_tagstruct_eof(t
)) {
2246 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2250 case PA_COMMAND_DELETE_PLAYBACK_STREAM
: {
2252 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !playback_stream_isinstance(s
)) {
2253 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2257 playback_stream_unlink(s
);
2261 case PA_COMMAND_DELETE_RECORD_STREAM
: {
2263 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, channel
))) {
2264 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2268 record_stream_unlink(s
);
2272 case PA_COMMAND_DELETE_UPLOAD_STREAM
: {
2275 if (!(s
= pa_idxset_get_by_index(c
->output_streams
, channel
)) || !upload_stream_isinstance(s
)) {
2276 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_EXIST
);
2280 upload_stream_unlink(s
);
2285 pa_assert_not_reached();
2288 pa_pstream_send_simple_ack(c
->pstream
, tag
);
2291 static void command_create_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2292 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2294 pa_buffer_attr attr
;
2295 uint32_t source_index
;
2296 const char *name
= NULL
, *source_name
;
2299 pa_tagstruct
*reply
;
2300 pa_source
*source
= NULL
;
2308 fix_channels
= FALSE
,
2310 variable_rate
= FALSE
,
2312 adjust_latency
= FALSE
,
2313 peak_detect
= FALSE
,
2314 early_requests
= FALSE
,
2315 dont_inhibit_auto_suspend
= FALSE
,
2318 fail_on_suspend
= FALSE
,
2319 relative_volume
= FALSE
,
2320 passthrough
= FALSE
;
2322 pa_source_output_flags_t flags
= 0;
2323 pa_proplist
*p
= NULL
;
2324 uint32_t direct_on_input_idx
= PA_INVALID_INDEX
;
2325 pa_sink_input
*direct_on_input
= NULL
;
2326 int ret
= PA_ERR_INVALID
;
2327 uint8_t n_formats
= 0;
2328 pa_format_info
*format
;
2329 pa_idxset
*formats
= NULL
;
2332 pa_native_connection_assert_ref(c
);
2335 memset(&attr
, 0, sizeof(attr
));
2337 if ((c
->version
< 13 && (pa_tagstruct_gets(t
, &name
) < 0 || !name
)) ||
2338 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2339 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2340 pa_tagstruct_getu32(t
, &source_index
) < 0 ||
2341 pa_tagstruct_gets(t
, &source_name
) < 0 ||
2342 pa_tagstruct_getu32(t
, &attr
.maxlength
) < 0 ||
2343 pa_tagstruct_get_boolean(t
, &corked
) < 0 ||
2344 pa_tagstruct_getu32(t
, &attr
.fragsize
) < 0) {
2350 CHECK_VALIDITY_GOTO(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
, finish
);
2351 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| pa_namereg_is_valid_name_or_wildcard(source_name
, PA_NAMEREG_SOURCE
), tag
, PA_ERR_INVALID
, finish
);
2352 CHECK_VALIDITY_GOTO(c
->pstream
, source_index
== PA_INVALID_INDEX
|| !source_name
, tag
, PA_ERR_INVALID
, finish
);
2353 CHECK_VALIDITY_GOTO(c
->pstream
, !source_name
|| source_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
, finish
);
2355 p
= pa_proplist_new();
2358 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2360 if (c
->version
>= 12) {
2361 /* Since 0.9.8 the user can ask for a couple of additional flags */
2363 if (pa_tagstruct_get_boolean(t
, &no_remap
) < 0 ||
2364 pa_tagstruct_get_boolean(t
, &no_remix
) < 0 ||
2365 pa_tagstruct_get_boolean(t
, &fix_format
) < 0 ||
2366 pa_tagstruct_get_boolean(t
, &fix_rate
) < 0 ||
2367 pa_tagstruct_get_boolean(t
, &fix_channels
) < 0 ||
2368 pa_tagstruct_get_boolean(t
, &no_move
) < 0 ||
2369 pa_tagstruct_get_boolean(t
, &variable_rate
) < 0) {
2376 if (c
->version
>= 13) {
2378 if (pa_tagstruct_get_boolean(t
, &peak_detect
) < 0 ||
2379 pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0 ||
2380 pa_tagstruct_get_proplist(t
, p
) < 0 ||
2381 pa_tagstruct_getu32(t
, &direct_on_input_idx
) < 0) {
2388 if (c
->version
>= 14) {
2390 if (pa_tagstruct_get_boolean(t
, &early_requests
) < 0) {
2396 if (c
->version
>= 15) {
2398 if (pa_tagstruct_get_boolean(t
, &dont_inhibit_auto_suspend
) < 0 ||
2399 pa_tagstruct_get_boolean(t
, &fail_on_suspend
) < 0) {
2406 if (c
->version
>= 22) {
2407 /* For newer client versions (with per-source-output volumes), we try
2408 * to make the behaviour for playback and record streams the same. */
2411 if (pa_tagstruct_getu8(t
, &n_formats
) < 0) {
2417 formats
= pa_idxset_new(NULL
, NULL
);
2419 for (i
= 0; i
< n_formats
; i
++) {
2420 format
= pa_format_info_new();
2421 if (pa_tagstruct_get_format_info(t
, format
) < 0) {
2425 pa_idxset_put(formats
, format
, NULL
);
2428 if (pa_tagstruct_get_cvolume(t
, &volume
) < 0 ||
2429 pa_tagstruct_get_boolean(t
, &muted
) < 0 ||
2430 pa_tagstruct_get_boolean(t
, &volume_set
) < 0 ||
2431 pa_tagstruct_get_boolean(t
, &muted_set
) < 0 ||
2432 pa_tagstruct_get_boolean(t
, &relative_volume
) < 0 ||
2433 pa_tagstruct_get_boolean(t
, &passthrough
) < 0) {
2439 CHECK_VALIDITY_GOTO(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
, finish
);
2442 if (n_formats
== 0) {
2443 CHECK_VALIDITY_GOTO(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
, finish
);
2444 CHECK_VALIDITY_GOTO(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
, finish
);
2445 CHECK_VALIDITY_GOTO(c
->pstream
, c
->version
< 22 || (volume
.channels
== ss
.channels
), tag
, PA_ERR_INVALID
, finish
);
2446 CHECK_VALIDITY_GOTO(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
, finish
);
2448 PA_IDXSET_FOREACH(format
, formats
, i
) {
2449 CHECK_VALIDITY_GOTO(c
->pstream
, pa_format_info_valid(format
), tag
, PA_ERR_INVALID
, finish
);
2454 if (!pa_tagstruct_eof(t
)) {
2459 if (source_index
!= PA_INVALID_INDEX
) {
2461 if (!(source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, source_index
))) {
2462 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2466 } else if (source_name
) {
2468 if (!(source
= pa_namereg_get(c
->protocol
->core
, source_name
, PA_NAMEREG_SOURCE
))) {
2469 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2474 if (direct_on_input_idx
!= PA_INVALID_INDEX
) {
2476 if (!(direct_on_input
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, direct_on_input_idx
))) {
2477 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2483 (corked
? PA_SOURCE_OUTPUT_START_CORKED
: 0) |
2484 (no_remap
? PA_SOURCE_OUTPUT_NO_REMAP
: 0) |
2485 (no_remix
? PA_SOURCE_OUTPUT_NO_REMIX
: 0) |
2486 (fix_format
? PA_SOURCE_OUTPUT_FIX_FORMAT
: 0) |
2487 (fix_rate
? PA_SOURCE_OUTPUT_FIX_RATE
: 0) |
2488 (fix_channels
? PA_SOURCE_OUTPUT_FIX_CHANNELS
: 0) |
2489 (no_move
? PA_SOURCE_OUTPUT_DONT_MOVE
: 0) |
2490 (variable_rate
? PA_SOURCE_OUTPUT_VARIABLE_RATE
: 0) |
2491 (dont_inhibit_auto_suspend
? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND
: 0) |
2492 (fail_on_suspend
? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND
|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND
: 0) |
2493 (passthrough
? PA_SOURCE_OUTPUT_PASSTHROUGH
: 0);
2495 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
);
2497 CHECK_VALIDITY_GOTO(c
->pstream
, s
, tag
, ret
, finish
);
2499 reply
= reply_new(tag
);
2500 pa_tagstruct_putu32(reply
, s
->index
);
2501 pa_assert(s
->source_output
);
2502 pa_tagstruct_putu32(reply
, s
->source_output
->index
);
2504 if (c
->version
>= 9) {
2505 /* Since 0.9 we support sending the buffer metrics back to the client */
2507 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.maxlength
);
2508 pa_tagstruct_putu32(reply
, (uint32_t) s
->buffer_attr
.fragsize
);
2511 if (c
->version
>= 12) {
2512 /* Since 0.9.8 we support sending the chosen sample
2513 * spec/channel map/device/suspend status back to the
2516 pa_tagstruct_put_sample_spec(reply
, &ss
);
2517 pa_tagstruct_put_channel_map(reply
, &map
);
2519 pa_tagstruct_putu32(reply
, s
->source_output
->source
->index
);
2520 pa_tagstruct_puts(reply
, s
->source_output
->source
->name
);
2522 pa_tagstruct_put_boolean(reply
, pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_SUSPENDED
);
2525 if (c
->version
>= 13)
2526 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
2528 if (c
->version
>= 22) {
2529 /* Send back the format we negotiated */
2530 if (s
->source_output
->format
)
2531 pa_tagstruct_put_format_info(reply
, s
->source_output
->format
);
2533 pa_format_info
*f
= pa_format_info_new();
2534 pa_tagstruct_put_format_info(reply
, f
);
2535 pa_format_info_free(f
);
2539 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2543 pa_proplist_free(p
);
2545 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
2548 static void command_exit(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2549 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2552 pa_native_connection_assert_ref(c
);
2555 if (!pa_tagstruct_eof(t
)) {
2560 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2561 ret
= pa_core_exit(c
->protocol
->core
, FALSE
, 0);
2562 CHECK_VALIDITY(c
->pstream
, ret
>= 0, tag
, PA_ERR_ACCESS
);
2564 pa_log_debug("Client %s asks us to terminate.", pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
)));
2566 pa_pstream_send_simple_ack(c
->pstream
, tag
); /* nonsense */
2569 static void command_auth(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2570 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2572 pa_tagstruct
*reply
;
2573 pa_bool_t shm_on_remote
= FALSE
, do_shm
;
2575 pa_native_connection_assert_ref(c
);
2578 if (pa_tagstruct_getu32(t
, &c
->version
) < 0 ||
2579 pa_tagstruct_get_arbitrary(t
, &cookie
, PA_NATIVE_COOKIE_LENGTH
) < 0 ||
2580 !pa_tagstruct_eof(t
)) {
2585 /* Minimum supported version */
2586 if (c
->version
< 8) {
2587 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_VERSION
);
2591 /* Starting with protocol version 13 the MSB of the version tag
2592 reflects if shm is available for this pa_native_connection or
2594 if (c
->version
>= 13) {
2595 shm_on_remote
= !!(c
->version
& 0x80000000U
);
2596 c
->version
&= 0x7FFFFFFFU
;
2599 pa_log_debug("Protocol version: remote %u, local %u", c
->version
, PA_PROTOCOL_VERSION
);
2601 pa_proplist_setf(c
->client
->proplist
, "native-protocol.version", "%u", c
->version
);
2603 if (!c
->authorized
) {
2604 pa_bool_t success
= FALSE
;
2607 const pa_creds
*creds
;
2609 if ((creds
= pa_pdispatch_creds(pd
))) {
2610 if (creds
->uid
== getuid())
2612 else if (c
->options
->auth_group
) {
2616 if ((gid
= pa_get_gid_of_group(c
->options
->auth_group
)) == (gid_t
) -1)
2617 pa_log_warn("Failed to get GID of group '%s'", c
->options
->auth_group
);
2618 else if (gid
== creds
->gid
)
2622 if ((r
= pa_uid_in_group(creds
->uid
, c
->options
->auth_group
)) < 0)
2623 pa_log_warn("Failed to check group membership.");
2629 pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2630 (unsigned long) creds
->uid
,
2631 (unsigned long) creds
->gid
,
2636 if (!success
&& c
->options
->auth_cookie
) {
2639 if ((ac
= pa_auth_cookie_read(c
->options
->auth_cookie
, PA_NATIVE_COOKIE_LENGTH
)))
2640 if (memcmp(ac
, cookie
, PA_NATIVE_COOKIE_LENGTH
) == 0)
2645 pa_log_warn("Denied access to client with invalid authorization data.");
2646 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_ACCESS
);
2650 c
->authorized
= TRUE
;
2651 if (c
->auth_timeout_event
) {
2652 c
->protocol
->core
->mainloop
->time_free(c
->auth_timeout_event
);
2653 c
->auth_timeout_event
= NULL
;
2657 /* Enable shared memory support if possible */
2659 pa_mempool_is_shared(c
->protocol
->core
->mempool
) &&
2662 pa_log_debug("SHM possible: %s", pa_yes_no(do_shm
));
2665 if (c
->version
< 10 || (c
->version
>= 13 && !shm_on_remote
))
2670 /* Only enable SHM if both sides are owned by the same
2671 * user. This is a security measure because otherwise data
2672 * private to the user might leak. */
2674 const pa_creds
*creds
;
2675 if (!(creds
= pa_pdispatch_creds(pd
)) || getuid() != creds
->uid
)
2680 pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm
));
2681 pa_pstream_enable_shm(c
->pstream
, do_shm
);
2683 reply
= reply_new(tag
);
2684 pa_tagstruct_putu32(reply
, PA_PROTOCOL_VERSION
| (do_shm
? 0x80000000 : 0));
2688 /* SHM support is only enabled after both sides made sure they are the same user. */
2692 ucred
.uid
= getuid();
2693 ucred
.gid
= getgid();
2695 pa_pstream_send_tagstruct_with_creds(c
->pstream
, reply
, &ucred
);
2698 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2702 static void command_set_client_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2703 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2704 const char *name
= NULL
;
2706 pa_tagstruct
*reply
;
2708 pa_native_connection_assert_ref(c
);
2711 p
= pa_proplist_new();
2713 if ((c
->version
< 13 && pa_tagstruct_gets(t
, &name
) < 0) ||
2714 (c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2715 !pa_tagstruct_eof(t
)) {
2718 pa_proplist_free(p
);
2723 if (pa_proplist_sets(p
, PA_PROP_APPLICATION_NAME
, name
) < 0) {
2724 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
2725 pa_proplist_free(p
);
2729 pa_client_update_proplist(c
->client
, PA_UPDATE_REPLACE
, p
);
2730 pa_proplist_free(p
);
2732 reply
= reply_new(tag
);
2734 if (c
->version
>= 13)
2735 pa_tagstruct_putu32(reply
, c
->client
->index
);
2737 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2740 static void command_lookup(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2741 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2743 uint32_t idx
= PA_IDXSET_INVALID
;
2745 pa_native_connection_assert_ref(c
);
2748 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2749 !pa_tagstruct_eof(t
)) {
2754 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2755 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
);
2757 if (command
== PA_COMMAND_LOOKUP_SINK
) {
2759 if ((sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
)))
2763 pa_assert(command
== PA_COMMAND_LOOKUP_SOURCE
);
2764 if ((source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
)))
2765 idx
= source
->index
;
2768 if (idx
== PA_IDXSET_INVALID
)
2769 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
2771 pa_tagstruct
*reply
;
2772 reply
= reply_new(tag
);
2773 pa_tagstruct_putu32(reply
, idx
);
2774 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2778 static void command_drain_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2779 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2783 pa_native_connection_assert_ref(c
);
2786 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2787 !pa_tagstruct_eof(t
)) {
2792 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2793 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2794 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2795 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2797 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
);
2800 static void command_stat(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2801 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2802 pa_tagstruct
*reply
;
2803 const pa_mempool_stat
*stat
;
2805 pa_native_connection_assert_ref(c
);
2808 if (!pa_tagstruct_eof(t
)) {
2813 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2815 stat
= pa_mempool_get_stat(c
->protocol
->core
->mempool
);
2817 reply
= reply_new(tag
);
2818 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_allocated
));
2819 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->allocated_size
));
2820 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->n_accumulated
));
2821 pa_tagstruct_putu32(reply
, (uint32_t) pa_atomic_load(&stat
->accumulated_size
));
2822 pa_tagstruct_putu32(reply
, (uint32_t) pa_scache_total_size(c
->protocol
->core
));
2823 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2826 static void command_get_playback_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2827 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2828 pa_tagstruct
*reply
;
2830 struct timeval tv
, now
;
2833 pa_native_connection_assert_ref(c
);
2836 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2837 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2838 !pa_tagstruct_eof(t
)) {
2843 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2844 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
2845 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2846 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2848 /* Get an atomic snapshot of all timing parameters */
2849 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);
2851 reply
= reply_new(tag
);
2852 pa_tagstruct_put_usec(reply
,
2853 s
->current_sink_latency
+
2854 pa_bytes_to_usec(s
->render_memblockq_length
, &s
->sink_input
->sink
->sample_spec
));
2855 pa_tagstruct_put_usec(reply
, 0);
2856 pa_tagstruct_put_boolean(reply
,
2857 s
->playing_for
> 0 &&
2858 pa_sink_get_state(s
->sink_input
->sink
) == PA_SINK_RUNNING
&&
2859 pa_sink_input_get_state(s
->sink_input
) == PA_SINK_INPUT_RUNNING
);
2860 pa_tagstruct_put_timeval(reply
, &tv
);
2861 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2862 pa_tagstruct_puts64(reply
, s
->write_index
);
2863 pa_tagstruct_puts64(reply
, s
->read_index
);
2865 if (c
->version
>= 13) {
2866 pa_tagstruct_putu64(reply
, s
->underrun_for
);
2867 pa_tagstruct_putu64(reply
, s
->playing_for
);
2870 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2873 static void command_get_record_latency(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2874 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2875 pa_tagstruct
*reply
;
2877 struct timeval tv
, now
;
2880 pa_native_connection_assert_ref(c
);
2883 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
2884 pa_tagstruct_get_timeval(t
, &tv
) < 0 ||
2885 !pa_tagstruct_eof(t
)) {
2890 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2891 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
2892 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2894 /* Get an atomic snapshot of all timing parameters */
2895 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);
2897 reply
= reply_new(tag
);
2898 pa_tagstruct_put_usec(reply
, s
->current_monitor_latency
);
2899 pa_tagstruct_put_usec(reply
,
2900 s
->current_source_latency
+
2901 pa_bytes_to_usec(s
->on_the_fly_snapshot
, &s
->source_output
->source
->sample_spec
));
2902 pa_tagstruct_put_boolean(reply
,
2903 pa_source_get_state(s
->source_output
->source
) == PA_SOURCE_RUNNING
&&
2904 pa_source_output_get_state(s
->source_output
) == PA_SOURCE_OUTPUT_RUNNING
);
2905 pa_tagstruct_put_timeval(reply
, &tv
);
2906 pa_tagstruct_put_timeval(reply
, pa_gettimeofday(&now
));
2907 pa_tagstruct_puts64(reply
, pa_memblockq_get_write_index(s
->memblockq
));
2908 pa_tagstruct_puts64(reply
, pa_memblockq_get_read_index(s
->memblockq
));
2909 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2912 static void command_create_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2913 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2916 const char *name
= NULL
;
2919 pa_tagstruct
*reply
;
2922 pa_native_connection_assert_ref(c
);
2925 if (pa_tagstruct_gets(t
, &name
) < 0 ||
2926 pa_tagstruct_get_sample_spec(t
, &ss
) < 0 ||
2927 pa_tagstruct_get_channel_map(t
, &map
) < 0 ||
2928 pa_tagstruct_getu32(t
, &length
) < 0) {
2933 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2934 CHECK_VALIDITY(c
->pstream
, pa_sample_spec_valid(&ss
), tag
, PA_ERR_INVALID
);
2935 CHECK_VALIDITY(c
->pstream
, pa_channel_map_valid(&map
), tag
, PA_ERR_INVALID
);
2936 CHECK_VALIDITY(c
->pstream
, map
.channels
== ss
.channels
, tag
, PA_ERR_INVALID
);
2937 CHECK_VALIDITY(c
->pstream
, (length
% pa_frame_size(&ss
)) == 0 && length
> 0, tag
, PA_ERR_INVALID
);
2938 CHECK_VALIDITY(c
->pstream
, length
<= PA_SCACHE_ENTRY_SIZE_MAX
, tag
, PA_ERR_TOOLARGE
);
2940 p
= pa_proplist_new();
2942 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
2943 !pa_tagstruct_eof(t
)) {
2946 pa_proplist_free(p
);
2950 if (c
->version
< 13)
2951 pa_proplist_sets(p
, PA_PROP_MEDIA_NAME
, name
);
2953 if (!(name
= pa_proplist_gets(p
, PA_PROP_EVENT_ID
)))
2954 name
= pa_proplist_gets(p
, PA_PROP_MEDIA_NAME
);
2956 if (!name
|| !pa_namereg_is_valid_name(name
)) {
2957 pa_proplist_free(p
);
2958 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
2961 s
= upload_stream_new(c
, &ss
, &map
, name
, length
, p
);
2962 pa_proplist_free(p
);
2964 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_INVALID
);
2966 reply
= reply_new(tag
);
2967 pa_tagstruct_putu32(reply
, s
->index
);
2968 pa_tagstruct_putu32(reply
, length
);
2969 pa_pstream_send_tagstruct(c
->pstream
, reply
);
2972 static void command_finish_upload_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
2973 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
2978 pa_native_connection_assert_ref(c
);
2981 if (pa_tagstruct_getu32(t
, &channel
) < 0 ||
2982 !pa_tagstruct_eof(t
)) {
2987 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
2989 s
= pa_idxset_get_by_index(c
->output_streams
, channel
);
2990 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
2991 CHECK_VALIDITY(c
->pstream
, upload_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
2993 if (!s
->memchunk
.memblock
)
2994 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_TOOLARGE
);
2995 else if (pa_scache_add_item(c
->protocol
->core
, s
->name
, &s
->sample_spec
, &s
->channel_map
, &s
->memchunk
, s
->proplist
, &idx
) < 0)
2996 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INTERNAL
);
2998 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3000 upload_stream_unlink(s
);
3003 static void command_play_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3004 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3005 uint32_t sink_index
;
3008 const char *name
, *sink_name
;
3011 pa_tagstruct
*reply
;
3013 pa_native_connection_assert_ref(c
);
3016 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3018 if (pa_tagstruct_getu32(t
, &sink_index
) < 0 ||
3019 pa_tagstruct_gets(t
, &sink_name
) < 0 ||
3020 pa_tagstruct_getu32(t
, &volume
) < 0 ||
3021 pa_tagstruct_gets(t
, &name
) < 0) {
3026 CHECK_VALIDITY(c
->pstream
, !sink_name
|| pa_namereg_is_valid_name_or_wildcard(sink_name
, PA_NAMEREG_SINK
), tag
, PA_ERR_INVALID
);
3027 CHECK_VALIDITY(c
->pstream
, sink_index
== PA_INVALID_INDEX
|| !sink_name
, tag
, PA_ERR_INVALID
);
3028 CHECK_VALIDITY(c
->pstream
, !sink_name
|| sink_index
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3029 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3031 if (sink_index
!= PA_INVALID_INDEX
)
3032 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, sink_index
);
3034 sink
= pa_namereg_get(c
->protocol
->core
, sink_name
, PA_NAMEREG_SINK
);
3036 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
3038 p
= pa_proplist_new();
3040 if ((c
->version
>= 13 && pa_tagstruct_get_proplist(t
, p
) < 0) ||
3041 !pa_tagstruct_eof(t
)) {
3043 pa_proplist_free(p
);
3047 pa_proplist_update(p
, PA_UPDATE_MERGE
, c
->client
->proplist
);
3049 if (pa_scache_play_item(c
->protocol
->core
, name
, sink
, volume
, p
, &idx
) < 0) {
3050 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3051 pa_proplist_free(p
);
3055 pa_proplist_free(p
);
3057 reply
= reply_new(tag
);
3059 if (c
->version
>= 13)
3060 pa_tagstruct_putu32(reply
, idx
);
3062 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3065 static void command_remove_sample(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3066 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3069 pa_native_connection_assert_ref(c
);
3072 if (pa_tagstruct_gets(t
, &name
) < 0 ||
3073 !pa_tagstruct_eof(t
)) {
3078 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3079 CHECK_VALIDITY(c
->pstream
, name
&& pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3081 if (pa_scache_remove_item(c
->protocol
->core
, name
) < 0) {
3082 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3086 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3089 static void fixup_sample_spec(pa_native_connection
*c
, pa_sample_spec
*fixed
, const pa_sample_spec
*original
) {
3092 pa_assert(original
);
3096 if (c
->version
< 12) {
3097 /* Before protocol version 12 we didn't support S32 samples,
3098 * so we need to lie about this to the client */
3100 if (fixed
->format
== PA_SAMPLE_S32LE
)
3101 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3102 if (fixed
->format
== PA_SAMPLE_S32BE
)
3103 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3106 if (c
->version
< 15) {
3107 if (fixed
->format
== PA_SAMPLE_S24LE
|| fixed
->format
== PA_SAMPLE_S24_32LE
)
3108 fixed
->format
= PA_SAMPLE_FLOAT32LE
;
3109 if (fixed
->format
== PA_SAMPLE_S24BE
|| fixed
->format
== PA_SAMPLE_S24_32BE
)
3110 fixed
->format
= PA_SAMPLE_FLOAT32BE
;
3114 static void sink_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink
*sink
) {
3115 pa_sample_spec fixed_ss
;
3118 pa_sink_assert_ref(sink
);
3120 fixup_sample_spec(c
, &fixed_ss
, &sink
->sample_spec
);
3124 PA_TAG_U32
, sink
->index
,
3125 PA_TAG_STRING
, sink
->name
,
3126 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(sink
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3127 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3128 PA_TAG_CHANNEL_MAP
, &sink
->channel_map
,
3129 PA_TAG_U32
, sink
->module
? sink
->module
->index
: PA_INVALID_INDEX
,
3130 PA_TAG_CVOLUME
, pa_sink_get_volume(sink
, FALSE
),
3131 PA_TAG_BOOLEAN
, pa_sink_get_mute(sink
, FALSE
),
3132 PA_TAG_U32
, sink
->monitor_source
? sink
->monitor_source
->index
: PA_INVALID_INDEX
,
3133 PA_TAG_STRING
, sink
->monitor_source
? sink
->monitor_source
->name
: NULL
,
3134 PA_TAG_USEC
, pa_sink_get_latency(sink
),
3135 PA_TAG_STRING
, sink
->driver
,
3136 PA_TAG_U32
, sink
->flags
& PA_SINK_CLIENT_FLAGS_MASK
,
3139 if (c
->version
>= 13) {
3140 pa_tagstruct_put_proplist(t
, sink
->proplist
);
3141 pa_tagstruct_put_usec(t
, pa_sink_get_requested_latency(sink
));
3144 if (c
->version
>= 15) {
3145 pa_tagstruct_put_volume(t
, sink
->base_volume
);
3146 if (PA_UNLIKELY(pa_sink_get_state(sink
) == PA_SINK_INVALID_STATE
))
3147 pa_log_error("Internal sink state is invalid.");
3148 pa_tagstruct_putu32(t
, pa_sink_get_state(sink
));
3149 pa_tagstruct_putu32(t
, sink
->n_volume_steps
);
3150 pa_tagstruct_putu32(t
, sink
->card
? sink
->card
->index
: PA_INVALID_INDEX
);
3153 if (c
->version
>= 16) {
3157 pa_tagstruct_putu32(t
, pa_hashmap_size(sink
->ports
));
3159 PA_HASHMAP_FOREACH(p
, sink
->ports
, state
) {
3160 pa_tagstruct_puts(t
, p
->name
);
3161 pa_tagstruct_puts(t
, p
->description
);
3162 pa_tagstruct_putu32(t
, p
->priority
);
3163 if (c
->version
>= 24)
3164 pa_tagstruct_putu32(t
, p
->available
);
3167 pa_tagstruct_puts(t
, sink
->active_port
? sink
->active_port
->name
: NULL
);
3170 if (c
->version
>= 21) {
3173 pa_idxset
*formats
= pa_sink_get_formats(sink
);
3175 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3176 PA_IDXSET_FOREACH(f
, formats
, i
) {
3177 pa_tagstruct_put_format_info(t
, f
);
3180 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
3184 static void source_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source
*source
) {
3185 pa_sample_spec fixed_ss
;
3188 pa_source_assert_ref(source
);
3190 fixup_sample_spec(c
, &fixed_ss
, &source
->sample_spec
);
3194 PA_TAG_U32
, source
->index
,
3195 PA_TAG_STRING
, source
->name
,
3196 PA_TAG_STRING
, pa_strnull(pa_proplist_gets(source
->proplist
, PA_PROP_DEVICE_DESCRIPTION
)),
3197 PA_TAG_SAMPLE_SPEC
, &fixed_ss
,
3198 PA_TAG_CHANNEL_MAP
, &source
->channel_map
,
3199 PA_TAG_U32
, source
->module
? source
->module
->index
: PA_INVALID_INDEX
,
3200 PA_TAG_CVOLUME
, pa_source_get_volume(source
, FALSE
),
3201 PA_TAG_BOOLEAN
, pa_source_get_mute(source
, FALSE
),
3202 PA_TAG_U32
, source
->monitor_of
? source
->monitor_of
->index
: PA_INVALID_INDEX
,
3203 PA_TAG_STRING
, source
->monitor_of
? source
->monitor_of
->name
: NULL
,
3204 PA_TAG_USEC
, pa_source_get_latency(source
),
3205 PA_TAG_STRING
, source
->driver
,
3206 PA_TAG_U32
, source
->flags
& PA_SOURCE_CLIENT_FLAGS_MASK
,
3209 if (c
->version
>= 13) {
3210 pa_tagstruct_put_proplist(t
, source
->proplist
);
3211 pa_tagstruct_put_usec(t
, pa_source_get_requested_latency(source
));
3214 if (c
->version
>= 15) {
3215 pa_tagstruct_put_volume(t
, source
->base_volume
);
3216 if (PA_UNLIKELY(pa_source_get_state(source
) == PA_SOURCE_INVALID_STATE
))
3217 pa_log_error("Internal source state is invalid.");
3218 pa_tagstruct_putu32(t
, pa_source_get_state(source
));
3219 pa_tagstruct_putu32(t
, source
->n_volume_steps
);
3220 pa_tagstruct_putu32(t
, source
->card
? source
->card
->index
: PA_INVALID_INDEX
);
3223 if (c
->version
>= 16) {
3227 pa_tagstruct_putu32(t
, pa_hashmap_size(source
->ports
));
3229 PA_HASHMAP_FOREACH(p
, source
->ports
, state
) {
3230 pa_tagstruct_puts(t
, p
->name
);
3231 pa_tagstruct_puts(t
, p
->description
);
3232 pa_tagstruct_putu32(t
, p
->priority
);
3233 if (c
->version
>= 24)
3234 pa_tagstruct_putu32(t
, p
->available
);
3237 pa_tagstruct_puts(t
, source
->active_port
? source
->active_port
->name
: NULL
);
3240 if (c
->version
>= 22) {
3243 pa_idxset
*formats
= pa_source_get_formats(source
);
3245 pa_tagstruct_putu8(t
, (uint8_t) pa_idxset_size(formats
));
3246 PA_IDXSET_FOREACH(f
, formats
, i
) {
3247 pa_tagstruct_put_format_info(t
, f
);
3250 pa_idxset_free(formats
, (pa_free_cb_t
) pa_format_info_free
);
3254 static void client_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_client
*client
) {
3258 pa_tagstruct_putu32(t
, client
->index
);
3259 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(client
->proplist
, PA_PROP_APPLICATION_NAME
)));
3260 pa_tagstruct_putu32(t
, client
->module
? client
->module
->index
: PA_INVALID_INDEX
);
3261 pa_tagstruct_puts(t
, client
->driver
);
3263 if (c
->version
>= 13)
3264 pa_tagstruct_put_proplist(t
, client
->proplist
);
3267 static void card_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_card
*card
) {
3270 pa_device_port
*port
;
3275 pa_tagstruct_putu32(t
, card
->index
);
3276 pa_tagstruct_puts(t
, card
->name
);
3277 pa_tagstruct_putu32(t
, card
->module
? card
->module
->index
: PA_INVALID_INDEX
);
3278 pa_tagstruct_puts(t
, card
->driver
);
3280 pa_tagstruct_putu32(t
, pa_hashmap_size(card
->profiles
));
3282 PA_HASHMAP_FOREACH(p
, card
->profiles
, state
) {
3283 pa_tagstruct_puts(t
, p
->name
);
3284 pa_tagstruct_puts(t
, p
->description
);
3285 pa_tagstruct_putu32(t
, p
->n_sinks
);
3286 pa_tagstruct_putu32(t
, p
->n_sources
);
3287 pa_tagstruct_putu32(t
, p
->priority
);
3290 pa_tagstruct_puts(t
, card
->active_profile
->name
);
3291 pa_tagstruct_put_proplist(t
, card
->proplist
);
3293 if (c
->version
< 26)
3296 pa_tagstruct_putu32(t
, pa_hashmap_size(card
->ports
));
3298 PA_HASHMAP_FOREACH(port
, card
->ports
, state
) {
3301 pa_tagstruct_puts(t
, port
->name
);
3302 pa_tagstruct_puts(t
, port
->description
);
3303 pa_tagstruct_putu32(t
, port
->priority
);
3304 pa_tagstruct_putu32(t
, port
->available
);
3305 pa_tagstruct_putu8(t
, /* FIXME: port->direction */ (port
->is_input
? PA_DIRECTION_INPUT
: 0) | (port
->is_output
? PA_DIRECTION_OUTPUT
: 0));
3306 pa_tagstruct_put_proplist(t
, port
->proplist
);
3308 pa_tagstruct_putu32(t
, pa_hashmap_size(port
->profiles
));
3310 PA_HASHMAP_FOREACH(p
, port
->profiles
, state2
)
3311 pa_tagstruct_puts(t
, p
->name
);
3313 if (c
->version
>= 27)
3314 pa_tagstruct_puts64(t
, port
->latency_offset
);
3318 static void module_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_module
*module
) {
3322 pa_tagstruct_putu32(t
, module
->index
);
3323 pa_tagstruct_puts(t
, module
->name
);
3324 pa_tagstruct_puts(t
, module
->argument
);
3325 pa_tagstruct_putu32(t
, (uint32_t) pa_module_get_n_used(module
));
3327 if (c
->version
< 15)
3328 pa_tagstruct_put_boolean(t
, FALSE
); /* autoload is obsolete */
3330 if (c
->version
>= 15)
3331 pa_tagstruct_put_proplist(t
, module
->proplist
);
3334 static void sink_input_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_sink_input
*s
) {
3335 pa_sample_spec fixed_ss
;
3336 pa_usec_t sink_latency
;
3338 pa_bool_t has_volume
= FALSE
;
3341 pa_sink_input_assert_ref(s
);
3343 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3345 has_volume
= pa_sink_input_is_volume_readable(s
);
3347 pa_sink_input_get_volume(s
, &v
, TRUE
);
3349 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3351 pa_tagstruct_putu32(t
, s
->index
);
3352 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3353 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3354 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3355 pa_tagstruct_putu32(t
, s
->sink
->index
);
3356 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3357 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3358 pa_tagstruct_put_cvolume(t
, &v
);
3359 pa_tagstruct_put_usec(t
, pa_sink_input_get_latency(s
, &sink_latency
));
3360 pa_tagstruct_put_usec(t
, sink_latency
);
3361 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_sink_input_get_resample_method(s
)));
3362 pa_tagstruct_puts(t
, s
->driver
);
3363 if (c
->version
>= 11)
3364 pa_tagstruct_put_boolean(t
, pa_sink_input_get_mute(s
));
3365 if (c
->version
>= 13)
3366 pa_tagstruct_put_proplist(t
, s
->proplist
);
3367 if (c
->version
>= 19)
3368 pa_tagstruct_put_boolean(t
, (pa_sink_input_get_state(s
) == PA_SINK_INPUT_CORKED
));
3369 if (c
->version
>= 20) {
3370 pa_tagstruct_put_boolean(t
, has_volume
);
3371 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3373 if (c
->version
>= 21)
3374 pa_tagstruct_put_format_info(t
, s
->format
);
3377 static void source_output_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_source_output
*s
) {
3378 pa_sample_spec fixed_ss
;
3379 pa_usec_t source_latency
;
3381 pa_bool_t has_volume
= FALSE
;
3384 pa_source_output_assert_ref(s
);
3386 fixup_sample_spec(c
, &fixed_ss
, &s
->sample_spec
);
3388 has_volume
= pa_source_output_is_volume_readable(s
);
3390 pa_source_output_get_volume(s
, &v
, TRUE
);
3392 pa_cvolume_reset(&v
, fixed_ss
.channels
);
3394 pa_tagstruct_putu32(t
, s
->index
);
3395 pa_tagstruct_puts(t
, pa_strnull(pa_proplist_gets(s
->proplist
, PA_PROP_MEDIA_NAME
)));
3396 pa_tagstruct_putu32(t
, s
->module
? s
->module
->index
: PA_INVALID_INDEX
);
3397 pa_tagstruct_putu32(t
, s
->client
? s
->client
->index
: PA_INVALID_INDEX
);
3398 pa_tagstruct_putu32(t
, s
->source
->index
);
3399 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3400 pa_tagstruct_put_channel_map(t
, &s
->channel_map
);
3401 pa_tagstruct_put_usec(t
, pa_source_output_get_latency(s
, &source_latency
));
3402 pa_tagstruct_put_usec(t
, source_latency
);
3403 pa_tagstruct_puts(t
, pa_resample_method_to_string(pa_source_output_get_resample_method(s
)));
3404 pa_tagstruct_puts(t
, s
->driver
);
3405 if (c
->version
>= 13)
3406 pa_tagstruct_put_proplist(t
, s
->proplist
);
3407 if (c
->version
>= 19)
3408 pa_tagstruct_put_boolean(t
, (pa_source_output_get_state(s
) == PA_SOURCE_OUTPUT_CORKED
));
3409 if (c
->version
>= 22) {
3410 pa_tagstruct_put_cvolume(t
, &v
);
3411 pa_tagstruct_put_boolean(t
, pa_source_output_get_mute(s
));
3412 pa_tagstruct_put_boolean(t
, has_volume
);
3413 pa_tagstruct_put_boolean(t
, s
->volume_writable
);
3414 pa_tagstruct_put_format_info(t
, s
->format
);
3418 static void scache_fill_tagstruct(pa_native_connection
*c
, pa_tagstruct
*t
, pa_scache_entry
*e
) {
3419 pa_sample_spec fixed_ss
;
3425 if (e
->memchunk
.memblock
)
3426 fixup_sample_spec(c
, &fixed_ss
, &e
->sample_spec
);
3428 memset(&fixed_ss
, 0, sizeof(fixed_ss
));
3430 pa_tagstruct_putu32(t
, e
->index
);
3431 pa_tagstruct_puts(t
, e
->name
);
3433 if (e
->volume_is_set
)
3436 pa_cvolume_init(&v
);
3438 pa_tagstruct_put_cvolume(t
, &v
);
3439 pa_tagstruct_put_usec(t
, e
->memchunk
.memblock
? pa_bytes_to_usec(e
->memchunk
.length
, &e
->sample_spec
) : 0);
3440 pa_tagstruct_put_sample_spec(t
, &fixed_ss
);
3441 pa_tagstruct_put_channel_map(t
, &e
->channel_map
);
3442 pa_tagstruct_putu32(t
, (uint32_t) e
->memchunk
.length
);
3443 pa_tagstruct_put_boolean(t
, e
->lazy
);
3444 pa_tagstruct_puts(t
, e
->filename
);
3446 if (c
->version
>= 13)
3447 pa_tagstruct_put_proplist(t
, e
->proplist
);
3450 static void command_get_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3451 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3453 pa_sink
*sink
= NULL
;
3454 pa_source
*source
= NULL
;
3455 pa_client
*client
= NULL
;
3456 pa_card
*card
= NULL
;
3457 pa_module
*module
= NULL
;
3458 pa_sink_input
*si
= NULL
;
3459 pa_source_output
*so
= NULL
;
3460 pa_scache_entry
*sce
= NULL
;
3461 const char *name
= NULL
;
3462 pa_tagstruct
*reply
;
3464 pa_native_connection_assert_ref(c
);
3467 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3468 (command
!= PA_COMMAND_GET_CLIENT_INFO
&&
3469 command
!= PA_COMMAND_GET_MODULE_INFO
&&
3470 command
!= PA_COMMAND_GET_SINK_INPUT_INFO
&&
3471 command
!= PA_COMMAND_GET_SOURCE_OUTPUT_INFO
&&
3472 pa_tagstruct_gets(t
, &name
) < 0) ||
3473 !pa_tagstruct_eof(t
)) {
3478 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3479 CHECK_VALIDITY(c
->pstream
, !name
||
3480 (command
== PA_COMMAND_GET_SINK_INFO
&&
3481 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SINK
)) ||
3482 (command
== PA_COMMAND_GET_SOURCE_INFO
&&
3483 pa_namereg_is_valid_name_or_wildcard(name
, PA_NAMEREG_SOURCE
)) ||
3484 pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
3485 CHECK_VALIDITY(c
->pstream
, command
== PA_COMMAND_GET_SINK_INFO
||
3486 command
== PA_COMMAND_GET_SOURCE_INFO
||
3487 (idx
!= PA_INVALID_INDEX
|| name
), tag
, PA_ERR_INVALID
);
3488 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3489 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3491 if (command
== PA_COMMAND_GET_SINK_INFO
) {
3492 if (idx
!= PA_INVALID_INDEX
)
3493 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3495 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3496 } else if (command
== PA_COMMAND_GET_SOURCE_INFO
) {
3497 if (idx
!= PA_INVALID_INDEX
)
3498 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3500 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3501 } else if (command
== PA_COMMAND_GET_CARD_INFO
) {
3502 if (idx
!= PA_INVALID_INDEX
)
3503 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
3505 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
3506 } else if (command
== PA_COMMAND_GET_CLIENT_INFO
)
3507 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
3508 else if (command
== PA_COMMAND_GET_MODULE_INFO
)
3509 module
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
3510 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO
)
3511 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3512 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO
)
3513 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3515 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO
);
3516 if (idx
!= PA_INVALID_INDEX
)
3517 sce
= pa_idxset_get_by_index(c
->protocol
->core
->scache
, idx
);
3519 sce
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SAMPLE
);
3522 if (!sink
&& !source
&& !client
&& !card
&& !module
&& !si
&& !so
&& !sce
) {
3523 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_NOENTITY
);
3527 reply
= reply_new(tag
);
3529 sink_fill_tagstruct(c
, reply
, sink
);
3531 source_fill_tagstruct(c
, reply
, source
);
3533 client_fill_tagstruct(c
, reply
, client
);
3535 card_fill_tagstruct(c
, reply
, card
);
3537 module_fill_tagstruct(c
, reply
, module
);
3539 sink_input_fill_tagstruct(c
, reply
, si
);
3541 source_output_fill_tagstruct(c
, reply
, so
);
3543 scache_fill_tagstruct(c
, reply
, sce
);
3544 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3547 static void command_get_info_list(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3548 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3552 pa_tagstruct
*reply
;
3554 pa_native_connection_assert_ref(c
);
3557 if (!pa_tagstruct_eof(t
)) {
3562 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3564 reply
= reply_new(tag
);
3566 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3567 i
= c
->protocol
->core
->sinks
;
3568 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3569 i
= c
->protocol
->core
->sources
;
3570 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3571 i
= c
->protocol
->core
->clients
;
3572 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3573 i
= c
->protocol
->core
->cards
;
3574 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3575 i
= c
->protocol
->core
->modules
;
3576 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3577 i
= c
->protocol
->core
->sink_inputs
;
3578 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3579 i
= c
->protocol
->core
->source_outputs
;
3581 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3582 i
= c
->protocol
->core
->scache
;
3586 PA_IDXSET_FOREACH(p
, i
, idx
) {
3587 if (command
== PA_COMMAND_GET_SINK_INFO_LIST
)
3588 sink_fill_tagstruct(c
, reply
, p
);
3589 else if (command
== PA_COMMAND_GET_SOURCE_INFO_LIST
)
3590 source_fill_tagstruct(c
, reply
, p
);
3591 else if (command
== PA_COMMAND_GET_CLIENT_INFO_LIST
)
3592 client_fill_tagstruct(c
, reply
, p
);
3593 else if (command
== PA_COMMAND_GET_CARD_INFO_LIST
)
3594 card_fill_tagstruct(c
, reply
, p
);
3595 else if (command
== PA_COMMAND_GET_MODULE_INFO_LIST
)
3596 module_fill_tagstruct(c
, reply
, p
);
3597 else if (command
== PA_COMMAND_GET_SINK_INPUT_INFO_LIST
)
3598 sink_input_fill_tagstruct(c
, reply
, p
);
3599 else if (command
== PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST
)
3600 source_output_fill_tagstruct(c
, reply
, p
);
3602 pa_assert(command
== PA_COMMAND_GET_SAMPLE_INFO_LIST
);
3603 scache_fill_tagstruct(c
, reply
, p
);
3608 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3611 static void command_get_server_info(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3612 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3613 pa_tagstruct
*reply
;
3615 pa_source
*def_source
;
3616 pa_sample_spec fixed_ss
;
3619 pa_native_connection_assert_ref(c
);
3622 if (!pa_tagstruct_eof(t
)) {
3627 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3629 reply
= reply_new(tag
);
3630 pa_tagstruct_puts(reply
, PACKAGE_NAME
);
3631 pa_tagstruct_puts(reply
, PACKAGE_VERSION
);
3633 u
= pa_get_user_name_malloc();
3634 pa_tagstruct_puts(reply
, u
);
3637 h
= pa_get_host_name_malloc();
3638 pa_tagstruct_puts(reply
, h
);
3641 fixup_sample_spec(c
, &fixed_ss
, &c
->protocol
->core
->default_sample_spec
);
3642 pa_tagstruct_put_sample_spec(reply
, &fixed_ss
);
3644 def_sink
= pa_namereg_get_default_sink(c
->protocol
->core
);
3645 pa_tagstruct_puts(reply
, def_sink
? def_sink
->name
: NULL
);
3646 def_source
= pa_namereg_get_default_source(c
->protocol
->core
);
3647 pa_tagstruct_puts(reply
, def_source
? def_source
->name
: NULL
);
3649 pa_tagstruct_putu32(reply
, c
->protocol
->core
->cookie
);
3651 if (c
->version
>= 15)
3652 pa_tagstruct_put_channel_map(reply
, &c
->protocol
->core
->default_channel_map
);
3654 pa_pstream_send_tagstruct(c
->pstream
, reply
);
3657 static void subscription_cb(pa_core
*core
, pa_subscription_event_type_t e
, uint32_t idx
, void *userdata
) {
3659 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3661 pa_native_connection_assert_ref(c
);
3663 t
= pa_tagstruct_new(NULL
, 0);
3664 pa_tagstruct_putu32(t
, PA_COMMAND_SUBSCRIBE_EVENT
);
3665 pa_tagstruct_putu32(t
, (uint32_t) -1);
3666 pa_tagstruct_putu32(t
, e
);
3667 pa_tagstruct_putu32(t
, idx
);
3668 pa_pstream_send_tagstruct(c
->pstream
, t
);
3671 static void command_subscribe(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3672 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3673 pa_subscription_mask_t m
;
3675 pa_native_connection_assert_ref(c
);
3678 if (pa_tagstruct_getu32(t
, &m
) < 0 ||
3679 !pa_tagstruct_eof(t
)) {
3684 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3685 CHECK_VALIDITY(c
->pstream
, (m
& ~PA_SUBSCRIPTION_MASK_ALL
) == 0, tag
, PA_ERR_INVALID
);
3687 if (c
->subscription
)
3688 pa_subscription_free(c
->subscription
);
3691 c
->subscription
= pa_subscription_new(c
->protocol
->core
, m
, subscription_cb
, c
);
3692 pa_assert(c
->subscription
);
3694 c
->subscription
= NULL
;
3696 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3699 static void command_set_volume(
3706 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3709 pa_sink
*sink
= NULL
;
3710 pa_source
*source
= NULL
;
3711 pa_sink_input
*si
= NULL
;
3712 pa_source_output
*so
= NULL
;
3713 const char *name
= NULL
;
3714 const char *client_name
;
3716 pa_native_connection_assert_ref(c
);
3719 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3720 (command
== PA_COMMAND_SET_SINK_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3721 (command
== PA_COMMAND_SET_SOURCE_VOLUME
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3722 pa_tagstruct_get_cvolume(t
, &volume
) ||
3723 !pa_tagstruct_eof(t
)) {
3728 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3729 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
);
3730 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3731 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3732 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3733 CHECK_VALIDITY(c
->pstream
, pa_cvolume_valid(&volume
), tag
, PA_ERR_INVALID
);
3737 case PA_COMMAND_SET_SINK_VOLUME
:
3738 if (idx
!= PA_INVALID_INDEX
)
3739 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3741 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3744 case PA_COMMAND_SET_SOURCE_VOLUME
:
3745 if (idx
!= PA_INVALID_INDEX
)
3746 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3748 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3751 case PA_COMMAND_SET_SINK_INPUT_VOLUME
:
3752 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3755 case PA_COMMAND_SET_SOURCE_OUTPUT_VOLUME
:
3756 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3760 pa_assert_not_reached();
3763 CHECK_VALIDITY(c
->pstream
, si
|| so
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3765 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3768 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &sink
->sample_spec
), tag
, PA_ERR_INVALID
);
3770 pa_log_debug("Client %s changes volume of sink %s.", client_name
, sink
->name
);
3771 pa_sink_set_volume(sink
, &volume
, TRUE
, TRUE
);
3772 } else if (source
) {
3773 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &source
->sample_spec
), tag
, PA_ERR_INVALID
);
3775 pa_log_debug("Client %s changes volume of source %s.", client_name
, source
->name
);
3776 pa_source_set_volume(source
, &volume
, TRUE
, TRUE
);
3778 CHECK_VALIDITY(c
->pstream
, si
->volume_writable
, tag
, PA_ERR_BADSTATE
);
3779 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &si
->sample_spec
), tag
, PA_ERR_INVALID
);
3781 pa_log_debug("Client %s changes volume of sink input %s.",
3783 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3784 pa_sink_input_set_volume(si
, &volume
, TRUE
, TRUE
);
3786 CHECK_VALIDITY(c
->pstream
, volume
.channels
== 1 || pa_cvolume_compatible(&volume
, &so
->sample_spec
), tag
, PA_ERR_INVALID
);
3788 pa_log_debug("Client %s changes volume of source output %s.",
3790 pa_strnull(pa_proplist_gets(so
->proplist
, PA_PROP_MEDIA_NAME
)));
3791 pa_source_output_set_volume(so
, &volume
, TRUE
, TRUE
);
3794 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3797 static void command_set_mute(
3804 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3807 pa_sink
*sink
= NULL
;
3808 pa_source
*source
= NULL
;
3809 pa_sink_input
*si
= NULL
;
3810 pa_source_output
*so
= NULL
;
3811 const char *name
= NULL
, *client_name
;
3813 pa_native_connection_assert_ref(c
);
3816 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3817 (command
== PA_COMMAND_SET_SINK_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3818 (command
== PA_COMMAND_SET_SOURCE_MUTE
&& pa_tagstruct_gets(t
, &name
) < 0) ||
3819 pa_tagstruct_get_boolean(t
, &mute
) ||
3820 !pa_tagstruct_eof(t
)) {
3825 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3826 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
);
3827 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
3828 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
3829 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3833 case PA_COMMAND_SET_SINK_MUTE
:
3834 if (idx
!= PA_INVALID_INDEX
)
3835 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
3837 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
3841 case PA_COMMAND_SET_SOURCE_MUTE
:
3842 if (idx
!= PA_INVALID_INDEX
)
3843 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
3845 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
3849 case PA_COMMAND_SET_SINK_INPUT_MUTE
:
3850 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
3853 case PA_COMMAND_SET_SOURCE_OUTPUT_MUTE
:
3854 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
3858 pa_assert_not_reached();
3861 CHECK_VALIDITY(c
->pstream
, si
|| so
|| sink
|| source
, tag
, PA_ERR_NOENTITY
);
3863 client_name
= pa_strnull(pa_proplist_gets(c
->client
->proplist
, PA_PROP_APPLICATION_PROCESS_BINARY
));
3866 pa_log_debug("Client %s changes mute of sink %s.", client_name
, sink
->name
);
3867 pa_sink_set_mute(sink
, mute
, TRUE
);
3868 } else if (source
) {
3869 pa_log_debug("Client %s changes mute of source %s.", client_name
, source
->name
);
3870 pa_source_set_mute(source
, mute
, TRUE
);
3872 pa_log_debug("Client %s changes mute of sink input %s.",
3874 pa_strnull(pa_proplist_gets(si
->proplist
, PA_PROP_MEDIA_NAME
)));
3875 pa_sink_input_set_mute(si
, mute
, TRUE
);
3877 pa_log_debug("Client %s changes mute of source output %s.",
3879 pa_strnull(pa_proplist_gets(so
->proplist
, PA_PROP_MEDIA_NAME
)));
3880 pa_source_output_set_mute(so
, mute
, TRUE
);
3883 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3886 static void command_cork_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3887 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3892 pa_native_connection_assert_ref(c
);
3895 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3896 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3897 !pa_tagstruct_eof(t
)) {
3902 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3903 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3904 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3905 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3906 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3908 pa_sink_input_cork(s
->sink_input
, b
);
3911 s
->is_underrun
= TRUE
;
3913 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3916 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3917 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3921 pa_native_connection_assert_ref(c
);
3924 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3925 !pa_tagstruct_eof(t
)) {
3930 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3931 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
3932 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
3933 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3934 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
3937 case PA_COMMAND_FLUSH_PLAYBACK_STREAM
:
3938 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_FLUSH
, NULL
, 0, NULL
);
3941 case PA_COMMAND_PREBUF_PLAYBACK_STREAM
:
3942 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_PREBUF_FORCE
, NULL
, 0, NULL
);
3945 case PA_COMMAND_TRIGGER_PLAYBACK_STREAM
:
3946 pa_asyncmsgq_send(s
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(s
->sink_input
), SINK_INPUT_MESSAGE_TRIGGER
, NULL
, 0, NULL
);
3950 pa_assert_not_reached();
3953 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3956 static void command_cork_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3957 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3962 pa_native_connection_assert_ref(c
);
3965 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3966 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
3967 !pa_tagstruct_eof(t
)) {
3972 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3973 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3974 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3976 pa_source_output_cork(s
->source_output
, b
);
3977 pa_memblockq_prebuf_force(s
->memblockq
);
3978 pa_pstream_send_simple_ack(c
->pstream
, tag
);
3981 static void command_flush_record_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
3982 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
3986 pa_native_connection_assert_ref(c
);
3989 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
3990 !pa_tagstruct_eof(t
)) {
3995 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
3996 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
3997 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
3999 pa_memblockq_flush_read(s
->memblockq
);
4000 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4003 static void command_set_stream_buffer_attr(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4004 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4007 pa_tagstruct
*reply
;
4009 pa_native_connection_assert_ref(c
);
4012 memset(&a
, 0, sizeof(a
));
4014 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
4019 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4021 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR
) {
4023 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
4025 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4026 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4027 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4029 if (pa_tagstruct_get(
4031 PA_TAG_U32
, &a
.maxlength
,
4032 PA_TAG_U32
, &a
.tlength
,
4033 PA_TAG_U32
, &a
.prebuf
,
4034 PA_TAG_U32
, &a
.minreq
,
4035 PA_TAG_INVALID
) < 0 ||
4036 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
4037 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
4038 !pa_tagstruct_eof(t
)) {
4043 s
->adjust_latency
= adjust_latency
;
4044 s
->early_requests
= early_requests
;
4045 s
->buffer_attr_req
= a
;
4047 fix_playback_buffer_attr(s
);
4048 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);
4050 reply
= reply_new(tag
);
4051 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
4052 pa_tagstruct_putu32(reply
, s
->buffer_attr
.tlength
);
4053 pa_tagstruct_putu32(reply
, s
->buffer_attr
.prebuf
);
4054 pa_tagstruct_putu32(reply
, s
->buffer_attr
.minreq
);
4056 if (c
->version
>= 13)
4057 pa_tagstruct_put_usec(reply
, s
->configured_sink_latency
);
4061 pa_bool_t adjust_latency
= FALSE
, early_requests
= FALSE
;
4062 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR
);
4064 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4065 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4067 if (pa_tagstruct_get(
4069 PA_TAG_U32
, &a
.maxlength
,
4070 PA_TAG_U32
, &a
.fragsize
,
4071 PA_TAG_INVALID
) < 0 ||
4072 (c
->version
>= 13 && pa_tagstruct_get_boolean(t
, &adjust_latency
) < 0) ||
4073 (c
->version
>= 14 && pa_tagstruct_get_boolean(t
, &early_requests
) < 0) ||
4074 !pa_tagstruct_eof(t
)) {
4079 s
->adjust_latency
= adjust_latency
;
4080 s
->early_requests
= early_requests
;
4081 s
->buffer_attr_req
= a
;
4083 fix_record_buffer_attr_pre(s
);
4084 pa_memblockq_set_maxlength(s
->memblockq
, s
->buffer_attr
.maxlength
);
4085 pa_memblockq_get_attr(s
->memblockq
, &s
->buffer_attr
);
4086 fix_record_buffer_attr_post(s
);
4088 reply
= reply_new(tag
);
4089 pa_tagstruct_putu32(reply
, s
->buffer_attr
.maxlength
);
4090 pa_tagstruct_putu32(reply
, s
->buffer_attr
.fragsize
);
4092 if (c
->version
>= 13)
4093 pa_tagstruct_put_usec(reply
, s
->configured_source_latency
);
4096 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4099 static void command_update_stream_sample_rate(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4100 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4104 pa_native_connection_assert_ref(c
);
4107 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4108 pa_tagstruct_getu32(t
, &rate
) < 0 ||
4109 !pa_tagstruct_eof(t
)) {
4114 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4115 CHECK_VALIDITY(c
->pstream
, rate
> 0 && rate
<= PA_RATE_MAX
, tag
, PA_ERR_INVALID
);
4117 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE
) {
4120 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4121 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4122 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4124 pa_sink_input_set_rate(s
->sink_input
, rate
);
4128 pa_assert(command
== PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE
);
4130 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4131 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4133 pa_source_output_set_rate(s
->source_output
, rate
);
4136 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4139 static void command_update_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4140 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4145 pa_native_connection_assert_ref(c
);
4148 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4150 p
= pa_proplist_new();
4152 if (command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
) {
4154 if (pa_tagstruct_getu32(t
, &mode
) < 0 ||
4155 pa_tagstruct_get_proplist(t
, p
) < 0 ||
4156 !pa_tagstruct_eof(t
)) {
4158 pa_proplist_free(p
);
4164 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4165 pa_tagstruct_getu32(t
, &mode
) < 0 ||
4166 pa_tagstruct_get_proplist(t
, p
) < 0 ||
4167 !pa_tagstruct_eof(t
)) {
4169 pa_proplist_free(p
);
4174 if (!(mode
== PA_UPDATE_SET
|| mode
== PA_UPDATE_MERGE
|| mode
== PA_UPDATE_REPLACE
)) {
4175 pa_proplist_free(p
);
4176 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_INVALID
);
4179 if (command
== PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST
) {
4182 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4183 if (!s
|| !playback_stream_isinstance(s
)) {
4184 pa_proplist_free(p
);
4185 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4187 pa_sink_input_update_proplist(s
->sink_input
, mode
, p
);
4189 } else if (command
== PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST
) {
4192 if (!(s
= pa_idxset_get_by_index(c
->record_streams
, idx
))) {
4193 pa_proplist_free(p
);
4194 CHECK_VALIDITY(c
->pstream
, FALSE
, tag
, PA_ERR_NOENTITY
);
4196 pa_source_output_update_proplist(s
->source_output
, mode
, p
);
4199 pa_assert(command
== PA_COMMAND_UPDATE_CLIENT_PROPLIST
);
4201 pa_client_update_proplist(c
->client
, mode
, p
);
4204 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4205 pa_proplist_free(p
);
4208 static void command_remove_proplist(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4209 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4211 unsigned changed
= 0;
4213 pa_strlist
*l
= NULL
;
4215 pa_native_connection_assert_ref(c
);
4218 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4220 if (command
!= PA_COMMAND_REMOVE_CLIENT_PROPLIST
) {
4222 if (pa_tagstruct_getu32(t
, &idx
) < 0) {
4228 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4231 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4232 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4233 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4235 p
= s
->sink_input
->proplist
;
4237 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4240 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4241 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4243 p
= s
->source_output
->proplist
;
4245 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4247 p
= c
->client
->proplist
;
4253 if (pa_tagstruct_gets(t
, &k
) < 0) {
4262 l
= pa_strlist_prepend(l
, k
);
4265 if (!pa_tagstruct_eof(t
)) {
4274 l
= pa_strlist_pop(l
, &z
);
4279 changed
+= (unsigned) (pa_proplist_unset(p
, z
) >= 0);
4283 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4286 if (command
== PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST
) {
4289 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4290 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SINK_INPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->sink_input
->index
);
4292 } else if (command
== PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST
) {
4295 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4296 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT
|PA_SUBSCRIPTION_EVENT_CHANGE
, s
->source_output
->index
);
4299 pa_assert(command
== PA_COMMAND_REMOVE_CLIENT_PROPLIST
);
4300 pa_subscription_post(c
->protocol
->core
, PA_SUBSCRIPTION_EVENT_CLIENT
|PA_SUBSCRIPTION_EVENT_CHANGE
, c
->client
->index
);
4305 static void command_set_default_sink_or_source(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4306 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4309 pa_native_connection_assert_ref(c
);
4312 if (pa_tagstruct_gets(t
, &s
) < 0 ||
4313 !pa_tagstruct_eof(t
)) {
4318 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4319 CHECK_VALIDITY(c
->pstream
, !s
|| pa_namereg_is_valid_name(s
), tag
, PA_ERR_INVALID
);
4321 if (command
== PA_COMMAND_SET_DEFAULT_SOURCE
) {
4324 source
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SOURCE
);
4325 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4327 pa_namereg_set_default_source(c
->protocol
->core
, source
);
4330 pa_assert(command
== PA_COMMAND_SET_DEFAULT_SINK
);
4332 sink
= pa_namereg_get(c
->protocol
->core
, s
, PA_NAMEREG_SINK
);
4333 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4335 pa_namereg_set_default_sink(c
->protocol
->core
, sink
);
4338 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4341 static void command_set_stream_name(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4342 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4346 pa_native_connection_assert_ref(c
);
4349 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4350 pa_tagstruct_gets(t
, &name
) < 0 ||
4351 !pa_tagstruct_eof(t
)) {
4356 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4357 CHECK_VALIDITY(c
->pstream
, name
&& pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4359 if (command
== PA_COMMAND_SET_PLAYBACK_STREAM_NAME
) {
4362 s
= pa_idxset_get_by_index(c
->output_streams
, idx
);
4363 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4364 CHECK_VALIDITY(c
->pstream
, playback_stream_isinstance(s
), tag
, PA_ERR_NOENTITY
);
4366 pa_sink_input_set_name(s
->sink_input
, name
);
4370 pa_assert(command
== PA_COMMAND_SET_RECORD_STREAM_NAME
);
4372 s
= pa_idxset_get_by_index(c
->record_streams
, idx
);
4373 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4375 pa_source_output_set_name(s
->source_output
, name
);
4378 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4381 static void command_kill(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4382 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4385 pa_native_connection_assert_ref(c
);
4388 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4389 !pa_tagstruct_eof(t
)) {
4394 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4396 if (command
== PA_COMMAND_KILL_CLIENT
) {
4399 client
= pa_idxset_get_by_index(c
->protocol
->core
->clients
, idx
);
4400 CHECK_VALIDITY(c
->pstream
, client
, tag
, PA_ERR_NOENTITY
);
4402 pa_native_connection_ref(c
);
4403 pa_client_kill(client
);
4405 } else if (command
== PA_COMMAND_KILL_SINK_INPUT
) {
4408 s
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4409 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4411 pa_native_connection_ref(c
);
4412 pa_sink_input_kill(s
);
4414 pa_source_output
*s
;
4416 pa_assert(command
== PA_COMMAND_KILL_SOURCE_OUTPUT
);
4418 s
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4419 CHECK_VALIDITY(c
->pstream
, s
, tag
, PA_ERR_NOENTITY
);
4421 pa_native_connection_ref(c
);
4422 pa_source_output_kill(s
);
4425 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4426 pa_native_connection_unref(c
);
4429 static void command_load_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4430 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4432 const char *name
, *argument
;
4433 pa_tagstruct
*reply
;
4435 pa_native_connection_assert_ref(c
);
4438 if (pa_tagstruct_gets(t
, &name
) < 0 ||
4439 pa_tagstruct_gets(t
, &argument
) < 0 ||
4440 !pa_tagstruct_eof(t
)) {
4445 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4446 CHECK_VALIDITY(c
->pstream
, name
&& *name
&& pa_utf8_valid(name
) && !strchr(name
, '/'), tag
, PA_ERR_INVALID
);
4447 CHECK_VALIDITY(c
->pstream
, !argument
|| pa_utf8_valid(argument
), tag
, PA_ERR_INVALID
);
4449 if (!(m
= pa_module_load(c
->protocol
->core
, name
, argument
))) {
4450 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_MODINITFAILED
);
4454 reply
= reply_new(tag
);
4455 pa_tagstruct_putu32(reply
, m
->index
);
4456 pa_pstream_send_tagstruct(c
->pstream
, reply
);
4459 static void command_unload_module(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4460 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4464 pa_native_connection_assert_ref(c
);
4467 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4468 !pa_tagstruct_eof(t
)) {
4473 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4474 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4475 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOENTITY
);
4477 pa_module_unload_request(m
, FALSE
);
4478 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4481 static void command_move_stream(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4482 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4483 uint32_t idx
= PA_INVALID_INDEX
, idx_device
= PA_INVALID_INDEX
;
4484 const char *name_device
= NULL
;
4486 pa_native_connection_assert_ref(c
);
4489 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4490 pa_tagstruct_getu32(t
, &idx_device
) < 0 ||
4491 pa_tagstruct_gets(t
, &name_device
) < 0 ||
4492 !pa_tagstruct_eof(t
)) {
4497 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4498 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4500 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
);
4501 CHECK_VALIDITY(c
->pstream
, idx_device
!= PA_INVALID_INDEX
|| name_device
, tag
, PA_ERR_INVALID
);
4502 CHECK_VALIDITY(c
->pstream
, idx_device
== PA_INVALID_INDEX
|| !name_device
, tag
, PA_ERR_INVALID
);
4503 CHECK_VALIDITY(c
->pstream
, !name_device
|| idx_device
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4505 if (command
== PA_COMMAND_MOVE_SINK_INPUT
) {
4506 pa_sink_input
*si
= NULL
;
4507 pa_sink
*sink
= NULL
;
4509 si
= pa_idxset_get_by_index(c
->protocol
->core
->sink_inputs
, idx
);
4511 if (idx_device
!= PA_INVALID_INDEX
)
4512 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx_device
);
4514 sink
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SINK
);
4516 CHECK_VALIDITY(c
->pstream
, si
&& sink
, tag
, PA_ERR_NOENTITY
);
4518 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
4519 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4523 pa_source_output
*so
= NULL
;
4526 pa_assert(command
== PA_COMMAND_MOVE_SOURCE_OUTPUT
);
4528 so
= pa_idxset_get_by_index(c
->protocol
->core
->source_outputs
, idx
);
4530 if (idx_device
!= PA_INVALID_INDEX
)
4531 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx_device
);
4533 source
= pa_namereg_get(c
->protocol
->core
, name_device
, PA_NAMEREG_SOURCE
);
4535 CHECK_VALIDITY(c
->pstream
, so
&& source
, tag
, PA_ERR_NOENTITY
);
4537 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
4538 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4543 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4546 static void command_suspend(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4547 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4548 uint32_t idx
= PA_INVALID_INDEX
;
4549 const char *name
= NULL
;
4552 pa_native_connection_assert_ref(c
);
4555 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4556 pa_tagstruct_gets(t
, &name
) < 0 ||
4557 pa_tagstruct_get_boolean(t
, &b
) < 0 ||
4558 !pa_tagstruct_eof(t
)) {
4563 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4564 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
);
4565 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4566 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4567 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4569 if (command
== PA_COMMAND_SUSPEND_SINK
) {
4571 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4573 pa_log_debug("%s all sinks", b
? "Suspending" : "Resuming");
4575 if (pa_sink_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4576 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4580 pa_sink
*sink
= NULL
;
4582 if (idx
!= PA_INVALID_INDEX
)
4583 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4585 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4587 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4589 pa_log_debug("%s of sink %s requested by client %" PRIu32
".",
4590 b
? "Suspending" : "Resuming", sink
->name
, c
->client
->index
);
4592 if (pa_sink_suspend(sink
, b
, PA_SUSPEND_USER
) < 0) {
4593 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4599 pa_assert(command
== PA_COMMAND_SUSPEND_SOURCE
);
4601 if (idx
== PA_INVALID_INDEX
&& name
&& !*name
) {
4603 pa_log_debug("%s all sources", b
? "Suspending" : "Resuming");
4605 if (pa_source_suspend_all(c
->protocol
->core
, b
, PA_SUSPEND_USER
) < 0) {
4606 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4613 if (idx
!= PA_INVALID_INDEX
)
4614 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4616 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4618 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4620 pa_log_debug("%s of source %s requested by client %" PRIu32
".",
4621 b
? "Suspending" : "Resuming", source
->name
, c
->client
->index
);
4623 if (pa_source_suspend(source
, b
, PA_SUSPEND_USER
) < 0) {
4624 pa_pstream_send_error(c
->pstream
, tag
, PA_ERR_INVALID
);
4630 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4633 static void command_extension(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4634 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4635 uint32_t idx
= PA_INVALID_INDEX
;
4636 const char *name
= NULL
;
4638 pa_native_protocol_ext_cb_t cb
;
4640 pa_native_connection_assert_ref(c
);
4643 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4644 pa_tagstruct_gets(t
, &name
) < 0) {
4649 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4650 CHECK_VALIDITY(c
->pstream
, !name
|| pa_utf8_valid(name
), tag
, PA_ERR_INVALID
);
4651 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4652 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4653 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4655 if (idx
!= PA_INVALID_INDEX
)
4656 m
= pa_idxset_get_by_index(c
->protocol
->core
->modules
, idx
);
4658 PA_IDXSET_FOREACH(m
, c
->protocol
->core
->modules
, idx
)
4659 if (pa_streq(name
, m
->name
))
4662 CHECK_VALIDITY(c
->pstream
, m
, tag
, PA_ERR_NOEXTENSION
);
4663 CHECK_VALIDITY(c
->pstream
, m
->load_once
|| idx
!= PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4665 cb
= (pa_native_protocol_ext_cb_t
) (unsigned long) pa_hashmap_get(c
->protocol
->extensions
, m
);
4666 CHECK_VALIDITY(c
->pstream
, cb
, tag
, PA_ERR_NOEXTENSION
);
4668 if (cb(c
->protocol
, m
, c
, tag
, t
) < 0)
4672 static void command_set_card_profile(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4673 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4674 uint32_t idx
= PA_INVALID_INDEX
;
4675 const char *name
= NULL
, *profile
= NULL
;
4676 pa_card
*card
= NULL
;
4679 pa_native_connection_assert_ref(c
);
4682 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4683 pa_tagstruct_gets(t
, &name
) < 0 ||
4684 pa_tagstruct_gets(t
, &profile
) < 0 ||
4685 !pa_tagstruct_eof(t
)) {
4690 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4691 CHECK_VALIDITY(c
->pstream
, !name
|| pa_namereg_is_valid_name(name
), tag
, PA_ERR_INVALID
);
4692 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| name
, tag
, PA_ERR_INVALID
);
4693 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !name
, tag
, PA_ERR_INVALID
);
4694 CHECK_VALIDITY(c
->pstream
, !name
|| idx
== PA_INVALID_INDEX
, tag
, PA_ERR_INVALID
);
4696 if (idx
!= PA_INVALID_INDEX
)
4697 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4699 card
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_CARD
);
4701 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4703 if ((ret
= pa_card_set_profile(card
, profile
, TRUE
)) < 0) {
4704 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4708 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4711 static void command_set_sink_or_source_port(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4712 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4713 uint32_t idx
= PA_INVALID_INDEX
;
4714 const char *name
= NULL
, *port
= NULL
;
4717 pa_native_connection_assert_ref(c
);
4720 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4721 pa_tagstruct_gets(t
, &name
) < 0 ||
4722 pa_tagstruct_gets(t
, &port
) < 0 ||
4723 !pa_tagstruct_eof(t
)) {
4728 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4729 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
);
4730 CHECK_VALIDITY(c
->pstream
, (idx
!= PA_INVALID_INDEX
) ^ (name
!= NULL
), tag
, PA_ERR_INVALID
);
4731 CHECK_VALIDITY(c
->pstream
, port
, tag
, PA_ERR_INVALID
);
4733 if (command
== PA_COMMAND_SET_SINK_PORT
) {
4736 if (idx
!= PA_INVALID_INDEX
)
4737 sink
= pa_idxset_get_by_index(c
->protocol
->core
->sinks
, idx
);
4739 sink
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SINK
);
4741 CHECK_VALIDITY(c
->pstream
, sink
, tag
, PA_ERR_NOENTITY
);
4743 if ((ret
= pa_sink_set_port(sink
, port
, TRUE
)) < 0) {
4744 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4750 pa_assert(command
= PA_COMMAND_SET_SOURCE_PORT
);
4752 if (idx
!= PA_INVALID_INDEX
)
4753 source
= pa_idxset_get_by_index(c
->protocol
->core
->sources
, idx
);
4755 source
= pa_namereg_get(c
->protocol
->core
, name
, PA_NAMEREG_SOURCE
);
4757 CHECK_VALIDITY(c
->pstream
, source
, tag
, PA_ERR_NOENTITY
);
4759 if ((ret
= pa_source_set_port(source
, port
, TRUE
)) < 0) {
4760 pa_pstream_send_error(c
->pstream
, tag
, -ret
);
4765 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4768 static void command_set_port_latency_offset(pa_pdispatch
*pd
, uint32_t command
, uint32_t tag
, pa_tagstruct
*t
, void *userdata
) {
4769 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4770 const char *port_name
, *card_name
;
4771 uint32_t idx
= PA_INVALID_INDEX
;
4773 pa_card
*card
= NULL
;
4774 pa_device_port
*port
= NULL
;
4776 pa_native_connection_assert_ref(c
);
4779 if (pa_tagstruct_getu32(t
, &idx
) < 0 ||
4780 pa_tagstruct_gets(t
, &card_name
) < 0 ||
4781 pa_tagstruct_gets(t
, &port_name
) < 0 ||
4782 pa_tagstruct_gets64(t
, &offset
) < 0 ||
4783 !pa_tagstruct_eof(t
)) {
4787 CHECK_VALIDITY(c
->pstream
, c
->authorized
, tag
, PA_ERR_ACCESS
);
4788 CHECK_VALIDITY(c
->pstream
, !card_name
|| pa_namereg_is_valid_name(card_name
), tag
, PA_ERR_INVALID
);
4789 CHECK_VALIDITY(c
->pstream
, idx
!= PA_INVALID_INDEX
|| card_name
, tag
, PA_ERR_INVALID
);
4790 CHECK_VALIDITY(c
->pstream
, idx
== PA_INVALID_INDEX
|| !card_name
, tag
, PA_ERR_INVALID
);
4791 CHECK_VALIDITY(c
->pstream
, port_name
, tag
, PA_ERR_INVALID
);
4793 if (idx
!= PA_INVALID_INDEX
)
4794 card
= pa_idxset_get_by_index(c
->protocol
->core
->cards
, idx
);
4796 card
= pa_namereg_get(c
->protocol
->core
, card_name
, PA_NAMEREG_CARD
);
4798 CHECK_VALIDITY(c
->pstream
, card
, tag
, PA_ERR_NOENTITY
);
4800 port
= pa_hashmap_get(card
->ports
, port_name
);
4801 CHECK_VALIDITY(c
->pstream
, port
, tag
, PA_ERR_NOENTITY
);
4803 pa_device_port_set_latency_offset(port
, offset
);
4805 pa_pstream_send_simple_ack(c
->pstream
, tag
);
4808 /*** pstream callbacks ***/
4810 static void pstream_packet_callback(pa_pstream
*p
, pa_packet
*packet
, const pa_creds
*creds
, void *userdata
) {
4811 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4815 pa_native_connection_assert_ref(c
);
4817 if (pa_pdispatch_run(c
->pdispatch
, packet
, creds
, c
) < 0) {
4818 pa_log("invalid packet.");
4819 native_connection_unlink(c
);
4823 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
) {
4824 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4825 output_stream
*stream
;
4829 pa_native_connection_assert_ref(c
);
4831 if (!(stream
= OUTPUT_STREAM(pa_idxset_get_by_index(c
->output_streams
, channel
)))) {
4832 pa_log_debug("Client sent block for invalid stream.");
4837 #ifdef PROTOCOL_NATIVE_DEBUG
4838 pa_log("got %lu bytes from client", (unsigned long) chunk
->length
);
4841 if (playback_stream_isinstance(stream
)) {
4842 playback_stream
*ps
= PLAYBACK_STREAM(stream
);
4844 pa_atomic_inc(&ps
->seek_or_post_in_queue
);
4845 if (chunk
->memblock
) {
4846 if (seek
!= PA_SEEK_RELATIVE
|| offset
!= 0)
4847 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
);
4849 pa_asyncmsgq_post(ps
->sink_input
->sink
->asyncmsgq
, PA_MSGOBJECT(ps
->sink_input
), SINK_INPUT_MESSAGE_POST_DATA
, NULL
, 0, chunk
, NULL
);
4851 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
);
4854 upload_stream
*u
= UPLOAD_STREAM(stream
);
4857 if (!u
->memchunk
.memblock
) {
4858 if (u
->length
== chunk
->length
&& chunk
->memblock
) {
4859 u
->memchunk
= *chunk
;
4860 pa_memblock_ref(u
->memchunk
.memblock
);
4863 u
->memchunk
.memblock
= pa_memblock_new(c
->protocol
->core
->mempool
, u
->length
);
4864 u
->memchunk
.index
= u
->memchunk
.length
= 0;
4868 pa_assert(u
->memchunk
.memblock
);
4871 if (l
> chunk
->length
)
4876 dst
= pa_memblock_acquire(u
->memchunk
.memblock
);
4878 if (chunk
->memblock
) {
4880 src
= pa_memblock_acquire(chunk
->memblock
);
4882 memcpy((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
,
4883 (uint8_t*) src
+ chunk
->index
, l
);
4885 pa_memblock_release(chunk
->memblock
);
4887 pa_silence_memory((uint8_t*) dst
+ u
->memchunk
.index
+ u
->memchunk
.length
, l
, &u
->sample_spec
);
4889 pa_memblock_release(u
->memchunk
.memblock
);
4891 u
->memchunk
.length
+= l
;
4897 static void pstream_die_callback(pa_pstream
*p
, void *userdata
) {
4898 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4901 pa_native_connection_assert_ref(c
);
4903 native_connection_unlink(c
);
4904 pa_log_info("Connection died.");
4907 static void pstream_drain_callback(pa_pstream
*p
, void *userdata
) {
4908 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4911 pa_native_connection_assert_ref(c
);
4913 native_connection_send_memblock(c
);
4916 static void pstream_revoke_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4919 if (!(q
= pa_thread_mq_get()))
4920 pa_pstream_send_revoke(p
, block_id
);
4922 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_REVOKE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4925 static void pstream_release_callback(pa_pstream
*p
, uint32_t block_id
, void *userdata
) {
4928 if (!(q
= pa_thread_mq_get()))
4929 pa_pstream_send_release(p
, block_id
);
4931 pa_asyncmsgq_post(q
->outq
, PA_MSGOBJECT(userdata
), CONNECTION_MESSAGE_RELEASE
, PA_UINT_TO_PTR(block_id
), 0, NULL
, NULL
);
4934 /*** client callbacks ***/
4936 static void client_kill_cb(pa_client
*c
) {
4939 native_connection_unlink(PA_NATIVE_CONNECTION(c
->userdata
));
4940 pa_log_info("Connection killed.");
4943 static void client_send_event_cb(pa_client
*client
, const char*event
, pa_proplist
*pl
) {
4945 pa_native_connection
*c
;
4948 c
= PA_NATIVE_CONNECTION(client
->userdata
);
4949 pa_native_connection_assert_ref(c
);
4951 if (c
->version
< 15)
4954 t
= pa_tagstruct_new(NULL
, 0);
4955 pa_tagstruct_putu32(t
, PA_COMMAND_CLIENT_EVENT
);
4956 pa_tagstruct_putu32(t
, (uint32_t) -1); /* tag */
4957 pa_tagstruct_puts(t
, event
);
4958 pa_tagstruct_put_proplist(t
, pl
);
4959 pa_pstream_send_tagstruct(c
->pstream
, t
);
4962 /*** module entry points ***/
4964 static void auth_timeout(pa_mainloop_api
*m
, pa_time_event
*e
, const struct timeval
*t
, void *userdata
) {
4965 pa_native_connection
*c
= PA_NATIVE_CONNECTION(userdata
);
4968 pa_native_connection_assert_ref(c
);
4969 pa_assert(c
->auth_timeout_event
== e
);
4971 if (!c
->authorized
) {
4972 native_connection_unlink(c
);
4973 pa_log_info("Connection terminated due to authentication timeout.");
4977 void pa_native_protocol_connect(pa_native_protocol
*p
, pa_iochannel
*io
, pa_native_options
*o
) {
4978 pa_native_connection
*c
;
4981 pa_client_new_data data
;
4987 if (pa_idxset_size(p
->connections
)+1 > MAX_CONNECTIONS
) {
4988 pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS
);
4989 pa_iochannel_free(io
);
4993 pa_client_new_data_init(&data
);
4994 data
.module
= o
->module
;
4995 data
.driver
= __FILE__
;
4996 pa_iochannel_socket_peer_to_string(io
, pname
, sizeof(pname
));
4997 pa_proplist_setf(data
.proplist
, PA_PROP_APPLICATION_NAME
, "Native client (%s)", pname
);
4998 pa_proplist_sets(data
.proplist
, "native-protocol.peer", pname
);
4999 client
= pa_client_new(p
->core
, &data
);
5000 pa_client_new_data_done(&data
);
5005 c
= pa_msgobject_new(pa_native_connection
);
5006 c
->parent
.parent
.free
= native_connection_free
;
5007 c
->parent
.process_msg
= native_connection_process_msg
;
5009 c
->options
= pa_native_options_ref(o
);
5010 c
->authorized
= FALSE
;
5012 if (o
->auth_anonymous
) {
5013 pa_log_info("Client authenticated anonymously.");
5014 c
->authorized
= TRUE
;
5017 if (!c
->authorized
&&
5019 pa_ip_acl_check(o
->auth_ip_acl
, pa_iochannel_get_recv_fd(io
)) > 0) {
5021 pa_log_info("Client authenticated by IP ACL.");
5022 c
->authorized
= TRUE
;
5026 c
->auth_timeout_event
= pa_core_rttime_new(p
->core
, pa_rtclock_now() + AUTH_TIMEOUT
, auth_timeout
, c
);
5028 c
->auth_timeout_event
= NULL
;
5030 c
->is_local
= pa_iochannel_socket_is_local(io
);
5034 c
->client
->kill
= client_kill_cb
;
5035 c
->client
->send_event
= client_send_event_cb
;
5036 c
->client
->userdata
= c
;
5038 c
->pstream
= pa_pstream_new(p
->core
->mainloop
, io
, p
->core
->mempool
);
5039 pa_pstream_set_receive_packet_callback(c
->pstream
, pstream_packet_callback
, c
);
5040 pa_pstream_set_receive_memblock_callback(c
->pstream
, pstream_memblock_callback
, c
);
5041 pa_pstream_set_die_callback(c
->pstream
, pstream_die_callback
, c
);
5042 pa_pstream_set_drain_callback(c
->pstream
, pstream_drain_callback
, c
);
5043 pa_pstream_set_revoke_callback(c
->pstream
, pstream_revoke_callback
, c
);
5044 pa_pstream_set_release_callback(c
->pstream
, pstream_release_callback
, c
);
5046 c
->pdispatch
= pa_pdispatch_new(p
->core
->mainloop
, TRUE
, command_table
, PA_COMMAND_MAX
);
5048 c
->record_streams
= pa_idxset_new(NULL
, NULL
);
5049 c
->output_streams
= pa_idxset_new(NULL
, NULL
);
5051 c
->rrobin_index
= PA_IDXSET_INVALID
;
5052 c
->subscription
= NULL
;
5054 pa_idxset_put(p
->connections
, c
, NULL
);
5057 if (pa_iochannel_creds_supported(io
))
5058 pa_iochannel_creds_enable(io
);
5061 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_CONNECTION_PUT
], c
);
5064 void pa_native_protocol_disconnect(pa_native_protocol
*p
, pa_module
*m
) {
5065 pa_native_connection
*c
;
5071 while ((c
= pa_idxset_iterate(p
->connections
, &state
, NULL
)))
5072 if (c
->options
->module
== m
)
5073 native_connection_unlink(c
);
5076 static pa_native_protocol
* native_protocol_new(pa_core
*c
) {
5077 pa_native_protocol
*p
;
5082 p
= pa_xnew(pa_native_protocol
, 1);
5085 p
->connections
= pa_idxset_new(NULL
, NULL
);
5089 p
->extensions
= pa_hashmap_new(pa_idxset_trivial_hash_func
, pa_idxset_trivial_compare_func
);
5091 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
5092 pa_hook_init(&p
->hooks
[h
], p
);
5094 pa_assert_se(pa_shared_set(c
, "native-protocol", p
) >= 0);
5099 pa_native_protocol
* pa_native_protocol_get(pa_core
*c
) {
5100 pa_native_protocol
*p
;
5102 if ((p
= pa_shared_get(c
, "native-protocol")))
5103 return pa_native_protocol_ref(p
);
5105 return native_protocol_new(c
);
5108 pa_native_protocol
* pa_native_protocol_ref(pa_native_protocol
*p
) {
5110 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5117 void pa_native_protocol_unref(pa_native_protocol
*p
) {
5118 pa_native_connection
*c
;
5122 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5124 if (PA_REFCNT_DEC(p
) > 0)
5127 while ((c
= pa_idxset_first(p
->connections
, NULL
)))
5128 native_connection_unlink(c
);
5130 pa_idxset_free(p
->connections
, NULL
);
5132 pa_strlist_free(p
->servers
);
5134 for (h
= 0; h
< PA_NATIVE_HOOK_MAX
; h
++)
5135 pa_hook_done(&p
->hooks
[h
]);
5137 pa_hashmap_free(p
->extensions
, NULL
);
5139 pa_assert_se(pa_shared_remove(p
->core
, "native-protocol") >= 0);
5144 void pa_native_protocol_add_server_string(pa_native_protocol
*p
, const char *name
) {
5146 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5149 p
->servers
= pa_strlist_prepend(p
->servers
, name
);
5151 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
5154 void pa_native_protocol_remove_server_string(pa_native_protocol
*p
, const char *name
) {
5156 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5159 p
->servers
= pa_strlist_remove(p
->servers
, name
);
5161 pa_hook_fire(&p
->hooks
[PA_NATIVE_HOOK_SERVERS_CHANGED
], p
->servers
);
5164 pa_hook
*pa_native_protocol_hooks(pa_native_protocol
*p
) {
5166 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5171 pa_strlist
*pa_native_protocol_servers(pa_native_protocol
*p
) {
5173 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5178 int pa_native_protocol_install_ext(pa_native_protocol
*p
, pa_module
*m
, pa_native_protocol_ext_cb_t cb
) {
5180 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5183 pa_assert(!pa_hashmap_get(p
->extensions
, m
));
5185 pa_assert_se(pa_hashmap_put(p
->extensions
, m
, (void*) (unsigned long) cb
) == 0);
5189 void pa_native_protocol_remove_ext(pa_native_protocol
*p
, pa_module
*m
) {
5191 pa_assert(PA_REFCNT_VALUE(p
) >= 1);
5194 pa_assert_se(pa_hashmap_remove(p
->extensions
, m
));
5197 pa_native_options
* pa_native_options_new(void) {
5198 pa_native_options
*o
;
5200 o
= pa_xnew0(pa_native_options
, 1);
5206 pa_native_options
* pa_native_options_ref(pa_native_options
*o
) {
5208 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5215 void pa_native_options_unref(pa_native_options
*o
) {
5217 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5219 if (PA_REFCNT_DEC(o
) > 0)
5222 pa_xfree(o
->auth_group
);
5225 pa_ip_acl_free(o
->auth_ip_acl
);
5228 pa_auth_cookie_unref(o
->auth_cookie
);
5233 int pa_native_options_parse(pa_native_options
*o
, pa_core
*c
, pa_modargs
*ma
) {
5238 pa_assert(PA_REFCNT_VALUE(o
) >= 1);
5241 if (pa_modargs_get_value_boolean(ma
, "auth-anonymous", &o
->auth_anonymous
) < 0) {
5242 pa_log("auth-anonymous= expects a boolean argument.");
5247 if (pa_modargs_get_value_boolean(ma
, "auth-group-enable", &enabled
) < 0) {
5248 pa_log("auth-group-enable= expects a boolean argument.");
5252 pa_xfree(o
->auth_group
);
5253 o
->auth_group
= enabled
? pa_xstrdup(pa_modargs_get_value(ma
, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP
: NULL
)) : NULL
;
5257 pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
5260 if ((acl
= pa_modargs_get_value(ma
, "auth-ip-acl", NULL
))) {
5263 if (!(ipa
= pa_ip_acl_new(acl
))) {
5264 pa_log("Failed to parse IP ACL '%s'", acl
);
5269 pa_ip_acl_free(o
->auth_ip_acl
);
5271 o
->auth_ip_acl
= ipa
;
5275 if (pa_modargs_get_value_boolean(ma
, "auth-cookie-enabled", &enabled
) < 0) {
5276 pa_log("auth-cookie-enabled= expects a boolean argument.");
5281 pa_auth_cookie_unref(o
->auth_cookie
);
5286 /* The new name for this is 'auth-cookie', for compat reasons
5287 * we check the old name too */
5288 cn
= pa_modargs_get_value(ma
, "auth-cookie", NULL
);
5290 cn
= pa_modargs_get_value(ma
, "cookie", NULL
);
5293 o
->auth_cookie
= pa_auth_cookie_get(c
, cn
, TRUE
, PA_NATIVE_COOKIE_LENGTH
);
5295 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE
, FALSE
, PA_NATIVE_COOKIE_LENGTH
);
5296 if (!o
->auth_cookie
) {
5297 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE_FALLBACK
, FALSE
, PA_NATIVE_COOKIE_LENGTH
);
5299 if (!o
->auth_cookie
)
5300 o
->auth_cookie
= pa_auth_cookie_get(c
, PA_NATIVE_COOKIE_FILE
, TRUE
, PA_NATIVE_COOKIE_LENGTH
);
5304 if (!o
->auth_cookie
)
5308 o
->auth_cookie
= NULL
;
5313 pa_pstream
* pa_native_connection_get_pstream(pa_native_connection
*c
) {
5314 pa_native_connection_assert_ref(c
);
5319 pa_client
* pa_native_connection_get_client(pa_native_connection
*c
) {
5320 pa_native_connection_assert_ref(c
);