mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
sink: Introduce structure needed to consolidate virtual sink code
This patch introduces the vsink structure which holds all data needed by virtual sinks. This is in preparation of the consolidation of the virtual sink code. The input_to_master field of the sink will be moved to the vsink structure after the consolidation. Until all virtual sinks are converted, sink->input_to_master and sink->vsink->input_to_master must both be supported.
This commit is contained in:
parent
ed3d4f0837
commit
d18756fda9
4 changed files with 124 additions and 11 deletions
|
|
@ -293,7 +293,10 @@ static bool find_paired_master(struct userdata *u, struct filter *filter, pa_obj
|
|||
if (pa_streq(module_name, si->sink->module->name)) {
|
||||
/* Make sure we're not routing to another instance of
|
||||
* the same filter. */
|
||||
filter->sink_master = si->sink->input_to_master->sink;
|
||||
if (si->sink->vsink)
|
||||
filter->sink_master = si->sink->vsink->input_to_master->sink;
|
||||
else
|
||||
filter->sink_master = si->sink->input_to_master->sink;
|
||||
} else {
|
||||
filter->sink_master = si->sink;
|
||||
}
|
||||
|
|
@ -461,7 +464,10 @@ static void find_filters_for_module(struct userdata *u, pa_module *m, const char
|
|||
if (sink->module == m) {
|
||||
pa_assert(pa_sink_is_filter(sink));
|
||||
|
||||
fltr = filter_new(name, parameters, sink->input_to_master->sink, NULL);
|
||||
if (sink->vsink)
|
||||
fltr = filter_new(name, parameters, sink->vsink->input_to_master->sink, NULL);
|
||||
else
|
||||
fltr = filter_new(name, parameters, sink->input_to_master->sink, NULL);
|
||||
fltr->module_index = m->index;
|
||||
fltr->sink = sink;
|
||||
|
||||
|
|
|
|||
|
|
@ -1784,10 +1784,20 @@ bool pa_sink_input_may_move(pa_sink_input *i) {
|
|||
|
||||
static bool find_filter_sink_input(pa_sink_input *target, pa_sink *s) {
|
||||
unsigned PA_UNUSED i = 0;
|
||||
while (s && s->input_to_master) {
|
||||
if (s->input_to_master == target)
|
||||
return true;
|
||||
s = s->input_to_master->sink;
|
||||
|
||||
/* During consolidation, we have to support s->input_to_master and
|
||||
* s->vsink->input_to_master. The first will disappear after all
|
||||
* virtual sinks use the new code. */
|
||||
while (s && (s->input_to_master || (s->vsink && s->vsink->input_to_master))) {
|
||||
if (s->vsink) {
|
||||
if (s->vsink->input_to_master == target)
|
||||
return true;
|
||||
s = s->vsink->input_to_master->sink;
|
||||
} else {
|
||||
if (s->input_to_master == target)
|
||||
return true;
|
||||
s = s->input_to_master->sink;
|
||||
}
|
||||
pa_assert(i++ < 100);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -1799,8 +1809,11 @@ static bool is_filter_sink_moving(pa_sink_input *i) {
|
|||
if (!sink)
|
||||
return false;
|
||||
|
||||
while (sink->input_to_master) {
|
||||
sink = sink->input_to_master->sink;
|
||||
while (sink->input_to_master || (sink->vsink && sink->vsink->input_to_master)) {
|
||||
if (sink->vsink)
|
||||
sink = sink->vsink->input_to_master->sink;
|
||||
else
|
||||
sink = sink->input_to_master->sink;
|
||||
|
||||
if (!sink)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -287,6 +287,7 @@ pa_sink* pa_sink_new(
|
|||
s->inputs = pa_idxset_new(NULL, NULL);
|
||||
s->n_corked = 0;
|
||||
s->input_to_master = NULL;
|
||||
s->vsink = NULL;
|
||||
|
||||
s->reference_volume = s->real_volume = data->volume;
|
||||
pa_cvolume_reset(&s->soft_volume, s->sample_spec.channels);
|
||||
|
|
@ -1692,11 +1693,19 @@ bool pa_sink_has_filter_attached(pa_sink *s) {
|
|||
pa_sink *pa_sink_get_master(pa_sink *s) {
|
||||
pa_sink_assert_ref(s);
|
||||
|
||||
/* During consolidation, we have to support s->input_to_master and
|
||||
* s->vsink->input_to_master. The first will disappear after all
|
||||
* virtual sinks use the new code. */
|
||||
while (s && (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
|
||||
if (PA_UNLIKELY(!s->input_to_master))
|
||||
if (PA_UNLIKELY(s->vsink && !s->vsink->input_to_master))
|
||||
return NULL;
|
||||
if (PA_UNLIKELY(!s->vsink && !s->input_to_master))
|
||||
return NULL;
|
||||
|
||||
s = s->input_to_master->sink;
|
||||
if (s->input_to_master)
|
||||
s = s->input_to_master->sink;
|
||||
else
|
||||
s = s->vsink->input_to_master->sink;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
|
@ -1706,7 +1715,7 @@ pa_sink *pa_sink_get_master(pa_sink *s) {
|
|||
bool pa_sink_is_filter(pa_sink *s) {
|
||||
pa_sink_assert_ref(s);
|
||||
|
||||
return (s->input_to_master != NULL);
|
||||
return ((s->vsink != NULL) || (s->input_to_master != NULL));
|
||||
}
|
||||
|
||||
/* Called from main context */
|
||||
|
|
|
|||
|
|
@ -56,6 +56,90 @@ typedef void(*pa_sink_cb_t)(pa_sink *s);
|
|||
|
||||
typedef int (*pa_sink_get_mute_cb_t)(pa_sink *s, bool *mute);
|
||||
|
||||
/* Virtual sink structure */
|
||||
typedef struct pa_vsink {
|
||||
pa_msgobject parent; /* Message object */
|
||||
pa_sink *sink; /* A pointer to the virtual sink */
|
||||
pa_sink_input *input_to_master; /* Sink input to the master sink */
|
||||
pa_memblockq *memblockq; /* Memblockq of the virtual sink, may be NULL */
|
||||
size_t drop_bytes; /* Number of bytes to drop during sink_input_pop()
|
||||
* in sink input sample speci. Used during rewind
|
||||
* of fixed block size filters */
|
||||
|
||||
bool auto_desc; /* Automatically adapt description on move */
|
||||
const char *desc_head; /* Leading part of description string used for the
|
||||
* sink and sink input when auto_desc is true */
|
||||
const char *sink_type; /* Name for the type of sink, used as suffix for
|
||||
* the sink name if the name is derived from the
|
||||
* master sink. */
|
||||
bool autoloaded; /* True if the sink was not loaded manually */
|
||||
size_t max_chunk_size; /* Maximum chunk size in bytes that the filter will
|
||||
* accept, set to pa_mempool_block_size_max() by default */
|
||||
size_t fixed_block_size; /* Block size in frames for fixed block size filters,
|
||||
* 0 if block size is controlled by pulseaudio. */
|
||||
size_t fixed_input_block_size; /* Input block size in frames. If not 0, input data for
|
||||
* process_chunk() will always have the same size.
|
||||
* If not enough new data is available, the remaining
|
||||
* samples will be filled with history. */
|
||||
size_t overlap_frames; /* Some filters require old input samples in addtion to
|
||||
* the current data. The variable contains the number of
|
||||
* previous frames that will be passed to process_chunk().
|
||||
* The actual number of history frames may be variable if
|
||||
* the filter defines the get_current_overlap() function.
|
||||
* In this case, overlap_frames contains the maximum
|
||||
* number of history frames. */
|
||||
size_t max_request_frames_min; /* Minimum value for max_request in frames, 0 if unused */
|
||||
pa_usec_t max_latency; /* Maximum latency allowed for the sink, 0 if unused */
|
||||
int max_rewind; /* Maximum number of frames that the sink can rewind.
|
||||
* 0 means unlimited, -1 disables rewinding */
|
||||
|
||||
/* Callback to rewind the filter when pulseaudio requests it. Called from
|
||||
* I/O thread context. May be NULL */
|
||||
void (*rewind_filter)(pa_sink *s, size_t amount);
|
||||
|
||||
/* Callback to process a chunk of data by the filter. Called from I/O thread
|
||||
* context. May be NULL */
|
||||
void (*process_chunk)(uint8_t *src, uint8_t *dst, unsigned in_count, unsigned out_count, void *userdata);
|
||||
|
||||
/* Callback to communicate the max_rewind value to the filter. Called from
|
||||
* I/O thread context whenever the max_rewind value changes. May be NULL */
|
||||
void (*set_filter_max_rewind)(pa_sink_input *i, size_t amount);
|
||||
|
||||
/* Callback to retrieve additional latency caused by the filter. Called from
|
||||
* I/O thread context. May be NULL */
|
||||
pa_usec_t (*get_extra_latency)(pa_sink *s);
|
||||
|
||||
/* If defined, this function is called from the sink-input pop() callback
|
||||
* to retrieve the current number of history frames to include in the next
|
||||
* chunk. Called from I/O thread. */
|
||||
size_t (*get_current_overlap)(pa_sink_input *i);
|
||||
|
||||
/* If set and dest is valid, this function is called in the moving() callback
|
||||
* to change the description of sink and sink_input. Called from main context.
|
||||
* May be NULL */
|
||||
void (*set_description)(pa_sink_input *i, pa_sink *dest);
|
||||
|
||||
/* If set, this function will be called after update_filter_parameters() to
|
||||
* inform the filter of the block sizes that will be used. These may differ
|
||||
* from the sizes set in update_filter_parameters() if the function tries to
|
||||
* set an invalid combination of block sizes. Called from I/O thread. */
|
||||
void (*update_block_sizes)(size_t fixed_block_size, size_t fixed_input_block_size, size_t overlap_frames, void *userdata);
|
||||
|
||||
/* If set, this function is called in I/O thread context when an update of the
|
||||
* filter parameters is requested. May be NULL. The function must replace
|
||||
* the currently used parameter structure by the new structure in parameters
|
||||
* and return a pointer to the old structure so that it can be freed in the
|
||||
* main thread using free_filter_parameters(). If the old structure can be
|
||||
* re-used, the function may return NULL. update_filter_parameters() may
|
||||
* also modify the block sizes. */
|
||||
void *(*update_filter_parameters)(void *parameters, void *userdata);
|
||||
|
||||
/* Frees a parameter structure. May only be NULL, if update_filter_parameters()
|
||||
* is also NULL or if update_filter_parameters() always returns NULL. Called
|
||||
* from main thread. */
|
||||
void (*free_filter_parameters)(void *parameters);
|
||||
} pa_vsink;
|
||||
|
||||
struct pa_sink {
|
||||
pa_msgobject parent;
|
||||
|
||||
|
|
@ -88,6 +172,7 @@ struct pa_sink {
|
|||
pa_idxset *inputs;
|
||||
unsigned n_corked;
|
||||
pa_source *monitor_source;
|
||||
pa_vsink *vsink; /* non-NULL only for filter sinks */
|
||||
pa_sink_input *input_to_master; /* non-NULL only for filter sinks */
|
||||
|
||||
pa_volume_t base_volume; /* shall be constant */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue