diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/pulsecore/sink-input.c | 59 | ||||
| -rw-r--r-- | src/pulsecore/sink-input.h | 7 | 
2 files changed, 56 insertions, 10 deletions
| diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 5f79ab1e..744c47ff 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -92,6 +92,18 @@ void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, co      }  } +void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor) { +    pa_assert(data); +    pa_assert(volume_factor); + +    if (data->volume_factor_sink_is_set) +        pa_sw_cvolume_multiply(&data->volume_factor_sink, &data->volume_factor_sink, volume_factor); +    else { +        data->volume_factor_sink_is_set = TRUE; +        data->volume_factor_sink = *volume_factor; +    } +} +  void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {      pa_assert(data); @@ -176,7 +188,6 @@ int pa_sink_input_new(              pa_channel_map_init_extend(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);      } -    pa_return_val_if_fail(pa_channel_map_valid(&data->channel_map), -PA_ERR_INVALID);      pa_return_val_if_fail(pa_channel_map_compatible(&data->channel_map, &data->sample_spec), -PA_ERR_INVALID);      if (!data->volume_is_set) { @@ -185,15 +196,18 @@ int pa_sink_input_new(          data->save_volume = FALSE;      } -    pa_return_val_if_fail(pa_cvolume_valid(&data->volume), -PA_ERR_INVALID);      pa_return_val_if_fail(pa_cvolume_compatible(&data->volume, &data->sample_spec), -PA_ERR_INVALID);      if (!data->volume_factor_is_set)          pa_cvolume_reset(&data->volume_factor, data->sample_spec.channels); -    pa_return_val_if_fail(pa_cvolume_valid(&data->volume_factor), -PA_ERR_INVALID);      pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor, &data->sample_spec), -PA_ERR_INVALID); +    if (!data->volume_factor_sink_is_set) +        pa_cvolume_reset(&data->volume_factor_sink, data->sink->sample_spec.channels); + +    pa_return_val_if_fail(pa_cvolume_compatible(&data->volume_factor_sink, &data->sink->sample_spec), -PA_ERR_INVALID); +      if (!data->muted_is_set)          data->muted = FALSE; @@ -283,6 +297,7 @@ int pa_sink_input_new(          i->volume = data->volume;      i->volume_factor = data->volume_factor; +    i->volume_factor_sink = data->volume_factor_sink;      i->real_ratio = i->reference_ratio = data->volume;      pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);      pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels); @@ -576,7 +591,7 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i, pa_usec_t *sink_latency) {  /* Called from thread context */  void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa_memchunk *chunk, pa_cvolume *volume) { -    pa_bool_t do_volume_adj_here; +    pa_bool_t do_volume_adj_here, need_volume_factor_sink;      pa_bool_t volume_is_norm;      size_t block_size_max_sink, block_size_max_sink_input;      size_t ilength; @@ -624,6 +639,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p      do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);      volume_is_norm = pa_cvolume_is_norm(&i->thread_info.soft_volume) && !i->thread_info.muted; +    need_volume_factor_sink = !pa_cvolume_is_norm(&i->volume_factor_sink);      while (!pa_memblockq_is_readable(i->thread_info.render_memblockq)) {          pa_memchunk tchunk; @@ -655,6 +671,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p          while (tchunk.length > 0) {              pa_memchunk wchunk; +            pa_bool_t nvfs = need_volume_factor_sink;              wchunk = tchunk;              pa_memblock_ref(wchunk.memblock); @@ -666,18 +683,41 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p              if (do_volume_adj_here && !volume_is_norm) {                  pa_memchunk_make_writable(&wchunk, 0); -                if (i->thread_info.muted) +                if (i->thread_info.muted) {                      pa_silence_memchunk(&wchunk, &i->thread_info.sample_spec); -                else +                    nvfs = FALSE; + +                } else if (!i->thread_info.resampler && nvfs) { +                    pa_cvolume v; + +                    /* If we don't need a resampler we can merge the +                     * post and the pre volume adjustment into one */ + +                    pa_sw_cvolume_multiply(&v, &i->thread_info.soft_volume, &i->volume_factor_sink); +                    pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &v); +                    nvfs = FALSE; + +                } else                      pa_volume_memchunk(&wchunk, &i->thread_info.sample_spec, &i->thread_info.soft_volume);              } -            if (!i->thread_info.resampler) +            if (!i->thread_info.resampler) { + +                if (nvfs) { +                    pa_memchunk_make_writable(&wchunk, 0); +                    pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink); +                } +                  pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk); -            else { +            } else {                  pa_memchunk rchunk;                  pa_resampler_run(i->thread_info.resampler, &wchunk, &rchunk); +                if (nvfs) { +                    pa_memchunk_make_writable(&rchunk, 0); +                    pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); +                } +  /*                 pa_log_debug("pushing %lu", (unsigned long) rchunk.length); */                  if (rchunk.memblock) { @@ -1186,6 +1226,7 @@ int pa_sink_input_start_move(pa_sink_input *i) {      pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);      pa_sink_update_status(i->sink); +    pa_cvolume_remap(&i->volume_factor_sink, &i->sink->channel_map, &i->channel_map);      i->sink = NULL;      pa_sink_input_unref(i); @@ -1240,6 +1281,8 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {      i->save_sink = save;      pa_idxset_put(dest->inputs, pa_sink_input_ref(i), NULL); +    pa_cvolume_remap(&i->volume_factor_sink, &i->channel_map, &i->sink->channel_map); +      if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)          i->sink->n_corked++; diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 59eabe36..415a801f 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -100,6 +100,8 @@ struct pa_sink_input {      pa_cvolume volume_factor;      /* An internally used volume factor that can be used by modules to apply effects and suchlike without having that visible to the outside */      pa_cvolume soft_volume;        /* The internal software volume we apply to all PCM data while it passes through. Usually calculated as real_ratio * volume_factor */ +    pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to */ +      pa_bool_t muted:1;      /* if TRUE then the source we are connected to and/or the volume @@ -273,13 +275,13 @@ typedef struct pa_sink_input_new_data {      pa_sample_spec sample_spec;      pa_channel_map channel_map; -    pa_cvolume volume, volume_factor; +    pa_cvolume volume, volume_factor, volume_factor_sink;      pa_bool_t muted:1;      pa_bool_t sample_spec_is_set:1;      pa_bool_t channel_map_is_set:1; -    pa_bool_t volume_is_set:1, volume_factor_is_set:1; +    pa_bool_t volume_is_set:1, volume_factor_is_set:1, volume_factor_sink_is_set:1;      pa_bool_t muted_is_set:1;      pa_bool_t volume_is_absolute:1; @@ -292,6 +294,7 @@ void pa_sink_input_new_data_set_sample_spec(pa_sink_input_new_data *data, const  void pa_sink_input_new_data_set_channel_map(pa_sink_input_new_data *data, const pa_channel_map *map);  void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cvolume *volume);  void pa_sink_input_new_data_apply_volume_factor(pa_sink_input_new_data *data, const pa_cvolume *volume_factor); +void pa_sink_input_new_data_apply_volume_factor_sink(pa_sink_input_new_data *data, const pa_cvolume *volume_factor);  void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute);  void pa_sink_input_new_data_done(pa_sink_input_new_data *data); | 
