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