protocol-native: replace use of pa_namereg_is_valid_name() by pa_namereg_is_valid_nam...
[profile/ivi/pulseaudio.git] / src / pulsecore / protocol-native.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20   USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <string.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31
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
39 #include <pulsecore/native-common.h>
40 #include <pulsecore/packet.h>
41 #include <pulsecore/client.h>
42 #include <pulsecore/source-output.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/pstream.h>
45 #include <pulsecore/tagstruct.h>
46 #include <pulsecore/pdispatch.h>
47 #include <pulsecore/pstream-util.h>
48 #include <pulsecore/authkey.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/core-subscribe.h>
52 #include <pulsecore/log.h>
53 #include <pulsecore/strlist.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/llist.h>
57 #include <pulsecore/creds.h>
58 #include <pulsecore/core-util.h>
59 #include <pulsecore/ipacl.h>
60 #include <pulsecore/thread-mq.h>
61
62 #include "protocol-native.h"
63
64 /* Kick a client if it doesn't authenticate within this time */
65 #define AUTH_TIMEOUT (60 * PA_USEC_PER_SEC)
66
67 /* Don't accept more connection than this */
68 #define MAX_CONNECTIONS 64
69
70 #define MAX_MEMBLOCKQ_LENGTH (4*1024*1024) /* 4MB */
71 #define DEFAULT_TLENGTH_MSEC 2000 /* 2s */
72 #define DEFAULT_PROCESS_MSEC 20   /* 20ms */
73 #define DEFAULT_FRAGSIZE_MSEC DEFAULT_TLENGTH_MSEC
74
75 struct pa_native_protocol;
76
77 typedef struct record_stream {
78     pa_msgobject parent;
79
80     pa_native_connection *connection;
81     uint32_t index;
82
83     pa_source_output *source_output;
84     pa_memblockq *memblockq;
85
86     pa_bool_t adjust_latency:1;
87     pa_bool_t early_requests:1;
88
89     pa_buffer_attr buffer_attr;
90
91     pa_atomic_t on_the_fly;
92     pa_usec_t configured_source_latency;
93     size_t drop_initial;
94
95     /* Only updated after SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY */
96     size_t on_the_fly_snapshot;
97     pa_usec_t current_monitor_latency;
98     pa_usec_t current_source_latency;
99 } record_stream;
100
101 #define RECORD_STREAM(o) (record_stream_cast(o))
102 PA_DEFINE_PRIVATE_CLASS(record_stream, pa_msgobject);
103
104 typedef struct output_stream {
105     pa_msgobject parent;
106 } output_stream;
107
108 #define OUTPUT_STREAM(o) (output_stream_cast(o))
109 PA_DEFINE_PRIVATE_CLASS(output_stream, pa_msgobject);
110
111 typedef struct playback_stream {
112     output_stream parent;
113
114     pa_native_connection *connection;
115     uint32_t index;
116
117     pa_sink_input *sink_input;
118     pa_memblockq *memblockq;
119
120     pa_bool_t adjust_latency:1;
121     pa_bool_t early_requests:1;
122
123     pa_bool_t is_underrun:1;
124     pa_bool_t drain_request:1;
125     uint32_t drain_tag;
126     uint32_t syncid;
127
128     pa_atomic_t missing;
129     pa_usec_t configured_sink_latency;
130     pa_buffer_attr buffer_attr;
131
132     /* Only updated after SINK_INPUT_MESSAGE_UPDATE_LATENCY */
133     int64_t read_index, write_index;
134     size_t render_memblockq_length;
135     pa_usec_t current_sink_latency;
136     uint64_t playing_for, underrun_for;
137 } playback_stream;
138
139 #define PLAYBACK_STREAM(o) (playback_stream_cast(o))
140 PA_DEFINE_PRIVATE_CLASS(playback_stream, output_stream);
141
142 typedef struct upload_stream {
143     output_stream parent;
144
145     pa_native_connection *connection;
146     uint32_t index;
147
148     pa_memchunk memchunk;
149     size_t length;
150     char *name;
151     pa_sample_spec sample_spec;
152     pa_channel_map channel_map;
153     pa_proplist *proplist;
154 } upload_stream;
155
156 #define UPLOAD_STREAM(o) (upload_stream_cast(o))
157 PA_DEFINE_PRIVATE_CLASS(upload_stream, output_stream);
158
159 struct pa_native_connection {
160     pa_msgobject parent;
161     pa_native_protocol *protocol;
162     pa_native_options *options;
163     pa_bool_t authorized:1;
164     pa_bool_t is_local:1;
165     uint32_t version;
166     pa_client *client;
167     pa_pstream *pstream;
168     pa_pdispatch *pdispatch;
169     pa_idxset *record_streams, *output_streams;
170     uint32_t rrobin_index;
171     pa_subscription *subscription;
172     pa_time_event *auth_timeout_event;
173 };
174
175 #define PA_NATIVE_CONNECTION(o) (pa_native_connection_cast(o))
176 PA_DEFINE_PRIVATE_CLASS(pa_native_connection, pa_msgobject);
177
178 struct pa_native_protocol {
179     PA_REFCNT_DECLARE;
180
181     pa_core *core;
182     pa_idxset *connections;
183
184     pa_strlist *servers;
185     pa_hook hooks[PA_NATIVE_HOOK_MAX];
186
187     pa_hashmap *extensions;
188 };
189
190 enum {
191     SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY = PA_SOURCE_OUTPUT_MESSAGE_MAX
192 };
193
194 enum {
195     SINK_INPUT_MESSAGE_POST_DATA = PA_SINK_INPUT_MESSAGE_MAX, /* data from main loop to sink input */
196     SINK_INPUT_MESSAGE_DRAIN, /* disabled prebuf, get playback started. */
197     SINK_INPUT_MESSAGE_FLUSH,
198     SINK_INPUT_MESSAGE_TRIGGER,
199     SINK_INPUT_MESSAGE_SEEK,
200     SINK_INPUT_MESSAGE_PREBUF_FORCE,
201     SINK_INPUT_MESSAGE_UPDATE_LATENCY,
202     SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR
203 };
204
205 enum {
206     PLAYBACK_STREAM_MESSAGE_REQUEST_DATA,      /* data requested from sink input from the main loop */
207     PLAYBACK_STREAM_MESSAGE_UNDERFLOW,
208     PLAYBACK_STREAM_MESSAGE_OVERFLOW,
209     PLAYBACK_STREAM_MESSAGE_DRAIN_ACK,
210     PLAYBACK_STREAM_MESSAGE_STARTED,
211     PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH
212 };
213
214 enum {
215     RECORD_STREAM_MESSAGE_POST_DATA         /* data from source output to main loop */
216 };
217
218 enum {
219     CONNECTION_MESSAGE_RELEASE,
220     CONNECTION_MESSAGE_REVOKE
221 };
222
223 static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
224 static void sink_input_kill_cb(pa_sink_input *i);
225 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
226 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest);
227 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes);
228 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes);
229 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes);
230 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl);
231
232 static void native_connection_send_memblock(pa_native_connection *c);
233 static void playback_stream_request_bytes(struct playback_stream*s);
234
235 static void source_output_kill_cb(pa_source_output *o);
236 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk);
237 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend);
238 static void source_output_moving_cb(pa_source_output *o, pa_source *dest);
239 static pa_usec_t source_output_get_latency_cb(pa_source_output *o);
240 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl);
241
242 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
243 static int source_output_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk);
244
245 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
246 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
247 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
248 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
249 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
250 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
251 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
252 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
253 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
254 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
255 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
256 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
257 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
258 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
259 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
260 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
261 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
262 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
263 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
264 static void command_set_volume(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
265 static void command_set_mute(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
266 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
267 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
268 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
269 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
270 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
271 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
272 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
273 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
274 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
275 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
276 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
277 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
278 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
279 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
280 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
281 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
282 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
283 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
284
285 static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
286     [PA_COMMAND_ERROR] = NULL,
287     [PA_COMMAND_TIMEOUT] = NULL,
288     [PA_COMMAND_REPLY] = NULL,
289     [PA_COMMAND_CREATE_PLAYBACK_STREAM] = command_create_playback_stream,
290     [PA_COMMAND_DELETE_PLAYBACK_STREAM] = command_delete_stream,
291     [PA_COMMAND_DRAIN_PLAYBACK_STREAM] = command_drain_playback_stream,
292     [PA_COMMAND_CREATE_RECORD_STREAM] = command_create_record_stream,
293     [PA_COMMAND_DELETE_RECORD_STREAM] = command_delete_stream,
294     [PA_COMMAND_AUTH] = command_auth,
295     [PA_COMMAND_REQUEST] = NULL,
296     [PA_COMMAND_EXIT] = command_exit,
297     [PA_COMMAND_SET_CLIENT_NAME] = command_set_client_name,
298     [PA_COMMAND_LOOKUP_SINK] = command_lookup,
299     [PA_COMMAND_LOOKUP_SOURCE] = command_lookup,
300     [PA_COMMAND_STAT] = command_stat,
301     [PA_COMMAND_GET_PLAYBACK_LATENCY] = command_get_playback_latency,
302     [PA_COMMAND_GET_RECORD_LATENCY] = command_get_record_latency,
303     [PA_COMMAND_CREATE_UPLOAD_STREAM] = command_create_upload_stream,
304     [PA_COMMAND_DELETE_UPLOAD_STREAM] = command_delete_stream,
305     [PA_COMMAND_FINISH_UPLOAD_STREAM] = command_finish_upload_stream,
306     [PA_COMMAND_PLAY_SAMPLE] = command_play_sample,
307     [PA_COMMAND_REMOVE_SAMPLE] = command_remove_sample,
308     [PA_COMMAND_GET_SINK_INFO] = command_get_info,
309     [PA_COMMAND_GET_SOURCE_INFO] = command_get_info,
310     [PA_COMMAND_GET_CLIENT_INFO] = command_get_info,
311     [PA_COMMAND_GET_CARD_INFO] = command_get_info,
312     [PA_COMMAND_GET_MODULE_INFO] = command_get_info,
313     [PA_COMMAND_GET_SINK_INPUT_INFO] = command_get_info,
314     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO] = command_get_info,
315     [PA_COMMAND_GET_SAMPLE_INFO] = command_get_info,
316     [PA_COMMAND_GET_SINK_INFO_LIST] = command_get_info_list,
317     [PA_COMMAND_GET_SOURCE_INFO_LIST] = command_get_info_list,
318     [PA_COMMAND_GET_MODULE_INFO_LIST] = command_get_info_list,
319     [PA_COMMAND_GET_CLIENT_INFO_LIST] = command_get_info_list,
320     [PA_COMMAND_GET_CARD_INFO_LIST] = command_get_info_list,
321     [PA_COMMAND_GET_SINK_INPUT_INFO_LIST] = command_get_info_list,
322     [PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST] = command_get_info_list,
323     [PA_COMMAND_GET_SAMPLE_INFO_LIST] = command_get_info_list,
324     [PA_COMMAND_GET_SERVER_INFO] = command_get_server_info,
325     [PA_COMMAND_SUBSCRIBE] = command_subscribe,
326
327     [PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
328     [PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
329     [PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
330
331     [PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
332     [PA_COMMAND_SET_SINK_INPUT_MUTE] = command_set_mute,
333     [PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
334
335     [PA_COMMAND_SUSPEND_SINK] = command_suspend,
336     [PA_COMMAND_SUSPEND_SOURCE] = command_suspend,
337
338     [PA_COMMAND_CORK_PLAYBACK_STREAM] = command_cork_playback_stream,
339     [PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
340     [PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
341     [PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_flush_or_prebuf_playback_stream,
342
343     [PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
344     [PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
345
346     [PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
347     [PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
348     [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
349     [PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
350     [PA_COMMAND_KILL_CLIENT] = command_kill,
351     [PA_COMMAND_KILL_SINK_INPUT] = command_kill,
352     [PA_COMMAND_KILL_SOURCE_OUTPUT] = command_kill,
353     [PA_COMMAND_LOAD_MODULE] = command_load_module,
354     [PA_COMMAND_UNLOAD_MODULE] = command_unload_module,
355
356     [PA_COMMAND_GET_AUTOLOAD_INFO___OBSOLETE] = NULL,
357     [PA_COMMAND_GET_AUTOLOAD_INFO_LIST___OBSOLETE] = NULL,
358     [PA_COMMAND_ADD_AUTOLOAD___OBSOLETE] = NULL,
359     [PA_COMMAND_REMOVE_AUTOLOAD___OBSOLETE] = NULL,
360
361     [PA_COMMAND_MOVE_SINK_INPUT] = command_move_stream,
362     [PA_COMMAND_MOVE_SOURCE_OUTPUT] = command_move_stream,
363
364     [PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
365     [PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR] = command_set_stream_buffer_attr,
366
367     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
368     [PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE] = command_update_stream_sample_rate,
369
370     [PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST] = command_update_proplist,
371     [PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST] = command_update_proplist,
372     [PA_COMMAND_UPDATE_CLIENT_PROPLIST] = command_update_proplist,
373
374     [PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST] = command_remove_proplist,
375     [PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST] = command_remove_proplist,
376     [PA_COMMAND_REMOVE_CLIENT_PROPLIST] = command_remove_proplist,
377
378     [PA_COMMAND_SET_CARD_PROFILE] = command_set_card_profile,
379
380     [PA_COMMAND_SET_SINK_PORT] = command_set_sink_or_source_port,
381     [PA_COMMAND_SET_SOURCE_PORT] = command_set_sink_or_source_port,
382
383     [PA_COMMAND_EXTENSION] = command_extension
384 };
385
386 /* structure management */
387
388 /* Called from main context */
389 static void upload_stream_unlink(upload_stream *s) {
390     pa_assert(s);
391
392     if (!s->connection)
393         return;
394
395     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
396     s->connection = NULL;
397     upload_stream_unref(s);
398 }
399
400 /* Called from main context */
401 static void upload_stream_free(pa_object *o) {
402     upload_stream *s = UPLOAD_STREAM(o);
403     pa_assert(s);
404
405     upload_stream_unlink(s);
406
407     pa_xfree(s->name);
408
409     if (s->proplist)
410         pa_proplist_free(s->proplist);
411
412     if (s->memchunk.memblock)
413         pa_memblock_unref(s->memchunk.memblock);
414
415     pa_xfree(s);
416 }
417
418 /* Called from main context */
419 static upload_stream* upload_stream_new(
420         pa_native_connection *c,
421         const pa_sample_spec *ss,
422         const pa_channel_map *map,
423         const char *name,
424         size_t length,
425         pa_proplist *p) {
426
427     upload_stream *s;
428
429     pa_assert(c);
430     pa_assert(ss);
431     pa_assert(name);
432     pa_assert(length > 0);
433     pa_assert(p);
434
435     s = pa_msgobject_new(upload_stream);
436     s->parent.parent.parent.free = upload_stream_free;
437     s->connection = c;
438     s->sample_spec = *ss;
439     s->channel_map = *map;
440     s->name = pa_xstrdup(name);
441     pa_memchunk_reset(&s->memchunk);
442     s->length = length;
443     s->proplist = pa_proplist_copy(p);
444     pa_proplist_update(s->proplist, PA_UPDATE_MERGE, c->client->proplist);
445
446     pa_idxset_put(c->output_streams, s, &s->index);
447
448     return s;
449 }
450
451 /* Called from main context */
452 static void record_stream_unlink(record_stream *s) {
453     pa_assert(s);
454
455     if (!s->connection)
456         return;
457
458     if (s->source_output) {
459         pa_source_output_unlink(s->source_output);
460         pa_source_output_unref(s->source_output);
461         s->source_output = NULL;
462     }
463
464     pa_assert_se(pa_idxset_remove_by_data(s->connection->record_streams, s, NULL) == s);
465     s->connection = NULL;
466     record_stream_unref(s);
467 }
468
469 /* Called from main context */
470 static void record_stream_free(pa_object *o) {
471     record_stream *s = RECORD_STREAM(o);
472     pa_assert(s);
473
474     record_stream_unlink(s);
475
476     pa_memblockq_free(s->memblockq);
477     pa_xfree(s);
478 }
479
480 /* Called from main context */
481 static int record_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
482     record_stream *s = RECORD_STREAM(o);
483     record_stream_assert_ref(s);
484
485     if (!s->connection)
486         return -1;
487
488     switch (code) {
489
490         case RECORD_STREAM_MESSAGE_POST_DATA:
491
492             /* We try to keep up to date with how many bytes are
493              * currently on the fly */
494             pa_atomic_sub(&s->on_the_fly, chunk->length);
495
496             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
497 /*                 pa_log_warn("Failed to push data into output queue."); */
498                 return -1;
499             }
500
501             if (!pa_pstream_is_pending(s->connection->pstream))
502                 native_connection_send_memblock(s->connection);
503
504             break;
505     }
506
507     return 0;
508 }
509
510 /* Called from main context */
511 static void fix_record_buffer_attr_pre(record_stream *s) {
512
513     size_t frame_size;
514     pa_usec_t orig_fragsize_usec, fragsize_usec, source_usec;
515
516     pa_assert(s);
517
518     /* This function will be called from the main thread, before as
519      * well as after the source output has been activated using
520      * pa_source_output_put()! That means it may not touch any
521      * ->thread_info data! */
522
523     frame_size = pa_frame_size(&s->source_output->sample_spec);
524
525     if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
526         s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
527     if (s->buffer_attr.maxlength <= 0)
528         s->buffer_attr.maxlength = (uint32_t) frame_size;
529
530     if (s->buffer_attr.fragsize == (uint32_t) -1)
531         s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(DEFAULT_FRAGSIZE_MSEC*PA_USEC_PER_MSEC, &s->source_output->sample_spec);
532     if (s->buffer_attr.fragsize <= 0)
533         s->buffer_attr.fragsize = (uint32_t) frame_size;
534
535     orig_fragsize_usec = fragsize_usec = pa_bytes_to_usec(s->buffer_attr.fragsize, &s->source_output->sample_spec);
536
537     if (s->early_requests) {
538
539         /* In early request mode we need to emulate the classic
540          * fragment-based playback model. We do this setting the source
541          * latency to the fragment size. */
542
543         source_usec = fragsize_usec;
544
545     } else if (s->adjust_latency) {
546
547         /* So, the user asked us to adjust the latency according to
548          * what the source can provide. Half the latency will be
549          * spent on the hw buffer, half of it in the async buffer
550          * queue we maintain for each client. */
551
552         source_usec = fragsize_usec/2;
553
554     } else {
555
556         /* Ok, the user didn't ask us to adjust the latency, hence we
557          * don't */
558
559         source_usec = (pa_usec_t) -1;
560     }
561
562     if (source_usec != (pa_usec_t) -1)
563         s->configured_source_latency = pa_source_output_set_requested_latency(s->source_output, source_usec);
564     else
565         s->configured_source_latency = 0;
566
567     if (s->early_requests) {
568
569         /* Ok, we didn't necessarily get what we were asking for, so
570          * let's tell the user */
571
572         fragsize_usec = s->configured_source_latency;
573
574     } else if (s->adjust_latency) {
575
576         /* Now subtract what we actually got */
577
578         if (fragsize_usec >= s->configured_source_latency*2)
579             fragsize_usec -= s->configured_source_latency;
580         else
581             fragsize_usec = s->configured_source_latency;
582     }
583
584     if (pa_usec_to_bytes(orig_fragsize_usec, &s->source_output->sample_spec) !=
585         pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec))
586
587         s->buffer_attr.fragsize = (uint32_t) pa_usec_to_bytes(fragsize_usec, &s->source_output->sample_spec);
588
589     if (s->buffer_attr.fragsize <= 0)
590         s->buffer_attr.fragsize = (uint32_t) frame_size;
591 }
592
593 /* Called from main context */
594 static void fix_record_buffer_attr_post(record_stream *s) {
595     size_t base;
596
597     pa_assert(s);
598
599     /* This function will be called from the main thread, before as
600      * well as after the source output has been activated using
601      * pa_source_output_put()! That means it may not touch and
602      * ->thread_info data! */
603
604     base = pa_frame_size(&s->source_output->sample_spec);
605
606     s->buffer_attr.fragsize = (s->buffer_attr.fragsize/base)*base;
607     if (s->buffer_attr.fragsize <= 0)
608         s->buffer_attr.fragsize = base;
609
610     if (s->buffer_attr.fragsize > s->buffer_attr.maxlength)
611         s->buffer_attr.fragsize = s->buffer_attr.maxlength;
612 }
613
614 /* Called from main context */
615 static record_stream* record_stream_new(
616         pa_native_connection *c,
617         pa_source *source,
618         pa_sample_spec *ss,
619         pa_channel_map *map,
620         pa_bool_t peak_detect,
621         pa_buffer_attr *attr,
622         pa_source_output_flags_t flags,
623         pa_proplist *p,
624         pa_bool_t adjust_latency,
625         pa_sink_input *direct_on_input,
626         pa_bool_t early_requests,
627         int *ret) {
628
629     record_stream *s;
630     pa_source_output *source_output = NULL;
631     size_t base;
632     pa_source_output_new_data data;
633
634     pa_assert(c);
635     pa_assert(ss);
636     pa_assert(p);
637     pa_assert(ret);
638
639     pa_source_output_new_data_init(&data);
640
641     pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
642     data.driver = __FILE__;
643     data.module = c->options->module;
644     data.client = c->client;
645     data.source = source;
646     data.direct_on_input = direct_on_input;
647     pa_source_output_new_data_set_sample_spec(&data, ss);
648     pa_source_output_new_data_set_channel_map(&data, map);
649     if (peak_detect)
650         data.resample_method = PA_RESAMPLER_PEAKS;
651     data.flags = flags;
652
653     *ret = -pa_source_output_new(&source_output, c->protocol->core, &data);
654
655     pa_source_output_new_data_done(&data);
656
657     if (!source_output)
658         return NULL;
659
660     s = pa_msgobject_new(record_stream);
661     s->parent.parent.free = record_stream_free;
662     s->parent.process_msg = record_stream_process_msg;
663     s->connection = c;
664     s->source_output = source_output;
665     s->buffer_attr = *attr;
666     s->adjust_latency = adjust_latency;
667     s->early_requests = early_requests;
668     pa_atomic_store(&s->on_the_fly, 0);
669
670     s->source_output->parent.process_msg = source_output_process_msg;
671     s->source_output->push = source_output_push_cb;
672     s->source_output->kill = source_output_kill_cb;
673     s->source_output->get_latency = source_output_get_latency_cb;
674     s->source_output->moving = source_output_moving_cb;
675     s->source_output->suspend = source_output_suspend_cb;
676     s->source_output->send_event = source_output_send_event_cb;
677     s->source_output->userdata = s;
678
679     fix_record_buffer_attr_pre(s);
680
681     s->memblockq = pa_memblockq_new(
682             0,
683             s->buffer_attr.maxlength,
684             0,
685             base = pa_frame_size(&source_output->sample_spec),
686             1,
687             0,
688             0,
689             NULL);
690
691     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
692     fix_record_buffer_attr_post(s);
693
694     *ss = s->source_output->sample_spec;
695     *map = s->source_output->channel_map;
696
697     pa_idxset_put(c->record_streams, s, &s->index);
698
699     pa_log_info("Final latency %0.2f ms = %0.2f ms + %0.2f ms",
700                 ((double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) + (double) s->configured_source_latency) / PA_USEC_PER_MSEC,
701                 (double) pa_bytes_to_usec(s->buffer_attr.fragsize, &source_output->sample_spec) / PA_USEC_PER_MSEC,
702                 (double) s->configured_source_latency / PA_USEC_PER_MSEC);
703
704     pa_source_output_put(s->source_output);
705     return s;
706 }
707
708 /* Called from main context */
709 static void record_stream_send_killed(record_stream *r) {
710     pa_tagstruct *t;
711     record_stream_assert_ref(r);
712
713     t = pa_tagstruct_new(NULL, 0);
714     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_KILLED);
715     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
716     pa_tagstruct_putu32(t, r->index);
717     pa_pstream_send_tagstruct(r->connection->pstream, t);
718 }
719
720 /* Called from main context */
721 static void playback_stream_unlink(playback_stream *s) {
722     pa_assert(s);
723
724     if (!s->connection)
725         return;
726
727     if (s->sink_input) {
728         pa_sink_input_unlink(s->sink_input);
729         pa_sink_input_unref(s->sink_input);
730         s->sink_input = NULL;
731     }
732
733     if (s->drain_request)
734         pa_pstream_send_error(s->connection->pstream, s->drain_tag, PA_ERR_NOENTITY);
735
736     pa_assert_se(pa_idxset_remove_by_data(s->connection->output_streams, s, NULL) == s);
737     s->connection = NULL;
738     playback_stream_unref(s);
739 }
740
741 /* Called from main context */
742 static void playback_stream_free(pa_object* o) {
743     playback_stream *s = PLAYBACK_STREAM(o);
744     pa_assert(s);
745
746     playback_stream_unlink(s);
747
748     pa_memblockq_free(s->memblockq);
749     pa_xfree(s);
750 }
751
752 /* Called from main context */
753 static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
754     playback_stream *s = PLAYBACK_STREAM(o);
755     playback_stream_assert_ref(s);
756
757     if (!s->connection)
758         return -1;
759
760     switch (code) {
761
762         case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: {
763             pa_tagstruct *t;
764             int l = 0;
765
766             for (;;) {
767                 if ((l = pa_atomic_load(&s->missing)) <= 0)
768                     return 0;
769
770                 if (pa_atomic_cmpxchg(&s->missing, l, 0))
771                     break;
772             }
773
774             t = pa_tagstruct_new(NULL, 0);
775             pa_tagstruct_putu32(t, PA_COMMAND_REQUEST);
776             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
777             pa_tagstruct_putu32(t, s->index);
778             pa_tagstruct_putu32(t, (uint32_t) l);
779             pa_pstream_send_tagstruct(s->connection->pstream, t);
780
781 /*             pa_log("Requesting %lu bytes", (unsigned long) l); */
782             break;
783         }
784
785         case PLAYBACK_STREAM_MESSAGE_UNDERFLOW: {
786             pa_tagstruct *t;
787
788 /*             pa_log("signalling underflow"); */
789
790             /* Report that we're empty */
791             t = pa_tagstruct_new(NULL, 0);
792             pa_tagstruct_putu32(t, PA_COMMAND_UNDERFLOW);
793             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
794             pa_tagstruct_putu32(t, s->index);
795             pa_pstream_send_tagstruct(s->connection->pstream, t);
796             break;
797         }
798
799         case PLAYBACK_STREAM_MESSAGE_OVERFLOW: {
800             pa_tagstruct *t;
801
802             /* Notify the user we're overflowed*/
803             t = pa_tagstruct_new(NULL, 0);
804             pa_tagstruct_putu32(t, PA_COMMAND_OVERFLOW);
805             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
806             pa_tagstruct_putu32(t, s->index);
807             pa_pstream_send_tagstruct(s->connection->pstream, t);
808             break;
809         }
810
811         case PLAYBACK_STREAM_MESSAGE_STARTED:
812
813             if (s->connection->version >= 13) {
814                 pa_tagstruct *t;
815
816                 /* Notify the user we started playback */
817                 t = pa_tagstruct_new(NULL, 0);
818                 pa_tagstruct_putu32(t, PA_COMMAND_STARTED);
819                 pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
820                 pa_tagstruct_putu32(t, s->index);
821                 pa_pstream_send_tagstruct(s->connection->pstream, t);
822             }
823
824             break;
825
826         case PLAYBACK_STREAM_MESSAGE_DRAIN_ACK:
827             pa_pstream_send_simple_ack(s->connection->pstream, PA_PTR_TO_UINT(userdata));
828             break;
829
830         case PLAYBACK_STREAM_MESSAGE_UPDATE_TLENGTH: {
831             pa_tagstruct *t;
832
833             s->buffer_attr.tlength = (uint32_t) offset;
834
835             t = pa_tagstruct_new(NULL, 0);
836             pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED);
837             pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
838             pa_tagstruct_putu32(t, s->index);
839             pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
840             pa_tagstruct_putu32(t, s->buffer_attr.tlength);
841             pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
842             pa_tagstruct_putu32(t, s->buffer_attr.minreq);
843             pa_tagstruct_put_usec(t, s->configured_sink_latency);
844             pa_pstream_send_tagstruct(s->connection->pstream, t);
845
846             break;
847         }
848     }
849
850     return 0;
851 }
852
853 /* Called from main context */
854 static void fix_playback_buffer_attr(playback_stream *s) {
855     size_t frame_size, max_prebuf;
856     pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
857
858     pa_assert(s);
859
860     /* This function will be called from the main thread, before as
861      * well as after the sink input has been activated using
862      * pa_sink_input_put()! That means it may not touch any
863      * ->thread_info data, such as the memblockq! */
864
865     frame_size = pa_frame_size(&s->sink_input->sample_spec);
866
867     if (s->buffer_attr.maxlength == (uint32_t) -1 || s->buffer_attr.maxlength > MAX_MEMBLOCKQ_LENGTH)
868         s->buffer_attr.maxlength = MAX_MEMBLOCKQ_LENGTH;
869     if (s->buffer_attr.maxlength <= 0)
870         s->buffer_attr.maxlength = (uint32_t) frame_size;
871
872     if (s->buffer_attr.tlength == (uint32_t) -1)
873         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_TLENGTH_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
874     if (s->buffer_attr.tlength <= 0)
875         s->buffer_attr.tlength = (uint32_t) frame_size;
876
877     if (s->buffer_attr.minreq == (uint32_t) -1)
878         s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes_round_up(DEFAULT_PROCESS_MSEC*PA_USEC_PER_MSEC, &s->sink_input->sample_spec);
879     if (s->buffer_attr.minreq <= 0)
880         s->buffer_attr.minreq = (uint32_t) frame_size;
881
882     if (s->buffer_attr.tlength < s->buffer_attr.minreq+frame_size)
883         s->buffer_attr.tlength = s->buffer_attr.minreq+(uint32_t) frame_size;
884
885     orig_tlength_usec = tlength_usec = pa_bytes_to_usec(s->buffer_attr.tlength, &s->sink_input->sample_spec);
886     orig_minreq_usec = minreq_usec = pa_bytes_to_usec(s->buffer_attr.minreq, &s->sink_input->sample_spec);
887
888     pa_log_info("Requested tlength=%0.2f ms, minreq=%0.2f ms",
889                 (double) tlength_usec / PA_USEC_PER_MSEC,
890                 (double) minreq_usec / PA_USEC_PER_MSEC);
891
892     if (s->early_requests) {
893
894         /* In early request mode we need to emulate the classic
895          * fragment-based playback model. We do this setting the sink
896          * latency to the fragment size. */
897
898         sink_usec = minreq_usec;
899         pa_log_debug("Early requests mode enabled, configuring sink latency to minreq.");
900
901     } else if (s->adjust_latency) {
902
903         /* So, the user asked us to adjust the latency of the stream
904          * buffer according to the what the sink can provide. The
905          * tlength passed in shall be the overall latency. Roughly
906          * half the latency will be spent on the hw buffer, the other
907          * half of it in the async buffer queue we maintain for each
908          * client. In between we'll have a safety space of size
909          * 2*minreq. Why the 2*minreq? When the hw buffer is completey
910          * empty and needs to be filled, then our buffer must have
911          * enough data to fulfill this request immediatly and thus
912          * have at least the same tlength as the size of the hw
913          * buffer. It additionally needs space for 2 times minreq
914          * because if the buffer ran empty and a partial fillup
915          * happens immediately on the next iteration we need to be
916          * able to fulfill it and give the application also minreq
917          * time to fill it up again for the next request Makes 2 times
918          * minreq in plus.. */
919
920         if (tlength_usec > minreq_usec*2)
921             sink_usec = (tlength_usec - minreq_usec*2)/2;
922         else
923             sink_usec = 0;
924
925         pa_log_debug("Adjust latency mode enabled, configuring sink latency to half of overall latency.");
926
927     } else {
928
929         /* Ok, the user didn't ask us to adjust the latency, but we
930          * still need to make sure that the parameters from the user
931          * do make sense. */
932
933         if (tlength_usec > minreq_usec*2)
934             sink_usec = (tlength_usec - minreq_usec*2);
935         else
936             sink_usec = 0;
937
938         pa_log_debug("Traditional mode enabled, modifying sink usec only for compat with minreq.");
939     }
940
941     s->configured_sink_latency = pa_sink_input_set_requested_latency(s->sink_input, sink_usec);
942
943     if (s->early_requests) {
944
945         /* Ok, we didn't necessarily get what we were asking for, so
946          * let's tell the user */
947
948         minreq_usec = s->configured_sink_latency;
949
950     } else if (s->adjust_latency) {
951
952         /* Ok, we didn't necessarily get what we were asking for, so
953          * let's subtract from what we asked for for the remaining
954          * buffer space */
955
956         if (tlength_usec >= s->configured_sink_latency)
957             tlength_usec -= s->configured_sink_latency;
958     }
959
960     /* FIXME: This is actually larger than necessary, since not all of
961      * the sink latency is actually rewritable. */
962     if (tlength_usec < s->configured_sink_latency + 2*minreq_usec)
963         tlength_usec = s->configured_sink_latency + 2*minreq_usec;
964
965     if (pa_usec_to_bytes_round_up(orig_tlength_usec, &s->sink_input->sample_spec) !=
966         pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec))
967         s->buffer_attr.tlength = (uint32_t) pa_usec_to_bytes_round_up(tlength_usec, &s->sink_input->sample_spec);
968
969     if (pa_usec_to_bytes(orig_minreq_usec, &s->sink_input->sample_spec) !=
970         pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec))
971         s->buffer_attr.minreq = (uint32_t) pa_usec_to_bytes(minreq_usec, &s->sink_input->sample_spec);
972
973     if (s->buffer_attr.minreq <= 0) {
974         s->buffer_attr.minreq = (uint32_t) frame_size;
975         s->buffer_attr.tlength += (uint32_t) frame_size*2;
976     }
977
978     if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
979         s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
980
981     max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
982
983     if (s->buffer_attr.prebuf == (uint32_t) -1 ||
984         s->buffer_attr.prebuf > max_prebuf)
985         s->buffer_attr.prebuf = max_prebuf;
986 }
987
988 /* Called from main context */
989 static playback_stream* playback_stream_new(
990         pa_native_connection *c,
991         pa_sink *sink,
992         pa_sample_spec *ss,
993         pa_channel_map *map,
994         pa_buffer_attr *a,
995         pa_cvolume *volume,
996         pa_bool_t muted,
997         pa_bool_t muted_set,
998         uint32_t syncid,
999         uint32_t *missing,
1000         pa_sink_input_flags_t flags,
1001         pa_proplist *p,
1002         pa_bool_t adjust_latency,
1003         pa_bool_t early_requests,
1004         int *ret) {
1005
1006     playback_stream *s, *ssync;
1007     pa_sink_input *sink_input = NULL;
1008     pa_memchunk silence;
1009     uint32_t idx;
1010     int64_t start_index;
1011     pa_sink_input_new_data data;
1012
1013     pa_assert(c);
1014     pa_assert(ss);
1015     pa_assert(missing);
1016     pa_assert(p);
1017     pa_assert(ret);
1018
1019     /* Find syncid group */
1020     for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
1021
1022         if (!playback_stream_isinstance(ssync))
1023             continue;
1024
1025         if (ssync->syncid == syncid)
1026             break;
1027     }
1028
1029     /* Synced streams must connect to the same sink */
1030     if (ssync) {
1031
1032         if (!sink)
1033             sink = ssync->sink_input->sink;
1034         else if (sink != ssync->sink_input->sink) {
1035             *ret = PA_ERR_INVALID;
1036             return NULL;
1037         }
1038     }
1039
1040     pa_sink_input_new_data_init(&data);
1041
1042     pa_proplist_update(data.proplist, PA_UPDATE_REPLACE, p);
1043     data.driver = __FILE__;
1044     data.module = c->options->module;
1045     data.client = c->client;
1046     data.sink = sink;
1047     pa_sink_input_new_data_set_sample_spec(&data, ss);
1048     pa_sink_input_new_data_set_channel_map(&data, map);
1049     if (volume)
1050         pa_sink_input_new_data_set_volume(&data, volume);
1051     if (muted_set)
1052         pa_sink_input_new_data_set_muted(&data, muted);
1053     data.sync_base = ssync ? ssync->sink_input : NULL;
1054     data.flags = flags;
1055
1056     *ret = -pa_sink_input_new(&sink_input, c->protocol->core, &data);
1057
1058     pa_sink_input_new_data_done(&data);
1059
1060     if (!sink_input)
1061         return NULL;
1062
1063     s = pa_msgobject_new(playback_stream);
1064     s->parent.parent.parent.free = playback_stream_free;
1065     s->parent.parent.process_msg = playback_stream_process_msg;
1066     s->connection = c;
1067     s->syncid = syncid;
1068     s->sink_input = sink_input;
1069     s->is_underrun = TRUE;
1070     s->drain_request = FALSE;
1071     pa_atomic_store(&s->missing, 0);
1072     s->buffer_attr = *a;
1073     s->adjust_latency = adjust_latency;
1074     s->early_requests = early_requests;
1075
1076     s->sink_input->parent.process_msg = sink_input_process_msg;
1077     s->sink_input->pop = sink_input_pop_cb;
1078     s->sink_input->process_rewind = sink_input_process_rewind_cb;
1079     s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1080     s->sink_input->update_max_request = sink_input_update_max_request_cb;
1081     s->sink_input->kill = sink_input_kill_cb;
1082     s->sink_input->moving = sink_input_moving_cb;
1083     s->sink_input->suspend = sink_input_suspend_cb;
1084     s->sink_input->send_event = sink_input_send_event_cb;
1085     s->sink_input->userdata = s;
1086
1087     start_index = ssync ? pa_memblockq_get_read_index(ssync->memblockq) : 0;
1088
1089     fix_playback_buffer_attr(s);
1090
1091     pa_sink_input_get_silence(sink_input, &silence);
1092     s->memblockq = pa_memblockq_new(
1093             start_index,
1094             s->buffer_attr.maxlength,
1095             s->buffer_attr.tlength,
1096             pa_frame_size(&sink_input->sample_spec),
1097             s->buffer_attr.prebuf,
1098             s->buffer_attr.minreq,
1099             0,
1100             &silence);
1101     pa_memblock_unref(silence.memblock);
1102
1103     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1104
1105     *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
1106
1107     *ss = s->sink_input->sample_spec;
1108     *map = s->sink_input->channel_map;
1109
1110     pa_idxset_put(c->output_streams, s, &s->index);
1111
1112     pa_log_info("Final latency %0.2f ms = %0.2f ms + 2*%0.2f ms + %0.2f ms",
1113                 ((double) pa_bytes_to_usec(s->buffer_attr.tlength, &sink_input->sample_spec) + (double) s->configured_sink_latency) / PA_USEC_PER_MSEC,
1114                 (double) pa_bytes_to_usec(s->buffer_attr.tlength-s->buffer_attr.minreq*2, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1115                 (double) pa_bytes_to_usec(s->buffer_attr.minreq, &sink_input->sample_spec) / PA_USEC_PER_MSEC,
1116                 (double) s->configured_sink_latency / PA_USEC_PER_MSEC);
1117
1118     pa_sink_input_put(s->sink_input);
1119     return s;
1120 }
1121
1122 /* Called from IO context */
1123 static void playback_stream_request_bytes(playback_stream *s) {
1124     size_t m, minreq;
1125     int previous_missing;
1126
1127     playback_stream_assert_ref(s);
1128
1129     m = pa_memblockq_pop_missing(s->memblockq);
1130
1131     /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
1132     /*        (unsigned long) m, */
1133     /*        pa_memblockq_get_tlength(s->memblockq), */
1134     /*        pa_memblockq_get_minreq(s->memblockq), */
1135     /*        pa_memblockq_get_length(s->memblockq)); */
1136
1137     if (m <= 0)
1138         return;
1139
1140 /*     pa_log("request_bytes(%lu)", (unsigned long) m); */
1141
1142     previous_missing = pa_atomic_add(&s->missing, (int) m);
1143     minreq = pa_memblockq_get_minreq(s->memblockq);
1144
1145     if (pa_memblockq_prebuf_active(s->memblockq) ||
1146         (previous_missing < (int) minreq && previous_missing + (int) m >= (int) minreq))
1147         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL);
1148 }
1149
1150 /* Called from main context */
1151 static void playback_stream_send_killed(playback_stream *p) {
1152     pa_tagstruct *t;
1153     playback_stream_assert_ref(p);
1154
1155     t = pa_tagstruct_new(NULL, 0);
1156     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_KILLED);
1157     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1158     pa_tagstruct_putu32(t, p->index);
1159     pa_pstream_send_tagstruct(p->connection->pstream, t);
1160 }
1161
1162 /* Called from main context */
1163 static int native_connection_process_msg(pa_msgobject *o, int code, void*userdata, int64_t offset, pa_memchunk *chunk) {
1164     pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1165     pa_native_connection_assert_ref(c);
1166
1167     if (!c->protocol)
1168         return -1;
1169
1170     switch (code) {
1171
1172         case CONNECTION_MESSAGE_REVOKE:
1173             pa_pstream_send_revoke(c->pstream, PA_PTR_TO_UINT(userdata));
1174             break;
1175
1176         case CONNECTION_MESSAGE_RELEASE:
1177             pa_pstream_send_release(c->pstream, PA_PTR_TO_UINT(userdata));
1178             break;
1179     }
1180
1181     return 0;
1182 }
1183
1184 /* Called from main context */
1185 static void native_connection_unlink(pa_native_connection *c) {
1186     record_stream *r;
1187     output_stream *o;
1188
1189     pa_assert(c);
1190
1191     if (!c->protocol)
1192         return;
1193
1194     pa_hook_fire(&c->protocol->hooks[PA_NATIVE_HOOK_CONNECTION_UNLINK], c);
1195
1196     if (c->options)
1197         pa_native_options_unref(c->options);
1198
1199     while ((r = pa_idxset_first(c->record_streams, NULL)))
1200         record_stream_unlink(r);
1201
1202     while ((o = pa_idxset_first(c->output_streams, NULL)))
1203         if (playback_stream_isinstance(o))
1204             playback_stream_unlink(PLAYBACK_STREAM(o));
1205         else
1206             upload_stream_unlink(UPLOAD_STREAM(o));
1207
1208     if (c->subscription)
1209         pa_subscription_free(c->subscription);
1210
1211     if (c->pstream)
1212         pa_pstream_unlink(c->pstream);
1213
1214     if (c->auth_timeout_event) {
1215         c->protocol->core->mainloop->time_free(c->auth_timeout_event);
1216         c->auth_timeout_event = NULL;
1217     }
1218
1219     pa_assert_se(pa_idxset_remove_by_data(c->protocol->connections, c, NULL) == c);
1220     c->protocol = NULL;
1221     pa_native_connection_unref(c);
1222 }
1223
1224 /* Called from main context */
1225 static void native_connection_free(pa_object *o) {
1226     pa_native_connection *c = PA_NATIVE_CONNECTION(o);
1227
1228     pa_assert(c);
1229
1230     native_connection_unlink(c);
1231
1232     pa_idxset_free(c->record_streams, NULL, NULL);
1233     pa_idxset_free(c->output_streams, NULL, NULL);
1234
1235     pa_pdispatch_unref(c->pdispatch);
1236     pa_pstream_unref(c->pstream);
1237     pa_client_free(c->client);
1238
1239     pa_xfree(c);
1240 }
1241
1242 /* Called from main context */
1243 static void native_connection_send_memblock(pa_native_connection *c) {
1244     uint32_t start;
1245     record_stream *r;
1246
1247     start = PA_IDXSET_INVALID;
1248     for (;;) {
1249         pa_memchunk chunk;
1250
1251         if (!(r = RECORD_STREAM(pa_idxset_rrobin(c->record_streams, &c->rrobin_index))))
1252             return;
1253
1254         if (start == PA_IDXSET_INVALID)
1255             start = c->rrobin_index;
1256         else if (start == c->rrobin_index)
1257             return;
1258
1259         if (pa_memblockq_peek(r->memblockq,  &chunk) >= 0) {
1260             pa_memchunk schunk = chunk;
1261
1262             if (schunk.length > r->buffer_attr.fragsize)
1263                 schunk.length = r->buffer_attr.fragsize;
1264
1265             pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
1266
1267             pa_memblockq_drop(r->memblockq, schunk.length);
1268             pa_memblock_unref(schunk.memblock);
1269
1270             return;
1271         }
1272     }
1273 }
1274
1275 /*** sink input callbacks ***/
1276
1277 /* Called from thread context */
1278 static void handle_seek(playback_stream *s, int64_t indexw) {
1279     playback_stream_assert_ref(s);
1280
1281 /*     pa_log("handle_seek: %llu -- %i", (unsigned long long) s->sink_input->thread_info.underrun_for, pa_memblockq_is_readable(s->memblockq)); */
1282
1283     if (s->sink_input->thread_info.underrun_for > 0) {
1284
1285 /*         pa_log("%lu vs. %lu", (unsigned long) pa_memblockq_get_length(s->memblockq), (unsigned long) pa_memblockq_get_prebuf(s->memblockq)); */
1286
1287         if (pa_memblockq_is_readable(s->memblockq)) {
1288
1289             /* We just ended an underrun, let's ask the sink
1290              * for a complete rewind rewrite */
1291
1292             pa_log_debug("Requesting rewind due to end of underrun.");
1293             pa_sink_input_request_rewind(s->sink_input,
1294                                          (size_t) (s->sink_input->thread_info.underrun_for == (uint64_t) -1 ? 0 :
1295                                                    s->sink_input->thread_info.underrun_for),
1296                                          FALSE, TRUE, FALSE);
1297         }
1298
1299     } else {
1300         int64_t indexr;
1301
1302         indexr = pa_memblockq_get_read_index(s->memblockq);
1303
1304         if (indexw < indexr) {
1305             /* OK, the sink already asked for this data, so
1306              * let's have it usk us again */
1307
1308             pa_log_debug("Requesting rewind due to rewrite.");
1309             pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE, FALSE);
1310         }
1311     }
1312
1313     playback_stream_request_bytes(s);
1314 }
1315
1316 /* Called from thread context */
1317 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1318     pa_sink_input *i = PA_SINK_INPUT(o);
1319     playback_stream *s;
1320
1321     pa_sink_input_assert_ref(i);
1322     s = PLAYBACK_STREAM(i->userdata);
1323     playback_stream_assert_ref(s);
1324
1325     switch (code) {
1326
1327         case SINK_INPUT_MESSAGE_SEEK: {
1328             int64_t windex;
1329
1330             windex = pa_memblockq_get_write_index(s->memblockq);
1331
1332             /* The client side is incapable of accounting correctly
1333              * for seeks of a type != PA_SEEK_RELATIVE. We need to be
1334              * able to deal with that. */
1335
1336             pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE);
1337
1338             handle_seek(s, windex);
1339             return 0;
1340         }
1341
1342         case SINK_INPUT_MESSAGE_POST_DATA: {
1343             int64_t windex;
1344
1345             pa_assert(chunk);
1346
1347             windex = pa_memblockq_get_write_index(s->memblockq);
1348
1349 /*             pa_log("sink input post: %lu %lli", (unsigned long) chunk->length, (long long) windex); */
1350
1351             if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
1352
1353                 if (pa_log_ratelimit())
1354                     pa_log_warn("Failed to push data into queue");
1355                 pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL);
1356                 pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE);
1357             }
1358
1359             handle_seek(s, windex);
1360
1361 /*             pa_log("sink input post2: %lu", (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1362
1363             return 0;
1364         }
1365
1366         case SINK_INPUT_MESSAGE_DRAIN:
1367         case SINK_INPUT_MESSAGE_FLUSH:
1368         case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1369         case SINK_INPUT_MESSAGE_TRIGGER: {
1370
1371             int64_t windex;
1372             pa_sink_input *isync;
1373             void (*func)(pa_memblockq *bq);
1374
1375             switch  (code) {
1376                 case SINK_INPUT_MESSAGE_FLUSH:
1377                     func = pa_memblockq_flush_write;
1378                     break;
1379
1380                 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
1381                     func = pa_memblockq_prebuf_force;
1382                     break;
1383
1384                 case SINK_INPUT_MESSAGE_DRAIN:
1385                 case SINK_INPUT_MESSAGE_TRIGGER:
1386                     func = pa_memblockq_prebuf_disable;
1387                     break;
1388
1389                 default:
1390                     pa_assert_not_reached();
1391             }
1392
1393             windex = pa_memblockq_get_write_index(s->memblockq);
1394             func(s->memblockq);
1395             handle_seek(s, windex);
1396
1397             /* Do the same for all other members in the sync group */
1398             for (isync = i->sync_prev; isync; isync = isync->sync_prev) {
1399                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1400                 windex = pa_memblockq_get_write_index(ssync->memblockq);
1401                 func(ssync->memblockq);
1402                 handle_seek(ssync, windex);
1403             }
1404
1405             for (isync = i->sync_next; isync; isync = isync->sync_next) {
1406                 playback_stream *ssync = PLAYBACK_STREAM(isync->userdata);
1407                 windex = pa_memblockq_get_write_index(ssync->memblockq);
1408                 func(ssync->memblockq);
1409                 handle_seek(ssync, windex);
1410             }
1411
1412             if (code == SINK_INPUT_MESSAGE_DRAIN) {
1413                 if (!pa_memblockq_is_readable(s->memblockq))
1414                     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, userdata, 0, NULL, NULL);
1415                 else {
1416                     s->drain_tag = PA_PTR_TO_UINT(userdata);
1417                     s->drain_request = TRUE;
1418                 }
1419             }
1420
1421             return 0;
1422         }
1423
1424         case SINK_INPUT_MESSAGE_UPDATE_LATENCY:
1425             /* Atomically get a snapshot of all timing parameters... */
1426             s->read_index = pa_memblockq_get_read_index(s->memblockq);
1427             s->write_index = pa_memblockq_get_write_index(s->memblockq);
1428             s->render_memblockq_length = pa_memblockq_get_length(s->sink_input->thread_info.render_memblockq);
1429             s->current_sink_latency = pa_sink_get_latency_within_thread(s->sink_input->sink);
1430             s->underrun_for = s->sink_input->thread_info.underrun_for;
1431             s->playing_for = s->sink_input->thread_info.playing_for;
1432
1433             return 0;
1434
1435         case PA_SINK_INPUT_MESSAGE_SET_STATE: {
1436             int64_t windex;
1437
1438             windex = pa_memblockq_get_write_index(s->memblockq);
1439
1440             pa_memblockq_prebuf_force(s->memblockq);
1441
1442             handle_seek(s, windex);
1443
1444             /* Fall through to the default handler */
1445             break;
1446         }
1447
1448         case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
1449             pa_usec_t *r = userdata;
1450
1451             *r = pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &i->sample_spec);
1452
1453             /* Fall through, the default handler will add in the extra
1454              * latency added by the resampler */
1455             break;
1456         }
1457
1458         case SINK_INPUT_MESSAGE_UPDATE_BUFFER_ATTR: {
1459             pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1460             pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1461             return 0;
1462         }
1463     }
1464
1465     return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
1466 }
1467
1468 /* Called from thread context */
1469 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
1470     playback_stream *s;
1471
1472     pa_sink_input_assert_ref(i);
1473     s = PLAYBACK_STREAM(i->userdata);
1474     playback_stream_assert_ref(s);
1475     pa_assert(chunk);
1476
1477 /*     pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq)); */
1478
1479     if (pa_memblockq_is_readable(s->memblockq))
1480         s->is_underrun = FALSE;
1481     else {
1482         if (!s->is_underrun)
1483             pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), (unsigned long) pa_memblockq_get_length(s->memblockq));
1484
1485         if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
1486             s->drain_request = FALSE;
1487             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);
1488         } else if (!s->is_underrun)
1489             pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, 0, NULL, NULL);
1490
1491         s->is_underrun = TRUE;
1492
1493         playback_stream_request_bytes(s);
1494     }
1495
1496     /* This call will not fail with prebuf=0, hence we check for
1497        underrun explicitly above */
1498     if (pa_memblockq_peek(s->memblockq, chunk) < 0)
1499         return -1;
1500
1501     chunk->length = PA_MIN(nbytes, chunk->length);
1502
1503     if (i->thread_info.underrun_for > 0)
1504         pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_STARTED, NULL, 0, NULL, NULL);
1505
1506     pa_memblockq_drop(s->memblockq, chunk->length);
1507     playback_stream_request_bytes(s);
1508
1509     return 0;
1510 }
1511
1512 /* Called from thread context */
1513 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
1514     playback_stream *s;
1515
1516     pa_sink_input_assert_ref(i);
1517     s = PLAYBACK_STREAM(i->userdata);
1518     playback_stream_assert_ref(s);
1519
1520     /* If we are in an underrun, then we don't rewind */
1521     if (i->thread_info.underrun_for > 0)
1522         return;
1523
1524     pa_memblockq_rewind(s->memblockq, nbytes);
1525 }
1526
1527 /* Called from thread context */
1528 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
1529     playback_stream *s;
1530
1531     pa_sink_input_assert_ref(i);
1532     s = PLAYBACK_STREAM(i->userdata);
1533     playback_stream_assert_ref(s);
1534
1535     pa_memblockq_set_maxrewind(s->memblockq, nbytes);
1536 }
1537
1538 /* Called from thread context */
1539 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
1540     playback_stream *s;
1541     size_t new_tlength, old_tlength;
1542
1543     pa_sink_input_assert_ref(i);
1544     s = PLAYBACK_STREAM(i->userdata);
1545     playback_stream_assert_ref(s);
1546
1547     old_tlength = pa_memblockq_get_tlength(s->memblockq);
1548     new_tlength = nbytes+2*pa_memblockq_get_minreq(s->memblockq);
1549
1550     if (old_tlength < new_tlength) {
1551         pa_log_debug("max_request changed, trying to update from %zu to %zu.", old_tlength, new_tlength);
1552         pa_memblockq_set_tlength(s->memblockq, new_tlength);
1553         new_tlength = pa_memblockq_get_tlength(s->memblockq);
1554
1555         if (new_tlength == old_tlength)
1556             pa_log_debug("Failed to increase tlength");
1557         else {
1558             pa_log_debug("Notifying client about increased tlength");
1559             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);
1560         }
1561     }
1562 }
1563
1564 /* Called from main context */
1565 static void sink_input_kill_cb(pa_sink_input *i) {
1566     playback_stream *s;
1567
1568     pa_sink_input_assert_ref(i);
1569     s = PLAYBACK_STREAM(i->userdata);
1570     playback_stream_assert_ref(s);
1571
1572     playback_stream_send_killed(s);
1573     playback_stream_unlink(s);
1574 }
1575
1576 /* Called from main context */
1577 static void sink_input_send_event_cb(pa_sink_input *i, const char *event, pa_proplist *pl) {
1578     playback_stream *s;
1579     pa_tagstruct *t;
1580
1581     pa_sink_input_assert_ref(i);
1582     s = PLAYBACK_STREAM(i->userdata);
1583     playback_stream_assert_ref(s);
1584
1585     if (s->connection->version < 15)
1586       return;
1587
1588     t = pa_tagstruct_new(NULL, 0);
1589     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_EVENT);
1590     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1591     pa_tagstruct_putu32(t, s->index);
1592     pa_tagstruct_puts(t, event);
1593     pa_tagstruct_put_proplist(t, pl);
1594     pa_pstream_send_tagstruct(s->connection->pstream, t);
1595 }
1596
1597 /* Called from main context */
1598 static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend) {
1599     playback_stream *s;
1600     pa_tagstruct *t;
1601
1602     pa_sink_input_assert_ref(i);
1603     s = PLAYBACK_STREAM(i->userdata);
1604     playback_stream_assert_ref(s);
1605
1606     if (s->connection->version < 12)
1607       return;
1608
1609     t = pa_tagstruct_new(NULL, 0);
1610     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_SUSPENDED);
1611     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1612     pa_tagstruct_putu32(t, s->index);
1613     pa_tagstruct_put_boolean(t, suspend);
1614     pa_pstream_send_tagstruct(s->connection->pstream, t);
1615 }
1616
1617 /* Called from main context */
1618 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1619     playback_stream *s;
1620     pa_tagstruct *t;
1621
1622     pa_sink_input_assert_ref(i);
1623     s = PLAYBACK_STREAM(i->userdata);
1624     playback_stream_assert_ref(s);
1625
1626     if (!dest)
1627         return;
1628
1629     fix_playback_buffer_attr(s);
1630     pa_memblockq_apply_attr(s->memblockq, &s->buffer_attr);
1631     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1632
1633     if (s->connection->version < 12)
1634       return;
1635
1636     t = pa_tagstruct_new(NULL, 0);
1637     pa_tagstruct_putu32(t, PA_COMMAND_PLAYBACK_STREAM_MOVED);
1638     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1639     pa_tagstruct_putu32(t, s->index);
1640     pa_tagstruct_putu32(t, dest->index);
1641     pa_tagstruct_puts(t, dest->name);
1642     pa_tagstruct_put_boolean(t, pa_sink_get_state(dest) == PA_SINK_SUSPENDED);
1643
1644     if (s->connection->version >= 13) {
1645         pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1646         pa_tagstruct_putu32(t, s->buffer_attr.tlength);
1647         pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
1648         pa_tagstruct_putu32(t, s->buffer_attr.minreq);
1649         pa_tagstruct_put_usec(t, s->configured_sink_latency);
1650     }
1651
1652     pa_pstream_send_tagstruct(s->connection->pstream, t);
1653 }
1654
1655 /*** source_output callbacks ***/
1656
1657 /* Called from thread context */
1658 static int source_output_process_msg(pa_msgobject *_o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1659     pa_source_output *o = PA_SOURCE_OUTPUT(_o);
1660     record_stream *s;
1661
1662     pa_source_output_assert_ref(o);
1663     s = RECORD_STREAM(o->userdata);
1664     record_stream_assert_ref(s);
1665
1666     switch (code) {
1667         case SOURCE_OUTPUT_MESSAGE_UPDATE_LATENCY:
1668             /* Atomically get a snapshot of all timing parameters... */
1669             s->current_monitor_latency = o->source->monitor_of ? pa_sink_get_latency_within_thread(o->source->monitor_of) : 0;
1670             s->current_source_latency = pa_source_get_latency_within_thread(o->source);
1671             s->on_the_fly_snapshot = pa_atomic_load(&s->on_the_fly);
1672             return 0;
1673     }
1674
1675     return pa_source_output_process_msg(_o, code, userdata, offset, chunk);
1676 }
1677
1678 /* Called from thread context */
1679 static void source_output_push_cb(pa_source_output *o, const pa_memchunk *chunk) {
1680     record_stream *s;
1681
1682     pa_source_output_assert_ref(o);
1683     s = RECORD_STREAM(o->userdata);
1684     record_stream_assert_ref(s);
1685     pa_assert(chunk);
1686
1687     pa_atomic_add(&s->on_the_fly, chunk->length);
1688     pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), RECORD_STREAM_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
1689 }
1690
1691 static void source_output_kill_cb(pa_source_output *o) {
1692     record_stream *s;
1693
1694     pa_source_output_assert_ref(o);
1695     s = RECORD_STREAM(o->userdata);
1696     record_stream_assert_ref(s);
1697
1698     record_stream_send_killed(s);
1699     record_stream_unlink(s);
1700 }
1701
1702 static pa_usec_t source_output_get_latency_cb(pa_source_output *o) {
1703     record_stream *s;
1704
1705     pa_source_output_assert_ref(o);
1706     s = RECORD_STREAM(o->userdata);
1707     record_stream_assert_ref(s);
1708
1709     /*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
1710
1711     return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
1712 }
1713
1714 /* Called from main context */
1715 static void source_output_send_event_cb(pa_source_output *o, const char *event, pa_proplist *pl) {
1716     record_stream *s;
1717     pa_tagstruct *t;
1718
1719     pa_source_output_assert_ref(o);
1720     s = RECORD_STREAM(o->userdata);
1721     record_stream_assert_ref(s);
1722
1723     if (s->connection->version < 15)
1724       return;
1725
1726     t = pa_tagstruct_new(NULL, 0);
1727     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_EVENT);
1728     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1729     pa_tagstruct_putu32(t, s->index);
1730     pa_tagstruct_puts(t, event);
1731     pa_tagstruct_put_proplist(t, pl);
1732     pa_pstream_send_tagstruct(s->connection->pstream, t);
1733 }
1734
1735 /* Called from main context */
1736 static void source_output_suspend_cb(pa_source_output *o, pa_bool_t suspend) {
1737     record_stream *s;
1738     pa_tagstruct *t;
1739
1740     pa_source_output_assert_ref(o);
1741     s = RECORD_STREAM(o->userdata);
1742     record_stream_assert_ref(s);
1743
1744     if (s->connection->version < 12)
1745       return;
1746
1747     t = pa_tagstruct_new(NULL, 0);
1748     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_SUSPENDED);
1749     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1750     pa_tagstruct_putu32(t, s->index);
1751     pa_tagstruct_put_boolean(t, suspend);
1752     pa_pstream_send_tagstruct(s->connection->pstream, t);
1753 }
1754
1755 /* Called from main context */
1756 static void source_output_moving_cb(pa_source_output *o, pa_source *dest) {
1757     record_stream *s;
1758     pa_tagstruct *t;
1759
1760     pa_source_output_assert_ref(o);
1761     s = RECORD_STREAM(o->userdata);
1762     record_stream_assert_ref(s);
1763
1764     if (!dest)
1765         return;
1766
1767     fix_record_buffer_attr_pre(s);
1768     pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
1769     pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
1770     fix_record_buffer_attr_post(s);
1771
1772     if (s->connection->version < 12)
1773       return;
1774
1775     t = pa_tagstruct_new(NULL, 0);
1776     pa_tagstruct_putu32(t, PA_COMMAND_RECORD_STREAM_MOVED);
1777     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
1778     pa_tagstruct_putu32(t, s->index);
1779     pa_tagstruct_putu32(t, dest->index);
1780     pa_tagstruct_puts(t, dest->name);
1781     pa_tagstruct_put_boolean(t, pa_source_get_state(dest) == PA_SOURCE_SUSPENDED);
1782
1783     if (s->connection->version >= 13) {
1784         pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
1785         pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
1786         pa_tagstruct_put_usec(t, s->configured_source_latency);
1787     }
1788
1789     pa_pstream_send_tagstruct(s->connection->pstream, t);
1790 }
1791
1792 /*** pdispatch callbacks ***/
1793
1794 static void protocol_error(pa_native_connection *c) {
1795     pa_log("protocol error, kicking client");
1796     native_connection_unlink(c);
1797 }
1798
1799 #define CHECK_VALIDITY(pstream, expression, tag, error) do { \
1800 if (!(expression)) { \
1801     pa_pstream_send_error((pstream), (tag), (error)); \
1802     return; \
1803 } \
1804 } while(0);
1805
1806 static pa_tagstruct *reply_new(uint32_t tag) {
1807     pa_tagstruct *reply;
1808
1809     reply = pa_tagstruct_new(NULL, 0);
1810     pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
1811     pa_tagstruct_putu32(reply, tag);
1812     return reply;
1813 }
1814
1815 static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
1816     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
1817     playback_stream *s;
1818     uint32_t sink_index, syncid, missing;
1819     pa_buffer_attr attr;
1820     const char *name = NULL, *sink_name;
1821     pa_sample_spec ss;
1822     pa_channel_map map;
1823     pa_tagstruct *reply;
1824     pa_sink *sink = NULL;
1825     pa_cvolume volume;
1826     pa_bool_t
1827         corked = FALSE,
1828         no_remap = FALSE,
1829         no_remix = FALSE,
1830         fix_format = FALSE,
1831         fix_rate = FALSE,
1832         fix_channels = FALSE,
1833         no_move = FALSE,
1834         variable_rate = FALSE,
1835         muted = FALSE,
1836         adjust_latency = FALSE,
1837         early_requests = FALSE,
1838         dont_inhibit_auto_suspend = FALSE,
1839         muted_set = FALSE,
1840         fail_on_suspend = FALSE;
1841     pa_sink_input_flags_t flags = 0;
1842     pa_proplist *p;
1843     pa_bool_t volume_set = TRUE;
1844     int ret = PA_ERR_INVALID;
1845
1846     pa_native_connection_assert_ref(c);
1847     pa_assert(t);
1848     memset(&attr, 0, sizeof(attr));
1849
1850     if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
1851         pa_tagstruct_get(
1852                 t,
1853                 PA_TAG_SAMPLE_SPEC, &ss,
1854                 PA_TAG_CHANNEL_MAP, &map,
1855                 PA_TAG_U32, &sink_index,
1856                 PA_TAG_STRING, &sink_name,
1857                 PA_TAG_U32, &attr.maxlength,
1858                 PA_TAG_BOOLEAN, &corked,
1859                 PA_TAG_U32, &attr.tlength,
1860                 PA_TAG_U32, &attr.prebuf,
1861                 PA_TAG_U32, &attr.minreq,
1862                 PA_TAG_U32, &syncid,
1863                 PA_TAG_CVOLUME, &volume,
1864                 PA_TAG_INVALID) < 0) {
1865
1866         protocol_error(c);
1867         return;
1868     }
1869
1870     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
1871     CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
1872     CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
1873     CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
1874     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
1875     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
1876     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
1877     CHECK_VALIDITY(c->pstream, map.channels == ss.channels && volume.channels == ss.channels, tag, PA_ERR_INVALID);
1878
1879     p = pa_proplist_new();
1880
1881     if (name)
1882         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
1883
1884     if (c->version >= 12)  {
1885         /* Since 0.9.8 the user can ask for a couple of additional flags */
1886
1887         if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
1888             pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
1889             pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
1890             pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
1891             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
1892             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
1893             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
1894
1895             protocol_error(c);
1896             pa_proplist_free(p);
1897             return;
1898         }
1899     }
1900
1901     if (c->version >= 13) {
1902
1903         if (pa_tagstruct_get_boolean(t, &muted) < 0 ||
1904             pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
1905             pa_tagstruct_get_proplist(t, p) < 0) {
1906             protocol_error(c);
1907             pa_proplist_free(p);
1908             return;
1909         }
1910     }
1911
1912     if (c->version >= 14) {
1913
1914         if (pa_tagstruct_get_boolean(t, &volume_set) < 0 ||
1915             pa_tagstruct_get_boolean(t, &early_requests) < 0) {
1916             protocol_error(c);
1917             pa_proplist_free(p);
1918             return;
1919         }
1920     }
1921
1922     if (c->version >= 15) {
1923
1924         if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
1925             pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
1926             pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
1927             protocol_error(c);
1928             pa_proplist_free(p);
1929             return;
1930         }
1931     }
1932
1933     if (!pa_tagstruct_eof(t)) {
1934         protocol_error(c);
1935         pa_proplist_free(p);
1936         return;
1937     }
1938
1939     if (sink_index != PA_INVALID_INDEX) {
1940
1941         if (!(sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index))) {
1942             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1943             pa_proplist_free(p);
1944             return;
1945         }
1946
1947     } else if (sink_name) {
1948
1949         if (!(sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK))) {
1950             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
1951             pa_proplist_free(p);
1952             return;
1953         }
1954     }
1955
1956     flags =
1957         (corked ?  PA_SINK_INPUT_START_CORKED : 0) |
1958         (no_remap ?  PA_SINK_INPUT_NO_REMAP : 0) |
1959         (no_remix ?  PA_SINK_INPUT_NO_REMIX : 0) |
1960         (fix_format ?  PA_SINK_INPUT_FIX_FORMAT : 0) |
1961         (fix_rate ?  PA_SINK_INPUT_FIX_RATE : 0) |
1962         (fix_channels ?  PA_SINK_INPUT_FIX_CHANNELS : 0) |
1963         (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
1964         (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0) |
1965         (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
1966         (fail_on_suspend ? PA_SINK_INPUT_NO_CREATE_ON_SUSPEND|PA_SINK_INPUT_KILL_ON_SUSPEND : 0);
1967
1968     /* Only since protocol version 15 there's a seperate muted_set
1969      * flag. For older versions we synthesize it here */
1970     muted_set = muted_set || muted;
1971
1972     s = playback_stream_new(c, sink, &ss, &map, &attr, volume_set ? &volume : NULL, muted, muted_set, syncid, &missing, flags, p, adjust_latency, early_requests, &ret);
1973     pa_proplist_free(p);
1974
1975     CHECK_VALIDITY(c->pstream, s, tag, ret);
1976
1977     reply = reply_new(tag);
1978     pa_tagstruct_putu32(reply, s->index);
1979     pa_assert(s->sink_input);
1980     pa_tagstruct_putu32(reply, s->sink_input->index);
1981     pa_tagstruct_putu32(reply, missing);
1982
1983 /*     pa_log("initial request is %u", missing); */
1984
1985     if (c->version >= 9) {
1986         /* Since 0.9.0 we support sending the buffer metrics back to the client */
1987
1988         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
1989         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.tlength);
1990         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.prebuf);
1991         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.minreq);
1992     }
1993
1994     if (c->version >= 12) {
1995         /* Since 0.9.8 we support sending the chosen sample
1996          * spec/channel map/device/suspend status back to the
1997          * client */
1998
1999         pa_tagstruct_put_sample_spec(reply, &ss);
2000         pa_tagstruct_put_channel_map(reply, &map);
2001
2002         pa_tagstruct_putu32(reply, s->sink_input->sink->index);
2003         pa_tagstruct_puts(reply, s->sink_input->sink->name);
2004
2005         pa_tagstruct_put_boolean(reply, pa_sink_get_state(s->sink_input->sink) == PA_SINK_SUSPENDED);
2006     }
2007
2008     if (c->version >= 13)
2009         pa_tagstruct_put_usec(reply, s->configured_sink_latency);
2010
2011     pa_pstream_send_tagstruct(c->pstream, reply);
2012 }
2013
2014 static void command_delete_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2015     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2016     uint32_t channel;
2017
2018     pa_native_connection_assert_ref(c);
2019     pa_assert(t);
2020
2021     if (pa_tagstruct_getu32(t, &channel) < 0 ||
2022         !pa_tagstruct_eof(t)) {
2023         protocol_error(c);
2024         return;
2025     }
2026
2027     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2028
2029     switch (command) {
2030
2031         case PA_COMMAND_DELETE_PLAYBACK_STREAM: {
2032             playback_stream *s;
2033             if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !playback_stream_isinstance(s)) {
2034                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2035                 return;
2036             }
2037
2038             playback_stream_unlink(s);
2039             break;
2040         }
2041
2042         case PA_COMMAND_DELETE_RECORD_STREAM: {
2043             record_stream *s;
2044             if (!(s = pa_idxset_get_by_index(c->record_streams, channel))) {
2045                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2046                 return;
2047             }
2048
2049             record_stream_unlink(s);
2050             break;
2051         }
2052
2053         case PA_COMMAND_DELETE_UPLOAD_STREAM: {
2054             upload_stream *s;
2055
2056             if (!(s = pa_idxset_get_by_index(c->output_streams, channel)) || !upload_stream_isinstance(s)) {
2057                 pa_pstream_send_error(c->pstream, tag, PA_ERR_EXIST);
2058                 return;
2059             }
2060
2061             upload_stream_unlink(s);
2062             break;
2063         }
2064
2065         default:
2066             pa_assert_not_reached();
2067     }
2068
2069     pa_pstream_send_simple_ack(c->pstream, tag);
2070 }
2071
2072 static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2073     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2074     record_stream *s;
2075     pa_buffer_attr attr;
2076     uint32_t source_index;
2077     const char *name = NULL, *source_name;
2078     pa_sample_spec ss;
2079     pa_channel_map map;
2080     pa_tagstruct *reply;
2081     pa_source *source = NULL;
2082     pa_bool_t
2083         corked = FALSE,
2084         no_remap = FALSE,
2085         no_remix = FALSE,
2086         fix_format = FALSE,
2087         fix_rate = FALSE,
2088         fix_channels = FALSE,
2089         no_move = FALSE,
2090         variable_rate = FALSE,
2091         adjust_latency = FALSE,
2092         peak_detect = FALSE,
2093         early_requests = FALSE,
2094         dont_inhibit_auto_suspend = FALSE,
2095         fail_on_suspend = FALSE;
2096     pa_source_output_flags_t flags = 0;
2097     pa_proplist *p;
2098     uint32_t direct_on_input_idx = PA_INVALID_INDEX;
2099     pa_sink_input *direct_on_input = NULL;
2100     int ret = PA_ERR_INVALID;
2101
2102     pa_native_connection_assert_ref(c);
2103     pa_assert(t);
2104
2105     memset(&attr, 0, sizeof(attr));
2106
2107     if ((c->version < 13 && (pa_tagstruct_gets(t, &name) < 0 || !name)) ||
2108         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2109         pa_tagstruct_get_channel_map(t, &map) < 0 ||
2110         pa_tagstruct_getu32(t, &source_index) < 0 ||
2111         pa_tagstruct_gets(t, &source_name) < 0 ||
2112         pa_tagstruct_getu32(t, &attr.maxlength) < 0 ||
2113         pa_tagstruct_get_boolean(t, &corked) < 0 ||
2114         pa_tagstruct_getu32(t, &attr.fragsize) < 0) {
2115         protocol_error(c);
2116         return;
2117     }
2118
2119     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2120     CHECK_VALIDITY(c->pstream, !source_name || pa_namereg_is_valid_name_or_wildcard(source_name, PA_NAMEREG_SOURCE), tag, PA_ERR_INVALID);
2121     CHECK_VALIDITY(c->pstream, source_index == PA_INVALID_INDEX || !source_name, tag, PA_ERR_INVALID);
2122     CHECK_VALIDITY(c->pstream, !source_name || source_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2123     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2124     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2125     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2126
2127     p = pa_proplist_new();
2128
2129     if (name)
2130         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2131
2132     if (c->version >= 12)  {
2133         /* Since 0.9.8 the user can ask for a couple of additional flags */
2134
2135         if (pa_tagstruct_get_boolean(t, &no_remap) < 0 ||
2136             pa_tagstruct_get_boolean(t, &no_remix) < 0 ||
2137             pa_tagstruct_get_boolean(t, &fix_format) < 0 ||
2138             pa_tagstruct_get_boolean(t, &fix_rate) < 0 ||
2139             pa_tagstruct_get_boolean(t, &fix_channels) < 0 ||
2140             pa_tagstruct_get_boolean(t, &no_move) < 0 ||
2141             pa_tagstruct_get_boolean(t, &variable_rate) < 0) {
2142
2143             protocol_error(c);
2144             pa_proplist_free(p);
2145             return;
2146         }
2147     }
2148
2149     if (c->version >= 13) {
2150
2151         if (pa_tagstruct_get_boolean(t, &peak_detect) < 0 ||
2152             pa_tagstruct_get_boolean(t, &adjust_latency) < 0 ||
2153             pa_tagstruct_get_proplist(t, p) < 0 ||
2154             pa_tagstruct_getu32(t, &direct_on_input_idx) < 0) {
2155             protocol_error(c);
2156             pa_proplist_free(p);
2157             return;
2158         }
2159     }
2160
2161     if (c->version >= 14) {
2162
2163         if (pa_tagstruct_get_boolean(t, &early_requests) < 0) {
2164             protocol_error(c);
2165             pa_proplist_free(p);
2166             return;
2167         }
2168     }
2169
2170     if (c->version >= 15) {
2171
2172         if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
2173             pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
2174             protocol_error(c);
2175             pa_proplist_free(p);
2176             return;
2177         }
2178     }
2179
2180     if (!pa_tagstruct_eof(t)) {
2181         protocol_error(c);
2182         pa_proplist_free(p);
2183         return;
2184     }
2185
2186     if (source_index != PA_INVALID_INDEX) {
2187
2188         if (!(source = pa_idxset_get_by_index(c->protocol->core->sources, source_index))) {
2189             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2190             pa_proplist_free(p);
2191             return;
2192         }
2193
2194     } else if (source_name) {
2195
2196         if (!(source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE))) {
2197             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2198             pa_proplist_free(p);
2199             return;
2200         }
2201     }
2202
2203     if (direct_on_input_idx != PA_INVALID_INDEX) {
2204
2205         if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) {
2206             pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2207             pa_proplist_free(p);
2208             return;
2209         }
2210     }
2211
2212     flags =
2213         (corked ?  PA_SOURCE_OUTPUT_START_CORKED : 0) |
2214         (no_remap ?  PA_SOURCE_OUTPUT_NO_REMAP : 0) |
2215         (no_remix ?  PA_SOURCE_OUTPUT_NO_REMIX : 0) |
2216         (fix_format ?  PA_SOURCE_OUTPUT_FIX_FORMAT : 0) |
2217         (fix_rate ?  PA_SOURCE_OUTPUT_FIX_RATE : 0) |
2218         (fix_channels ?  PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
2219         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
2220         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
2221         (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
2222         (fail_on_suspend ? PA_SOURCE_OUTPUT_NO_CREATE_ON_SUSPEND|PA_SOURCE_OUTPUT_KILL_ON_SUSPEND : 0);
2223
2224     s = record_stream_new(c, source, &ss, &map, peak_detect, &attr, flags, p, adjust_latency, direct_on_input, early_requests, &ret);
2225     pa_proplist_free(p);
2226
2227     CHECK_VALIDITY(c->pstream, s, tag, ret);
2228
2229     reply = reply_new(tag);
2230     pa_tagstruct_putu32(reply, s->index);
2231     pa_assert(s->source_output);
2232     pa_tagstruct_putu32(reply, s->source_output->index);
2233
2234     if (c->version >= 9) {
2235         /* Since 0.9 we support sending the buffer metrics back to the client */
2236
2237         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.maxlength);
2238         pa_tagstruct_putu32(reply, (uint32_t) s->buffer_attr.fragsize);
2239     }
2240
2241     if (c->version >= 12) {
2242         /* Since 0.9.8 we support sending the chosen sample
2243          * spec/channel map/device/suspend status back to the
2244          * client */
2245
2246         pa_tagstruct_put_sample_spec(reply, &ss);
2247         pa_tagstruct_put_channel_map(reply, &map);
2248
2249         pa_tagstruct_putu32(reply, s->source_output->source->index);
2250         pa_tagstruct_puts(reply, s->source_output->source->name);
2251
2252         pa_tagstruct_put_boolean(reply, pa_source_get_state(s->source_output->source) == PA_SOURCE_SUSPENDED);
2253     }
2254
2255     if (c->version >= 13)
2256         pa_tagstruct_put_usec(reply, s->configured_source_latency);
2257
2258     pa_pstream_send_tagstruct(c->pstream, reply);
2259 }
2260
2261 static void command_exit(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2262     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2263     int ret;
2264
2265     pa_native_connection_assert_ref(c);
2266     pa_assert(t);
2267
2268     if (!pa_tagstruct_eof(t)) {
2269         protocol_error(c);
2270         return;
2271     }
2272
2273     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2274     ret = pa_core_exit(c->protocol->core, FALSE, 0);
2275     CHECK_VALIDITY(c->pstream, ret >= 0, tag, PA_ERR_ACCESS);
2276
2277     pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
2278 }
2279
2280 static void command_auth(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2281     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2282     const void*cookie;
2283     pa_tagstruct *reply;
2284     pa_bool_t shm_on_remote = FALSE, do_shm;
2285
2286     pa_native_connection_assert_ref(c);
2287     pa_assert(t);
2288
2289     if (pa_tagstruct_getu32(t, &c->version) < 0 ||
2290         pa_tagstruct_get_arbitrary(t, &cookie, PA_NATIVE_COOKIE_LENGTH) < 0 ||
2291         !pa_tagstruct_eof(t)) {
2292         protocol_error(c);
2293         return;
2294     }
2295
2296     /* Minimum supported version */
2297     if (c->version < 8) {
2298         pa_pstream_send_error(c->pstream, tag, PA_ERR_VERSION);
2299         return;
2300     }
2301
2302     /* Starting with protocol version 13 the MSB of the version tag
2303        reflects if shm is available for this pa_native_connection or
2304        not. */
2305     if (c->version >= 13) {
2306         shm_on_remote = !!(c->version & 0x80000000U);
2307         c->version &= 0x7FFFFFFFU;
2308     }
2309
2310     pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION);
2311
2312     pa_proplist_setf(c->client->proplist, "native-protocol.version", "%u", c->version);
2313
2314     if (!c->authorized) {
2315         pa_bool_t success = FALSE;
2316
2317 #ifdef HAVE_CREDS
2318         const pa_creds *creds;
2319
2320         if ((creds = pa_pdispatch_creds(pd))) {
2321             if (creds->uid == getuid())
2322                 success = TRUE;
2323             else if (c->options->auth_group) {
2324                 int r;
2325                 gid_t gid;
2326
2327                 if ((gid = pa_get_gid_of_group(c->options->auth_group)) == (gid_t) -1)
2328                     pa_log_warn("Failed to get GID of group '%s'", c->options->auth_group);
2329                 else if (gid == creds->gid)
2330                     success = TRUE;
2331
2332                 if (!success) {
2333                     if ((r = pa_uid_in_group(creds->uid, c->options->auth_group)) < 0)
2334                         pa_log_warn("Failed to check group membership.");
2335                     else if (r > 0)
2336                         success = TRUE;
2337                 }
2338             }
2339
2340             pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
2341                         (unsigned long) creds->uid,
2342                         (unsigned long) creds->gid,
2343                         (int) success);
2344         }
2345 #endif
2346
2347         if (!success && c->options->auth_cookie) {
2348             const uint8_t *ac;
2349
2350             if ((ac = pa_auth_cookie_read(c->options->auth_cookie, PA_NATIVE_COOKIE_LENGTH)))
2351                 if (memcmp(ac, cookie, PA_NATIVE_COOKIE_LENGTH) == 0)
2352                     success = TRUE;
2353         }
2354
2355         if (!success) {
2356             pa_log_warn("Denied access to client with invalid authorization data.");
2357             pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
2358             return;
2359         }
2360
2361         c->authorized = TRUE;
2362         if (c->auth_timeout_event) {
2363             c->protocol->core->mainloop->time_free(c->auth_timeout_event);
2364             c->auth_timeout_event = NULL;
2365         }
2366     }
2367
2368     /* Enable shared memory support if possible */
2369     do_shm =
2370         pa_mempool_is_shared(c->protocol->core->mempool) &&
2371         c->is_local;
2372
2373     pa_log_debug("SHM possible: %s", pa_yes_no(do_shm));
2374
2375     if (do_shm)
2376         if (c->version < 10 || (c->version >= 13 && !shm_on_remote))
2377             do_shm = FALSE;
2378
2379 #ifdef HAVE_CREDS
2380     if (do_shm) {
2381         /* Only enable SHM if both sides are owned by the same
2382          * user. This is a security measure because otherwise data
2383          * private to the user might leak. */
2384
2385         const pa_creds *creds;
2386         if (!(creds = pa_pdispatch_creds(pd)) || getuid() != creds->uid)
2387             do_shm = FALSE;
2388     }
2389 #endif
2390
2391     pa_log_debug("Negotiated SHM: %s", pa_yes_no(do_shm));
2392     pa_pstream_enable_shm(c->pstream, do_shm);
2393
2394     reply = reply_new(tag);
2395     pa_tagstruct_putu32(reply, PA_PROTOCOL_VERSION | (do_shm ? 0x80000000 : 0));
2396
2397 #ifdef HAVE_CREDS
2398 {
2399     /* SHM support is only enabled after both sides made sure they are the same user. */
2400
2401     pa_creds ucred;
2402
2403     ucred.uid = getuid();
2404     ucred.gid = getgid();
2405
2406     pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
2407 }
2408 #else
2409     pa_pstream_send_tagstruct(c->pstream, reply);
2410 #endif
2411 }
2412
2413 static void command_set_client_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2414     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2415     const char *name = NULL;
2416     pa_proplist *p;
2417     pa_tagstruct *reply;
2418
2419     pa_native_connection_assert_ref(c);
2420     pa_assert(t);
2421
2422     p = pa_proplist_new();
2423
2424     if ((c->version < 13 && pa_tagstruct_gets(t, &name) < 0) ||
2425         (c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2426         !pa_tagstruct_eof(t)) {
2427
2428         protocol_error(c);
2429         pa_proplist_free(p);
2430         return;
2431     }
2432
2433     if (name)
2434         if (pa_proplist_sets(p, PA_PROP_APPLICATION_NAME, name) < 0) {
2435             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
2436             pa_proplist_free(p);
2437             return;
2438         }
2439
2440     pa_client_update_proplist(c->client, PA_UPDATE_REPLACE, p);
2441     pa_proplist_free(p);
2442
2443     reply = reply_new(tag);
2444
2445     if (c->version >= 13)
2446         pa_tagstruct_putu32(reply, c->client->index);
2447
2448     pa_pstream_send_tagstruct(c->pstream, reply);
2449 }
2450
2451 static void command_lookup(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2452     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2453     const char *name;
2454     uint32_t idx = PA_IDXSET_INVALID;
2455
2456     pa_native_connection_assert_ref(c);
2457     pa_assert(t);
2458
2459     if (pa_tagstruct_gets(t, &name) < 0 ||
2460         !pa_tagstruct_eof(t)) {
2461         protocol_error(c);
2462         return;
2463     }
2464
2465     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2466     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);
2467
2468     if (command == PA_COMMAND_LOOKUP_SINK) {
2469         pa_sink *sink;
2470         if ((sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK)))
2471             idx = sink->index;
2472     } else {
2473         pa_source *source;
2474         pa_assert(command == PA_COMMAND_LOOKUP_SOURCE);
2475         if ((source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE)))
2476             idx = source->index;
2477     }
2478
2479     if (idx == PA_IDXSET_INVALID)
2480         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2481     else {
2482         pa_tagstruct *reply;
2483         reply = reply_new(tag);
2484         pa_tagstruct_putu32(reply, idx);
2485         pa_pstream_send_tagstruct(c->pstream, reply);
2486     }
2487 }
2488
2489 static void command_drain_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2490     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2491     uint32_t idx;
2492     playback_stream *s;
2493
2494     pa_native_connection_assert_ref(c);
2495     pa_assert(t);
2496
2497     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2498         !pa_tagstruct_eof(t)) {
2499         protocol_error(c);
2500         return;
2501     }
2502
2503     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2504     s = pa_idxset_get_by_index(c->output_streams, idx);
2505     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2506     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2507
2508     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);
2509 }
2510
2511 static void command_stat(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2512     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2513     pa_tagstruct *reply;
2514     const pa_mempool_stat *stat;
2515
2516     pa_native_connection_assert_ref(c);
2517     pa_assert(t);
2518
2519     if (!pa_tagstruct_eof(t)) {
2520         protocol_error(c);
2521         return;
2522     }
2523
2524     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2525
2526     stat = pa_mempool_get_stat(c->protocol->core->mempool);
2527
2528     reply = reply_new(tag);
2529     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_allocated));
2530     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->allocated_size));
2531     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->n_accumulated));
2532     pa_tagstruct_putu32(reply, (uint32_t) pa_atomic_load(&stat->accumulated_size));
2533     pa_tagstruct_putu32(reply, (uint32_t) pa_scache_total_size(c->protocol->core));
2534     pa_pstream_send_tagstruct(c->pstream, reply);
2535 }
2536
2537 static void command_get_playback_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2538     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2539     pa_tagstruct *reply;
2540     playback_stream *s;
2541     struct timeval tv, now;
2542     uint32_t idx;
2543
2544     pa_native_connection_assert_ref(c);
2545     pa_assert(t);
2546
2547     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2548         pa_tagstruct_get_timeval(t, &tv) < 0 ||
2549         !pa_tagstruct_eof(t)) {
2550         protocol_error(c);
2551         return;
2552     }
2553
2554     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2555     s = pa_idxset_get_by_index(c->output_streams, idx);
2556     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2557     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2558
2559     /* Get an atomic snapshot of all timing parameters */
2560     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);
2561
2562     reply = reply_new(tag);
2563     pa_tagstruct_put_usec(reply,
2564                           s->current_sink_latency +
2565                           pa_bytes_to_usec(s->render_memblockq_length, &s->sink_input->sink->sample_spec));
2566     pa_tagstruct_put_usec(reply, 0);
2567     pa_tagstruct_put_boolean(reply,
2568                              s->playing_for > 0 &&
2569                              pa_sink_get_state(s->sink_input->sink) == PA_SINK_RUNNING &&
2570                              pa_sink_input_get_state(s->sink_input) == PA_SINK_INPUT_RUNNING);
2571     pa_tagstruct_put_timeval(reply, &tv);
2572     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2573     pa_tagstruct_puts64(reply, s->write_index);
2574     pa_tagstruct_puts64(reply, s->read_index);
2575
2576     if (c->version >= 13) {
2577         pa_tagstruct_putu64(reply, s->underrun_for);
2578         pa_tagstruct_putu64(reply, s->playing_for);
2579     }
2580
2581     pa_pstream_send_tagstruct(c->pstream, reply);
2582 }
2583
2584 static void command_get_record_latency(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2585     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2586     pa_tagstruct *reply;
2587     record_stream *s;
2588     struct timeval tv, now;
2589     uint32_t idx;
2590
2591     pa_native_connection_assert_ref(c);
2592     pa_assert(t);
2593
2594     if (pa_tagstruct_getu32(t, &idx) < 0 ||
2595         pa_tagstruct_get_timeval(t, &tv) < 0 ||
2596         !pa_tagstruct_eof(t)) {
2597         protocol_error(c);
2598         return;
2599     }
2600
2601     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2602     s = pa_idxset_get_by_index(c->record_streams, idx);
2603     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2604
2605     /* Get an atomic snapshot of all timing parameters */
2606     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);
2607
2608     reply = reply_new(tag);
2609     pa_tagstruct_put_usec(reply, s->current_monitor_latency);
2610     pa_tagstruct_put_usec(reply,
2611                           s->current_source_latency +
2612                           pa_bytes_to_usec(s->on_the_fly_snapshot, &s->source_output->sample_spec));
2613     pa_tagstruct_put_boolean(reply,
2614                              pa_source_get_state(s->source_output->source) == PA_SOURCE_RUNNING &&
2615                              pa_source_output_get_state(s->source_output) == PA_SOURCE_OUTPUT_RUNNING);
2616     pa_tagstruct_put_timeval(reply, &tv);
2617     pa_tagstruct_put_timeval(reply, pa_gettimeofday(&now));
2618     pa_tagstruct_puts64(reply, pa_memblockq_get_write_index(s->memblockq));
2619     pa_tagstruct_puts64(reply, pa_memblockq_get_read_index(s->memblockq));
2620     pa_pstream_send_tagstruct(c->pstream, reply);
2621 }
2622
2623 static void command_create_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2624     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2625     upload_stream *s;
2626     uint32_t length;
2627     const char *name = NULL;
2628     pa_sample_spec ss;
2629     pa_channel_map map;
2630     pa_tagstruct *reply;
2631     pa_proplist *p;
2632
2633     pa_native_connection_assert_ref(c);
2634     pa_assert(t);
2635
2636     if (pa_tagstruct_gets(t, &name) < 0 ||
2637         pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
2638         pa_tagstruct_get_channel_map(t, &map) < 0 ||
2639         pa_tagstruct_getu32(t, &length) < 0) {
2640         protocol_error(c);
2641         return;
2642     }
2643
2644     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2645     CHECK_VALIDITY(c->pstream, pa_sample_spec_valid(&ss), tag, PA_ERR_INVALID);
2646     CHECK_VALIDITY(c->pstream, pa_channel_map_valid(&map), tag, PA_ERR_INVALID);
2647     CHECK_VALIDITY(c->pstream, map.channels == ss.channels, tag, PA_ERR_INVALID);
2648     CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
2649     CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
2650
2651     p = pa_proplist_new();
2652
2653     if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2654         !pa_tagstruct_eof(t)) {
2655
2656         protocol_error(c);
2657         pa_proplist_free(p);
2658         return;
2659     }
2660
2661     if (c->version < 13)
2662         pa_proplist_sets(p, PA_PROP_MEDIA_NAME, name);
2663     else if (!name)
2664         if (!(name = pa_proplist_gets(p, PA_PROP_EVENT_ID)))
2665             name = pa_proplist_gets(p, PA_PROP_MEDIA_NAME);
2666
2667     if (!name || !pa_namereg_is_valid_name(name)) {
2668         pa_proplist_free(p);
2669         CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
2670     }
2671
2672     s = upload_stream_new(c, &ss, &map, name, length, p);
2673     pa_proplist_free(p);
2674
2675     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
2676
2677     reply = reply_new(tag);
2678     pa_tagstruct_putu32(reply, s->index);
2679     pa_tagstruct_putu32(reply, length);
2680     pa_pstream_send_tagstruct(c->pstream, reply);
2681 }
2682
2683 static void command_finish_upload_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2684     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2685     uint32_t channel;
2686     upload_stream *s;
2687     uint32_t idx;
2688
2689     pa_native_connection_assert_ref(c);
2690     pa_assert(t);
2691
2692     if (pa_tagstruct_getu32(t, &channel) < 0 ||
2693         !pa_tagstruct_eof(t)) {
2694         protocol_error(c);
2695         return;
2696     }
2697
2698     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2699
2700     s = pa_idxset_get_by_index(c->output_streams, channel);
2701     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
2702     CHECK_VALIDITY(c->pstream, upload_stream_isinstance(s), tag, PA_ERR_NOENTITY);
2703
2704     if (!s->memchunk.memblock)
2705         pa_pstream_send_error(c->pstream, tag, PA_ERR_TOOLARGE);
2706     else if (pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, s->proplist, &idx) < 0)
2707         pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
2708     else
2709         pa_pstream_send_simple_ack(c->pstream, tag);
2710
2711     upload_stream_unlink(s);
2712 }
2713
2714 static void command_play_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2715     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2716     uint32_t sink_index;
2717     pa_volume_t volume;
2718     pa_sink *sink;
2719     const char *name, *sink_name;
2720     uint32_t idx;
2721     pa_proplist *p;
2722     pa_tagstruct *reply;
2723
2724     pa_native_connection_assert_ref(c);
2725     pa_assert(t);
2726
2727     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2728
2729     if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
2730         pa_tagstruct_gets(t, &sink_name) < 0 ||
2731         pa_tagstruct_getu32(t, &volume) < 0 ||
2732         pa_tagstruct_gets(t, &name) < 0) {
2733         protocol_error(c);
2734         return;
2735     }
2736
2737     CHECK_VALIDITY(c->pstream, !sink_name || pa_namereg_is_valid_name_or_wildcard(sink_name, PA_NAMEREG_SINK), tag, PA_ERR_INVALID);
2738     CHECK_VALIDITY(c->pstream, sink_index == PA_INVALID_INDEX || !sink_name, tag, PA_ERR_INVALID);
2739     CHECK_VALIDITY(c->pstream, !sink_name || sink_index == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
2740     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2741
2742     if (sink_index != PA_INVALID_INDEX)
2743         sink = pa_idxset_get_by_index(c->protocol->core->sinks, sink_index);
2744     else
2745         sink = pa_namereg_get(c->protocol->core, sink_name, PA_NAMEREG_SINK);
2746
2747     CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
2748
2749     p = pa_proplist_new();
2750
2751     if ((c->version >= 13 && pa_tagstruct_get_proplist(t, p) < 0) ||
2752         !pa_tagstruct_eof(t)) {
2753         protocol_error(c);
2754         pa_proplist_free(p);
2755         return;
2756     }
2757
2758     pa_proplist_update(p, PA_UPDATE_MERGE, c->client->proplist);
2759
2760     if (pa_scache_play_item(c->protocol->core, name, sink, volume, p, &idx) < 0) {
2761         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2762         pa_proplist_free(p);
2763         return;
2764     }
2765
2766     pa_proplist_free(p);
2767
2768     reply = reply_new(tag);
2769
2770     if (c->version >= 13)
2771         pa_tagstruct_putu32(reply, idx);
2772
2773     pa_pstream_send_tagstruct(c->pstream, reply);
2774 }
2775
2776 static void command_remove_sample(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
2777     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
2778     const char *name;
2779
2780     pa_native_connection_assert_ref(c);
2781     pa_assert(t);
2782
2783     if (pa_tagstruct_gets(t, &name) < 0 ||
2784         !pa_tagstruct_eof(t)) {
2785         protocol_error(c);
2786         return;
2787     }
2788
2789     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
2790     CHECK_VALIDITY(c->pstream, name && pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
2791
2792     if (pa_scache_remove_item(c->protocol->core, name) < 0) {
2793         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
2794         return;
2795     }
2796
2797     pa_pstream_send_simple_ack(c->pstream, tag);
2798 }
2799
2800 static void fixup_sample_spec(pa_native_connection *c, pa_sample_spec *fixed, const pa_sample_spec *original) {
2801     pa_assert(c);
2802     pa_assert(fixed);
2803     pa_assert(original);
2804
2805     *fixed = *original;
2806
2807     if (c->version < 12) {
2808         /* Before protocol version 12 we didn't support S32 samples,
2809          * so we need to lie about this to the client */
2810
2811         if (fixed->format == PA_SAMPLE_S32LE)
2812             fixed->format = PA_SAMPLE_FLOAT32LE;
2813         if (fixed->format == PA_SAMPLE_S32BE)
2814             fixed->format = PA_SAMPLE_FLOAT32BE;
2815     }
2816
2817     if (c->version < 15) {
2818         if (fixed->format == PA_SAMPLE_S24LE || fixed->format == PA_SAMPLE_S24_32LE)
2819             fixed->format = PA_SAMPLE_FLOAT32LE;
2820         if (fixed->format == PA_SAMPLE_S24BE || fixed->format == PA_SAMPLE_S24_32BE)
2821             fixed->format = PA_SAMPLE_FLOAT32BE;
2822     }
2823 }
2824
2825 static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink *sink) {
2826     pa_sample_spec fixed_ss;
2827
2828     pa_assert(t);
2829     pa_sink_assert_ref(sink);
2830
2831     fixup_sample_spec(c, &fixed_ss, &sink->sample_spec);
2832
2833     pa_tagstruct_put(
2834         t,
2835         PA_TAG_U32, sink->index,
2836         PA_TAG_STRING, sink->name,
2837         PA_TAG_STRING, pa_strnull(pa_proplist_gets(sink->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2838         PA_TAG_SAMPLE_SPEC, &fixed_ss,
2839         PA_TAG_CHANNEL_MAP, &sink->channel_map,
2840         PA_TAG_U32, sink->module ? sink->module->index : PA_INVALID_INDEX,
2841         PA_TAG_CVOLUME, pa_sink_get_volume(sink, FALSE),
2842         PA_TAG_BOOLEAN, pa_sink_get_mute(sink, FALSE),
2843         PA_TAG_U32, sink->monitor_source ? sink->monitor_source->index : PA_INVALID_INDEX,
2844         PA_TAG_STRING, sink->monitor_source ? sink->monitor_source->name : NULL,
2845         PA_TAG_USEC, pa_sink_get_latency(sink),
2846         PA_TAG_STRING, sink->driver,
2847         PA_TAG_U32, sink->flags,
2848         PA_TAG_INVALID);
2849
2850     if (c->version >= 13) {
2851         pa_tagstruct_put_proplist(t, sink->proplist);
2852         pa_tagstruct_put_usec(t, pa_sink_get_requested_latency(sink));
2853     }
2854
2855     if (c->version >= 15) {
2856         pa_tagstruct_put_volume(t, sink->base_volume);
2857         if (PA_UNLIKELY(pa_sink_get_state(sink) == PA_SINK_INVALID_STATE))
2858             pa_log_error("Internal sink state is invalid.");
2859         pa_tagstruct_putu32(t, pa_sink_get_state(sink));
2860         pa_tagstruct_putu32(t, sink->n_volume_steps);
2861         pa_tagstruct_putu32(t, sink->card ? sink->card->index : PA_INVALID_INDEX);
2862     }
2863
2864     if (c->version >= 16) {
2865         pa_tagstruct_putu32(t, sink->ports ? pa_hashmap_size(sink->ports) : 0);
2866
2867         if (sink->ports) {
2868             void *state;
2869             pa_device_port *p;
2870
2871             PA_HASHMAP_FOREACH(p, sink->ports, state) {
2872                 pa_tagstruct_puts(t, p->name);
2873                 pa_tagstruct_puts(t, p->description);
2874                 pa_tagstruct_putu32(t, p->priority);
2875             }
2876         }
2877
2878         pa_tagstruct_puts(t, sink->active_port ? sink->active_port->name : NULL);
2879     }
2880 }
2881
2882 static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source *source) {
2883     pa_sample_spec fixed_ss;
2884
2885     pa_assert(t);
2886     pa_source_assert_ref(source);
2887
2888     fixup_sample_spec(c, &fixed_ss, &source->sample_spec);
2889
2890     pa_tagstruct_put(
2891         t,
2892         PA_TAG_U32, source->index,
2893         PA_TAG_STRING, source->name,
2894         PA_TAG_STRING, pa_strnull(pa_proplist_gets(source->proplist, PA_PROP_DEVICE_DESCRIPTION)),
2895         PA_TAG_SAMPLE_SPEC, &fixed_ss,
2896         PA_TAG_CHANNEL_MAP, &source->channel_map,
2897         PA_TAG_U32, source->module ? source->module->index : PA_INVALID_INDEX,
2898         PA_TAG_CVOLUME, pa_source_get_volume(source, FALSE),
2899         PA_TAG_BOOLEAN, pa_source_get_mute(source, FALSE),
2900         PA_TAG_U32, source->monitor_of ? source->monitor_of->index : PA_INVALID_INDEX,
2901         PA_TAG_STRING, source->monitor_of ? source->monitor_of->name : NULL,
2902         PA_TAG_USEC, pa_source_get_latency(source),
2903         PA_TAG_STRING, source->driver,
2904         PA_TAG_U32, source->flags,
2905         PA_TAG_INVALID);
2906
2907     if (c->version >= 13) {
2908         pa_tagstruct_put_proplist(t, source->proplist);
2909         pa_tagstruct_put_usec(t, pa_source_get_requested_latency(source));
2910     }
2911
2912     if (c->version >= 15) {
2913         pa_tagstruct_put_volume(t, source->base_volume);
2914         if (PA_UNLIKELY(pa_source_get_state(source) == PA_SOURCE_INVALID_STATE))
2915             pa_log_error("Internal source state is invalid.");
2916         pa_tagstruct_putu32(t, pa_source_get_state(source));
2917         pa_tagstruct_putu32(t, source->n_volume_steps);
2918         pa_tagstruct_putu32(t, source->card ? source->card->index : PA_INVALID_INDEX);
2919     }
2920
2921     if (c->version >= 16) {
2922
2923         pa_tagstruct_putu32(t, source->ports ? pa_hashmap_size(source->ports) : 0);
2924
2925         if (source->ports) {
2926             void *state;
2927             pa_device_port *p;
2928
2929             PA_HASHMAP_FOREACH(p, source->ports, state) {
2930                 pa_tagstruct_puts(t, p->name);
2931                 pa_tagstruct_puts(t, p->description);
2932                 pa_tagstruct_putu32(t, p->priority);
2933             }
2934         }
2935
2936         pa_tagstruct_puts(t, source->active_port ? source->active_port->name : NULL);
2937     }
2938 }
2939
2940 static void client_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_client *client) {
2941     pa_assert(t);
2942     pa_assert(client);
2943
2944     pa_tagstruct_putu32(t, client->index);
2945     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(client->proplist, PA_PROP_APPLICATION_NAME)));
2946     pa_tagstruct_putu32(t, client->module ? client->module->index : PA_INVALID_INDEX);
2947     pa_tagstruct_puts(t, client->driver);
2948
2949     if (c->version >= 13)
2950         pa_tagstruct_put_proplist(t, client->proplist);
2951 }
2952
2953 static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_card *card) {
2954     void *state = NULL;
2955     pa_card_profile *p;
2956
2957     pa_assert(t);
2958     pa_assert(card);
2959
2960     pa_tagstruct_putu32(t, card->index);
2961     pa_tagstruct_puts(t, card->name);
2962     pa_tagstruct_putu32(t, card->module ? card->module->index : PA_INVALID_INDEX);
2963     pa_tagstruct_puts(t, card->driver);
2964
2965     pa_tagstruct_putu32(t, card->profiles ? pa_hashmap_size(card->profiles) : 0);
2966
2967     if (card->profiles) {
2968         while ((p = pa_hashmap_iterate(card->profiles, &state, NULL))) {
2969             pa_tagstruct_puts(t, p->name);
2970             pa_tagstruct_puts(t, p->description);
2971             pa_tagstruct_putu32(t, p->n_sinks);
2972             pa_tagstruct_putu32(t, p->n_sources);
2973             pa_tagstruct_putu32(t, p->priority);
2974         }
2975     }
2976
2977     pa_tagstruct_puts(t, card->active_profile ? card->active_profile->name : NULL);
2978     pa_tagstruct_put_proplist(t, card->proplist);
2979 }
2980
2981 static void module_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_module *module) {
2982     pa_assert(t);
2983     pa_assert(module);
2984
2985     pa_tagstruct_putu32(t, module->index);
2986     pa_tagstruct_puts(t, module->name);
2987     pa_tagstruct_puts(t, module->argument);
2988     pa_tagstruct_putu32(t, (uint32_t) pa_module_get_n_used(module));
2989
2990     if (c->version < 15)
2991         pa_tagstruct_put_boolean(t, FALSE); /* autoload is obsolete */
2992
2993     if (c->version >= 15)
2994         pa_tagstruct_put_proplist(t, module->proplist);
2995 }
2996
2997 static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sink_input *s) {
2998     pa_sample_spec fixed_ss;
2999     pa_usec_t sink_latency;
3000     pa_cvolume v;
3001
3002     pa_assert(t);
3003     pa_sink_input_assert_ref(s);
3004
3005     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3006
3007     pa_tagstruct_putu32(t, s->index);
3008     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3009     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3010     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3011     pa_tagstruct_putu32(t, s->sink->index);
3012     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3013     pa_tagstruct_put_channel_map(t, &s->channel_map);
3014     pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s, &v, TRUE));
3015     pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
3016     pa_tagstruct_put_usec(t, sink_latency);
3017     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
3018     pa_tagstruct_puts(t, s->driver);
3019     if (c->version >= 11)
3020         pa_tagstruct_put_boolean(t, pa_sink_input_get_mute(s));
3021     if (c->version >= 13)
3022         pa_tagstruct_put_proplist(t, s->proplist);
3023 }
3024
3025 static void source_output_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_source_output *s) {
3026     pa_sample_spec fixed_ss;
3027     pa_usec_t source_latency;
3028
3029     pa_assert(t);
3030     pa_source_output_assert_ref(s);
3031
3032     fixup_sample_spec(c, &fixed_ss, &s->sample_spec);
3033
3034     pa_tagstruct_putu32(t, s->index);
3035     pa_tagstruct_puts(t, pa_strnull(pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME)));
3036     pa_tagstruct_putu32(t, s->module ? s->module->index : PA_INVALID_INDEX);
3037     pa_tagstruct_putu32(t, s->client ? s->client->index : PA_INVALID_INDEX);
3038     pa_tagstruct_putu32(t, s->source->index);
3039     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3040     pa_tagstruct_put_channel_map(t, &s->channel_map);
3041     pa_tagstruct_put_usec(t, pa_source_output_get_latency(s, &source_latency));
3042     pa_tagstruct_put_usec(t, source_latency);
3043     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
3044     pa_tagstruct_puts(t, s->driver);
3045
3046     if (c->version >= 13)
3047         pa_tagstruct_put_proplist(t, s->proplist);
3048 }
3049
3050 static void scache_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_scache_entry *e) {
3051     pa_sample_spec fixed_ss;
3052     pa_cvolume v;
3053
3054     pa_assert(t);
3055     pa_assert(e);
3056
3057     if (e->memchunk.memblock)
3058         fixup_sample_spec(c, &fixed_ss, &e->sample_spec);
3059     else
3060         memset(&fixed_ss, 0, sizeof(fixed_ss));
3061
3062     pa_tagstruct_putu32(t, e->index);
3063     pa_tagstruct_puts(t, e->name);
3064
3065     if (e->volume_is_set)
3066         v = e->volume;
3067     else
3068         pa_cvolume_init(&v);
3069
3070     pa_tagstruct_put_cvolume(t, &v);
3071     pa_tagstruct_put_usec(t, e->memchunk.memblock ? pa_bytes_to_usec(e->memchunk.length, &e->sample_spec) : 0);
3072     pa_tagstruct_put_sample_spec(t, &fixed_ss);
3073     pa_tagstruct_put_channel_map(t, &e->channel_map);
3074     pa_tagstruct_putu32(t, (uint32_t) e->memchunk.length);
3075     pa_tagstruct_put_boolean(t, e->lazy);
3076     pa_tagstruct_puts(t, e->filename);
3077
3078     if (c->version >= 13)
3079         pa_tagstruct_put_proplist(t, e->proplist);
3080 }
3081
3082 static void command_get_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3083     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3084     uint32_t idx;
3085     pa_sink *sink = NULL;
3086     pa_source *source = NULL;
3087     pa_client *client = NULL;
3088     pa_card *card = NULL;
3089     pa_module *module = NULL;
3090     pa_sink_input *si = NULL;
3091     pa_source_output *so = NULL;
3092     pa_scache_entry *sce = NULL;
3093     const char *name = NULL;
3094     pa_tagstruct *reply;
3095
3096     pa_native_connection_assert_ref(c);
3097     pa_assert(t);
3098
3099     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3100         (command != PA_COMMAND_GET_CLIENT_INFO &&
3101          command != PA_COMMAND_GET_MODULE_INFO &&
3102          command != PA_COMMAND_GET_SINK_INPUT_INFO &&
3103          command != PA_COMMAND_GET_SOURCE_OUTPUT_INFO &&
3104          pa_tagstruct_gets(t, &name) < 0) ||
3105         !pa_tagstruct_eof(t)) {
3106         protocol_error(c);
3107         return;
3108     }
3109
3110     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3111     CHECK_VALIDITY(c->pstream, !name ||
3112                    (command == PA_COMMAND_GET_SINK_INFO &&
3113                     pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SINK)) ||
3114                    (command == PA_COMMAND_GET_SOURCE_INFO &&
3115                     pa_namereg_is_valid_name_or_wildcard(name, PA_NAMEREG_SOURCE)) ||
3116                    pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3117     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3118     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3119     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3120
3121     if (command == PA_COMMAND_GET_SINK_INFO) {
3122         if (idx != PA_INVALID_INDEX)
3123             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3124         else
3125             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3126     } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3127         if (idx != PA_INVALID_INDEX)
3128             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3129         else
3130             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3131     } else if (command == PA_COMMAND_GET_CARD_INFO) {
3132         if (idx != PA_INVALID_INDEX)
3133             card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3134         else
3135             card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3136     } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3137         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3138     else if (command == PA_COMMAND_GET_MODULE_INFO)
3139         module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3140     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3141         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3142     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3143         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3144     else {
3145         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3146         if (idx != PA_INVALID_INDEX)
3147             sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3148         else
3149             sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3150     }
3151
3152     if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3153         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3154         return;
3155     }
3156
3157     reply = reply_new(tag);
3158     if (sink)
3159         sink_fill_tagstruct(c, reply, sink);
3160     else if (source)
3161         source_fill_tagstruct(c, reply, source);
3162     else if (client)
3163         client_fill_tagstruct(c, reply, client);
3164     else if (card)
3165         card_fill_tagstruct(c, reply, card);
3166     else if (module)
3167         module_fill_tagstruct(c, reply, module);
3168     else if (si)
3169         sink_input_fill_tagstruct(c, reply, si);
3170     else if (so)
3171         source_output_fill_tagstruct(c, reply, so);
3172     else
3173         scache_fill_tagstruct(c, reply, sce);
3174     pa_pstream_send_tagstruct(c->pstream, reply);
3175 }
3176
3177 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3178     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3179     pa_idxset *i;
3180     uint32_t idx;
3181     void *p;
3182     pa_tagstruct *reply;
3183
3184     pa_native_connection_assert_ref(c);
3185     pa_assert(t);
3186
3187     if (!pa_tagstruct_eof(t)) {
3188         protocol_error(c);
3189         return;
3190     }
3191
3192     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3193
3194     reply = reply_new(tag);
3195
3196     if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3197         i = c->protocol->core->sinks;
3198     else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3199         i = c->protocol->core->sources;
3200     else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3201         i = c->protocol->core->clients;
3202     else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3203         i = c->protocol->core->cards;
3204     else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3205         i = c->protocol->core->modules;
3206     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3207         i = c->protocol->core->sink_inputs;
3208     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3209         i = c->protocol->core->source_outputs;
3210     else {
3211         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3212         i = c->protocol->core->scache;
3213     }
3214
3215     if (i) {
3216         for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
3217             if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3218                 sink_fill_tagstruct(c, reply, p);
3219             else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3220                 source_fill_tagstruct(c, reply, p);
3221             else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3222                 client_fill_tagstruct(c, reply, p);
3223             else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3224                 card_fill_tagstruct(c, reply, p);
3225             else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3226                 module_fill_tagstruct(c, reply, p);
3227             else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3228                 sink_input_fill_tagstruct(c, reply, p);
3229             else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3230                 source_output_fill_tagstruct(c, reply, p);
3231             else {
3232                 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3233                 scache_fill_tagstruct(c, reply, p);
3234             }
3235         }
3236     }
3237
3238     pa_pstream_send_tagstruct(c->pstream, reply);
3239 }
3240
3241 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3242     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3243     pa_tagstruct *reply;
3244     pa_sink *def_sink;
3245     pa_source *def_source;
3246     pa_sample_spec fixed_ss;
3247     char *h, *u;
3248
3249     pa_native_connection_assert_ref(c);
3250     pa_assert(t);
3251
3252     if (!pa_tagstruct_eof(t)) {
3253         protocol_error(c);
3254         return;
3255     }
3256
3257     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3258
3259     reply = reply_new(tag);
3260     pa_tagstruct_puts(reply, PACKAGE_NAME);
3261     pa_tagstruct_puts(reply, PACKAGE_VERSION);
3262
3263     u = pa_get_user_name_malloc();
3264     pa_tagstruct_puts(reply, u);
3265     pa_xfree(u);
3266
3267     h = pa_get_host_name_malloc();
3268     pa_tagstruct_puts(reply, h);
3269     pa_xfree(h);
3270
3271     fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3272     pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3273
3274     def_sink = pa_namereg_get_default_sink(c->protocol->core);
3275     pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3276     def_source = pa_namereg_get_default_source(c->protocol->core);
3277     pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3278
3279     pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3280
3281     if (c->version >= 15)
3282         pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3283
3284     pa_pstream_send_tagstruct(c->pstream, reply);
3285 }
3286
3287 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3288     pa_tagstruct *t;
3289     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3290
3291     pa_native_connection_assert_ref(c);
3292
3293     t = pa_tagstruct_new(NULL, 0);
3294     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3295     pa_tagstruct_putu32(t, (uint32_t) -1);
3296     pa_tagstruct_putu32(t, e);
3297     pa_tagstruct_putu32(t, idx);
3298     pa_pstream_send_tagstruct(c->pstream, t);
3299 }
3300
3301 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3302     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3303     pa_subscription_mask_t m;
3304
3305     pa_native_connection_assert_ref(c);
3306     pa_assert(t);
3307
3308     if (pa_tagstruct_getu32(t, &m) < 0 ||
3309         !pa_tagstruct_eof(t)) {
3310         protocol_error(c);
3311         return;
3312     }
3313
3314     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3315     CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3316
3317     if (c->subscription)
3318         pa_subscription_free(c->subscription);
3319
3320     if (m != 0) {
3321         c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3322         pa_assert(c->subscription);
3323     } else
3324         c->subscription = NULL;
3325
3326     pa_pstream_send_simple_ack(c->pstream, tag);
3327 }
3328
3329 static void command_set_volume(
3330         pa_pdispatch *pd,
3331         uint32_t command,
3332         uint32_t tag,
3333         pa_tagstruct *t,
3334         void *userdata) {
3335
3336     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3337     uint32_t idx;
3338     pa_cvolume volume;
3339     pa_sink *sink = NULL;
3340     pa_source *source = NULL;
3341     pa_sink_input *si = NULL;
3342     const char *name = NULL;
3343     const char *client_name;
3344
3345     pa_native_connection_assert_ref(c);
3346     pa_assert(t);
3347
3348     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3349         (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3350         (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3351         pa_tagstruct_get_cvolume(t, &volume) ||
3352         !pa_tagstruct_eof(t)) {
3353         protocol_error(c);
3354         return;
3355     }
3356
3357     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3358     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);
3359     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3360     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3361     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3362     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3363
3364     switch (command) {
3365
3366         case PA_COMMAND_SET_SINK_VOLUME:
3367             if (idx != PA_INVALID_INDEX)
3368                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3369             else
3370                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3371             break;
3372
3373         case PA_COMMAND_SET_SOURCE_VOLUME:
3374             if (idx != PA_INVALID_INDEX)
3375                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3376             else
3377                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3378             break;
3379
3380         case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3381             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3382             break;
3383
3384         default:
3385             pa_assert_not_reached();
3386     }
3387
3388     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3389
3390     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3391
3392     if (sink) {
3393         pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3394         pa_sink_set_volume(sink, &volume, TRUE, TRUE);
3395     } else if (source) {
3396         pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3397         pa_source_set_volume(source, &volume, TRUE);
3398     } else if (si) {
3399         pa_log_debug("Client %s changes volume of sink input %s.",
3400                      client_name,
3401                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3402         pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
3403     }
3404
3405     pa_pstream_send_simple_ack(c->pstream, tag);
3406 }
3407
3408 static void command_set_mute(
3409         pa_pdispatch *pd,
3410         uint32_t command,
3411         uint32_t tag,
3412         pa_tagstruct *t,
3413         void *userdata) {
3414
3415     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3416     uint32_t idx;
3417     pa_bool_t mute;
3418     pa_sink *sink = NULL;
3419     pa_source *source = NULL;
3420     pa_sink_input *si = NULL;
3421     const char *name = NULL, *client_name;
3422
3423     pa_native_connection_assert_ref(c);
3424     pa_assert(t);
3425
3426     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3427         (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3428         (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3429         pa_tagstruct_get_boolean(t, &mute) ||
3430         !pa_tagstruct_eof(t)) {
3431         protocol_error(c);
3432         return;
3433     }
3434
3435     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3436     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);
3437     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3438     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3439     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3440
3441     switch (command) {
3442
3443         case PA_COMMAND_SET_SINK_MUTE:
3444
3445             if (idx != PA_INVALID_INDEX)
3446                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3447             else
3448                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3449
3450             break;
3451
3452         case PA_COMMAND_SET_SOURCE_MUTE:
3453             if (idx != PA_INVALID_INDEX)
3454                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3455             else
3456                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3457
3458             break;
3459
3460         case PA_COMMAND_SET_SINK_INPUT_MUTE:
3461             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3462             break;
3463
3464         default:
3465             pa_assert_not_reached();
3466     }
3467
3468     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3469
3470     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3471
3472     if (sink) {
3473         pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3474         pa_sink_set_mute(sink, mute, TRUE);
3475     } else if (source) {
3476         pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3477         pa_source_set_mute(source, mute, TRUE);
3478     } else if (si) {
3479         pa_log_debug("Client %s changes mute of sink input %s.",
3480                      client_name,
3481                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3482         pa_sink_input_set_mute(si, mute, TRUE);
3483     }
3484
3485     pa_pstream_send_simple_ack(c->pstream, tag);
3486 }
3487
3488 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3489     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3490     uint32_t idx;
3491     pa_bool_t b;
3492     playback_stream *s;
3493
3494     pa_native_connection_assert_ref(c);
3495     pa_assert(t);
3496
3497     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3498         pa_tagstruct_get_boolean(t, &b) < 0 ||
3499         !pa_tagstruct_eof(t)) {
3500         protocol_error(c);
3501         return;
3502     }
3503
3504     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3505     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3506     s = pa_idxset_get_by_index(c->output_streams, idx);
3507     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3508     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3509
3510     pa_sink_input_cork(s->sink_input, b);
3511
3512     if (b)
3513         s->is_underrun = TRUE;
3514
3515     pa_pstream_send_simple_ack(c->pstream, tag);
3516 }
3517
3518 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3519     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3520     uint32_t idx;
3521     playback_stream *s;
3522
3523     pa_native_connection_assert_ref(c);
3524     pa_assert(t);
3525
3526     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3527         !pa_tagstruct_eof(t)) {
3528         protocol_error(c);
3529         return;
3530     }
3531
3532     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3533     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3534     s = pa_idxset_get_by_index(c->output_streams, idx);
3535     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3536     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3537
3538     switch (command) {
3539         case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3540             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3541             break;
3542
3543         case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3544             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3545             break;
3546
3547         case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3548             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3549             break;
3550
3551         default:
3552             pa_assert_not_reached();
3553     }
3554
3555     pa_pstream_send_simple_ack(c->pstream, tag);
3556 }
3557
3558 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3559     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3560     uint32_t idx;
3561     record_stream *s;
3562     pa_bool_t b;
3563
3564     pa_native_connection_assert_ref(c);
3565     pa_assert(t);
3566
3567     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3568         pa_tagstruct_get_boolean(t, &b) < 0 ||
3569         !pa_tagstruct_eof(t)) {
3570         protocol_error(c);
3571         return;
3572     }
3573
3574     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3575     s = pa_idxset_get_by_index(c->record_streams, idx);
3576     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3577
3578     pa_source_output_cork(s->source_output, b);
3579     pa_memblockq_prebuf_force(s->memblockq);
3580     pa_pstream_send_simple_ack(c->pstream, tag);
3581 }
3582
3583 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3584     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3585     uint32_t idx;
3586     record_stream *s;
3587
3588     pa_native_connection_assert_ref(c);
3589     pa_assert(t);
3590
3591     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3592         !pa_tagstruct_eof(t)) {
3593         protocol_error(c);
3594         return;
3595     }
3596
3597     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3598     s = pa_idxset_get_by_index(c->record_streams, idx);
3599     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3600
3601     pa_memblockq_flush_read(s->memblockq);
3602     pa_pstream_send_simple_ack(c->pstream, tag);
3603 }
3604
3605 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3606     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3607     uint32_t idx;
3608     pa_buffer_attr a;
3609     pa_tagstruct *reply;
3610
3611     pa_native_connection_assert_ref(c);
3612     pa_assert(t);
3613
3614     memset(&a, 0, sizeof(a));
3615
3616     if (pa_tagstruct_getu32(t, &idx) < 0) {
3617         protocol_error(c);
3618         return;
3619     }
3620
3621     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3622
3623     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3624         playback_stream *s;
3625         pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3626
3627         s = pa_idxset_get_by_index(c->output_streams, idx);
3628         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3629         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3630
3631         if (pa_tagstruct_get(
3632                     t,
3633                     PA_TAG_U32, &a.maxlength,
3634                     PA_TAG_U32, &a.tlength,
3635                     PA_TAG_U32, &a.prebuf,
3636                     PA_TAG_U32, &a.minreq,
3637                     PA_TAG_INVALID) < 0 ||
3638             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3639             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3640             !pa_tagstruct_eof(t)) {
3641             protocol_error(c);
3642             return;
3643         }
3644
3645         s->adjust_latency = adjust_latency;
3646         s->early_requests = early_requests;
3647         s->buffer_attr = a;
3648
3649         fix_playback_buffer_attr(s);
3650         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);
3651
3652         reply = reply_new(tag);
3653         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3654         pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3655         pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3656         pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3657
3658         if (c->version >= 13)
3659             pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3660
3661     } else {
3662         record_stream *s;
3663         pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3664         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3665
3666         s = pa_idxset_get_by_index(c->record_streams, idx);
3667         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3668
3669         if (pa_tagstruct_get(
3670                     t,
3671                     PA_TAG_U32, &a.maxlength,
3672                     PA_TAG_U32, &a.fragsize,
3673                     PA_TAG_INVALID) < 0 ||
3674             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3675             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3676             !pa_tagstruct_eof(t)) {
3677             protocol_error(c);
3678             return;
3679         }
3680
3681         s->adjust_latency = adjust_latency;
3682         s->early_requests = early_requests;
3683         s->buffer_attr = a;
3684
3685         fix_record_buffer_attr_pre(s);
3686         pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
3687         pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
3688         fix_record_buffer_attr_post(s);
3689
3690         reply = reply_new(tag);
3691         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3692         pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
3693
3694         if (c->version >= 13)
3695             pa_tagstruct_put_usec(reply, s->configured_source_latency);
3696     }
3697
3698     pa_pstream_send_tagstruct(c->pstream, reply);
3699 }
3700
3701 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3702     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3703     uint32_t idx;
3704     uint32_t rate;
3705
3706     pa_native_connection_assert_ref(c);
3707     pa_assert(t);
3708
3709     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3710         pa_tagstruct_getu32(t, &rate) < 0 ||
3711         !pa_tagstruct_eof(t)) {
3712         protocol_error(c);
3713         return;
3714     }
3715
3716     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3717     CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
3718
3719     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
3720         playback_stream *s;
3721
3722         s = pa_idxset_get_by_index(c->output_streams, idx);
3723         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3724         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3725
3726         pa_sink_input_set_rate(s->sink_input, rate);
3727
3728     } else {
3729         record_stream *s;
3730         pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
3731
3732         s = pa_idxset_get_by_index(c->record_streams, idx);
3733         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3734
3735         pa_source_output_set_rate(s->source_output, rate);
3736     }
3737
3738     pa_pstream_send_simple_ack(c->pstream, tag);
3739 }
3740
3741 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3742     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3743     uint32_t idx;
3744     uint32_t mode;
3745     pa_proplist *p;
3746
3747     pa_native_connection_assert_ref(c);
3748     pa_assert(t);
3749
3750     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3751
3752     p = pa_proplist_new();
3753
3754     if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
3755
3756         if (pa_tagstruct_getu32(t, &mode) < 0 ||
3757             pa_tagstruct_get_proplist(t, p) < 0 ||
3758             !pa_tagstruct_eof(t)) {
3759             protocol_error(c);
3760             pa_proplist_free(p);
3761             return;
3762         }
3763
3764     } else {
3765
3766         if (pa_tagstruct_getu32(t, &idx) < 0 ||
3767             pa_tagstruct_getu32(t, &mode) < 0 ||
3768             pa_tagstruct_get_proplist(t, p) < 0 ||
3769             !pa_tagstruct_eof(t)) {
3770             protocol_error(c);
3771             pa_proplist_free(p);
3772             return;
3773         }
3774     }
3775
3776     if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
3777         pa_proplist_free(p);
3778         CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
3779     }
3780
3781     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
3782         playback_stream *s;
3783
3784         s = pa_idxset_get_by_index(c->output_streams, idx);
3785         if (!s || !playback_stream_isinstance(s)) {
3786             pa_proplist_free(p);
3787             CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3788         }
3789         pa_sink_input_update_proplist(s->sink_input, mode, p);
3790
3791     } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
3792         record_stream *s;
3793
3794         if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
3795             pa_proplist_free(p);
3796             CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3797         }
3798         pa_source_output_update_proplist(s->source_output, mode, p);
3799
3800     } else {
3801         pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
3802
3803         pa_client_update_proplist(c->client, mode, p);
3804     }
3805
3806     pa_pstream_send_simple_ack(c->pstream, tag);
3807     pa_proplist_free(p);
3808 }
3809
3810 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3811     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3812     uint32_t idx;
3813     unsigned changed = 0;
3814     pa_proplist *p;
3815     pa_strlist *l = NULL;
3816
3817     pa_native_connection_assert_ref(c);
3818     pa_assert(t);
3819
3820     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3821
3822     if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
3823
3824         if (pa_tagstruct_getu32(t, &idx) < 0) {
3825             protocol_error(c);
3826             return;
3827         }
3828     }
3829
3830     if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3831         playback_stream *s;
3832
3833         s = pa_idxset_get_by_index(c->output_streams, idx);
3834         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3835         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3836
3837         p = s->sink_input->proplist;
3838
3839     } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3840         record_stream *s;
3841
3842         s = pa_idxset_get_by_index(c->record_streams, idx);
3843         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3844
3845         p = s->source_output->proplist;
3846     } else {
3847         pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3848
3849         p = c->client->proplist;
3850     }
3851
3852     for (;;) {
3853         const char *k;
3854
3855         if (pa_tagstruct_gets(t, &k) < 0) {
3856             protocol_error(c);
3857             pa_strlist_free(l);
3858             return;
3859         }
3860
3861         if (!k)
3862             break;
3863
3864         l = pa_strlist_prepend(l, k);
3865     }
3866
3867     if (!pa_tagstruct_eof(t)) {
3868         protocol_error(c);
3869         pa_strlist_free(l);
3870         return;
3871     }
3872
3873     for (;;) {
3874         char *z;
3875
3876         l = pa_strlist_pop(l, &z);
3877
3878         if (!z)
3879             break;
3880
3881         changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
3882         pa_xfree(z);
3883     }
3884
3885     pa_pstream_send_simple_ack(c->pstream, tag);
3886
3887     if (changed) {
3888         if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3889             playback_stream *s;
3890
3891             s = pa_idxset_get_by_index(c->output_streams, idx);
3892             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3893
3894         } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3895             record_stream *s;
3896
3897             s = pa_idxset_get_by_index(c->record_streams, idx);
3898             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3899
3900         } else {
3901             pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3902             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3903         }
3904     }
3905 }
3906
3907 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3908     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3909     const char *s;
3910
3911     pa_native_connection_assert_ref(c);
3912     pa_assert(t);
3913
3914     if (pa_tagstruct_gets(t, &s) < 0 ||
3915         !pa_tagstruct_eof(t)) {
3916         protocol_error(c);
3917         return;
3918     }
3919
3920     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3921     CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
3922
3923     if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
3924         pa_source *source;
3925
3926         source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
3927         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
3928
3929         pa_namereg_set_default_source(c->protocol->core, source);
3930     } else {
3931         pa_sink *sink;
3932         pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
3933
3934         sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
3935         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
3936
3937         pa_namereg_set_default_sink(c->protocol->core, sink);
3938     }
3939
3940     pa_pstream_send_simple_ack(c->pstream, tag);
3941 }
3942
3943 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3944     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3945     uint32_t idx;
3946     const char *name;
3947
3948     pa_native_connection_assert_ref(c);
3949     pa_assert(t);
3950
3951     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3952         pa_tagstruct_gets(t, &name) < 0 ||
3953         !pa_tagstruct_eof(t)) {
3954         protocol_error(c);
3955         return;
3956     }
3957
3958     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3959     CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
3960
3961     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
3962         playback_stream *s;
3963
3964         s = pa_idxset_get_by_index(c->output_streams, idx);
3965         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3966         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3967
3968         pa_sink_input_set_name(s->sink_input, name);
3969
3970     } else {
3971         record_stream *s;
3972         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
3973
3974         s = pa_idxset_get_by_index(c->record_streams, idx);
3975         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3976
3977         pa_source_output_set_name(s->source_output, name);
3978     }
3979
3980     pa_pstream_send_simple_ack(c->pstream, tag);
3981 }
3982
3983 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3984     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3985     uint32_t idx;
3986
3987     pa_native_connection_assert_ref(c);
3988     pa_assert(t);
3989
3990     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3991         !pa_tagstruct_eof(t)) {
3992         protocol_error(c);
3993         return;
3994     }
3995
3996     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3997
3998     if (command == PA_COMMAND_KILL_CLIENT) {
3999         pa_client *client;
4000
4001         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
4002         CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
4003
4004         pa_native_connection_ref(c);
4005         pa_client_kill(client);
4006
4007     } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4008         pa_sink_input *s;
4009
4010         s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4011         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4012
4013         pa_native_connection_ref(c);
4014         pa_sink_input_kill(s);
4015     } else {
4016         pa_source_output *s;
4017
4018         pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4019
4020         s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4021         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4022
4023         pa_native_connection_ref(c);
4024         pa_source_output_kill(s);
4025     }
4026
4027     pa_pstream_send_simple_ack(c->pstream, tag);
4028     pa_native_connection_unref(c);
4029 }
4030
4031 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4032     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4033     pa_module *m;
4034     const char *name, *argument;
4035     pa_tagstruct *reply;
4036
4037     pa_native_connection_assert_ref(c);
4038     pa_assert(t);
4039
4040     if (pa_tagstruct_gets(t, &name) < 0 ||
4041         pa_tagstruct_gets(t, &argument) < 0 ||
4042         !pa_tagstruct_eof(t)) {
4043         protocol_error(c);
4044         return;
4045     }
4046
4047     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4048     CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4049     CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4050
4051     if (!(m = pa_module_load(c->protocol->core, name, argument))) {
4052         pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4053         return;
4054     }
4055
4056     reply = reply_new(tag);
4057     pa_tagstruct_putu32(reply, m->index);
4058     pa_pstream_send_tagstruct(c->pstream, reply);
4059 }
4060
4061 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4062     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4063     uint32_t idx;
4064     pa_module *m;
4065
4066     pa_native_connection_assert_ref(c);
4067     pa_assert(t);
4068
4069     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4070         !pa_tagstruct_eof(t)) {
4071         protocol_error(c);
4072         return;
4073     }
4074
4075     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4076     m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4077     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4078
4079     pa_module_unload_request(m, FALSE);
4080     pa_pstream_send_simple_ack(c->pstream, tag);
4081 }
4082
4083 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4084     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4085     uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4086     const char *name_device = NULL;
4087
4088     pa_native_connection_assert_ref(c);
4089     pa_assert(t);
4090
4091     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4092         pa_tagstruct_getu32(t, &idx_device) < 0 ||
4093         pa_tagstruct_gets(t, &name_device) < 0 ||
4094         !pa_tagstruct_eof(t)) {
4095         protocol_error(c);
4096         return;
4097     }
4098
4099     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4100     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4101
4102     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);
4103     CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
4104     CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
4105     CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4106
4107     if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4108         pa_sink_input *si = NULL;
4109         pa_sink *sink = NULL;
4110
4111         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4112
4113         if (idx_device != PA_INVALID_INDEX)
4114             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4115         else
4116             sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4117
4118         CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4119
4120         if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
4121             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4122             return;
4123         }
4124     } else {
4125         pa_source_output *so = NULL;
4126         pa_source *source;
4127
4128         pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4129
4130         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4131
4132         if (idx_device != PA_INVALID_INDEX)
4133             source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4134         else
4135             source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4136
4137         CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4138
4139         if (pa_source_output_move_to(so, source, TRUE) < 0) {
4140             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4141             return;
4142         }
4143     }
4144
4145     pa_pstream_send_simple_ack(c->pstream, tag);
4146 }
4147
4148 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4149     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4150     uint32_t idx = PA_INVALID_INDEX;
4151     const char *name = NULL;
4152     pa_bool_t b;
4153
4154     pa_native_connection_assert_ref(c);
4155     pa_assert(t);
4156
4157     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4158         pa_tagstruct_gets(t, &name) < 0 ||
4159         pa_tagstruct_get_boolean(t, &b) < 0 ||
4160         !pa_tagstruct_eof(t)) {
4161         protocol_error(c);
4162         return;
4163     }
4164
4165     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4166     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);
4167     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4168     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4169     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4170
4171     if (command == PA_COMMAND_SUSPEND_SINK) {
4172
4173         if (idx == PA_INVALID_INDEX && name && !*name) {
4174
4175             pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4176
4177             if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4178                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4179                 return;
4180             }
4181         } else {
4182             pa_sink *sink = NULL;
4183
4184             if (idx != PA_INVALID_INDEX)
4185                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4186             else
4187                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4188
4189             CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4190
4191             if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4192                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4193                 return;
4194             }
4195         }
4196     } else {
4197
4198         pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4199
4200         if (idx == PA_INVALID_INDEX && name && !*name) {
4201
4202             pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4203
4204             if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4205                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4206                 return;
4207             }
4208
4209         } else {
4210             pa_source *source;
4211
4212             if (idx != PA_INVALID_INDEX)
4213                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4214             else
4215                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4216
4217             CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4218
4219             if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4220                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4221                 return;
4222             }
4223         }
4224     }
4225
4226     pa_pstream_send_simple_ack(c->pstream, tag);
4227 }
4228
4229 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4230     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4231     uint32_t idx = PA_INVALID_INDEX;
4232     const char *name = NULL;
4233     pa_module *m;
4234     pa_native_protocol_ext_cb_t cb;
4235
4236     pa_native_connection_assert_ref(c);
4237     pa_assert(t);
4238
4239     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4240         pa_tagstruct_gets(t, &name) < 0) {
4241         protocol_error(c);
4242         return;
4243     }
4244
4245     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4246     CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4247     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4248     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4249     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4250
4251     if (idx != PA_INVALID_INDEX)
4252         m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4253     else {
4254         for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx))
4255             if (strcmp(name, m->name) == 0)
4256                 break;
4257     }
4258
4259     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4260     CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4261
4262     cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4263     CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4264
4265     if (cb(c->protocol, m, c, tag, t) < 0)
4266         protocol_error(c);
4267 }
4268
4269 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4270     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4271     uint32_t idx = PA_INVALID_INDEX;
4272     const char *name = NULL, *profile = NULL;
4273     pa_card *card = NULL;
4274     int ret;
4275
4276     pa_native_connection_assert_ref(c);
4277     pa_assert(t);
4278
4279     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4280         pa_tagstruct_gets(t, &name) < 0 ||
4281         pa_tagstruct_gets(t, &profile) < 0 ||
4282         !pa_tagstruct_eof(t)) {
4283         protocol_error(c);
4284         return;
4285     }
4286
4287     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4288     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4289     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4290     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4291     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4292
4293     if (idx != PA_INVALID_INDEX)
4294         card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4295     else
4296         card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4297
4298     CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4299
4300     if ((ret = pa_card_set_profile(card, profile, TRUE)) < 0) {
4301         pa_pstream_send_error(c->pstream, tag, -ret);
4302         return;
4303     }
4304
4305     pa_pstream_send_simple_ack(c->pstream, tag);
4306 }
4307
4308 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4309     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4310     uint32_t idx = PA_INVALID_INDEX;
4311     const char *name = NULL, *port = NULL;
4312     int ret;
4313
4314     pa_native_connection_assert_ref(c);
4315     pa_assert(t);
4316
4317     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4318         pa_tagstruct_gets(t, &name) < 0 ||
4319         pa_tagstruct_gets(t, &port) < 0 ||
4320         !pa_tagstruct_eof(t)) {
4321         protocol_error(c);
4322         return;
4323     }
4324
4325     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4326     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);
4327     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4328     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4329     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4330
4331     if (command == PA_COMMAND_SET_SINK_PORT) {
4332         pa_sink *sink;
4333
4334         if (idx != PA_INVALID_INDEX)
4335             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4336         else
4337             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4338
4339         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4340
4341         if ((ret = pa_sink_set_port(sink, port, TRUE)) < 0) {
4342             pa_pstream_send_error(c->pstream, tag, -ret);
4343             return;
4344         }
4345     } else {
4346         pa_source *source;
4347
4348         pa_assert(command = PA_COMMAND_SET_SOURCE_PORT);
4349
4350         if (idx != PA_INVALID_INDEX)
4351             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4352         else
4353             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4354
4355         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4356
4357         if ((ret = pa_source_set_port(source, port, TRUE)) < 0) {
4358             pa_pstream_send_error(c->pstream, tag, -ret);
4359             return;
4360         }
4361     }
4362
4363     pa_pstream_send_simple_ack(c->pstream, tag);
4364 }
4365
4366 /*** pstream callbacks ***/
4367
4368 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4369     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4370
4371     pa_assert(p);
4372     pa_assert(packet);
4373     pa_native_connection_assert_ref(c);
4374
4375     if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4376         pa_log("invalid packet.");
4377         native_connection_unlink(c);
4378     }
4379 }
4380
4381 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) {
4382     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4383     output_stream *stream;
4384
4385     pa_assert(p);
4386     pa_assert(chunk);
4387     pa_native_connection_assert_ref(c);
4388
4389     if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4390         pa_log_debug("Client sent block for invalid stream.");
4391         /* Ignoring */
4392         return;
4393     }
4394
4395 /*     pa_log("got %lu bytes", (unsigned long) chunk->length); */
4396
4397     if (playback_stream_isinstance(stream)) {
4398         playback_stream *ps = PLAYBACK_STREAM(stream);
4399
4400         if (chunk->memblock) {
4401             if (seek != PA_SEEK_RELATIVE || offset != 0)
4402                 pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_SEEK, PA_UINT_TO_PTR(seek), offset, NULL, NULL);
4403
4404             pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4405         } else
4406             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);
4407
4408     } else {
4409         upload_stream *u = UPLOAD_STREAM(stream);
4410         size_t l;
4411
4412         if (!u->memchunk.memblock) {
4413             if (u->length == chunk->length && chunk->memblock) {
4414                 u->memchunk = *chunk;
4415                 pa_memblock_ref(u->memchunk.memblock);
4416                 u->length = 0;
4417             } else {
4418                 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4419                 u->memchunk.index = u->memchunk.length = 0;
4420             }
4421         }
4422
4423         pa_assert(u->memchunk.memblock);
4424
4425         l = u->length;
4426         if (l > chunk->length)
4427             l = chunk->length;
4428
4429         if (l > 0) {
4430             void *dst;
4431             dst = pa_memblock_acquire(u->memchunk.memblock);
4432
4433             if (chunk->memblock) {
4434                 void *src;
4435                 src = pa_memblock_acquire(chunk->memblock);
4436
4437                 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4438                        (uint8_t*) src + chunk->index, l);
4439
4440                 pa_memblock_release(chunk->memblock);
4441             } else
4442                 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4443
4444             pa_memblock_release(u->memchunk.memblock);
4445
4446             u->memchunk.length += l;
4447             u->length -= l;
4448         }
4449     }
4450 }
4451
4452 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4453     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4454
4455     pa_assert(p);
4456     pa_native_connection_assert_ref(c);
4457
4458     native_connection_unlink(c);
4459     pa_log_info("Connection died.");
4460 }
4461
4462 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4463     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4464
4465     pa_assert(p);
4466     pa_native_connection_assert_ref(c);
4467
4468     native_connection_send_memblock(c);
4469 }
4470
4471 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4472     pa_thread_mq *q;
4473
4474     if (!(q = pa_thread_mq_get()))
4475         pa_pstream_send_revoke(p, block_id);
4476     else
4477         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4478 }
4479
4480 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4481     pa_thread_mq *q;
4482
4483     if (!(q = pa_thread_mq_get()))
4484         pa_pstream_send_release(p, block_id);
4485     else
4486         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4487 }
4488
4489 /*** client callbacks ***/
4490
4491 static void client_kill_cb(pa_client *c) {
4492     pa_assert(c);
4493
4494     native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4495     pa_log_info("Connection killed.");
4496 }
4497
4498 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4499     pa_tagstruct *t;
4500     pa_native_connection *c;
4501
4502     pa_assert(client);
4503     c = PA_NATIVE_CONNECTION(client->userdata);
4504     pa_native_connection_assert_ref(c);
4505
4506     if (c->version < 15)
4507       return;
4508
4509     t = pa_tagstruct_new(NULL, 0);
4510     pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4511     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4512     pa_tagstruct_puts(t, event);
4513     pa_tagstruct_put_proplist(t, pl);
4514     pa_pstream_send_tagstruct(c->pstream, t);
4515 }
4516
4517 /*** module entry points ***/
4518
4519 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
4520     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4521
4522     pa_assert(m);
4523     pa_native_connection_assert_ref(c);
4524     pa_assert(c->auth_timeout_event == e);
4525
4526     if (!c->authorized) {
4527         native_connection_unlink(c);
4528         pa_log_info("Connection terminated due to authentication timeout.");
4529     }
4530 }
4531
4532 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4533     pa_native_connection *c;
4534     char pname[128];
4535     pa_client *client;
4536     pa_client_new_data data;
4537
4538     pa_assert(p);
4539     pa_assert(io);
4540     pa_assert(o);
4541
4542     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4543         pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4544         pa_iochannel_free(io);
4545         return;
4546     }
4547
4548     pa_client_new_data_init(&data);
4549     data.module = o->module;
4550     data.driver = __FILE__;
4551     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
4552     pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
4553     pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
4554     client = pa_client_new(p->core, &data);
4555     pa_client_new_data_done(&data);
4556
4557     if (!client)
4558         return;
4559
4560     c = pa_msgobject_new(pa_native_connection);
4561     c->parent.parent.free = native_connection_free;
4562     c->parent.process_msg = native_connection_process_msg;
4563     c->protocol = p;
4564     c->options = pa_native_options_ref(o);
4565     c->authorized = FALSE;
4566
4567     if (o->auth_anonymous) {
4568         pa_log_info("Client authenticated anonymously.");
4569         c->authorized = TRUE;
4570     }
4571
4572     if (!c->authorized &&
4573         o->auth_ip_acl &&
4574         pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
4575
4576         pa_log_info("Client authenticated by IP ACL.");
4577         c->authorized = TRUE;
4578     }
4579
4580     if (!c->authorized)
4581         c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
4582     else
4583         c->auth_timeout_event = NULL;
4584
4585     c->is_local = pa_iochannel_socket_is_local(io);
4586     c->version = 8;
4587
4588     c->client = client;
4589     c->client->kill = client_kill_cb;
4590     c->client->send_event = client_send_event_cb;
4591     c->client->userdata = c;
4592
4593     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
4594     pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
4595     pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
4596     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
4597     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
4598     pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
4599     pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
4600
4601     c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX);
4602
4603     c->record_streams = pa_idxset_new(NULL, NULL);
4604     c->output_streams = pa_idxset_new(NULL, NULL);
4605
4606     c->rrobin_index = PA_IDXSET_INVALID;
4607     c->subscription = NULL;
4608
4609     pa_idxset_put(p->connections, c, NULL);
4610
4611 #ifdef HAVE_CREDS
4612     if (pa_iochannel_creds_supported(io))
4613         pa_iochannel_creds_enable(io);
4614 #endif
4615
4616     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
4617 }
4618
4619 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
4620     pa_native_connection *c;
4621     void *state = NULL;
4622
4623     pa_assert(p);
4624     pa_assert(m);
4625
4626     while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
4627         if (c->options->module == m)
4628             native_connection_unlink(c);
4629 }
4630
4631 static pa_native_protocol* native_protocol_new(pa_core *c) {
4632     pa_native_protocol *p;
4633     pa_native_hook_t h;
4634
4635     pa_assert(c);
4636
4637     p = pa_xnew(pa_native_protocol, 1);
4638     PA_REFCNT_INIT(p);
4639     p->core = c;
4640     p->connections = pa_idxset_new(NULL, NULL);
4641
4642     p->servers = NULL;
4643
4644     p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4645
4646     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4647         pa_hook_init(&p->hooks[h], p);
4648
4649     pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
4650
4651     return p;
4652 }
4653
4654 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
4655     pa_native_protocol *p;
4656
4657     if ((p = pa_shared_get(c, "native-protocol")))
4658         return pa_native_protocol_ref(p);
4659
4660     return native_protocol_new(c);
4661 }
4662
4663 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
4664     pa_assert(p);
4665     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4666
4667     PA_REFCNT_INC(p);
4668
4669     return p;
4670 }
4671
4672 void pa_native_protocol_unref(pa_native_protocol *p) {
4673     pa_native_connection *c;
4674     pa_native_hook_t h;
4675
4676     pa_assert(p);
4677     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4678
4679     if (PA_REFCNT_DEC(p) > 0)
4680         return;
4681
4682     while ((c = pa_idxset_first(p->connections, NULL)))
4683         native_connection_unlink(c);
4684
4685     pa_idxset_free(p->connections, NULL, NULL);
4686
4687     pa_strlist_free(p->servers);
4688
4689     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4690         pa_hook_done(&p->hooks[h]);
4691
4692     pa_hashmap_free(p->extensions, NULL, NULL);
4693
4694     pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
4695
4696     pa_xfree(p);
4697 }
4698
4699 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
4700     pa_assert(p);
4701     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4702     pa_assert(name);
4703
4704     p->servers = pa_strlist_prepend(p->servers, name);
4705
4706     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4707 }
4708
4709 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
4710     pa_assert(p);
4711     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4712     pa_assert(name);
4713
4714     p->servers = pa_strlist_remove(p->servers, name);
4715
4716     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4717 }
4718
4719 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
4720     pa_assert(p);
4721     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4722
4723     return p->hooks;
4724 }
4725
4726 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
4727     pa_assert(p);
4728     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4729
4730     return p->servers;
4731 }
4732
4733 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
4734     pa_assert(p);
4735     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4736     pa_assert(m);
4737     pa_assert(cb);
4738     pa_assert(!pa_hashmap_get(p->extensions, m));
4739
4740     pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
4741     return 0;
4742 }
4743
4744 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
4745     pa_assert(p);
4746     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4747     pa_assert(m);
4748
4749     pa_assert_se(pa_hashmap_remove(p->extensions, m));
4750 }
4751
4752 pa_native_options* pa_native_options_new(void) {
4753     pa_native_options *o;
4754
4755     o = pa_xnew0(pa_native_options, 1);
4756     PA_REFCNT_INIT(o);
4757
4758     return o;
4759 }
4760
4761 pa_native_options* pa_native_options_ref(pa_native_options *o) {
4762     pa_assert(o);
4763     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4764
4765     PA_REFCNT_INC(o);
4766
4767     return o;
4768 }
4769
4770 void pa_native_options_unref(pa_native_options *o) {
4771     pa_assert(o);
4772     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4773
4774     if (PA_REFCNT_DEC(o) > 0)
4775         return;
4776
4777     pa_xfree(o->auth_group);
4778
4779     if (o->auth_ip_acl)
4780         pa_ip_acl_free(o->auth_ip_acl);
4781
4782     if (o->auth_cookie)
4783         pa_auth_cookie_unref(o->auth_cookie);
4784
4785     pa_xfree(o);
4786 }
4787
4788 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
4789     pa_bool_t enabled;
4790     const char *acl;
4791
4792     pa_assert(o);
4793     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4794     pa_assert(ma);
4795
4796     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
4797         pa_log("auth-anonymous= expects a boolean argument.");
4798         return -1;
4799     }
4800
4801     enabled = TRUE;
4802     if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &enabled) < 0) {
4803         pa_log("auth-group-enabled= expects a boolean argument.");
4804         return -1;
4805     }
4806
4807     pa_xfree(o->auth_group);
4808     o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
4809
4810 #ifndef HAVE_CREDS
4811     if (o->auth_group)
4812         pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4813 #endif
4814
4815     if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
4816         pa_ip_acl *ipa;
4817
4818         if (!(ipa = pa_ip_acl_new(acl))) {
4819             pa_log("Failed to parse IP ACL '%s'", acl);
4820             return -1;
4821         }
4822
4823         if (o->auth_ip_acl)
4824             pa_ip_acl_free(o->auth_ip_acl);
4825
4826         o->auth_ip_acl = ipa;
4827     }
4828
4829     enabled = TRUE;
4830     if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
4831         pa_log("auth-cookie-enabled= expects a boolean argument.");
4832         return -1;
4833     }
4834
4835     if (o->auth_cookie)
4836         pa_auth_cookie_unref(o->auth_cookie);
4837
4838     if (enabled) {
4839         const char *cn;
4840
4841         /* The new name for this is 'auth-cookie', for compat reasons
4842          * we check the old name too */
4843         if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
4844             if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
4845                 cn = PA_NATIVE_COOKIE_FILE;
4846
4847         if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, PA_NATIVE_COOKIE_LENGTH)))
4848             return -1;
4849
4850     } else
4851           o->auth_cookie = NULL;
4852
4853     return 0;
4854 }
4855
4856 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
4857     pa_native_connection_assert_ref(c);
4858
4859     return c->pstream;
4860 }
4861
4862 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
4863    pa_native_connection_assert_ref(c);
4864
4865    return c->client;
4866 }