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