+/* Called from main thread */
+int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
+ int ret = -1;
+ uint32_t desired_rate = rate;
+ uint32_t default_rate = s->default_sample_rate;
+ uint32_t alternate_rate = s->alternate_sample_rate;
+ uint32_t idx;
+ pa_sink_input *i;
+ bool use_alternate = false;
+
+ if (rate == s->sample_spec.rate)
+ return 0;
+
+ if (!s->update_rate)
+ return -1;
+
+ if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough)) {
+ pa_log_debug("Default and alternate sample rates are the same.");
+ return -1;
+ }
+
+ if (PA_SINK_IS_RUNNING(s->state)) {
+ pa_log_info("Cannot update rate, SINK_IS_RUNNING, will keep using %u Hz",
+ s->sample_spec.rate);
+ return -1;
+ }
+
+ if (s->monitor_source) {
+ if (PA_SOURCE_IS_RUNNING(s->monitor_source->state) == true) {
+ pa_log_info("Cannot update rate, monitor source is RUNNING");
+ return -1;
+ }
+ }
+
+ if (PA_UNLIKELY(!pa_sample_rate_valid(desired_rate)))
+ return -1;
+
+ if (!passthrough) {
+ pa_assert((default_rate % 4000 == 0) || (default_rate % 11025 == 0));
+ pa_assert((alternate_rate % 4000 == 0) || (alternate_rate % 11025 == 0));
+
+ if (default_rate % 11025 == 0) {
+ if ((alternate_rate % 4000 == 0) && (desired_rate % 4000 == 0))
+ use_alternate=true;
+ } else {
+ /* default is 4000 multiple */
+ if ((alternate_rate % 11025 == 0) && (desired_rate % 11025 == 0))
+ use_alternate=true;
+ }
+
+ if (use_alternate)
+ desired_rate = alternate_rate;
+ else
+ desired_rate = default_rate;
+ } else {
+ desired_rate = rate; /* use stream sampling rate, discard default/alternate settings */
+ }
+
+ if (desired_rate == s->sample_spec.rate)
+ return -1;
+
+ if (!passthrough && pa_sink_used_by(s) > 0)
+ return -1;
+
+ pa_log_debug("Suspending sink %s due to changing the sample rate.", s->name);
+ pa_sink_suspend(s, true, PA_SUSPEND_INTERNAL);
+
+ if (s->update_rate(s, desired_rate) >= 0) {
+ /* update monitor source as well */
+ if (s->monitor_source && !passthrough)
+ pa_source_update_rate(s->monitor_source, desired_rate, false);
+ pa_log_info("Changed sampling rate successfully");
+
+ PA_IDXSET_FOREACH(i, s->inputs, idx) {
+ if (i->state == PA_SINK_INPUT_CORKED)
+ pa_sink_input_update_rate(i);
+ }
+
+ ret = 0;
+ }
+
+ pa_sink_suspend(s, false, PA_SUSPEND_INTERNAL);
+
+ return ret;
+}
+