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