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