core: move 'flags' field into 'pa_sink_input_new_data' structure so that hooks can...
[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(sink_name), 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(source_name), 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(name), 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(sink_name), 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 || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3112     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3113     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3114     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3115
3116     if (command == PA_COMMAND_GET_SINK_INFO) {
3117         if (idx != PA_INVALID_INDEX)
3118             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3119         else
3120             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3121     } else if (command == PA_COMMAND_GET_SOURCE_INFO) {
3122         if (idx != PA_INVALID_INDEX)
3123             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3124         else
3125             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3126     } else if (command == PA_COMMAND_GET_CARD_INFO) {
3127         if (idx != PA_INVALID_INDEX)
3128             card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
3129         else
3130             card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
3131     } else if (command == PA_COMMAND_GET_CLIENT_INFO)
3132         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3133     else if (command == PA_COMMAND_GET_MODULE_INFO)
3134         module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
3135     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
3136         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3137     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO)
3138         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
3139     else {
3140         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO);
3141         if (idx != PA_INVALID_INDEX)
3142             sce = pa_idxset_get_by_index(c->protocol->core->scache, idx);
3143         else
3144             sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE);
3145     }
3146
3147     if (!sink && !source && !client && !card && !module && !si && !so && !sce) {
3148         pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
3149         return;
3150     }
3151
3152     reply = reply_new(tag);
3153     if (sink)
3154         sink_fill_tagstruct(c, reply, sink);
3155     else if (source)
3156         source_fill_tagstruct(c, reply, source);
3157     else if (client)
3158         client_fill_tagstruct(c, reply, client);
3159     else if (card)
3160         card_fill_tagstruct(c, reply, card);
3161     else if (module)
3162         module_fill_tagstruct(c, reply, module);
3163     else if (si)
3164         sink_input_fill_tagstruct(c, reply, si);
3165     else if (so)
3166         source_output_fill_tagstruct(c, reply, so);
3167     else
3168         scache_fill_tagstruct(c, reply, sce);
3169     pa_pstream_send_tagstruct(c->pstream, reply);
3170 }
3171
3172 static void command_get_info_list(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3173     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3174     pa_idxset *i;
3175     uint32_t idx;
3176     void *p;
3177     pa_tagstruct *reply;
3178
3179     pa_native_connection_assert_ref(c);
3180     pa_assert(t);
3181
3182     if (!pa_tagstruct_eof(t)) {
3183         protocol_error(c);
3184         return;
3185     }
3186
3187     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3188
3189     reply = reply_new(tag);
3190
3191     if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3192         i = c->protocol->core->sinks;
3193     else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3194         i = c->protocol->core->sources;
3195     else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3196         i = c->protocol->core->clients;
3197     else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3198         i = c->protocol->core->cards;
3199     else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3200         i = c->protocol->core->modules;
3201     else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3202         i = c->protocol->core->sink_inputs;
3203     else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3204         i = c->protocol->core->source_outputs;
3205     else {
3206         pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3207         i = c->protocol->core->scache;
3208     }
3209
3210     if (i) {
3211         for (p = pa_idxset_first(i, &idx); p; p = pa_idxset_next(i, &idx)) {
3212             if (command == PA_COMMAND_GET_SINK_INFO_LIST)
3213                 sink_fill_tagstruct(c, reply, p);
3214             else if (command == PA_COMMAND_GET_SOURCE_INFO_LIST)
3215                 source_fill_tagstruct(c, reply, p);
3216             else if (command == PA_COMMAND_GET_CLIENT_INFO_LIST)
3217                 client_fill_tagstruct(c, reply, p);
3218             else if (command == PA_COMMAND_GET_CARD_INFO_LIST)
3219                 card_fill_tagstruct(c, reply, p);
3220             else if (command == PA_COMMAND_GET_MODULE_INFO_LIST)
3221                 module_fill_tagstruct(c, reply, p);
3222             else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
3223                 sink_input_fill_tagstruct(c, reply, p);
3224             else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
3225                 source_output_fill_tagstruct(c, reply, p);
3226             else {
3227                 pa_assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
3228                 scache_fill_tagstruct(c, reply, p);
3229             }
3230         }
3231     }
3232
3233     pa_pstream_send_tagstruct(c->pstream, reply);
3234 }
3235
3236 static void command_get_server_info(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3237     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3238     pa_tagstruct *reply;
3239     pa_sink *def_sink;
3240     pa_source *def_source;
3241     pa_sample_spec fixed_ss;
3242     char *h, *u;
3243
3244     pa_native_connection_assert_ref(c);
3245     pa_assert(t);
3246
3247     if (!pa_tagstruct_eof(t)) {
3248         protocol_error(c);
3249         return;
3250     }
3251
3252     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3253
3254     reply = reply_new(tag);
3255     pa_tagstruct_puts(reply, PACKAGE_NAME);
3256     pa_tagstruct_puts(reply, PACKAGE_VERSION);
3257
3258     u = pa_get_user_name_malloc();
3259     pa_tagstruct_puts(reply, u);
3260     pa_xfree(u);
3261
3262     h = pa_get_host_name_malloc();
3263     pa_tagstruct_puts(reply, h);
3264     pa_xfree(h);
3265
3266     fixup_sample_spec(c, &fixed_ss, &c->protocol->core->default_sample_spec);
3267     pa_tagstruct_put_sample_spec(reply, &fixed_ss);
3268
3269     def_sink = pa_namereg_get_default_sink(c->protocol->core);
3270     pa_tagstruct_puts(reply, def_sink ? def_sink->name : NULL);
3271     def_source = pa_namereg_get_default_source(c->protocol->core);
3272     pa_tagstruct_puts(reply, def_source ? def_source->name : NULL);
3273
3274     pa_tagstruct_putu32(reply, c->protocol->core->cookie);
3275
3276     if (c->version >= 15)
3277         pa_tagstruct_put_channel_map(reply, &c->protocol->core->default_channel_map);
3278
3279     pa_pstream_send_tagstruct(c->pstream, reply);
3280 }
3281
3282 static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
3283     pa_tagstruct *t;
3284     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3285
3286     pa_native_connection_assert_ref(c);
3287
3288     t = pa_tagstruct_new(NULL, 0);
3289     pa_tagstruct_putu32(t, PA_COMMAND_SUBSCRIBE_EVENT);
3290     pa_tagstruct_putu32(t, (uint32_t) -1);
3291     pa_tagstruct_putu32(t, e);
3292     pa_tagstruct_putu32(t, idx);
3293     pa_pstream_send_tagstruct(c->pstream, t);
3294 }
3295
3296 static void command_subscribe(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3297     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3298     pa_subscription_mask_t m;
3299
3300     pa_native_connection_assert_ref(c);
3301     pa_assert(t);
3302
3303     if (pa_tagstruct_getu32(t, &m) < 0 ||
3304         !pa_tagstruct_eof(t)) {
3305         protocol_error(c);
3306         return;
3307     }
3308
3309     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3310     CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
3311
3312     if (c->subscription)
3313         pa_subscription_free(c->subscription);
3314
3315     if (m != 0) {
3316         c->subscription = pa_subscription_new(c->protocol->core, m, subscription_cb, c);
3317         pa_assert(c->subscription);
3318     } else
3319         c->subscription = NULL;
3320
3321     pa_pstream_send_simple_ack(c->pstream, tag);
3322 }
3323
3324 static void command_set_volume(
3325         pa_pdispatch *pd,
3326         uint32_t command,
3327         uint32_t tag,
3328         pa_tagstruct *t,
3329         void *userdata) {
3330
3331     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3332     uint32_t idx;
3333     pa_cvolume volume;
3334     pa_sink *sink = NULL;
3335     pa_source *source = NULL;
3336     pa_sink_input *si = NULL;
3337     const char *name = NULL;
3338     const char *client_name;
3339
3340     pa_native_connection_assert_ref(c);
3341     pa_assert(t);
3342
3343     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3344         (command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3345         (command == PA_COMMAND_SET_SOURCE_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
3346         pa_tagstruct_get_cvolume(t, &volume) ||
3347         !pa_tagstruct_eof(t)) {
3348         protocol_error(c);
3349         return;
3350     }
3351
3352     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3353     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3354     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3355     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3356     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3357     CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
3358
3359     switch (command) {
3360
3361         case PA_COMMAND_SET_SINK_VOLUME:
3362             if (idx != PA_INVALID_INDEX)
3363                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3364             else
3365                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3366             break;
3367
3368         case PA_COMMAND_SET_SOURCE_VOLUME:
3369             if (idx != PA_INVALID_INDEX)
3370                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3371             else
3372                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3373             break;
3374
3375         case PA_COMMAND_SET_SINK_INPUT_VOLUME:
3376             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3377             break;
3378
3379         default:
3380             pa_assert_not_reached();
3381     }
3382
3383     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3384
3385     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3386
3387     if (sink) {
3388         pa_log_debug("Client %s changes volume of sink %s.", client_name, sink->name);
3389         pa_sink_set_volume(sink, &volume, TRUE, TRUE);
3390     } else if (source) {
3391         pa_log_debug("Client %s changes volume of source %s.", client_name, source->name);
3392         pa_source_set_volume(source, &volume, TRUE);
3393     } else if (si) {
3394         pa_log_debug("Client %s changes volume of sink input %s.",
3395                      client_name,
3396                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3397         pa_sink_input_set_volume(si, &volume, TRUE, TRUE);
3398     }
3399
3400     pa_pstream_send_simple_ack(c->pstream, tag);
3401 }
3402
3403 static void command_set_mute(
3404         pa_pdispatch *pd,
3405         uint32_t command,
3406         uint32_t tag,
3407         pa_tagstruct *t,
3408         void *userdata) {
3409
3410     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3411     uint32_t idx;
3412     pa_bool_t mute;
3413     pa_sink *sink = NULL;
3414     pa_source *source = NULL;
3415     pa_sink_input *si = NULL;
3416     const char *name = NULL, *client_name;
3417
3418     pa_native_connection_assert_ref(c);
3419     pa_assert(t);
3420
3421     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3422         (command == PA_COMMAND_SET_SINK_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3423         (command == PA_COMMAND_SET_SOURCE_MUTE && pa_tagstruct_gets(t, &name) < 0) ||
3424         pa_tagstruct_get_boolean(t, &mute) ||
3425         !pa_tagstruct_eof(t)) {
3426         protocol_error(c);
3427         return;
3428     }
3429
3430     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3431     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
3432     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
3433     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
3434     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3435
3436     switch (command) {
3437
3438         case PA_COMMAND_SET_SINK_MUTE:
3439
3440             if (idx != PA_INVALID_INDEX)
3441                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
3442             else
3443                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
3444
3445             break;
3446
3447         case PA_COMMAND_SET_SOURCE_MUTE:
3448             if (idx != PA_INVALID_INDEX)
3449                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
3450             else
3451                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
3452
3453             break;
3454
3455         case PA_COMMAND_SET_SINK_INPUT_MUTE:
3456             si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
3457             break;
3458
3459         default:
3460             pa_assert_not_reached();
3461     }
3462
3463     CHECK_VALIDITY(c->pstream, si || sink || source, tag, PA_ERR_NOENTITY);
3464
3465     client_name = pa_strnull(pa_proplist_gets(c->client->proplist, PA_PROP_APPLICATION_PROCESS_BINARY));
3466
3467     if (sink) {
3468         pa_log_debug("Client %s changes mute of sink %s.", client_name, sink->name);
3469         pa_sink_set_mute(sink, mute, TRUE);
3470     } else if (source) {
3471         pa_log_debug("Client %s changes mute of source %s.", client_name, source->name);
3472         pa_source_set_mute(source, mute, TRUE);
3473     } else if (si) {
3474         pa_log_debug("Client %s changes mute of sink input %s.",
3475                      client_name,
3476                      pa_strnull(pa_proplist_gets(si->proplist, PA_PROP_MEDIA_NAME)));
3477         pa_sink_input_set_mute(si, mute, TRUE);
3478     }
3479
3480     pa_pstream_send_simple_ack(c->pstream, tag);
3481 }
3482
3483 static void command_cork_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3484     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3485     uint32_t idx;
3486     pa_bool_t b;
3487     playback_stream *s;
3488
3489     pa_native_connection_assert_ref(c);
3490     pa_assert(t);
3491
3492     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3493         pa_tagstruct_get_boolean(t, &b) < 0 ||
3494         !pa_tagstruct_eof(t)) {
3495         protocol_error(c);
3496         return;
3497     }
3498
3499     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3500     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3501     s = pa_idxset_get_by_index(c->output_streams, idx);
3502     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3503     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3504
3505     pa_sink_input_cork(s->sink_input, b);
3506
3507     if (b)
3508         s->is_underrun = TRUE;
3509
3510     pa_pstream_send_simple_ack(c->pstream, tag);
3511 }
3512
3513 static void command_trigger_or_flush_or_prebuf_playback_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3514     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3515     uint32_t idx;
3516     playback_stream *s;
3517
3518     pa_native_connection_assert_ref(c);
3519     pa_assert(t);
3520
3521     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3522         !pa_tagstruct_eof(t)) {
3523         protocol_error(c);
3524         return;
3525     }
3526
3527     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3528     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
3529     s = pa_idxset_get_by_index(c->output_streams, idx);
3530     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3531     CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3532
3533     switch (command) {
3534         case PA_COMMAND_FLUSH_PLAYBACK_STREAM:
3535             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_FLUSH, NULL, 0, NULL);
3536             break;
3537
3538         case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
3539             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_PREBUF_FORCE, NULL, 0, NULL);
3540             break;
3541
3542         case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
3543             pa_asyncmsgq_send(s->sink_input->sink->asyncmsgq, PA_MSGOBJECT(s->sink_input), SINK_INPUT_MESSAGE_TRIGGER, NULL, 0, NULL);
3544             break;
3545
3546         default:
3547             pa_assert_not_reached();
3548     }
3549
3550     pa_pstream_send_simple_ack(c->pstream, tag);
3551 }
3552
3553 static void command_cork_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3554     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3555     uint32_t idx;
3556     record_stream *s;
3557     pa_bool_t b;
3558
3559     pa_native_connection_assert_ref(c);
3560     pa_assert(t);
3561
3562     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3563         pa_tagstruct_get_boolean(t, &b) < 0 ||
3564         !pa_tagstruct_eof(t)) {
3565         protocol_error(c);
3566         return;
3567     }
3568
3569     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3570     s = pa_idxset_get_by_index(c->record_streams, idx);
3571     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3572
3573     pa_source_output_cork(s->source_output, b);
3574     pa_memblockq_prebuf_force(s->memblockq);
3575     pa_pstream_send_simple_ack(c->pstream, tag);
3576 }
3577
3578 static void command_flush_record_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3579     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3580     uint32_t idx;
3581     record_stream *s;
3582
3583     pa_native_connection_assert_ref(c);
3584     pa_assert(t);
3585
3586     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3587         !pa_tagstruct_eof(t)) {
3588         protocol_error(c);
3589         return;
3590     }
3591
3592     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3593     s = pa_idxset_get_by_index(c->record_streams, idx);
3594     CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3595
3596     pa_memblockq_flush_read(s->memblockq);
3597     pa_pstream_send_simple_ack(c->pstream, tag);
3598 }
3599
3600 static void command_set_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3601     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3602     uint32_t idx;
3603     pa_buffer_attr a;
3604     pa_tagstruct *reply;
3605
3606     pa_native_connection_assert_ref(c);
3607     pa_assert(t);
3608
3609     memset(&a, 0, sizeof(a));
3610
3611     if (pa_tagstruct_getu32(t, &idx) < 0) {
3612         protocol_error(c);
3613         return;
3614     }
3615
3616     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3617
3618     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
3619         playback_stream *s;
3620         pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3621
3622         s = pa_idxset_get_by_index(c->output_streams, idx);
3623         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3624         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3625
3626         if (pa_tagstruct_get(
3627                     t,
3628                     PA_TAG_U32, &a.maxlength,
3629                     PA_TAG_U32, &a.tlength,
3630                     PA_TAG_U32, &a.prebuf,
3631                     PA_TAG_U32, &a.minreq,
3632                     PA_TAG_INVALID) < 0 ||
3633             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3634             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3635             !pa_tagstruct_eof(t)) {
3636             protocol_error(c);
3637             return;
3638         }
3639
3640         s->adjust_latency = adjust_latency;
3641         s->early_requests = early_requests;
3642         s->buffer_attr = a;
3643
3644         fix_playback_buffer_attr(s);
3645         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);
3646
3647         reply = reply_new(tag);
3648         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3649         pa_tagstruct_putu32(reply, s->buffer_attr.tlength);
3650         pa_tagstruct_putu32(reply, s->buffer_attr.prebuf);
3651         pa_tagstruct_putu32(reply, s->buffer_attr.minreq);
3652
3653         if (c->version >= 13)
3654             pa_tagstruct_put_usec(reply, s->configured_sink_latency);
3655
3656     } else {
3657         record_stream *s;
3658         pa_bool_t adjust_latency = FALSE, early_requests = FALSE;
3659         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_BUFFER_ATTR);
3660
3661         s = pa_idxset_get_by_index(c->record_streams, idx);
3662         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3663
3664         if (pa_tagstruct_get(
3665                     t,
3666                     PA_TAG_U32, &a.maxlength,
3667                     PA_TAG_U32, &a.fragsize,
3668                     PA_TAG_INVALID) < 0 ||
3669             (c->version >= 13 && pa_tagstruct_get_boolean(t, &adjust_latency) < 0) ||
3670             (c->version >= 14 && pa_tagstruct_get_boolean(t, &early_requests) < 0) ||
3671             !pa_tagstruct_eof(t)) {
3672             protocol_error(c);
3673             return;
3674         }
3675
3676         s->adjust_latency = adjust_latency;
3677         s->early_requests = early_requests;
3678         s->buffer_attr = a;
3679
3680         fix_record_buffer_attr_pre(s);
3681         pa_memblockq_set_maxlength(s->memblockq, s->buffer_attr.maxlength);
3682         pa_memblockq_get_attr(s->memblockq, &s->buffer_attr);
3683         fix_record_buffer_attr_post(s);
3684
3685         reply = reply_new(tag);
3686         pa_tagstruct_putu32(reply, s->buffer_attr.maxlength);
3687         pa_tagstruct_putu32(reply, s->buffer_attr.fragsize);
3688
3689         if (c->version >= 13)
3690             pa_tagstruct_put_usec(reply, s->configured_source_latency);
3691     }
3692
3693     pa_pstream_send_tagstruct(c->pstream, reply);
3694 }
3695
3696 static void command_update_stream_sample_rate(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3697     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3698     uint32_t idx;
3699     uint32_t rate;
3700
3701     pa_native_connection_assert_ref(c);
3702     pa_assert(t);
3703
3704     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3705         pa_tagstruct_getu32(t, &rate) < 0 ||
3706         !pa_tagstruct_eof(t)) {
3707         protocol_error(c);
3708         return;
3709     }
3710
3711     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3712     CHECK_VALIDITY(c->pstream, rate > 0 && rate <= PA_RATE_MAX, tag, PA_ERR_INVALID);
3713
3714     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_SAMPLE_RATE) {
3715         playback_stream *s;
3716
3717         s = pa_idxset_get_by_index(c->output_streams, idx);
3718         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3719         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3720
3721         pa_sink_input_set_rate(s->sink_input, rate);
3722
3723     } else {
3724         record_stream *s;
3725         pa_assert(command == PA_COMMAND_UPDATE_RECORD_STREAM_SAMPLE_RATE);
3726
3727         s = pa_idxset_get_by_index(c->record_streams, idx);
3728         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3729
3730         pa_source_output_set_rate(s->source_output, rate);
3731     }
3732
3733     pa_pstream_send_simple_ack(c->pstream, tag);
3734 }
3735
3736 static void command_update_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3737     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3738     uint32_t idx;
3739     uint32_t mode;
3740     pa_proplist *p;
3741
3742     pa_native_connection_assert_ref(c);
3743     pa_assert(t);
3744
3745     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3746
3747     p = pa_proplist_new();
3748
3749     if (command == PA_COMMAND_UPDATE_CLIENT_PROPLIST) {
3750
3751         if (pa_tagstruct_getu32(t, &mode) < 0 ||
3752             pa_tagstruct_get_proplist(t, p) < 0 ||
3753             !pa_tagstruct_eof(t)) {
3754             protocol_error(c);
3755             pa_proplist_free(p);
3756             return;
3757         }
3758
3759     } else {
3760
3761         if (pa_tagstruct_getu32(t, &idx) < 0 ||
3762             pa_tagstruct_getu32(t, &mode) < 0 ||
3763             pa_tagstruct_get_proplist(t, p) < 0 ||
3764             !pa_tagstruct_eof(t)) {
3765             protocol_error(c);
3766             pa_proplist_free(p);
3767             return;
3768         }
3769     }
3770
3771     if (!(mode == PA_UPDATE_SET || mode == PA_UPDATE_MERGE || mode == PA_UPDATE_REPLACE)) {
3772         pa_proplist_free(p);
3773         CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_INVALID);
3774     }
3775
3776     if (command == PA_COMMAND_UPDATE_PLAYBACK_STREAM_PROPLIST) {
3777         playback_stream *s;
3778
3779         s = pa_idxset_get_by_index(c->output_streams, idx);
3780         if (!s || !playback_stream_isinstance(s)) {
3781             pa_proplist_free(p);
3782             CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3783         }
3784         pa_sink_input_update_proplist(s->sink_input, mode, p);
3785
3786     } else if (command == PA_COMMAND_UPDATE_RECORD_STREAM_PROPLIST) {
3787         record_stream *s;
3788
3789         if (!(s = pa_idxset_get_by_index(c->record_streams, idx))) {
3790             pa_proplist_free(p);
3791             CHECK_VALIDITY(c->pstream, FALSE, tag, PA_ERR_NOENTITY);
3792         }
3793         pa_source_output_update_proplist(s->source_output, mode, p);
3794
3795     } else {
3796         pa_assert(command == PA_COMMAND_UPDATE_CLIENT_PROPLIST);
3797
3798         pa_client_update_proplist(c->client, mode, p);
3799     }
3800
3801     pa_pstream_send_simple_ack(c->pstream, tag);
3802     pa_proplist_free(p);
3803 }
3804
3805 static void command_remove_proplist(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3806     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3807     uint32_t idx;
3808     unsigned changed = 0;
3809     pa_proplist *p;
3810     pa_strlist *l = NULL;
3811
3812     pa_native_connection_assert_ref(c);
3813     pa_assert(t);
3814
3815     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3816
3817     if (command != PA_COMMAND_REMOVE_CLIENT_PROPLIST) {
3818
3819         if (pa_tagstruct_getu32(t, &idx) < 0) {
3820             protocol_error(c);
3821             return;
3822         }
3823     }
3824
3825     if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3826         playback_stream *s;
3827
3828         s = pa_idxset_get_by_index(c->output_streams, idx);
3829         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3830         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3831
3832         p = s->sink_input->proplist;
3833
3834     } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3835         record_stream *s;
3836
3837         s = pa_idxset_get_by_index(c->record_streams, idx);
3838         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3839
3840         p = s->source_output->proplist;
3841     } else {
3842         pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3843
3844         p = c->client->proplist;
3845     }
3846
3847     for (;;) {
3848         const char *k;
3849
3850         if (pa_tagstruct_gets(t, &k) < 0) {
3851             protocol_error(c);
3852             pa_strlist_free(l);
3853             return;
3854         }
3855
3856         if (!k)
3857             break;
3858
3859         l = pa_strlist_prepend(l, k);
3860     }
3861
3862     if (!pa_tagstruct_eof(t)) {
3863         protocol_error(c);
3864         pa_strlist_free(l);
3865         return;
3866     }
3867
3868     for (;;) {
3869         char *z;
3870
3871         l = pa_strlist_pop(l, &z);
3872
3873         if (!z)
3874             break;
3875
3876         changed += (unsigned) (pa_proplist_unset(p, z) >= 0);
3877         pa_xfree(z);
3878     }
3879
3880     pa_pstream_send_simple_ack(c->pstream, tag);
3881
3882     if (changed) {
3883         if (command == PA_COMMAND_REMOVE_PLAYBACK_STREAM_PROPLIST) {
3884             playback_stream *s;
3885
3886             s = pa_idxset_get_by_index(c->output_streams, idx);
3887             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->sink_input->index);
3888
3889         } else if (command == PA_COMMAND_REMOVE_RECORD_STREAM_PROPLIST) {
3890             record_stream *s;
3891
3892             s = pa_idxset_get_by_index(c->record_streams, idx);
3893             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, s->source_output->index);
3894
3895         } else {
3896             pa_assert(command == PA_COMMAND_REMOVE_CLIENT_PROPLIST);
3897             pa_subscription_post(c->protocol->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_CHANGE, c->client->index);
3898         }
3899     }
3900 }
3901
3902 static void command_set_default_sink_or_source(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3903     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3904     const char *s;
3905
3906     pa_native_connection_assert_ref(c);
3907     pa_assert(t);
3908
3909     if (pa_tagstruct_gets(t, &s) < 0 ||
3910         !pa_tagstruct_eof(t)) {
3911         protocol_error(c);
3912         return;
3913     }
3914
3915     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3916     CHECK_VALIDITY(c->pstream, !s || pa_namereg_is_valid_name(s), tag, PA_ERR_INVALID);
3917
3918     if (command == PA_COMMAND_SET_DEFAULT_SOURCE) {
3919         pa_source *source;
3920
3921         source = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SOURCE);
3922         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
3923
3924         pa_namereg_set_default_source(c->protocol->core, source);
3925     } else {
3926         pa_sink *sink;
3927         pa_assert(command == PA_COMMAND_SET_DEFAULT_SINK);
3928
3929         sink = pa_namereg_get(c->protocol->core, s, PA_NAMEREG_SINK);
3930         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
3931
3932         pa_namereg_set_default_sink(c->protocol->core, sink);
3933     }
3934
3935     pa_pstream_send_simple_ack(c->pstream, tag);
3936 }
3937
3938 static void command_set_stream_name(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3939     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3940     uint32_t idx;
3941     const char *name;
3942
3943     pa_native_connection_assert_ref(c);
3944     pa_assert(t);
3945
3946     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3947         pa_tagstruct_gets(t, &name) < 0 ||
3948         !pa_tagstruct_eof(t)) {
3949         protocol_error(c);
3950         return;
3951     }
3952
3953     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3954     CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
3955
3956     if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
3957         playback_stream *s;
3958
3959         s = pa_idxset_get_by_index(c->output_streams, idx);
3960         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3961         CHECK_VALIDITY(c->pstream, playback_stream_isinstance(s), tag, PA_ERR_NOENTITY);
3962
3963         pa_sink_input_set_name(s->sink_input, name);
3964
3965     } else {
3966         record_stream *s;
3967         pa_assert(command == PA_COMMAND_SET_RECORD_STREAM_NAME);
3968
3969         s = pa_idxset_get_by_index(c->record_streams, idx);
3970         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
3971
3972         pa_source_output_set_name(s->source_output, name);
3973     }
3974
3975     pa_pstream_send_simple_ack(c->pstream, tag);
3976 }
3977
3978 static void command_kill(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
3979     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
3980     uint32_t idx;
3981
3982     pa_native_connection_assert_ref(c);
3983     pa_assert(t);
3984
3985     if (pa_tagstruct_getu32(t, &idx) < 0 ||
3986         !pa_tagstruct_eof(t)) {
3987         protocol_error(c);
3988         return;
3989     }
3990
3991     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
3992
3993     if (command == PA_COMMAND_KILL_CLIENT) {
3994         pa_client *client;
3995
3996         client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
3997         CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
3998
3999         pa_native_connection_ref(c);
4000         pa_client_kill(client);
4001
4002     } else if (command == PA_COMMAND_KILL_SINK_INPUT) {
4003         pa_sink_input *s;
4004
4005         s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4006         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4007
4008         pa_native_connection_ref(c);
4009         pa_sink_input_kill(s);
4010     } else {
4011         pa_source_output *s;
4012
4013         pa_assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
4014
4015         s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4016         CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
4017
4018         pa_native_connection_ref(c);
4019         pa_source_output_kill(s);
4020     }
4021
4022     pa_pstream_send_simple_ack(c->pstream, tag);
4023     pa_native_connection_unref(c);
4024 }
4025
4026 static void command_load_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4027     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4028     pa_module *m;
4029     const char *name, *argument;
4030     pa_tagstruct *reply;
4031
4032     pa_native_connection_assert_ref(c);
4033     pa_assert(t);
4034
4035     if (pa_tagstruct_gets(t, &name) < 0 ||
4036         pa_tagstruct_gets(t, &argument) < 0 ||
4037         !pa_tagstruct_eof(t)) {
4038         protocol_error(c);
4039         return;
4040     }
4041
4042     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4043     CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
4044     CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
4045
4046     if (!(m = pa_module_load(c->protocol->core, name, argument))) {
4047         pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
4048         return;
4049     }
4050
4051     reply = reply_new(tag);
4052     pa_tagstruct_putu32(reply, m->index);
4053     pa_pstream_send_tagstruct(c->pstream, reply);
4054 }
4055
4056 static void command_unload_module(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4057     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4058     uint32_t idx;
4059     pa_module *m;
4060
4061     pa_native_connection_assert_ref(c);
4062     pa_assert(t);
4063
4064     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4065         !pa_tagstruct_eof(t)) {
4066         protocol_error(c);
4067         return;
4068     }
4069
4070     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4071     m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4072     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
4073
4074     pa_module_unload_request(m, FALSE);
4075     pa_pstream_send_simple_ack(c->pstream, tag);
4076 }
4077
4078 static void command_move_stream(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4079     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4080     uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
4081     const char *name_device = NULL;
4082
4083     pa_native_connection_assert_ref(c);
4084     pa_assert(t);
4085
4086     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4087         pa_tagstruct_getu32(t, &idx_device) < 0 ||
4088         pa_tagstruct_gets(t, &name_device) < 0 ||
4089         !pa_tagstruct_eof(t)) {
4090         protocol_error(c);
4091         return;
4092     }
4093
4094     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4095     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4096
4097     CHECK_VALIDITY(c->pstream, !name_device || pa_namereg_is_valid_name(name_device), tag, PA_ERR_INVALID);
4098     CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || name_device, tag, PA_ERR_INVALID);
4099     CHECK_VALIDITY(c->pstream, idx_device == PA_INVALID_INDEX || !name_device, tag, PA_ERR_INVALID);
4100     CHECK_VALIDITY(c->pstream, !name_device || idx_device == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4101
4102     if (command == PA_COMMAND_MOVE_SINK_INPUT) {
4103         pa_sink_input *si = NULL;
4104         pa_sink *sink = NULL;
4105
4106         si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
4107
4108         if (idx_device != PA_INVALID_INDEX)
4109             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
4110         else
4111             sink = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SINK);
4112
4113         CHECK_VALIDITY(c->pstream, si && sink, tag, PA_ERR_NOENTITY);
4114
4115         if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
4116             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4117             return;
4118         }
4119     } else {
4120         pa_source_output *so = NULL;
4121         pa_source *source;
4122
4123         pa_assert(command == PA_COMMAND_MOVE_SOURCE_OUTPUT);
4124
4125         so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
4126
4127         if (idx_device != PA_INVALID_INDEX)
4128             source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
4129         else
4130             source = pa_namereg_get(c->protocol->core, name_device, PA_NAMEREG_SOURCE);
4131
4132         CHECK_VALIDITY(c->pstream, so && source, tag, PA_ERR_NOENTITY);
4133
4134         if (pa_source_output_move_to(so, source, TRUE) < 0) {
4135             pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4136             return;
4137         }
4138     }
4139
4140     pa_pstream_send_simple_ack(c->pstream, tag);
4141 }
4142
4143 static void command_suspend(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4144     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4145     uint32_t idx = PA_INVALID_INDEX;
4146     const char *name = NULL;
4147     pa_bool_t b;
4148
4149     pa_native_connection_assert_ref(c);
4150     pa_assert(t);
4151
4152     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4153         pa_tagstruct_gets(t, &name) < 0 ||
4154         pa_tagstruct_get_boolean(t, &b) < 0 ||
4155         !pa_tagstruct_eof(t)) {
4156         protocol_error(c);
4157         return;
4158     }
4159
4160     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4161     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name) || *name == 0, tag, PA_ERR_INVALID);
4162     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4163     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4164     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4165
4166     if (command == PA_COMMAND_SUSPEND_SINK) {
4167
4168         if (idx == PA_INVALID_INDEX && name && !*name) {
4169
4170             pa_log_debug("%s all sinks", b ? "Suspending" : "Resuming");
4171
4172             if (pa_sink_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4173                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4174                 return;
4175             }
4176         } else {
4177             pa_sink *sink = NULL;
4178
4179             if (idx != PA_INVALID_INDEX)
4180                 sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4181             else
4182                 sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4183
4184             CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4185
4186             if (pa_sink_suspend(sink, b, PA_SUSPEND_USER) < 0) {
4187                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4188                 return;
4189             }
4190         }
4191     } else {
4192
4193         pa_assert(command == PA_COMMAND_SUSPEND_SOURCE);
4194
4195         if (idx == PA_INVALID_INDEX && name && !*name) {
4196
4197             pa_log_debug("%s all sources", b ? "Suspending" : "Resuming");
4198
4199             if (pa_source_suspend_all(c->protocol->core, b, PA_SUSPEND_USER) < 0) {
4200                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4201                 return;
4202             }
4203
4204         } else {
4205             pa_source *source;
4206
4207             if (idx != PA_INVALID_INDEX)
4208                 source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4209             else
4210                 source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4211
4212             CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4213
4214             if (pa_source_suspend(source, b, PA_SUSPEND_USER) < 0) {
4215                 pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID);
4216                 return;
4217             }
4218         }
4219     }
4220
4221     pa_pstream_send_simple_ack(c->pstream, tag);
4222 }
4223
4224 static void command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4225     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4226     uint32_t idx = PA_INVALID_INDEX;
4227     const char *name = NULL;
4228     pa_module *m;
4229     pa_native_protocol_ext_cb_t cb;
4230
4231     pa_native_connection_assert_ref(c);
4232     pa_assert(t);
4233
4234     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4235         pa_tagstruct_gets(t, &name) < 0) {
4236         protocol_error(c);
4237         return;
4238     }
4239
4240     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4241     CHECK_VALIDITY(c->pstream, !name || pa_utf8_valid(name), tag, PA_ERR_INVALID);
4242     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4243     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4244     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4245
4246     if (idx != PA_INVALID_INDEX)
4247         m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
4248     else {
4249         for (m = pa_idxset_first(c->protocol->core->modules, &idx); m; m = pa_idxset_next(c->protocol->core->modules, &idx))
4250             if (strcmp(name, m->name) == 0)
4251                 break;
4252     }
4253
4254     CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOEXTENSION);
4255     CHECK_VALIDITY(c->pstream, m->load_once || idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4256
4257     cb = (pa_native_protocol_ext_cb_t) (unsigned long) pa_hashmap_get(c->protocol->extensions, m);
4258     CHECK_VALIDITY(c->pstream, cb, tag, PA_ERR_NOEXTENSION);
4259
4260     if (cb(c->protocol, m, c, tag, t) < 0)
4261         protocol_error(c);
4262 }
4263
4264 static void command_set_card_profile(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4265     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4266     uint32_t idx = PA_INVALID_INDEX;
4267     const char *name = NULL, *profile = NULL;
4268     pa_card *card = NULL;
4269     int ret;
4270
4271     pa_native_connection_assert_ref(c);
4272     pa_assert(t);
4273
4274     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4275         pa_tagstruct_gets(t, &name) < 0 ||
4276         pa_tagstruct_gets(t, &profile) < 0 ||
4277         !pa_tagstruct_eof(t)) {
4278         protocol_error(c);
4279         return;
4280     }
4281
4282     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4283     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4284     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4285     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4286     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4287
4288     if (idx != PA_INVALID_INDEX)
4289         card = pa_idxset_get_by_index(c->protocol->core->cards, idx);
4290     else
4291         card = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_CARD);
4292
4293     CHECK_VALIDITY(c->pstream, card, tag, PA_ERR_NOENTITY);
4294
4295     if ((ret = pa_card_set_profile(card, profile, TRUE)) < 0) {
4296         pa_pstream_send_error(c->pstream, tag, -ret);
4297         return;
4298     }
4299
4300     pa_pstream_send_simple_ack(c->pstream, tag);
4301 }
4302
4303 static void command_set_sink_or_source_port(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
4304     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4305     uint32_t idx = PA_INVALID_INDEX;
4306     const char *name = NULL, *port = NULL;
4307     int ret;
4308
4309     pa_native_connection_assert_ref(c);
4310     pa_assert(t);
4311
4312     if (pa_tagstruct_getu32(t, &idx) < 0 ||
4313         pa_tagstruct_gets(t, &name) < 0 ||
4314         pa_tagstruct_gets(t, &port) < 0 ||
4315         !pa_tagstruct_eof(t)) {
4316         protocol_error(c);
4317         return;
4318     }
4319
4320     CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
4321     CHECK_VALIDITY(c->pstream, !name || pa_namereg_is_valid_name(name), tag, PA_ERR_INVALID);
4322     CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || name, tag, PA_ERR_INVALID);
4323     CHECK_VALIDITY(c->pstream, idx == PA_INVALID_INDEX || !name, tag, PA_ERR_INVALID);
4324     CHECK_VALIDITY(c->pstream, !name || idx == PA_INVALID_INDEX, tag, PA_ERR_INVALID);
4325
4326     if (command == PA_COMMAND_SET_SINK_PORT) {
4327         pa_sink *sink;
4328
4329         if (idx != PA_INVALID_INDEX)
4330             sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx);
4331         else
4332             sink = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SINK);
4333
4334         CHECK_VALIDITY(c->pstream, sink, tag, PA_ERR_NOENTITY);
4335
4336         if ((ret = pa_sink_set_port(sink, port, TRUE)) < 0) {
4337             pa_pstream_send_error(c->pstream, tag, -ret);
4338             return;
4339         }
4340     } else {
4341         pa_source *source;
4342
4343         pa_assert(command = PA_COMMAND_SET_SOURCE_PORT);
4344
4345         if (idx != PA_INVALID_INDEX)
4346             source = pa_idxset_get_by_index(c->protocol->core->sources, idx);
4347         else
4348             source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE);
4349
4350         CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
4351
4352         if ((ret = pa_source_set_port(source, port, TRUE)) < 0) {
4353             pa_pstream_send_error(c->pstream, tag, -ret);
4354             return;
4355         }
4356     }
4357
4358     pa_pstream_send_simple_ack(c->pstream, tag);
4359 }
4360
4361 /*** pstream callbacks ***/
4362
4363 static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
4364     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4365
4366     pa_assert(p);
4367     pa_assert(packet);
4368     pa_native_connection_assert_ref(c);
4369
4370     if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0) {
4371         pa_log("invalid packet.");
4372         native_connection_unlink(c);
4373     }
4374 }
4375
4376 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) {
4377     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4378     output_stream *stream;
4379
4380     pa_assert(p);
4381     pa_assert(chunk);
4382     pa_native_connection_assert_ref(c);
4383
4384     if (!(stream = OUTPUT_STREAM(pa_idxset_get_by_index(c->output_streams, channel)))) {
4385         pa_log_debug("Client sent block for invalid stream.");
4386         /* Ignoring */
4387         return;
4388     }
4389
4390 /*     pa_log("got %lu bytes", (unsigned long) chunk->length); */
4391
4392     if (playback_stream_isinstance(stream)) {
4393         playback_stream *ps = PLAYBACK_STREAM(stream);
4394
4395         if (chunk->memblock) {
4396             if (seek != PA_SEEK_RELATIVE || offset != 0)
4397                 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);
4398
4399             pa_asyncmsgq_post(ps->sink_input->sink->asyncmsgq, PA_MSGOBJECT(ps->sink_input), SINK_INPUT_MESSAGE_POST_DATA, NULL, 0, chunk, NULL);
4400         } else
4401             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);
4402
4403     } else {
4404         upload_stream *u = UPLOAD_STREAM(stream);
4405         size_t l;
4406
4407         if (!u->memchunk.memblock) {
4408             if (u->length == chunk->length && chunk->memblock) {
4409                 u->memchunk = *chunk;
4410                 pa_memblock_ref(u->memchunk.memblock);
4411                 u->length = 0;
4412             } else {
4413                 u->memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, u->length);
4414                 u->memchunk.index = u->memchunk.length = 0;
4415             }
4416         }
4417
4418         pa_assert(u->memchunk.memblock);
4419
4420         l = u->length;
4421         if (l > chunk->length)
4422             l = chunk->length;
4423
4424         if (l > 0) {
4425             void *dst;
4426             dst = pa_memblock_acquire(u->memchunk.memblock);
4427
4428             if (chunk->memblock) {
4429                 void *src;
4430                 src = pa_memblock_acquire(chunk->memblock);
4431
4432                 memcpy((uint8_t*) dst + u->memchunk.index + u->memchunk.length,
4433                        (uint8_t*) src + chunk->index, l);
4434
4435                 pa_memblock_release(chunk->memblock);
4436             } else
4437                 pa_silence_memory((uint8_t*) dst + u->memchunk.index + u->memchunk.length, l, &u->sample_spec);
4438
4439             pa_memblock_release(u->memchunk.memblock);
4440
4441             u->memchunk.length += l;
4442             u->length -= l;
4443         }
4444     }
4445 }
4446
4447 static void pstream_die_callback(pa_pstream *p, void *userdata) {
4448     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4449
4450     pa_assert(p);
4451     pa_native_connection_assert_ref(c);
4452
4453     native_connection_unlink(c);
4454     pa_log_info("Connection died.");
4455 }
4456
4457 static void pstream_drain_callback(pa_pstream *p, void *userdata) {
4458     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4459
4460     pa_assert(p);
4461     pa_native_connection_assert_ref(c);
4462
4463     native_connection_send_memblock(c);
4464 }
4465
4466 static void pstream_revoke_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4467     pa_thread_mq *q;
4468
4469     if (!(q = pa_thread_mq_get()))
4470         pa_pstream_send_revoke(p, block_id);
4471     else
4472         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_REVOKE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4473 }
4474
4475 static void pstream_release_callback(pa_pstream *p, uint32_t block_id, void *userdata) {
4476     pa_thread_mq *q;
4477
4478     if (!(q = pa_thread_mq_get()))
4479         pa_pstream_send_release(p, block_id);
4480     else
4481         pa_asyncmsgq_post(q->outq, PA_MSGOBJECT(userdata), CONNECTION_MESSAGE_RELEASE, PA_UINT_TO_PTR(block_id), 0, NULL, NULL);
4482 }
4483
4484 /*** client callbacks ***/
4485
4486 static void client_kill_cb(pa_client *c) {
4487     pa_assert(c);
4488
4489     native_connection_unlink(PA_NATIVE_CONNECTION(c->userdata));
4490     pa_log_info("Connection killed.");
4491 }
4492
4493 static void client_send_event_cb(pa_client *client, const char*event, pa_proplist *pl) {
4494     pa_tagstruct *t;
4495     pa_native_connection *c;
4496
4497     pa_assert(client);
4498     c = PA_NATIVE_CONNECTION(client->userdata);
4499     pa_native_connection_assert_ref(c);
4500
4501     if (c->version < 15)
4502       return;
4503
4504     t = pa_tagstruct_new(NULL, 0);
4505     pa_tagstruct_putu32(t, PA_COMMAND_CLIENT_EVENT);
4506     pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */
4507     pa_tagstruct_puts(t, event);
4508     pa_tagstruct_put_proplist(t, pl);
4509     pa_pstream_send_tagstruct(c->pstream, t);
4510 }
4511
4512 /*** module entry points ***/
4513
4514 static void auth_timeout(pa_mainloop_api*m, pa_time_event *e, const struct timeval *t, void *userdata) {
4515     pa_native_connection *c = PA_NATIVE_CONNECTION(userdata);
4516
4517     pa_assert(m);
4518     pa_native_connection_assert_ref(c);
4519     pa_assert(c->auth_timeout_event == e);
4520
4521     if (!c->authorized) {
4522         native_connection_unlink(c);
4523         pa_log_info("Connection terminated due to authentication timeout.");
4524     }
4525 }
4526
4527 void pa_native_protocol_connect(pa_native_protocol *p, pa_iochannel *io, pa_native_options *o) {
4528     pa_native_connection *c;
4529     char pname[128];
4530     pa_client *client;
4531     pa_client_new_data data;
4532
4533     pa_assert(p);
4534     pa_assert(io);
4535     pa_assert(o);
4536
4537     if (pa_idxset_size(p->connections)+1 > MAX_CONNECTIONS) {
4538         pa_log_warn("Warning! Too many connections (%u), dropping incoming connection.", MAX_CONNECTIONS);
4539         pa_iochannel_free(io);
4540         return;
4541     }
4542
4543     pa_client_new_data_init(&data);
4544     data.module = o->module;
4545     data.driver = __FILE__;
4546     pa_iochannel_socket_peer_to_string(io, pname, sizeof(pname));
4547     pa_proplist_setf(data.proplist, PA_PROP_APPLICATION_NAME, "Native client (%s)", pname);
4548     pa_proplist_sets(data.proplist, "native-protocol.peer", pname);
4549     client = pa_client_new(p->core, &data);
4550     pa_client_new_data_done(&data);
4551
4552     if (!client)
4553         return;
4554
4555     c = pa_msgobject_new(pa_native_connection);
4556     c->parent.parent.free = native_connection_free;
4557     c->parent.process_msg = native_connection_process_msg;
4558     c->protocol = p;
4559     c->options = pa_native_options_ref(o);
4560     c->authorized = FALSE;
4561
4562     if (o->auth_anonymous) {
4563         pa_log_info("Client authenticated anonymously.");
4564         c->authorized = TRUE;
4565     }
4566
4567     if (!c->authorized &&
4568         o->auth_ip_acl &&
4569         pa_ip_acl_check(o->auth_ip_acl, pa_iochannel_get_recv_fd(io)) > 0) {
4570
4571         pa_log_info("Client authenticated by IP ACL.");
4572         c->authorized = TRUE;
4573     }
4574
4575     if (!c->authorized)
4576         c->auth_timeout_event = pa_core_rttime_new(p->core, pa_rtclock_now() + AUTH_TIMEOUT, auth_timeout, c);
4577     else
4578         c->auth_timeout_event = NULL;
4579
4580     c->is_local = pa_iochannel_socket_is_local(io);
4581     c->version = 8;
4582
4583     c->client = client;
4584     c->client->kill = client_kill_cb;
4585     c->client->send_event = client_send_event_cb;
4586     c->client->userdata = c;
4587
4588     c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
4589     pa_pstream_set_recieve_packet_callback(c->pstream, pstream_packet_callback, c);
4590     pa_pstream_set_recieve_memblock_callback(c->pstream, pstream_memblock_callback, c);
4591     pa_pstream_set_die_callback(c->pstream, pstream_die_callback, c);
4592     pa_pstream_set_drain_callback(c->pstream, pstream_drain_callback, c);
4593     pa_pstream_set_revoke_callback(c->pstream, pstream_revoke_callback, c);
4594     pa_pstream_set_release_callback(c->pstream, pstream_release_callback, c);
4595
4596     c->pdispatch = pa_pdispatch_new(p->core->mainloop, TRUE, command_table, PA_COMMAND_MAX);
4597
4598     c->record_streams = pa_idxset_new(NULL, NULL);
4599     c->output_streams = pa_idxset_new(NULL, NULL);
4600
4601     c->rrobin_index = PA_IDXSET_INVALID;
4602     c->subscription = NULL;
4603
4604     pa_idxset_put(p->connections, c, NULL);
4605
4606 #ifdef HAVE_CREDS
4607     if (pa_iochannel_creds_supported(io))
4608         pa_iochannel_creds_enable(io);
4609 #endif
4610
4611     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_CONNECTION_PUT], c);
4612 }
4613
4614 void pa_native_protocol_disconnect(pa_native_protocol *p, pa_module *m) {
4615     pa_native_connection *c;
4616     void *state = NULL;
4617
4618     pa_assert(p);
4619     pa_assert(m);
4620
4621     while ((c = pa_idxset_iterate(p->connections, &state, NULL)))
4622         if (c->options->module == m)
4623             native_connection_unlink(c);
4624 }
4625
4626 static pa_native_protocol* native_protocol_new(pa_core *c) {
4627     pa_native_protocol *p;
4628     pa_native_hook_t h;
4629
4630     pa_assert(c);
4631
4632     p = pa_xnew(pa_native_protocol, 1);
4633     PA_REFCNT_INIT(p);
4634     p->core = c;
4635     p->connections = pa_idxset_new(NULL, NULL);
4636
4637     p->servers = NULL;
4638
4639     p->extensions = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
4640
4641     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4642         pa_hook_init(&p->hooks[h], p);
4643
4644     pa_assert_se(pa_shared_set(c, "native-protocol", p) >= 0);
4645
4646     return p;
4647 }
4648
4649 pa_native_protocol* pa_native_protocol_get(pa_core *c) {
4650     pa_native_protocol *p;
4651
4652     if ((p = pa_shared_get(c, "native-protocol")))
4653         return pa_native_protocol_ref(p);
4654
4655     return native_protocol_new(c);
4656 }
4657
4658 pa_native_protocol* pa_native_protocol_ref(pa_native_protocol *p) {
4659     pa_assert(p);
4660     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4661
4662     PA_REFCNT_INC(p);
4663
4664     return p;
4665 }
4666
4667 void pa_native_protocol_unref(pa_native_protocol *p) {
4668     pa_native_connection *c;
4669     pa_native_hook_t h;
4670
4671     pa_assert(p);
4672     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4673
4674     if (PA_REFCNT_DEC(p) > 0)
4675         return;
4676
4677     while ((c = pa_idxset_first(p->connections, NULL)))
4678         native_connection_unlink(c);
4679
4680     pa_idxset_free(p->connections, NULL, NULL);
4681
4682     pa_strlist_free(p->servers);
4683
4684     for (h = 0; h < PA_NATIVE_HOOK_MAX; h++)
4685         pa_hook_done(&p->hooks[h]);
4686
4687     pa_hashmap_free(p->extensions, NULL, NULL);
4688
4689     pa_assert_se(pa_shared_remove(p->core, "native-protocol") >= 0);
4690
4691     pa_xfree(p);
4692 }
4693
4694 void pa_native_protocol_add_server_string(pa_native_protocol *p, const char *name) {
4695     pa_assert(p);
4696     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4697     pa_assert(name);
4698
4699     p->servers = pa_strlist_prepend(p->servers, name);
4700
4701     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4702 }
4703
4704 void pa_native_protocol_remove_server_string(pa_native_protocol *p, const char *name) {
4705     pa_assert(p);
4706     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4707     pa_assert(name);
4708
4709     p->servers = pa_strlist_remove(p->servers, name);
4710
4711     pa_hook_fire(&p->hooks[PA_NATIVE_HOOK_SERVERS_CHANGED], p->servers);
4712 }
4713
4714 pa_hook *pa_native_protocol_hooks(pa_native_protocol *p) {
4715     pa_assert(p);
4716     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4717
4718     return p->hooks;
4719 }
4720
4721 pa_strlist *pa_native_protocol_servers(pa_native_protocol *p) {
4722     pa_assert(p);
4723     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4724
4725     return p->servers;
4726 }
4727
4728 int pa_native_protocol_install_ext(pa_native_protocol *p, pa_module *m, pa_native_protocol_ext_cb_t cb) {
4729     pa_assert(p);
4730     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4731     pa_assert(m);
4732     pa_assert(cb);
4733     pa_assert(!pa_hashmap_get(p->extensions, m));
4734
4735     pa_assert_se(pa_hashmap_put(p->extensions, m, (void*) (unsigned long) cb) == 0);
4736     return 0;
4737 }
4738
4739 void pa_native_protocol_remove_ext(pa_native_protocol *p, pa_module *m) {
4740     pa_assert(p);
4741     pa_assert(PA_REFCNT_VALUE(p) >= 1);
4742     pa_assert(m);
4743
4744     pa_assert_se(pa_hashmap_remove(p->extensions, m));
4745 }
4746
4747 pa_native_options* pa_native_options_new(void) {
4748     pa_native_options *o;
4749
4750     o = pa_xnew0(pa_native_options, 1);
4751     PA_REFCNT_INIT(o);
4752
4753     return o;
4754 }
4755
4756 pa_native_options* pa_native_options_ref(pa_native_options *o) {
4757     pa_assert(o);
4758     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4759
4760     PA_REFCNT_INC(o);
4761
4762     return o;
4763 }
4764
4765 void pa_native_options_unref(pa_native_options *o) {
4766     pa_assert(o);
4767     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4768
4769     if (PA_REFCNT_DEC(o) > 0)
4770         return;
4771
4772     pa_xfree(o->auth_group);
4773
4774     if (o->auth_ip_acl)
4775         pa_ip_acl_free(o->auth_ip_acl);
4776
4777     if (o->auth_cookie)
4778         pa_auth_cookie_unref(o->auth_cookie);
4779
4780     pa_xfree(o);
4781 }
4782
4783 int pa_native_options_parse(pa_native_options *o, pa_core *c, pa_modargs *ma) {
4784     pa_bool_t enabled;
4785     const char *acl;
4786
4787     pa_assert(o);
4788     pa_assert(PA_REFCNT_VALUE(o) >= 1);
4789     pa_assert(ma);
4790
4791     if (pa_modargs_get_value_boolean(ma, "auth-anonymous", &o->auth_anonymous) < 0) {
4792         pa_log("auth-anonymous= expects a boolean argument.");
4793         return -1;
4794     }
4795
4796     enabled = TRUE;
4797     if (pa_modargs_get_value_boolean(ma, "auth-group-enabled", &enabled) < 0) {
4798         pa_log("auth-group-enabled= expects a boolean argument.");
4799         return -1;
4800     }
4801
4802     pa_xfree(o->auth_group);
4803     o->auth_group = enabled ? pa_xstrdup(pa_modargs_get_value(ma, "auth-group", pa_in_system_mode() ? PA_ACCESS_GROUP : NULL)) : NULL;
4804
4805 #ifndef HAVE_CREDS
4806     if (o->auth_group)
4807         pa_log_warn("Authentication group configured, but not available on local system. Ignoring.");
4808 #endif
4809
4810     if ((acl = pa_modargs_get_value(ma, "auth-ip-acl", NULL))) {
4811         pa_ip_acl *ipa;
4812
4813         if (!(ipa = pa_ip_acl_new(acl))) {
4814             pa_log("Failed to parse IP ACL '%s'", acl);
4815             return -1;
4816         }
4817
4818         if (o->auth_ip_acl)
4819             pa_ip_acl_free(o->auth_ip_acl);
4820
4821         o->auth_ip_acl = ipa;
4822     }
4823
4824     enabled = TRUE;
4825     if (pa_modargs_get_value_boolean(ma, "auth-cookie-enabled", &enabled) < 0) {
4826         pa_log("auth-cookie-enabled= expects a boolean argument.");
4827         return -1;
4828     }
4829
4830     if (o->auth_cookie)
4831         pa_auth_cookie_unref(o->auth_cookie);
4832
4833     if (enabled) {
4834         const char *cn;
4835
4836         /* The new name for this is 'auth-cookie', for compat reasons
4837          * we check the old name too */
4838         if (!(cn = pa_modargs_get_value(ma, "auth-cookie", NULL)))
4839             if (!(cn = pa_modargs_get_value(ma, "cookie", NULL)))
4840                 cn = PA_NATIVE_COOKIE_FILE;
4841
4842         if (!(o->auth_cookie = pa_auth_cookie_get(c, cn, PA_NATIVE_COOKIE_LENGTH)))
4843             return -1;
4844
4845     } else
4846           o->auth_cookie = NULL;
4847
4848     return 0;
4849 }
4850
4851 pa_pstream* pa_native_connection_get_pstream(pa_native_connection *c) {
4852     pa_native_connection_assert_ref(c);
4853
4854     return c->pstream;
4855 }
4856
4857 pa_client* pa_native_connection_get_client(pa_native_connection *c) {
4858    pa_native_connection_assert_ref(c);
4859
4860    return c->client;
4861 }