]> code.delx.au - pulseaudio/blob - src/pulsecore/source.c
capture: Add the passthrough format negotiation to capture streams.
[pulseaudio] / src / pulsecore / source.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <pulse/utf8.h>
32 #include <pulse/xmalloc.h>
33 #include <pulse/timeval.h>
34 #include <pulse/util.h>
35 #include <pulse/internal.h>
36
37 #include <pulsecore/core-util.h>
38 #include <pulsecore/source-output.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/core-subscribe.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/sample-util.h>
43
44 #include "source.h"
45
46 #define ABSOLUTE_MIN_LATENCY (500)
47 #define ABSOLUTE_MAX_LATENCY (10*PA_USEC_PER_SEC)
48 #define DEFAULT_FIXED_LATENCY (250*PA_USEC_PER_MSEC)
49
50 PA_DEFINE_PUBLIC_CLASS(pa_source, pa_msgobject);
51
52 static void source_free(pa_object *o);
53
54 pa_source_new_data* pa_source_new_data_init(pa_source_new_data *data) {
55 pa_assert(data);
56
57 pa_zero(*data);
58 data->proplist = pa_proplist_new();
59
60 return data;
61 }
62
63 void pa_source_new_data_set_name(pa_source_new_data *data, const char *name) {
64 pa_assert(data);
65
66 pa_xfree(data->name);
67 data->name = pa_xstrdup(name);
68 }
69
70 void pa_source_new_data_set_sample_spec(pa_source_new_data *data, const pa_sample_spec *spec) {
71 pa_assert(data);
72
73 if ((data->sample_spec_is_set = !!spec))
74 data->sample_spec = *spec;
75 }
76
77 void pa_source_new_data_set_channel_map(pa_source_new_data *data, const pa_channel_map *map) {
78 pa_assert(data);
79
80 if ((data->channel_map_is_set = !!map))
81 data->channel_map = *map;
82 }
83
84 void pa_source_new_data_set_volume(pa_source_new_data *data, const pa_cvolume *volume) {
85 pa_assert(data);
86
87 if ((data->volume_is_set = !!volume))
88 data->volume = *volume;
89 }
90
91 void pa_source_new_data_set_muted(pa_source_new_data *data, pa_bool_t mute) {
92 pa_assert(data);
93
94 data->muted_is_set = TRUE;
95 data->muted = !!mute;
96 }
97
98 void pa_source_new_data_set_port(pa_source_new_data *data, const char *port) {
99 pa_assert(data);
100
101 pa_xfree(data->active_port);
102 data->active_port = pa_xstrdup(port);
103 }
104
105 void pa_source_new_data_done(pa_source_new_data *data) {
106 pa_assert(data);
107
108 pa_proplist_free(data->proplist);
109
110 if (data->ports) {
111 pa_device_port *p;
112
113 while ((p = pa_hashmap_steal_first(data->ports)))
114 pa_device_port_free(p);
115
116 pa_hashmap_free(data->ports, NULL, NULL);
117 }
118
119 pa_xfree(data->name);
120 pa_xfree(data->active_port);
121 }
122
123 /* Called from main context */
124 static void reset_callbacks(pa_source *s) {
125 pa_assert(s);
126
127 s->set_state = NULL;
128 s->get_volume = NULL;
129 s->set_volume = NULL;
130 s->get_mute = NULL;
131 s->set_mute = NULL;
132 s->update_requested_latency = NULL;
133 s->set_port = NULL;
134 s->get_formats = NULL;
135 }
136
137 /* Called from main context */
138 pa_source* pa_source_new(
139 pa_core *core,
140 pa_source_new_data *data,
141 pa_source_flags_t flags) {
142
143 pa_source *s;
144 const char *name;
145 char st[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
146 char *pt;
147
148 pa_assert(core);
149 pa_assert(data);
150 pa_assert(data->name);
151 pa_assert_ctl_context();
152
153 s = pa_msgobject_new(pa_source);
154
155 if (!(name = pa_namereg_register(core, data->name, PA_NAMEREG_SOURCE, s, data->namereg_fail))) {
156 pa_log_debug("Failed to register name %s.", data->name);
157 pa_xfree(s);
158 return NULL;
159 }
160
161 pa_source_new_data_set_name(data, name);
162
163 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_NEW], data) < 0) {
164 pa_xfree(s);
165 pa_namereg_unregister(core, name);
166 return NULL;
167 }
168
169 /* FIXME, need to free s here on failure */
170
171 pa_return_null_if_fail(!data->driver || pa_utf8_valid(data->driver));
172 pa_return_null_if_fail(data->name && pa_utf8_valid(data->name) && data->name[0]);
173
174 pa_return_null_if_fail(data->sample_spec_is_set && pa_sample_spec_valid(&data->sample_spec));
175
176 if (!data->channel_map_is_set)
177 pa_return_null_if_fail(pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT));
178
179 pa_return_null_if_fail(pa_channel_map_valid(&data->channel_map));
180 pa_return_null_if_fail(data->channel_map.channels == data->sample_spec.channels);
181
182 if (!data->volume_is_set)
183 pa_cvolume_reset(&data->volume, data->sample_spec.channels);
184
185 pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
186 pa_return_null_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec));
187
188 if (!data->muted_is_set)
189 data->muted = FALSE;
190
191 if (data->card)
192 pa_proplist_update(data->proplist, PA_UPDATE_MERGE, data->card->proplist);
193
194 pa_device_init_description(data->proplist);
195 pa_device_init_icon(data->proplist, FALSE);
196 pa_device_init_intended_roles(data->proplist);
197
198 if (pa_hook_fire(&core->hooks[PA_CORE_HOOK_SOURCE_FIXATE], data) < 0) {
199 pa_xfree(s);
200 pa_namereg_unregister(core, name);
201 return NULL;
202 }
203
204 s->parent.parent.free = source_free;
205 s->parent.process_msg = pa_source_process_msg;
206
207 s->core = core;
208 s->state = PA_SOURCE_INIT;
209 s->flags = flags;
210 s->priority = 0;
211 s->suspend_cause = 0;
212 s->name = pa_xstrdup(name);
213 s->proplist = pa_proplist_copy(data->proplist);
214 s->driver = pa_xstrdup(pa_path_get_filename(data->driver));
215 s->module = data->module;
216 s->card = data->card;
217
218 s->priority = pa_device_init_priority(s->proplist);
219
220 s->sample_spec = data->sample_spec;
221 s->channel_map = data->channel_map;
222
223 s->outputs = pa_idxset_new(NULL, NULL);
224 s->n_corked = 0;
225 s->monitor_of = NULL;
226 s->output_from_master = NULL;
227
228 s->volume = data->volume;
229 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
230 s->base_volume = PA_VOLUME_NORM;
231 s->n_volume_steps = PA_VOLUME_NORM+1;
232 s->muted = data->muted;
233 s->refresh_volume = s->refresh_muted = FALSE;
234
235 reset_callbacks(s);
236 s->userdata = NULL;
237
238 s->asyncmsgq = NULL;
239
240 /* As a minor optimization we just steal the list instead of
241 * copying it here */
242 s->ports = data->ports;
243 data->ports = NULL;
244
245 s->active_port = NULL;
246 s->save_port = FALSE;
247
248 if (data->active_port && s->ports)
249 if ((s->active_port = pa_hashmap_get(s->ports, data->active_port)))
250 s->save_port = data->save_port;
251
252 if (!s->active_port && s->ports) {
253 void *state;
254 pa_device_port *p;
255
256 PA_HASHMAP_FOREACH(p, s->ports, state)
257 if (!s->active_port || p->priority > s->active_port->priority)
258 s->active_port = p;
259 }
260
261 s->save_volume = data->save_volume;
262 s->save_muted = data->save_muted;
263
264 pa_silence_memchunk_get(
265 &core->silence_cache,
266 core->mempool,
267 &s->silence,
268 &s->sample_spec,
269 0);
270
271 s->thread_info.rtpoll = NULL;
272 s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
273 s->thread_info.soft_volume = s->soft_volume;
274 s->thread_info.soft_muted = s->muted;
275 s->thread_info.state = s->state;
276 s->thread_info.max_rewind = 0;
277 s->thread_info.requested_latency_valid = FALSE;
278 s->thread_info.requested_latency = 0;
279 s->thread_info.min_latency = ABSOLUTE_MIN_LATENCY;
280 s->thread_info.max_latency = ABSOLUTE_MAX_LATENCY;
281 s->thread_info.fixed_latency = flags & PA_SOURCE_DYNAMIC_LATENCY ? 0 : DEFAULT_FIXED_LATENCY;
282
283 pa_assert_se(pa_idxset_put(core->sources, s, &s->index) >= 0);
284
285 if (s->card)
286 pa_assert_se(pa_idxset_put(s->card->sources, s, NULL) >= 0);
287
288 pt = pa_proplist_to_string_sep(s->proplist, "\n ");
289 pa_log_info("Created source %u \"%s\" with sample spec %s and channel map %s\n %s",
290 s->index,
291 s->name,
292 pa_sample_spec_snprint(st, sizeof(st), &s->sample_spec),
293 pa_channel_map_snprint(cm, sizeof(cm), &s->channel_map),
294 pt);
295 pa_xfree(pt);
296
297 return s;
298 }
299
300 /* Called from main context */
301 static int source_set_state(pa_source *s, pa_source_state_t state) {
302 int ret;
303 pa_bool_t suspend_change;
304 pa_source_state_t original_state;
305
306 pa_assert(s);
307 pa_assert_ctl_context();
308
309 if (s->state == state)
310 return 0;
311
312 original_state = s->state;
313
314 suspend_change =
315 (original_state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(state)) ||
316 (PA_SOURCE_IS_OPENED(original_state) && state == PA_SOURCE_SUSPENDED);
317
318 if (s->set_state)
319 if ((ret = s->set_state(s, state)) < 0)
320 return ret;
321
322 if (s->asyncmsgq)
323 if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
324
325 if (s->set_state)
326 s->set_state(s, original_state);
327
328 return ret;
329 }
330
331 s->state = state;
332
333 if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
334 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
335 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
336 }
337
338 if (suspend_change) {
339 pa_source_output *o;
340 uint32_t idx;
341
342 /* We're suspending or resuming, tell everyone about it */
343
344 PA_IDXSET_FOREACH(o, s->outputs, idx)
345 if (s->state == PA_SOURCE_SUSPENDED &&
346 (o->flags & PA_SOURCE_OUTPUT_KILL_ON_SUSPEND))
347 pa_source_output_kill(o);
348 else if (o->suspend)
349 o->suspend(o, state == PA_SOURCE_SUSPENDED);
350 }
351
352 return 0;
353 }
354
355 /* Called from main context */
356 void pa_source_put(pa_source *s) {
357 pa_source_assert_ref(s);
358 pa_assert_ctl_context();
359
360 pa_assert(s->state == PA_SOURCE_INIT);
361
362 /* The following fields must be initialized properly when calling _put() */
363 pa_assert(s->asyncmsgq);
364 pa_assert(s->thread_info.min_latency <= s->thread_info.max_latency);
365
366 /* Generally, flags should be initialized via pa_source_new(). As
367 * a special exception we allow volume related flags to be set
368 * between _new() and _put(). */
369
370 if (!(s->flags & PA_SOURCE_HW_VOLUME_CTRL))
371 s->flags |= PA_SOURCE_DECIBEL_VOLUME;
372
373 s->thread_info.soft_volume = s->soft_volume;
374 s->thread_info.soft_muted = s->muted;
375
376 pa_assert((s->flags & PA_SOURCE_HW_VOLUME_CTRL) || (s->base_volume == PA_VOLUME_NORM && s->flags & PA_SOURCE_DECIBEL_VOLUME));
377 pa_assert(!(s->flags & PA_SOURCE_DECIBEL_VOLUME) || s->n_volume_steps == PA_VOLUME_NORM+1);
378 pa_assert(!(s->flags & PA_SOURCE_DYNAMIC_LATENCY) == (s->thread_info.fixed_latency != 0));
379
380 pa_assert_se(source_set_state(s, PA_SOURCE_IDLE) == 0);
381
382 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
383 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PUT], s);
384 }
385
386 /* Called from main context */
387 void pa_source_unlink(pa_source *s) {
388 pa_bool_t linked;
389 pa_source_output *o, *j = NULL;
390
391 pa_assert(s);
392 pa_assert_ctl_context();
393
394 /* See pa_sink_unlink() for a couple of comments how this function
395 * works. */
396
397 linked = PA_SOURCE_IS_LINKED(s->state);
398
399 if (linked)
400 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], s);
401
402 if (s->state != PA_SOURCE_UNLINKED)
403 pa_namereg_unregister(s->core, s->name);
404 pa_idxset_remove_by_data(s->core->sources, s, NULL);
405
406 if (s->card)
407 pa_idxset_remove_by_data(s->card->sources, s, NULL);
408
409 while ((o = pa_idxset_first(s->outputs, NULL))) {
410 pa_assert(o != j);
411 pa_source_output_kill(o);
412 j = o;
413 }
414
415 if (linked)
416 source_set_state(s, PA_SOURCE_UNLINKED);
417 else
418 s->state = PA_SOURCE_UNLINKED;
419
420 reset_callbacks(s);
421
422 if (linked) {
423 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
424 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK_POST], s);
425 }
426 }
427
428 /* Called from main context */
429 static void source_free(pa_object *o) {
430 pa_source_output *so;
431 pa_source *s = PA_SOURCE(o);
432
433 pa_assert(s);
434 pa_assert_ctl_context();
435 pa_assert(pa_source_refcnt(s) == 0);
436
437 if (PA_SOURCE_IS_LINKED(s->state))
438 pa_source_unlink(s);
439
440 pa_log_info("Freeing source %u \"%s\"", s->index, s->name);
441
442 pa_idxset_free(s->outputs, NULL, NULL);
443
444 while ((so = pa_hashmap_steal_first(s->thread_info.outputs)))
445 pa_source_output_unref(so);
446
447 pa_hashmap_free(s->thread_info.outputs, NULL, NULL);
448
449 if (s->silence.memblock)
450 pa_memblock_unref(s->silence.memblock);
451
452 pa_xfree(s->name);
453 pa_xfree(s->driver);
454
455 if (s->proplist)
456 pa_proplist_free(s->proplist);
457
458 if (s->ports) {
459 pa_device_port *p;
460
461 while ((p = pa_hashmap_steal_first(s->ports)))
462 pa_device_port_free(p);
463
464 pa_hashmap_free(s->ports, NULL, NULL);
465 }
466
467 pa_xfree(s);
468 }
469
470 /* Called from main context, and not while the IO thread is active, please */
471 void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) {
472 pa_source_assert_ref(s);
473 pa_assert_ctl_context();
474
475 s->asyncmsgq = q;
476 }
477
478 /* Called from main context, and not while the IO thread is active, please */
479 void pa_source_update_flags(pa_source *s, pa_source_flags_t mask, pa_source_flags_t value) {
480 pa_source_assert_ref(s);
481 pa_assert_ctl_context();
482
483 if (mask == 0)
484 return;
485
486 /* For now, allow only a minimal set of flags to be changed. */
487 pa_assert((mask & ~(PA_SOURCE_DYNAMIC_LATENCY|PA_SOURCE_LATENCY)) == 0);
488
489 s->flags = (s->flags & ~mask) | (value & mask);
490 }
491
492 /* Called from IO context, or before _put() from main context */
493 void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) {
494 pa_source_assert_ref(s);
495 pa_source_assert_io_context(s);
496
497 s->thread_info.rtpoll = p;
498 }
499
500 /* Called from main context */
501 int pa_source_update_status(pa_source*s) {
502 pa_source_assert_ref(s);
503 pa_assert_ctl_context();
504 pa_assert(PA_SOURCE_IS_LINKED(s->state));
505
506 if (s->state == PA_SOURCE_SUSPENDED)
507 return 0;
508
509 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
510 }
511
512 /* Called from main context */
513 int pa_source_suspend(pa_source *s, pa_bool_t suspend, pa_suspend_cause_t cause) {
514 pa_source_assert_ref(s);
515 pa_assert_ctl_context();
516 pa_assert(PA_SOURCE_IS_LINKED(s->state));
517 pa_assert(cause != 0);
518
519 if (s->monitor_of && cause != PA_SUSPEND_PASSTHROUGH)
520 return -PA_ERR_NOTSUPPORTED;
521
522 if (suspend)
523 s->suspend_cause |= cause;
524 else
525 s->suspend_cause &= ~cause;
526
527 if ((pa_source_get_state(s) == PA_SOURCE_SUSPENDED) == !!s->suspend_cause)
528 return 0;
529
530 pa_log_debug("Suspend cause of source %s is 0x%04x, %s", s->name, s->suspend_cause, s->suspend_cause ? "suspending" : "resuming");
531
532 if (suspend)
533 return source_set_state(s, PA_SOURCE_SUSPENDED);
534 else
535 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
536 }
537
538 /* Called from main context */
539 int pa_source_sync_suspend(pa_source *s) {
540 pa_sink_state_t state;
541
542 pa_source_assert_ref(s);
543 pa_assert_ctl_context();
544 pa_assert(PA_SOURCE_IS_LINKED(s->state));
545 pa_assert(s->monitor_of);
546
547 state = pa_sink_get_state(s->monitor_of);
548
549 if (state == PA_SINK_SUSPENDED)
550 return source_set_state(s, PA_SOURCE_SUSPENDED);
551
552 pa_assert(PA_SINK_IS_OPENED(state));
553
554 return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE);
555 }
556
557 /* Called from main context */
558 pa_queue *pa_source_move_all_start(pa_source *s, pa_queue *q) {
559 pa_source_output *o, *n;
560 uint32_t idx;
561
562 pa_source_assert_ref(s);
563 pa_assert_ctl_context();
564 pa_assert(PA_SOURCE_IS_LINKED(s->state));
565
566 if (!q)
567 q = pa_queue_new();
568
569 for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = n) {
570 n = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx));
571
572 pa_source_output_ref(o);
573
574 if (pa_source_output_start_move(o) >= 0)
575 pa_queue_push(q, o);
576 else
577 pa_source_output_unref(o);
578 }
579
580 return q;
581 }
582
583 /* Called from main context */
584 void pa_source_move_all_finish(pa_source *s, pa_queue *q, pa_bool_t save) {
585 pa_source_output *o;
586
587 pa_source_assert_ref(s);
588 pa_assert_ctl_context();
589 pa_assert(PA_SOURCE_IS_LINKED(s->state));
590 pa_assert(q);
591
592 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
593 if (pa_source_output_finish_move(o, s, save) < 0)
594 pa_source_output_fail_move(o);
595
596 pa_source_output_unref(o);
597 }
598
599 pa_queue_free(q, NULL, NULL);
600 }
601
602 /* Called from main context */
603 void pa_source_move_all_fail(pa_queue *q) {
604 pa_source_output *o;
605
606 pa_assert_ctl_context();
607 pa_assert(q);
608
609 while ((o = PA_SOURCE_OUTPUT(pa_queue_pop(q)))) {
610 pa_source_output_fail_move(o);
611 pa_source_output_unref(o);
612 }
613
614 pa_queue_free(q, NULL, NULL);
615 }
616
617 /* Called from IO thread context */
618 void pa_source_process_rewind(pa_source *s, size_t nbytes) {
619 pa_source_output *o;
620 void *state = NULL;
621
622 pa_source_assert_ref(s);
623 pa_source_assert_io_context(s);
624 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
625
626 if (nbytes <= 0)
627 return;
628
629 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
630 return;
631
632 pa_log_debug("Processing rewind...");
633
634 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state) {
635 pa_source_output_assert_ref(o);
636 pa_source_output_process_rewind(o, nbytes);
637 }
638 }
639
640 /* Called from IO thread context */
641 void pa_source_post(pa_source*s, const pa_memchunk *chunk) {
642 pa_source_output *o;
643 void *state = NULL;
644
645 pa_source_assert_ref(s);
646 pa_source_assert_io_context(s);
647 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
648 pa_assert(chunk);
649
650 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
651 return;
652
653 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
654 pa_memchunk vchunk = *chunk;
655
656 pa_memblock_ref(vchunk.memblock);
657 pa_memchunk_make_writable(&vchunk, 0);
658
659 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
660 pa_silence_memchunk(&vchunk, &s->sample_spec);
661 else
662 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
663
664 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
665 pa_source_output_assert_ref(o);
666
667 if (!o->thread_info.direct_on_input)
668 pa_source_output_push(o, &vchunk);
669 }
670
671 pa_memblock_unref(vchunk.memblock);
672 } else {
673
674 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) {
675 pa_source_output_assert_ref(o);
676
677 if (!o->thread_info.direct_on_input)
678 pa_source_output_push(o, chunk);
679 }
680 }
681 }
682
683 /* Called from IO thread context */
684 void pa_source_post_direct(pa_source*s, pa_source_output *o, const pa_memchunk *chunk) {
685 pa_source_assert_ref(s);
686 pa_source_assert_io_context(s);
687 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
688 pa_source_output_assert_ref(o);
689 pa_assert(o->thread_info.direct_on_input);
690 pa_assert(chunk);
691
692 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
693 return;
694
695 if (s->thread_info.soft_muted || !pa_cvolume_is_norm(&s->thread_info.soft_volume)) {
696 pa_memchunk vchunk = *chunk;
697
698 pa_memblock_ref(vchunk.memblock);
699 pa_memchunk_make_writable(&vchunk, 0);
700
701 if (s->thread_info.soft_muted || pa_cvolume_is_muted(&s->thread_info.soft_volume))
702 pa_silence_memchunk(&vchunk, &s->sample_spec);
703 else
704 pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume);
705
706 pa_source_output_push(o, &vchunk);
707
708 pa_memblock_unref(vchunk.memblock);
709 } else
710 pa_source_output_push(o, chunk);
711 }
712
713 /* Called from main thread */
714 pa_usec_t pa_source_get_latency(pa_source *s) {
715 pa_usec_t usec;
716
717 pa_source_assert_ref(s);
718 pa_assert_ctl_context();
719 pa_assert(PA_SOURCE_IS_LINKED(s->state));
720
721 if (s->state == PA_SOURCE_SUSPENDED)
722 return 0;
723
724 if (!(s->flags & PA_SOURCE_LATENCY))
725 return 0;
726
727 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
728
729 return usec;
730 }
731
732 /* Called from IO thread */
733 pa_usec_t pa_source_get_latency_within_thread(pa_source *s) {
734 pa_usec_t usec = 0;
735 pa_msgobject *o;
736
737 pa_source_assert_ref(s);
738 pa_source_assert_io_context(s);
739 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
740
741 /* The returned value is supposed to be in the time domain of the sound card! */
742
743 if (s->thread_info.state == PA_SOURCE_SUSPENDED)
744 return 0;
745
746 if (!(s->flags & PA_SOURCE_LATENCY))
747 return 0;
748
749 o = PA_MSGOBJECT(s);
750
751 /* We probably should make this a proper vtable callback instead of going through process_msg() */
752
753 if (o->process_msg(o, PA_SOURCE_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
754 return -1;
755
756 return usec;
757 }
758
759 /* Called from main context */
760 pa_bool_t pa_source_is_passthrough(pa_source *s) {
761
762 pa_source_assert_ref(s);
763
764 /* NB Currently only monitor sources support passthrough mode */
765 return (s->monitor_of && pa_sink_is_passthrough(s->monitor_of));
766 }
767
768 /* Called from main thread */
769 void pa_source_set_volume(
770 pa_source *s,
771 const pa_cvolume *volume,
772 pa_bool_t save) {
773
774 pa_bool_t real_changed;
775 pa_cvolume old_volume;
776
777 pa_source_assert_ref(s);
778 pa_assert_ctl_context();
779 pa_assert(PA_SOURCE_IS_LINKED(s->state));
780 pa_assert(pa_cvolume_valid(volume));
781 pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
782
783 old_volume = s->volume;
784
785 if (pa_cvolume_compatible(volume, &s->sample_spec))
786 s->volume = *volume;
787 else
788 pa_cvolume_scale(&s->volume, pa_cvolume_max(volume));
789
790 real_changed = !pa_cvolume_equal(&old_volume, &s->volume);
791 s->save_volume = (!real_changed && s->save_volume) || save;
792
793 if (s->set_volume) {
794 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
795 s->set_volume(s);
796 } else
797 s->soft_volume = s->volume;
798
799 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
800
801 if (real_changed)
802 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
803 }
804
805 /* Called from main thread. Only to be called by source implementor */
806 void pa_source_set_soft_volume(pa_source *s, const pa_cvolume *volume) {
807 pa_source_assert_ref(s);
808 pa_assert_ctl_context();
809
810 if (!volume)
811 pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
812 else
813 s->soft_volume = *volume;
814
815 if (PA_SOURCE_IS_LINKED(s->state))
816 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_VOLUME, NULL, 0, NULL) == 0);
817 else
818 s->thread_info.soft_volume = s->soft_volume;
819 }
820
821 /* Called from main thread */
822 const pa_cvolume *pa_source_get_volume(pa_source *s, pa_bool_t force_refresh) {
823 pa_source_assert_ref(s);
824 pa_assert_ctl_context();
825 pa_assert(PA_SOURCE_IS_LINKED(s->state));
826
827 if (s->refresh_volume || force_refresh) {
828 pa_cvolume old_volume;
829
830 old_volume = s->volume;
831
832 if (s->get_volume)
833 s->get_volume(s);
834
835 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_VOLUME, NULL, 0, NULL) == 0);
836
837 if (!pa_cvolume_equal(&old_volume, &s->volume)) {
838 s->save_volume = TRUE;
839 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
840 }
841 }
842
843 return &s->volume;
844 }
845
846 /* Called from main thread */
847 void pa_source_volume_changed(pa_source *s, const pa_cvolume *new_volume) {
848 pa_source_assert_ref(s);
849 pa_assert_ctl_context();
850 pa_assert(PA_SOURCE_IS_LINKED(s->state));
851
852 /* The source implementor may call this if the volume changed to make sure everyone is notified */
853
854 if (pa_cvolume_equal(&s->volume, new_volume))
855 return;
856
857 s->volume = *new_volume;
858 s->save_volume = TRUE;
859
860 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
861 }
862
863 /* Called from main thread */
864 void pa_source_set_mute(pa_source *s, pa_bool_t mute, pa_bool_t save) {
865 pa_bool_t old_muted;
866
867 pa_source_assert_ref(s);
868 pa_assert_ctl_context();
869 pa_assert(PA_SOURCE_IS_LINKED(s->state));
870
871 old_muted = s->muted;
872 s->muted = mute;
873 s->save_muted = (old_muted == s->muted && s->save_muted) || save;
874
875 if (s->set_mute)
876 s->set_mute(s);
877
878 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
879
880 if (old_muted != s->muted)
881 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
882 }
883
884 /* Called from main thread */
885 pa_bool_t pa_source_get_mute(pa_source *s, pa_bool_t force_refresh) {
886 pa_source_assert_ref(s);
887 pa_assert_ctl_context();
888 pa_assert(PA_SOURCE_IS_LINKED(s->state));
889
890 if (s->refresh_muted || force_refresh) {
891 pa_bool_t old_muted = s->muted;
892
893 if (s->get_mute)
894 s->get_mute(s);
895
896 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MUTE, NULL, 0, NULL) == 0);
897
898 if (old_muted != s->muted) {
899 s->save_muted = TRUE;
900
901 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
902
903 /* Make sure the soft mute status stays in sync */
904 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MUTE, NULL, 0, NULL) == 0);
905 }
906 }
907
908 return s->muted;
909 }
910
911 /* Called from main thread */
912 void pa_source_mute_changed(pa_source *s, pa_bool_t new_muted) {
913 pa_source_assert_ref(s);
914 pa_assert_ctl_context();
915 pa_assert(PA_SOURCE_IS_LINKED(s->state));
916
917 /* The source implementor may call this if the mute state changed to make sure everyone is notified */
918
919 if (s->muted == new_muted)
920 return;
921
922 s->muted = new_muted;
923 s->save_muted = TRUE;
924
925 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
926 }
927
928 /* Called from main thread */
929 pa_bool_t pa_source_update_proplist(pa_source *s, pa_update_mode_t mode, pa_proplist *p) {
930 pa_source_assert_ref(s);
931 pa_assert_ctl_context();
932
933 if (p)
934 pa_proplist_update(s->proplist, mode, p);
935
936 if (PA_SOURCE_IS_LINKED(s->state)) {
937 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
938 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
939 }
940
941 return TRUE;
942 }
943
944 /* Called from main thread */
945 /* FIXME -- this should be dropped and be merged into pa_source_update_proplist() */
946 void pa_source_set_description(pa_source *s, const char *description) {
947 const char *old;
948 pa_source_assert_ref(s);
949 pa_assert_ctl_context();
950
951 if (!description && !pa_proplist_contains(s->proplist, PA_PROP_DEVICE_DESCRIPTION))
952 return;
953
954 old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
955
956 if (old && description && pa_streq(old, description))
957 return;
958
959 if (description)
960 pa_proplist_sets(s->proplist, PA_PROP_DEVICE_DESCRIPTION, description);
961 else
962 pa_proplist_unset(s->proplist, PA_PROP_DEVICE_DESCRIPTION);
963
964 if (PA_SOURCE_IS_LINKED(s->state)) {
965 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
966 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PROPLIST_CHANGED], s);
967 }
968 }
969
970 /* Called from main thread */
971 unsigned pa_source_linked_by(pa_source *s) {
972 pa_source_assert_ref(s);
973 pa_assert(PA_SOURCE_IS_LINKED(s->state));
974 pa_assert_ctl_context();
975
976 return pa_idxset_size(s->outputs);
977 }
978
979 /* Called from main thread */
980 unsigned pa_source_used_by(pa_source *s) {
981 unsigned ret;
982
983 pa_source_assert_ref(s);
984 pa_assert(PA_SOURCE_IS_LINKED(s->state));
985 pa_assert_ctl_context();
986
987 ret = pa_idxset_size(s->outputs);
988 pa_assert(ret >= s->n_corked);
989
990 return ret - s->n_corked;
991 }
992
993 /* Called from main thread */
994 unsigned pa_source_check_suspend(pa_source *s) {
995 unsigned ret;
996 pa_source_output *o;
997 uint32_t idx;
998
999 pa_source_assert_ref(s);
1000 pa_assert_ctl_context();
1001
1002 if (!PA_SOURCE_IS_LINKED(s->state))
1003 return 0;
1004
1005 ret = 0;
1006
1007 PA_IDXSET_FOREACH(o, s->outputs, idx) {
1008 pa_source_output_state_t st;
1009
1010 st = pa_source_output_get_state(o);
1011
1012 /* We do not assert here. It is perfectly valid for a source output to
1013 * be in the INIT state (i.e. created, marked done but not yet put)
1014 * and we should not care if it's unlinked as it won't contribute
1015 * towarards our busy status.
1016 */
1017 if (!PA_SOURCE_OUTPUT_IS_LINKED(st))
1018 continue;
1019
1020 if (st == PA_SOURCE_OUTPUT_CORKED)
1021 continue;
1022
1023 if (o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND)
1024 continue;
1025
1026 ret ++;
1027 }
1028
1029 return ret;
1030 }
1031
1032 /* Called from IO thread, except when it is not */
1033 int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
1034 pa_source *s = PA_SOURCE(object);
1035 pa_source_assert_ref(s);
1036
1037 switch ((pa_source_message_t) code) {
1038
1039 case PA_SOURCE_MESSAGE_ADD_OUTPUT: {
1040 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
1041
1042 pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o));
1043
1044 if (o->direct_on_input) {
1045 o->thread_info.direct_on_input = o->direct_on_input;
1046 pa_hashmap_put(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index), o);
1047 }
1048
1049 pa_assert(!o->thread_info.attached);
1050 o->thread_info.attached = TRUE;
1051
1052 if (o->attach)
1053 o->attach(o);
1054
1055 pa_source_output_set_state_within_thread(o, o->state);
1056
1057 if (o->thread_info.requested_source_latency != (pa_usec_t) -1)
1058 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
1059
1060 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1061
1062 /* We don't just invalidate the requested latency here,
1063 * because if we are in a move we might need to fix up the
1064 * requested latency. */
1065 pa_source_output_set_requested_latency_within_thread(o, o->thread_info.requested_source_latency);
1066
1067 return 0;
1068 }
1069
1070 case PA_SOURCE_MESSAGE_REMOVE_OUTPUT: {
1071 pa_source_output *o = PA_SOURCE_OUTPUT(userdata);
1072
1073 pa_source_output_set_state_within_thread(o, o->state);
1074
1075 if (o->detach)
1076 o->detach(o);
1077
1078 pa_assert(o->thread_info.attached);
1079 o->thread_info.attached = FALSE;
1080
1081 if (o->thread_info.direct_on_input) {
1082 pa_hashmap_remove(o->thread_info.direct_on_input->thread_info.direct_outputs, PA_UINT32_TO_PTR(o->index));
1083 o->thread_info.direct_on_input = NULL;
1084 }
1085
1086 if (pa_hashmap_remove(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index)))
1087 pa_source_output_unref(o);
1088
1089 pa_source_invalidate_requested_latency(s, TRUE);
1090
1091 return 0;
1092 }
1093
1094 case PA_SOURCE_MESSAGE_SET_VOLUME:
1095 s->thread_info.soft_volume = s->soft_volume;
1096 return 0;
1097
1098 case PA_SOURCE_MESSAGE_GET_VOLUME:
1099 return 0;
1100
1101 case PA_SOURCE_MESSAGE_SET_MUTE:
1102 s->thread_info.soft_muted = s->muted;
1103 return 0;
1104
1105 case PA_SOURCE_MESSAGE_GET_MUTE:
1106 return 0;
1107
1108 case PA_SOURCE_MESSAGE_SET_STATE: {
1109
1110 pa_bool_t suspend_change =
1111 (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
1112 (PA_SOURCE_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SOURCE_SUSPENDED);
1113
1114 s->thread_info.state = PA_PTR_TO_UINT(userdata);
1115
1116 if (suspend_change) {
1117 pa_source_output *o;
1118 void *state = NULL;
1119
1120 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1121 if (o->suspend_within_thread)
1122 o->suspend_within_thread(o, s->thread_info.state == PA_SOURCE_SUSPENDED);
1123 }
1124
1125
1126 return 0;
1127 }
1128
1129 case PA_SOURCE_MESSAGE_DETACH:
1130
1131 /* Detach all streams */
1132 pa_source_detach_within_thread(s);
1133 return 0;
1134
1135 case PA_SOURCE_MESSAGE_ATTACH:
1136
1137 /* Reattach all streams */
1138 pa_source_attach_within_thread(s);
1139 return 0;
1140
1141 case PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY: {
1142
1143 pa_usec_t *usec = userdata;
1144 *usec = pa_source_get_requested_latency_within_thread(s);
1145
1146 if (*usec == (pa_usec_t) -1)
1147 *usec = s->thread_info.max_latency;
1148
1149 return 0;
1150 }
1151
1152 case PA_SOURCE_MESSAGE_SET_LATENCY_RANGE: {
1153 pa_usec_t *r = userdata;
1154
1155 pa_source_set_latency_range_within_thread(s, r[0], r[1]);
1156
1157 return 0;
1158 }
1159
1160 case PA_SOURCE_MESSAGE_GET_LATENCY_RANGE: {
1161 pa_usec_t *r = userdata;
1162
1163 r[0] = s->thread_info.min_latency;
1164 r[1] = s->thread_info.max_latency;
1165
1166 return 0;
1167 }
1168
1169 case PA_SOURCE_MESSAGE_GET_FIXED_LATENCY:
1170
1171 *((pa_usec_t*) userdata) = s->thread_info.fixed_latency;
1172 return 0;
1173
1174 case PA_SOURCE_MESSAGE_SET_FIXED_LATENCY:
1175
1176 pa_source_set_fixed_latency_within_thread(s, (pa_usec_t) offset);
1177 return 0;
1178
1179 case PA_SOURCE_MESSAGE_GET_MAX_REWIND:
1180
1181 *((size_t*) userdata) = s->thread_info.max_rewind;
1182 return 0;
1183
1184 case PA_SOURCE_MESSAGE_SET_MAX_REWIND:
1185
1186 pa_source_set_max_rewind_within_thread(s, (size_t) offset);
1187 return 0;
1188
1189 case PA_SOURCE_MESSAGE_GET_LATENCY:
1190
1191 if (s->monitor_of) {
1192 *((pa_usec_t*) userdata) = 0;
1193 return 0;
1194 }
1195
1196 /* Implementors need to overwrite this implementation! */
1197 return -1;
1198
1199 case PA_SOURCE_MESSAGE_MAX:
1200 ;
1201 }
1202
1203 return -1;
1204 }
1205
1206 /* Called from main thread */
1207 int pa_source_suspend_all(pa_core *c, pa_bool_t suspend, pa_suspend_cause_t cause) {
1208 uint32_t idx;
1209 pa_source *source;
1210 int ret = 0;
1211
1212 pa_core_assert_ref(c);
1213 pa_assert_ctl_context();
1214 pa_assert(cause != 0);
1215
1216 for (source = PA_SOURCE(pa_idxset_first(c->sources, &idx)); source; source = PA_SOURCE(pa_idxset_next(c->sources, &idx))) {
1217 int r;
1218
1219 if (source->monitor_of)
1220 continue;
1221
1222 if ((r = pa_source_suspend(source, suspend, cause)) < 0)
1223 ret = r;
1224 }
1225
1226 return ret;
1227 }
1228
1229 /* Called from main thread */
1230 void pa_source_detach(pa_source *s) {
1231 pa_source_assert_ref(s);
1232 pa_assert_ctl_context();
1233 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1234
1235 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_DETACH, NULL, 0, NULL) == 0);
1236 }
1237
1238 /* Called from main thread */
1239 void pa_source_attach(pa_source *s) {
1240 pa_source_assert_ref(s);
1241 pa_assert_ctl_context();
1242 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1243
1244 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_ATTACH, NULL, 0, NULL) == 0);
1245 }
1246
1247 /* Called from IO thread */
1248 void pa_source_detach_within_thread(pa_source *s) {
1249 pa_source_output *o;
1250 void *state = NULL;
1251
1252 pa_source_assert_ref(s);
1253 pa_source_assert_io_context(s);
1254 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1255
1256 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1257 if (o->detach)
1258 o->detach(o);
1259 }
1260
1261 /* Called from IO thread */
1262 void pa_source_attach_within_thread(pa_source *s) {
1263 pa_source_output *o;
1264 void *state = NULL;
1265
1266 pa_source_assert_ref(s);
1267 pa_source_assert_io_context(s);
1268 pa_assert(PA_SOURCE_IS_LINKED(s->thread_info.state));
1269
1270 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1271 if (o->attach)
1272 o->attach(o);
1273 }
1274
1275 /* Called from IO thread */
1276 pa_usec_t pa_source_get_requested_latency_within_thread(pa_source *s) {
1277 pa_usec_t result = (pa_usec_t) -1;
1278 pa_source_output *o;
1279 void *state = NULL;
1280
1281 pa_source_assert_ref(s);
1282 pa_source_assert_io_context(s);
1283
1284 if (!(s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1285 return PA_CLAMP(s->thread_info.fixed_latency, s->thread_info.min_latency, s->thread_info.max_latency);
1286
1287 if (s->thread_info.requested_latency_valid)
1288 return s->thread_info.requested_latency;
1289
1290 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1291 if (o->thread_info.requested_source_latency != (pa_usec_t) -1 &&
1292 (result == (pa_usec_t) -1 || result > o->thread_info.requested_source_latency))
1293 result = o->thread_info.requested_source_latency;
1294
1295 if (result != (pa_usec_t) -1)
1296 result = PA_CLAMP(result, s->thread_info.min_latency, s->thread_info.max_latency);
1297
1298 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1299 /* Only cache this if we are fully set up */
1300 s->thread_info.requested_latency = result;
1301 s->thread_info.requested_latency_valid = TRUE;
1302 }
1303
1304 return result;
1305 }
1306
1307 /* Called from main thread */
1308 pa_usec_t pa_source_get_requested_latency(pa_source *s) {
1309 pa_usec_t usec = 0;
1310
1311 pa_source_assert_ref(s);
1312 pa_assert_ctl_context();
1313 pa_assert(PA_SOURCE_IS_LINKED(s->state));
1314
1315 if (s->state == PA_SOURCE_SUSPENDED)
1316 return 0;
1317
1318 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0);
1319
1320 return usec;
1321 }
1322
1323 /* Called from IO thread */
1324 void pa_source_set_max_rewind_within_thread(pa_source *s, size_t max_rewind) {
1325 pa_source_output *o;
1326 void *state = NULL;
1327
1328 pa_source_assert_ref(s);
1329 pa_source_assert_io_context(s);
1330
1331 if (max_rewind == s->thread_info.max_rewind)
1332 return;
1333
1334 s->thread_info.max_rewind = max_rewind;
1335
1336 if (PA_SOURCE_IS_LINKED(s->thread_info.state))
1337 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1338 pa_source_output_update_max_rewind(o, s->thread_info.max_rewind);
1339 }
1340
1341 /* Called from main thread */
1342 void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) {
1343 pa_source_assert_ref(s);
1344 pa_assert_ctl_context();
1345
1346 if (PA_SOURCE_IS_LINKED(s->state))
1347 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_MAX_REWIND, NULL, max_rewind, NULL) == 0);
1348 else
1349 pa_source_set_max_rewind_within_thread(s, max_rewind);
1350 }
1351
1352 /* Called from IO thread */
1353 void pa_source_invalidate_requested_latency(pa_source *s, pa_bool_t dynamic) {
1354 pa_source_output *o;
1355 void *state = NULL;
1356
1357 pa_source_assert_ref(s);
1358 pa_source_assert_io_context(s);
1359
1360 if ((s->flags & PA_SOURCE_DYNAMIC_LATENCY))
1361 s->thread_info.requested_latency_valid = FALSE;
1362 else if (dynamic)
1363 return;
1364
1365 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1366
1367 if (s->update_requested_latency)
1368 s->update_requested_latency(s);
1369
1370 while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL)))
1371 if (o->update_source_requested_latency)
1372 o->update_source_requested_latency(o);
1373 }
1374
1375 if (s->monitor_of)
1376 pa_sink_invalidate_requested_latency(s->monitor_of, dynamic);
1377 }
1378
1379 /* Called from main thread */
1380 void pa_source_set_latency_range(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1381 pa_source_assert_ref(s);
1382 pa_assert_ctl_context();
1383
1384 /* min_latency == 0: no limit
1385 * min_latency anything else: specified limit
1386 *
1387 * Similar for max_latency */
1388
1389 if (min_latency < ABSOLUTE_MIN_LATENCY)
1390 min_latency = ABSOLUTE_MIN_LATENCY;
1391
1392 if (max_latency <= 0 ||
1393 max_latency > ABSOLUTE_MAX_LATENCY)
1394 max_latency = ABSOLUTE_MAX_LATENCY;
1395
1396 pa_assert(min_latency <= max_latency);
1397
1398 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1399 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1400 max_latency == ABSOLUTE_MAX_LATENCY) ||
1401 (s->flags & PA_SOURCE_DYNAMIC_LATENCY));
1402
1403 if (PA_SOURCE_IS_LINKED(s->state)) {
1404 pa_usec_t r[2];
1405
1406 r[0] = min_latency;
1407 r[1] = max_latency;
1408
1409 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_LATENCY_RANGE, r, 0, NULL) == 0);
1410 } else
1411 pa_source_set_latency_range_within_thread(s, min_latency, max_latency);
1412 }
1413
1414 /* Called from main thread */
1415 void pa_source_get_latency_range(pa_source *s, pa_usec_t *min_latency, pa_usec_t *max_latency) {
1416 pa_source_assert_ref(s);
1417 pa_assert_ctl_context();
1418 pa_assert(min_latency);
1419 pa_assert(max_latency);
1420
1421 if (PA_SOURCE_IS_LINKED(s->state)) {
1422 pa_usec_t r[2] = { 0, 0 };
1423
1424 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_LATENCY_RANGE, r, 0, NULL) == 0);
1425
1426 *min_latency = r[0];
1427 *max_latency = r[1];
1428 } else {
1429 *min_latency = s->thread_info.min_latency;
1430 *max_latency = s->thread_info.max_latency;
1431 }
1432 }
1433
1434 /* Called from IO thread, and from main thread before pa_source_put() is called */
1435 void pa_source_set_latency_range_within_thread(pa_source *s, pa_usec_t min_latency, pa_usec_t max_latency) {
1436 pa_source_assert_ref(s);
1437 pa_source_assert_io_context(s);
1438
1439 pa_assert(min_latency >= ABSOLUTE_MIN_LATENCY);
1440 pa_assert(max_latency <= ABSOLUTE_MAX_LATENCY);
1441 pa_assert(min_latency <= max_latency);
1442
1443 /* Hmm, let's see if someone forgot to set PA_SOURCE_DYNAMIC_LATENCY here... */
1444 pa_assert((min_latency == ABSOLUTE_MIN_LATENCY &&
1445 max_latency == ABSOLUTE_MAX_LATENCY) ||
1446 (s->flags & PA_SOURCE_DYNAMIC_LATENCY) ||
1447 s->monitor_of);
1448
1449 if (s->thread_info.min_latency == min_latency &&
1450 s->thread_info.max_latency == max_latency)
1451 return;
1452
1453 s->thread_info.min_latency = min_latency;
1454 s->thread_info.max_latency = max_latency;
1455
1456 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1457 pa_source_output *o;
1458 void *state = NULL;
1459
1460 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1461 if (o->update_source_latency_range)
1462 o->update_source_latency_range(o);
1463 }
1464
1465 pa_source_invalidate_requested_latency(s, FALSE);
1466 }
1467
1468 /* Called from main thread, before the source is put */
1469 void pa_source_set_fixed_latency(pa_source *s, pa_usec_t latency) {
1470 pa_source_assert_ref(s);
1471 pa_assert_ctl_context();
1472
1473 if (s->flags & PA_SOURCE_DYNAMIC_LATENCY) {
1474 pa_assert(latency == 0);
1475 return;
1476 }
1477
1478 if (latency < ABSOLUTE_MIN_LATENCY)
1479 latency = ABSOLUTE_MIN_LATENCY;
1480
1481 if (latency > ABSOLUTE_MAX_LATENCY)
1482 latency = ABSOLUTE_MAX_LATENCY;
1483
1484 if (PA_SOURCE_IS_LINKED(s->state))
1485 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_FIXED_LATENCY, NULL, (int64_t) latency, NULL) == 0);
1486 else
1487 s->thread_info.fixed_latency = latency;
1488 }
1489
1490 /* Called from main thread */
1491 pa_usec_t pa_source_get_fixed_latency(pa_source *s) {
1492 pa_usec_t latency;
1493
1494 pa_source_assert_ref(s);
1495 pa_assert_ctl_context();
1496
1497 if (s->flags & PA_SOURCE_DYNAMIC_LATENCY)
1498 return 0;
1499
1500 if (PA_SOURCE_IS_LINKED(s->state))
1501 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_FIXED_LATENCY, &latency, 0, NULL) == 0);
1502 else
1503 latency = s->thread_info.fixed_latency;
1504
1505 return latency;
1506 }
1507
1508 /* Called from IO thread */
1509 void pa_source_set_fixed_latency_within_thread(pa_source *s, pa_usec_t latency) {
1510 pa_source_assert_ref(s);
1511 pa_source_assert_io_context(s);
1512
1513 if (s->flags & PA_SOURCE_DYNAMIC_LATENCY) {
1514 pa_assert(latency == 0);
1515 return;
1516 }
1517
1518 pa_assert(latency >= ABSOLUTE_MIN_LATENCY);
1519 pa_assert(latency <= ABSOLUTE_MAX_LATENCY);
1520
1521 if (s->thread_info.fixed_latency == latency)
1522 return;
1523
1524 s->thread_info.fixed_latency = latency;
1525
1526 if (PA_SOURCE_IS_LINKED(s->thread_info.state)) {
1527 pa_source_output *o;
1528 void *state = NULL;
1529
1530 PA_HASHMAP_FOREACH(o, s->thread_info.outputs, state)
1531 if (o->update_source_fixed_latency)
1532 o->update_source_fixed_latency(o);
1533 }
1534
1535 pa_source_invalidate_requested_latency(s, FALSE);
1536 }
1537
1538 /* Called from main thread */
1539 size_t pa_source_get_max_rewind(pa_source *s) {
1540 size_t r;
1541 pa_assert_ctl_context();
1542 pa_source_assert_ref(s);
1543
1544 if (!PA_SOURCE_IS_LINKED(s->state))
1545 return s->thread_info.max_rewind;
1546
1547 pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_GET_MAX_REWIND, &r, 0, NULL) == 0);
1548
1549 return r;
1550 }
1551
1552 /* Called from main context */
1553 int pa_source_set_port(pa_source *s, const char *name, pa_bool_t save) {
1554 pa_device_port *port;
1555
1556 pa_assert(s);
1557 pa_assert_ctl_context();
1558
1559 if (!s->set_port) {
1560 pa_log_debug("set_port() operation not implemented for source %u \"%s\"", s->index, s->name);
1561 return -PA_ERR_NOTIMPLEMENTED;
1562 }
1563
1564 if (!s->ports)
1565 return -PA_ERR_NOENTITY;
1566
1567 if (!(port = pa_hashmap_get(s->ports, name)))
1568 return -PA_ERR_NOENTITY;
1569
1570 if (s->active_port == port) {
1571 s->save_port = s->save_port || save;
1572 return 0;
1573 }
1574
1575 if ((s->set_port(s, port)) < 0)
1576 return -PA_ERR_NOENTITY;
1577
1578 pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
1579
1580 pa_log_info("Changed port of source %u \"%s\" to %s", s->index, s->name, port->name);
1581
1582 s->active_port = port;
1583 s->save_port = save;
1584
1585 pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_PORT_CHANGED], s);
1586
1587 return 0;
1588 }
1589
1590 /* Called from the main thread */
1591 /* Gets the list of formats supported by the source. The members and idxset must
1592 * be freed by the caller. */
1593 pa_idxset* pa_source_get_formats(pa_source *s) {
1594 pa_idxset *ret;
1595
1596 pa_assert(s);
1597
1598 if (s->get_formats) {
1599 /* Source supports format query, all is good */
1600 ret = s->get_formats(s);
1601 } else {
1602 /* Source doesn't support format query, so assume it does PCM */
1603 pa_format_info *f = pa_format_info_new();
1604 f->encoding = PA_ENCODING_PCM;
1605
1606 ret = pa_idxset_new(NULL, NULL);
1607 pa_idxset_put(ret, f, NULL);
1608 }
1609
1610 return ret;
1611 }
1612
1613 /* Called from the main thread */
1614 /* Checks if the source can accept this format */
1615 pa_bool_t pa_source_check_format(pa_source *s, pa_format_info *f)
1616 {
1617 pa_idxset *formats = NULL;
1618 pa_bool_t ret = FALSE;
1619
1620 pa_assert(s);
1621 pa_assert(f);
1622
1623 formats = pa_source_get_formats(s);
1624
1625 if (formats) {
1626 pa_format_info *finfo_device;
1627 uint32_t i;
1628
1629 PA_IDXSET_FOREACH(finfo_device, formats, i) {
1630 if (pa_format_info_is_compatible(finfo_device, f)) {
1631 ret = TRUE;
1632 break;
1633 }
1634 }
1635
1636 pa_idxset_free(formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
1637 }
1638
1639 return ret;
1640 }
1641
1642 /* Called from the main thread */
1643 /* Calculates the intersection between formats supported by the source and
1644 * in_formats, and returns these, in the order of the source's formats. */
1645 pa_idxset* pa_source_check_formats(pa_source *s, pa_idxset *in_formats) {
1646 pa_idxset *out_formats = pa_idxset_new(NULL, NULL), *source_formats = NULL;
1647 pa_format_info *f_source, *f_in;
1648 uint32_t i, j;
1649
1650 pa_assert(s);
1651
1652 if (!in_formats || pa_idxset_isempty(in_formats))
1653 goto done;
1654
1655 source_formats = pa_source_get_formats(s);
1656
1657 PA_IDXSET_FOREACH(f_source, source_formats, i) {
1658 PA_IDXSET_FOREACH(f_in, in_formats, j) {
1659 if (pa_format_info_is_compatible(f_source, f_in))
1660 pa_idxset_put(out_formats, pa_format_info_copy(f_in), NULL);
1661 }
1662 }
1663
1664 done:
1665 if (source_formats)
1666 pa_idxset_free(source_formats, (pa_free2_cb_t) pa_format_info_free2, NULL);
1667
1668 return out_formats;
1669 }