* consider absolute when the sink is in flat volume mode,
* relative otherwise. \since 0.9.20 */
- PA_STREAM_PASSTHROUGH = 0x80000U,
+ PA_STREAM_PASSTHROUGH = 0x80000U
/**< Used to tag content that will be rendered by passthrough sinks.
* The data will be left as is and not reformatted, resampled.
* \since 1.0 */
- PA_STREAM_START_RAMP_MUTED = 0x100000U
- /**< Used to tag content that the stream will be started ramp volume
- * muted so that you can nicely fade it in */
-
} pa_stream_flags_t;
/** \cond fulldocs */
#define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
#define PA_STREAM_RELATIVE_VOLUME PA_STREAM_RELATIVE_VOLUME
#define PA_STREAM_PASSTHROUGH PA_STREAM_PASSTHROUGH
-#define PA_STREAM_START_RAMP_MUTED PA_STREAM_START_RAMP_MUTED
/** \endcond */
/** \endcond */
-
-/** Volume ramp type
-*/
-typedef enum pa_volume_ramp_type {
- PA_VOLUME_RAMP_TYPE_LINEAR = 0, /**< linear */
- PA_VOLUME_RAMP_TYPE_LOGARITHMIC = 1, /**< logarithmic */
- PA_VOLUME_RAMP_TYPE_CUBIC = 2,
-} pa_volume_ramp_type_t;
-
-/** \cond fulldocs */
-#define PA_VOLUMER_RAMP_TYPE_LINEAR PA_VOLUMER_RAMP_TYPE_LINEAR
-#define PA_VOLUMER_RAMP_TYPE_LOGARITHMIC PA_VOLUMER_RAMP_TYPE_LOGARITHMIC
-#define PA_VOLUMER_RAMP_TYPE_CUBIC PA_VOLUMER_RAMP_TYPE_CUBIC
-/** \endcond */
-
PA_C_DECL_END
#endif
usec = pa_bytes_to_usec_round_up(size, from);
return pa_usec_to_bytes_round_up(usec, to);
}
-
-void calc_linear_integer_volume_no_mapping(int32_t [], float [], unsigned);
-void calc_linear_float_volume_no_mapping(float [], float [], unsigned);
-
-void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) {
- unsigned channel, padding;
-
- pa_assert(linear);
- pa_assert(volume);
-
- for (channel = 0; channel < nchannels; channel++)
- linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U);
-
- for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
- linear[channel] = linear[padding];
-}
-
-void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) {
- unsigned channel, padding;
-
- pa_assert(linear);
- pa_assert(volume);
-
- for (channel = 0; channel < nchannels; channel++)
- linear[channel] = volume[channel];
-
- for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
- linear[channel] = linear[padding];
-}
-
-typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels);
-
-static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = {
- [PA_SAMPLE_U8] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_ALAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_ULAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S16LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S16BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping,
- [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping,
- [PA_SAMPLE_S32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S24LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S24BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S24_32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
- [PA_SAMPLE_S24_32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping
-};
-
-static const unsigned format_sample_size_table[] = {
- [PA_SAMPLE_U8] = 1,
- [PA_SAMPLE_ALAW] = 1,
- [PA_SAMPLE_ULAW] = 1,
- [PA_SAMPLE_S16LE] = 2,
- [PA_SAMPLE_S16BE] = 2,
- [PA_SAMPLE_FLOAT32LE] = 4,
- [PA_SAMPLE_FLOAT32BE] = 4,
- [PA_SAMPLE_S32LE] = 4,
- [PA_SAMPLE_S32BE] = 4,
- [PA_SAMPLE_S24LE] = 3,
- [PA_SAMPLE_S24BE] = 3,
- [PA_SAMPLE_S24_32LE] = 4,
- [PA_SAMPLE_S24_32BE] = 4
-};
-
-float calc_volume_ramp_linear(pa_volume_ramp *);
-float calc_volume_ramp_logarithmic(pa_volume_ramp *);
-float calc_volume_ramp_cubic(pa_volume_ramp *);
-void pa_ramp_volume_multiply(float *, const pa_cvolume *, float);
-
-typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp *);
-
-static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = {
- [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear,
- [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic,
- [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic
-};
-
-float calc_volume_ramp_linear(pa_volume_ramp *ramp) {
-
- pa_assert(ramp);
- pa_assert(ramp->length > 0);
-
- /* basic linear interpolation */
- return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / ramp->length;
-}
-
-float calc_volume_ramp_logarithmic(pa_volume_ramp *ramp) {
-
- float x_val, s, e;
- long temp;
-
- pa_assert(ramp);
- pa_assert(ramp->length > 0);
-
- if (ramp->end > ramp->start) {
- temp = ramp->left;
- s = ramp->end;
- e = ramp->start;
- }
- else {
- temp = ramp->length - ramp->left;
- s = ramp->start;
- e = ramp->end;
- }
-
- x_val = temp == 0 ? 0.0 : pow((float)temp, 10);
-
- /* base 10 logarithmic interpolation */
- return s + x_val * (e - s) / pow((float)ramp->length, 10);
-}
-
-float calc_volume_ramp_cubic(pa_volume_ramp *ramp) {
-
- float x_val, s, e;
- long temp;
-
- pa_assert(ramp);
- pa_assert(ramp->length > 0);
-
- if (ramp->end > ramp->start) {
- temp = ramp->left;
- s = ramp->end;
- e = ramp->start;
- }
- else {
- temp = ramp->length - ramp->left;
- s = ramp->start;
- e = ramp->end;
- }
-
- x_val = temp == 0 ? 0.0 : cbrt((float)temp);
-
- /* cubic interpolation */
- return s + x_val * (e - s) / cbrt((float)ramp->length);
-}
-
-void pa_ramp_volume_multiply(float *dest, const pa_cvolume *volume, float ramp_vol) {
- unsigned i;
- float conv;
-
- pa_assert(dest);
- pa_assert(volume);
-
- /* multiplying ramp with volume with pa internal mapping */
- for (i = 0; i < volume->channels; i++) {
- conv = volume->values[i] / 0x10000U;
- conv = conv * conv * conv;
- dest[i] = ramp_vol * conv;
- }
-}
-
-void pa_volume_ramp_memchunk(
- pa_memchunk*c,
- const pa_sample_spec *spec,
- pa_volume_ramp *ramp,
- const pa_cvolume *volume) {
-
- void *ptr;
- volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING];
- float vol_adjusted[PA_CHANNELS_MAX + VOLUME_PADDING];
- pa_do_volume_func_t do_volume;
- long length_in_frames;
-
- pa_assert(c);
- pa_assert(spec);
- pa_assert(pa_frame_aligned(c->length, spec));
- pa_assert(ramp);
-
- length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels;
-
- if (pa_memblock_is_silence(c->memblock)) {
- ramp->length -= length_in_frames;
- return;
- }
-
- if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) {
- pa_log_warn("Unable to change volume of format");
- return;
- }
-
- do_volume = pa_get_volume_func(spec->format);
- pa_assert(do_volume);
-
- ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
-
- for (int i = 0; i < length_in_frames; i++) {
- ramp->curr = calc_volume_ramp_table[ramp->type] (ramp);
- pa_ramp_volume_multiply(vol_adjusted, volume, ramp->curr);
- calc_volume_table_no_mapping[spec->format] ((void *)linear, vol_adjusted, spec->channels);
-
- /* we only process one sample per iteration */
- do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels);
-
- ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels;
-
- if (ramp->left > 0)
- ramp->left--;
- }
-
- pa_memblock_release(c->memblock);
-}
pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length);
-/** A structure encapsulating a volume ramp */
-typedef struct pa_volume_ramp {
- pa_volume_ramp_type_t type;
- long length;
- long left;
- float start;
- float end;
- float curr;
- pa_cvolume end_mapped;
-} pa_volume_ramp;
-
typedef struct pa_mix_info {
pa_memchunk chunk;
pa_cvolume volume;
const pa_sample_spec *spec,
const pa_cvolume *volume);
-void pa_volume_ramp_memchunk(
- pa_memchunk*c,
- const pa_sample_spec *spec,
- pa_volume_ramp *ramp,
- const pa_cvolume *volume);
-
size_t pa_frame_align(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) PA_GCC_PURE;
reset_callbacks(i);
i->userdata = NULL;
- if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED) {
- i->ramp.type = PA_VOLUME_RAMP_TYPE_LINEAR;
- i->ramp.length = 0;
- i->ramp.left = 0;
- i->ramp.start = 0.0;
- i->ramp.end = 0.0;
- i->ramp.curr = 0.0;
- pa_cvolume_reset(&i->ramp.end_mapped, data->sample_spec.channels);
- pa_cvolume_set(&i->ramp.end_mapped, data->sample_spec.channels, PA_VOLUME_MUTED);
- }
- else {
- i->ramp.type = PA_VOLUME_RAMP_TYPE_LINEAR;
- i->ramp.length = 0;
- i->ramp.left = 0;
- i->ramp.start = 1.0;
- i->ramp.end = 1.0;
- i->ramp.curr = 1.0;
- pa_cvolume_reset(&i->ramp.end_mapped, data->sample_spec.channels);
- pa_cvolume_set(&i->ramp.end_mapped, data->sample_spec.channels, PA_VOLUME_NORM);
- }
-
i->thread_info.state = i->state;
i->thread_info.attached = FALSE;
pa_atomic_store(&i->thread_info.drained, 1);
i->thread_info.playing_for = 0;
i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
- i->thread_info.ramp = i->ramp;
-
pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0);
pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0);
pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink);
}
- /* check for possible volume ramp */
- if (i->thread_info.ramp.left > 0) {
- pa_cvolume volume_adj;
- pa_memchunk_make_writable(&wchunk, 0);
- volume_adj.channels = i->sample_spec.channels;
- pa_cvolume_set(&volume_adj, i->sample_spec.channels, PA_VOLUME_NORM);
- pa_volume_ramp_memchunk(&wchunk, &i->sample_spec, &(i->thread_info.ramp), &volume_adj);
- } else if (!pa_cvolume_is_norm(&(i->thread_info.ramp.end_mapped))) {
- pa_memchunk_make_writable(&wchunk, 0);
- pa_volume_memchunk(&wchunk, &i->sample_spec, &(i->thread_info.ramp.end_mapped));
- }
-
pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk);
} else {
pa_memchunk rchunk;
pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink);
}
- /* check for possible volume ramp */
- if (i->thread_info.ramp.left > 0) {
- pa_cvolume volume_adj;
- pa_memchunk_make_writable(&rchunk, 0);
- volume_adj.channels = i->sample_spec.channels;
- pa_cvolume_set(&volume_adj, i->sample_spec.channels, PA_VOLUME_NORM);
- pa_volume_ramp_memchunk(&rchunk, &i->sample_spec, &(i->thread_info.ramp), &volume_adj);
- } else if (!pa_cvolume_is_norm(&(i->thread_info.ramp.end_mapped))) {
- pa_memchunk_make_writable(&rchunk, 0);
- pa_volume_memchunk(&rchunk, &i->sample_spec, &(i->thread_info.ramp.end_mapped));
- }
-
pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk);
pa_memblock_unref(rchunk.memblock);
}
pa_subscription_post(i->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
-/* Called from main thread */
-void pa_sink_input_set_volume_ramp(
- pa_sink_input *i,
- const pa_cvolume *volume,
- uint32_t time,
- uint8_t type,
- pa_bool_t send_msg,
- pa_bool_t save) {
-
- float temp;
-
- pa_sink_input_assert_ref(i);
- pa_assert_ctl_context();
- pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
- pa_assert(!volume || pa_cvolume_valid(volume));
- pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
-
- i->ramp.type = type;
- i->ramp.length = time * i->sink->default_sample_rate / 1000;
- i->ramp.left = i->ramp.length;
- i->ramp.start = i->ramp.end;
- i->ramp.end_mapped = *volume;
- /* scale to pulse internal mapping */
- temp = volume->values[0] / (float)0x10000U;
- i->ramp.end = temp * temp * temp;
-
- pa_log_debug("ramp length is %d ms, in samples %ld", time, i->ramp.length);
-
- /* This tells the sink that volume ramp changed */
- if (send_msg)
- pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
-}
-
/* Called from main context */
static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
pa_sink_input_assert_ref(i);
}
return 0;
- case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP:
- /* we have ongoing ramp where we take current start values */
- if (i->thread_info.ramp.left > 0)
- i->ramp.start = i->thread_info.ramp.curr;
- i->thread_info.ramp = i->ramp;
- return 0;
-
case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE:
if (i->thread_info.muted != i->muted) {
i->thread_info.muted = i->muted;
PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256,
PA_SINK_INPUT_NO_CREATE_ON_SUSPEND = 512,
PA_SINK_INPUT_KILL_ON_SUSPEND = 1024,
- PA_SINK_INPUT_PASSTHROUGH = 2048,
- PA_SINK_INPUT_START_RAMP_MUTED = 4096,
+ PA_SINK_INPUT_PASSTHROUGH = 2048
} pa_sink_input_flags_t;
struct pa_sink_input {
* this.*/
pa_bool_t save_sink:1, save_volume:1, save_muted:1;
- /* for volume ramps */
- pa_volume_ramp ramp;
-
pa_resample_method_t requested_resample_method, actual_resample_method;
/* Returns the chunk of audio data and drops it from the
pa_usec_t requested_sink_latency;
pa_hashmap *direct_outputs;
-
- pa_volume_ramp ramp;
} thread_info;
void *userdata;
PA_SINK_INPUT_MESSAGE_SET_STATE,
PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY,
PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY,
- PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP,
PA_SINK_INPUT_MESSAGE_MAX
};
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save);
pa_bool_t pa_sink_input_get_mute(pa_sink_input *i);
-void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume *volume, uint32_t time, uint8_t type, pa_bool_t send_msg, pa_bool_t save);
-
void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t mode, pa_proplist *p);
pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i);
&s->sample_spec,
0);
- s->ramp.type = PA_VOLUME_RAMP_TYPE_LINEAR;
- s->ramp.length = 0;
- s->ramp.left = 0;
- s->ramp.start = 1.0;
- s->ramp.end = 1.0;
- s->ramp.curr = 1.0;
- pa_cvolume_reset(&s->ramp.end_mapped, data->sample_spec.channels);
- pa_cvolume_set(&s->ramp.end_mapped, data->sample_spec.channels, PA_VOLUME_NORM);
-
s->thread_info.rtpoll = NULL;
s->thread_info.inputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
s->thread_info.soft_volume = s->soft_volume;
s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
- s->thread_info.ramp = s->ramp;
-
/* FIXME: This should probably be moved to pa_sink_put() */
pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
result,
&s->sample_spec,
result->length);
- } else if (!pa_cvolume_is_norm(&volume) || !pa_cvolume_is_norm(&(s->thread_info.ramp.end_mapped)) || s->thread_info.ramp.left > 0) {
- pa_memchunk_make_writable(result, 0);
- if (s->thread_info.ramp.left > 0)
- pa_volume_ramp_memchunk(result, &s->sample_spec, &(s->thread_info.ramp), &volume);
- else {
- if (!pa_cvolume_is_norm(&(s->thread_info.ramp.end_mapped)))
- pa_sw_cvolume_multiply(&volume, &volume, &(s->thread_info.ramp.end_mapped));
-
- pa_volume_memchunk(result, &s->sample_spec, &volume);
- }
- }
+ } else if (!pa_cvolume_is_norm(&volume)) {
+ pa_memchunk_make_writable(result, 0);
+ pa_volume_memchunk(result, &s->sample_spec, &volume);
+ }
} else {
void *ptr;
result->memblock = pa_memblock_new(s->core->mempool, length);
&s->sample_spec,
&s->thread_info.soft_volume,
s->thread_info.soft_muted);
-
- if (!pa_cvolume_is_norm(&(s->thread_info.ramp.end_mapped)) || s->thread_info.ramp.left > 0) {
- pa_cvolume volume;
- pa_cvolume_set(&volume, s->sample_spec.channels, PA_VOLUME_NORM);
- if (s->thread_info.ramp.left > 0)
- pa_volume_ramp_memchunk(result, &s->sample_spec, &(s->thread_info.ramp), &volume);
- else
- pa_volume_memchunk(result, &s->sample_spec, &(s->thread_info.ramp.end_mapped));
- }
-
pa_memblock_release(result->memblock);
result->index = 0;
if (vchunk.length > length)
vchunk.length = length;
- if (!pa_cvolume_is_norm(&volume) || !pa_cvolume_is_norm(&(s->thread_info.ramp.end_mapped)) || s->thread_info.ramp.left > 0) {
- pa_memchunk_make_writable(&vchunk, 0);
- if (s->thread_info.ramp.left > 0)
- pa_volume_ramp_memchunk(&vchunk, &s->sample_spec, &(s->thread_info.ramp), &volume);
- else {
- if (!pa_cvolume_is_norm(&(s->thread_info.ramp.end_mapped)))
- pa_sw_cvolume_multiply(&volume, &volume, &(s->thread_info.ramp.end_mapped));
-
- pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
- }
- }
+ if (!pa_cvolume_is_norm(&volume)) {
+ pa_memchunk_make_writable(&vchunk, 0);
+ pa_volume_memchunk(&vchunk, &s->sample_spec, &volume);
+ }
pa_memchunk_memcpy(target, &vchunk);
pa_memblock_unref(vchunk.memblock);
&s->thread_info.soft_volume,
s->thread_info.soft_muted);
- if (!pa_cvolume_is_norm(&(s->thread_info.ramp.end_mapped)) || s->thread_info.ramp.left > 0) {
- pa_cvolume volume;
- pa_cvolume_set(&volume, s->sample_spec.channels, PA_VOLUME_NORM);
- if (s->thread_info.ramp.left > 0)
- pa_volume_ramp_memchunk(target, &s->sample_spec, &(s->thread_info.ramp), &volume);
- else
- pa_volume_memchunk(target, &s->sample_spec, &(s->thread_info.ramp.end_mapped));
- }
-
pa_memblock_release(target->memblock);
}
pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq, PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL) == 0);
}
-/* Called from main thread */
-void pa_sink_set_volume_ramp(
- pa_sink *s,
- const pa_cvolume *volume,
- uint32_t time,
- uint8_t type,
- pa_bool_t send_msg,
- pa_bool_t save) {
-
- float temp;
-
- pa_sink_assert_ref(s);
- pa_assert_ctl_context();
- pa_assert(PA_SINK_IS_LINKED(s->state));
- pa_assert(!volume || pa_cvolume_valid(volume));
- pa_assert(!volume || volume->channels == 1 || pa_cvolume_compatible(volume, &s->sample_spec));
-
- /* make sure we don't change the volume when a PASSTHROUGH input is connected ...
- * ... *except* if we're being invoked to reset the volume to ensure 0 dB gain */
- if (pa_sink_is_passthrough(s)) {
- pa_log_warn("Cannot do volume ramp, Sink is connected to PASSTHROUGH input");
- return;
- }
-
- s->ramp.type = type;
- /* ms to samples */
- s->ramp.length = time * s->default_sample_rate / 1000;
- s->ramp.left = s->ramp.length;
- s->ramp.start = s->ramp.end;
- s->ramp.end_mapped = *volume;
- /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */
- temp = volume->values[0] / (float)0x10000U;
- s->ramp.end = temp * temp * temp;
-
- pa_log_debug("ramp length is %d ms, in samples %ld", time, s->ramp.length);
-
- /* This tells the sink that volume ramp changed */
- if (send_msg)
- pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
-}
-
/* Called from the io thread if sync volume is used, otherwise from the main thread.
* Only to be called by sink implementor */
void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
s->thread_info.soft_volume = s->soft_volume;
pa_sink_request_rewind(s, (size_t) -1);
}
+
/* Fall through ... */
case PA_SINK_MESSAGE_SYNC_VOLUMES:
sync_input_volumes_within_thread(s);
return 0;
- case PA_SINK_MESSAGE_SET_VOLUME_RAMP:
- /* we have ongoing ramp where we take current start values */
- if (s->thread_info.ramp.left > 0)
- s->ramp.start = s->thread_info.ramp.curr;
- s->thread_info.ramp = s->ramp;
- return 0;
-
case PA_SINK_MESSAGE_GET_VOLUME:
if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) {
pa_cvolume saved_volume;
pa_bool_t saved_save_volume:1;
- /* for volume ramps */
- pa_volume_ramp ramp;
-
pa_asyncmsgq *asyncmsgq;
pa_memchunk silence;
uint32_t volume_change_safety_margin;
/* Usec delay added to all volume change events, may be negative. */
int32_t volume_change_extra_delay;
-
- pa_volume_ramp ramp;
} thread_info;
void *userdata;
PA_SINK_MESSAGE_SET_MAX_REQUEST,
PA_SINK_MESSAGE_SET_PORT,
PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE,
- PA_SINK_MESSAGE_SET_VOLUME_RAMP,
PA_SINK_MESSAGE_MAX
} pa_sink_message_t;
void pa_sink_set_mute(pa_sink *sink, pa_bool_t mute, pa_bool_t save);
pa_bool_t pa_sink_get_mute(pa_sink *sink, pa_bool_t force_refresh);
-void pa_sink_set_volume_ramp(pa_sink *s, const pa_cvolume *volume, uint32_t time, uint8_t type, pa_bool_t send_msg, pa_bool_t save);
-
pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p);
int pa_sink_set_port(pa_sink *s, const char *name, pa_bool_t save);