X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Faudio_output%2Ffilters.c;h=796da1f15d89a2ee933f8cf631f14bb4d8a916f6;hb=8eae542ad94652396035ee70920ca2ab107033ed;hp=bd4dbbbd892e343657d3c403e8770dd1cfe4a64a;hpb=3a2ba96b99e5ea08212759e5c5845f6054584f03;p=vlc diff --git a/src/audio_output/filters.c b/src/audio_output/filters.c index bd4dbbbd89..796da1f15d 100644 --- a/src/audio_output/filters.c +++ b/src/audio_output/filters.c @@ -42,44 +42,47 @@ #include #include "aout_internal.h" -/***************************************************************************** - * FindFilter: find an audio filter for a specific transformation - *****************************************************************************/ -static filter_t * FindFilter( vlc_object_t *obj, - const audio_sample_format_t *infmt, - const audio_sample_format_t *outfmt ) +static filter_t *CreateFilter (vlc_object_t *obj, const char *type, + const char *name, filter_owner_sys_t *owner, + const audio_sample_format_t *infmt, + const audio_sample_format_t *outfmt) { - static const char typename[] = "audio converter"; - const char *type = "audio converter", *name = NULL; - filter_t * p_filter; - - p_filter = vlc_custom_create( obj, sizeof(*p_filter), typename ); - - if ( p_filter == NULL ) return NULL; - - p_filter->fmt_in.audio = *infmt; - p_filter->fmt_in.i_codec = infmt->i_format; - p_filter->fmt_out.audio = *outfmt; - p_filter->fmt_out.i_codec = outfmt->i_format; + filter_t *filter = vlc_custom_create (obj, sizeof (*filter), type); + if (unlikely(filter == NULL)) + return NULL; - if( infmt->i_format == outfmt->i_format - && infmt->i_physical_channels == outfmt->i_physical_channels - && infmt->i_original_channels == outfmt->i_original_channels ) + filter->p_owner = owner; + filter->fmt_in.audio = *infmt; + filter->fmt_in.i_codec = infmt->i_format; + filter->fmt_out.audio = *outfmt; + filter->fmt_out.i_codec = outfmt->i_format; + filter->p_module = module_need (filter, type, name, false); + if (filter->p_module == NULL) { - assert( infmt->i_rate != outfmt->i_rate ); - type = "audio resampler"; - name = "$audio-resampler"; + /* If probing failed, formats shall not have been modified. */ + assert (AOUT_FMTS_IDENTICAL(&filter->fmt_in.audio, infmt)); + assert (AOUT_FMTS_IDENTICAL(&filter->fmt_out.audio, outfmt)); + vlc_object_release (filter); + filter = NULL; } + else + assert (filter->pf_audio_filter != NULL); + return filter; +} - p_filter->p_module = module_need( p_filter, type, name, false ); - if ( p_filter->p_module == NULL ) - { - vlc_object_release( p_filter ); - return NULL; - } +static filter_t *FindConverter (vlc_object_t *obj, + const audio_sample_format_t *infmt, + const audio_sample_format_t *outfmt) +{ + return CreateFilter (obj, "audio converter", NULL, NULL, infmt, outfmt); +} - assert( p_filter->pf_audio_filter ); - return p_filter; +static filter_t *FindResampler (vlc_object_t *obj, + const audio_sample_format_t *infmt, + const audio_sample_format_t *outfmt) +{ + return CreateFilter (obj, "audio resampler", "$audio-resampler", NULL, + infmt, outfmt); } /** @@ -105,7 +108,7 @@ static filter_t *TryFormat (vlc_object_t *obj, vlc_fourcc_t codec, output.i_format = codec; aout_FormatPrepare (&output); - filter_t *filter = FindFilter (obj, fmt, &output); + filter_t *filter = FindConverter (obj, fmt, &output); if (filter != NULL) *fmt = output; return filter; @@ -134,23 +137,15 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, * and cannot do. This seems hardly avoidable, the conversion problem need * to be reduced somehow. */ audio_sample_format_t input = *infmt; - bool same_codec = infmt->i_format == outfmt->i_format; - bool same_rate = infmt->i_rate == outfmt->i_rate; - bool same_mix = infmt->i_physical_channels == outfmt->i_physical_channels - && infmt->i_original_channels == outfmt->i_original_channels; unsigned n = 0; /* Encapsulate or decode non-linear formats */ - if (!AOUT_FMT_LINEAR(infmt) && !same_codec) + if (!AOUT_FMT_LINEAR(infmt) && infmt->i_format != outfmt->i_format) { if (n == max) goto overflow; - filter_t *f = NULL; - if (!AOUT_FMT_LINEAR(outfmt)) - f = TryFormat (obj, outfmt->i_format, &input); - if (f == NULL) - f = TryFormat (obj, VLC_CODEC_FI32, &input); + filter_t *f = TryFormat (obj, VLC_CODEC_S32N, &input); if (f == NULL) f = TryFormat (obj, VLC_CODEC_FL32, &input); if (f == NULL) @@ -161,16 +156,12 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, } filters[n++] = f; - same_codec = input.i_format == outfmt->i_format; } - assert (AOUT_FMT_LINEAR(&input)); - /* Conversion cannot be done in foreign endianess. */ - /* TODO: convert to native endian if needed */ - /* Remix channels */ - if (!same_mix) + if (infmt->i_physical_channels != outfmt->i_physical_channels + || infmt->i_original_channels != outfmt->i_original_channels) { /* Remixing currently requires FL32... TODO: S16N */ if (input.i_format != VLC_CODEC_FL32) { @@ -186,7 +177,6 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, } filters[n++] = f; - same_codec = input.i_format == outfmt->i_format; } if (n == max) @@ -199,7 +189,7 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, output.i_original_channels = outfmt->i_original_channels; aout_FormatPrepare (&output); - filter_t *f = FindFilter (obj, &input, &output); + filter_t *f = FindConverter (obj, &input, &output); if (f == NULL) { msg_Err (obj, "cannot find %s for conversion pipeline", @@ -209,11 +199,10 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, input = output; filters[n++] = f; - //same_mix = true; } /* Resample */ - if (!same_rate) + if (input.i_rate != outfmt->i_rate) { /* Resampling works with any linear format, but may be ugly. */ if (n == max) goto overflow; @@ -221,7 +210,7 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, audio_sample_format_t output = input; output.i_rate = outfmt->i_rate; - filter_t *f = FindFilter (obj, &input, &output); + filter_t *f = FindConverter (obj, &input, &output); if (f == NULL) { msg_Err (obj, "cannot find %s for conversion pipeline", @@ -231,10 +220,10 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, input = output; filters[n++] = f; - //same_rate = true; } - if (!same_codec) + /* Format */ + if (input.i_format != outfmt->i_format) { if (max == 0) goto overflow; @@ -247,11 +236,8 @@ static int aout_FiltersPipelineCreate(vlc_object_t *obj, filter_t **filters, goto error; } filters[n++] = f; - //same_codec = true; } - /* TODO: convert to foreign endian if needed */ - msg_Dbg (obj, "conversion pipeline complete"); *count += n; return 0; @@ -265,15 +251,6 @@ error: return -1; } -#define aout_FiltersPipelineCreate(obj,f,n,m,i,o) \ - aout_FiltersPipelineCreate(VLC_OBJECT(obj),f,n,m,i,o) - -static inline bool ChangeFiltersString (vlc_object_t *aout, const char *var, - const char *filter, bool add) -{ - return aout_ChangeFilterString (aout, aout, var, filter, add); -} - /** * Filters an audio buffer through a chain of filters. */ @@ -292,250 +269,213 @@ static block_t *aout_FiltersPipelinePlay(filter_t *const *filters, return block; } +#define AOUT_MAX_FILTERS 10 + +struct aout_filters +{ + filter_t *rate_filter; /**< The filter adjusting samples count + (either the scaletempo filter or a resampler) */ + filter_t *resampler; /**< The resampler */ + int resampling; /**< Current resampling (Hz) */ + + unsigned count; /**< Number of filters */ + filter_t *tab[AOUT_MAX_FILTERS]; /**< Configured user filters + (e.g. equalization) and their conversions */ +}; + /** Callback for visualization selection */ -static int VisualizationCallback (vlc_object_t *obj, char const *var, +static int VisualizationCallback (vlc_object_t *obj, const char *var, vlc_value_t oldval, vlc_value_t newval, void *data) { - audio_output_t *aout = (audio_output_t *)obj; const char *mode = newval.psz_string; if (!*mode) - { - ChangeFiltersString (obj, "audio-visual", "goom", false); - ChangeFiltersString (obj, "audio-visual", "visual", false); - ChangeFiltersString (obj, "audio-visual", "projectm", false); - ChangeFiltersString (obj, "audio-visual", "vsxu", false); - } - else if (!strcmp ("goom", mode)) - { - ChangeFiltersString (obj, "audio-visual", "visual", false ); - ChangeFiltersString (obj, "audio-visual", "goom", true ); - ChangeFiltersString (obj, "audio-visual", "projectm", false ); - ChangeFiltersString (obj, "audio-visual", "vsxu", false); - } - else if (!strcmp ("projectm", mode)) - { - ChangeFiltersString (obj, "audio-visual", "visual", false); - ChangeFiltersString (obj, "audio-visual", "goom", false); - ChangeFiltersString (obj, "audio-visual", "projectm", true); - ChangeFiltersString (obj, "audio-visual", "vsxu", false); - } - else if (!strcmp ("vsxu", mode)) - { - ChangeFiltersString (obj, "audio-visual", "visual", false); - ChangeFiltersString (obj, "audio-visual", "goom", false); - ChangeFiltersString (obj, "audio-visual", "projectm", false); - ChangeFiltersString (obj, "audio-visual", "vsxu", true); - } - else + mode = "none"; + /* FIXME: This ugly hack enforced by visual effect-list, as is the need for + * separate "visual" (external) and "audio-visual" (internal) variables... + * The visual plugin should have one submodule per effect instead. */ + if (strcasecmp (mode, "none") && strcasecmp (mode, "goom") + && strcasecmp (mode, "projectm") && strcasecmp (mode, "vsxu") + && strcasecmp (mode, "glspectrum")) { var_Create (obj, "effect-list", VLC_VAR_STRING); var_SetString (obj, "effect-list", mode); - - ChangeFiltersString (obj, "audio-visual", "goom", false); - ChangeFiltersString (obj, "audio-visual", "visual", true); - ChangeFiltersString (obj, "audio-visual", "projectm", false); + mode = "visual"; } - aout_InputRequestRestart (aout); + var_SetString (obj, "audio-visual", mode); + aout_InputRequestRestart ((audio_output_t *)obj); (void) var; (void) oldval; (void) data; return VLC_SUCCESS; } -static int EqualizerCallback (vlc_object_t *obj, char const *var, +static int EqualizerCallback (vlc_object_t *obj, const char *var, vlc_value_t oldval, vlc_value_t newval, void *data) { - audio_output_t *aout = (audio_output_t *)obj; - char *mode = newval.psz_string; - bool ret; - - if (!*mode) - ret = ChangeFiltersString (obj, "audio-filter", "equalizer", false); - else + const char *val = newval.psz_string; + if (!strcmp("equalizer", var) && *val) { var_Create (obj, "equalizer-preset", VLC_VAR_STRING); - var_SetString (obj, "equalizer-preset", mode); - ret = ChangeFiltersString (obj, "audio-filter", "equalizer", true); + var_SetString (obj, "equalizer-preset", val); } - /* That sucks */ - if (ret) - aout_InputRequestRestart (aout); + if (aout_ChangeFilterString (obj, obj, "audio-filter", "equalizer", *val)) + aout_InputRequestRestart ((audio_output_t *)obj); /* <- That sucks! */ + (void) var; (void) oldval; (void) data; return VLC_SUCCESS; } -static vout_thread_t *RequestVout (void *data, vout_thread_t *vout, - video_format_t *fmt, bool recycle) -{ - audio_output_t *aout = data; - vout_configuration_t cfg = { - .vout = vout, - .input = NULL, - .change_fmt = true, - .fmt = fmt, - .dpb_size = 1, - }; - - (void) recycle; - return vout_Request (aout, &cfg); -} - vout_thread_t *aout_filter_RequestVout (filter_t *filter, vout_thread_t *vout, video_format_t *fmt) { - /* NOTE: This only works from audio output. + /* NOTE: This only works from aout_filters_t. * If you want to use visualization filters from another place, you will * need to add a new pf_aout_request_vout callback or store a pointer * to aout_request_vout_t inside filter_t (i.e. a level of indirection). */ - aout_owner_t *owner = aout_owner ((audio_output_t *)filter->p_parent); - aout_request_vout_t *req = &owner->request_vout; + const aout_request_vout_t *req = (void *)filter->p_owner; + char *visual = var_InheritString (filter->p_parent, "audio-visual"); + bool recycle = (visual != NULL) && strcasecmp(visual, "none"); + free (visual); - return req->pf_request_vout (req->p_private, vout, fmt, - owner->recycle_vout); + return req->pf_request_vout (req->p_private, vout, fmt, recycle); } -static filter_t *CreateFilter (vlc_object_t *parent, const char *name, - const audio_sample_format_t *restrict infmt, - const audio_sample_format_t *restrict outfmt, - bool visu) +static int AppendFilter(vlc_object_t *obj, const char *type, const char *name, + aout_filters_t *restrict filters, const void *owner, + audio_sample_format_t *restrict infmt, + const audio_sample_format_t *restrict outfmt) { - filter_t *filter = vlc_custom_create (parent, sizeof (*filter), - "audio filter"); - if (unlikely(filter == NULL)) - return NULL; - - /*filter->p_owner = NOT NEEDED;*/ - filter->fmt_in.i_codec = infmt->i_format; - filter->fmt_in.audio = *infmt; - filter->fmt_out.i_codec = outfmt->i_format; - filter->fmt_out.audio = *outfmt; - - if (!visu) + const unsigned max = sizeof (filters->tab) / sizeof (filters->tab[0]); + if (filters->count >= max) { - filter->p_module = module_need (filter, "audio filter", name, true); - if (filter->p_module != NULL) - return filter; + msg_Err (obj, "maximum of %u filters reached", max); + return -1; + } - /* If probing failed, formats shall not have been modified. */ - assert (AOUT_FMTS_IDENTICAL(&filter->fmt_in.audio, infmt)); - assert (AOUT_FMTS_IDENTICAL(&filter->fmt_out.audio, outfmt)); + filter_t *filter = CreateFilter (obj, type, name, + (void *)owner, infmt, outfmt); + if (filter == NULL) + { + msg_Err (obj, "cannot add user %s \"%s\" (skipped)", type, name); + return -1; } - filter->p_module = module_need (filter, "visualization2", name, true); - if (filter->p_module != NULL) - return filter; + /* convert to the filter input format if necessary */ + if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count, + max - 1, infmt, &filter->fmt_in.audio)) + { + msg_Err (filter, "cannot add user %s \"%s\" (skipped)", type, name); + module_unneed (filter, filter->p_module); + vlc_object_release (filter); + return -1; + } - vlc_object_release (filter); - return NULL; + assert (filters->count < max); + filters->tab[filters->count] = filter; + filters->count++; + *infmt = filter->fmt_out.audio; + return 0; } +#undef aout_FiltersNew /** - * Sets up the audio filters. + * Sets a chain of audio filters up. + * \param obj parent object for the filters + * \param infmt chain input format [IN] + * \param outfmt chain output format [IN] + * \param request_vout visualization video output request callback + * \return a filters chain or NULL on failure + * + * \note + * *request_vout (if not NULL) must remain valid until aout_FiltersDelete(). + * + * \bug + * If request_vout is non NULL, obj is assumed to be an audio_output_t pointer. */ -int aout_FiltersNew (audio_output_t *aout, - const audio_sample_format_t *restrict infmt, - const audio_sample_format_t *restrict outfmt, - const aout_request_vout_t *request_vout) +aout_filters_t *aout_FiltersNew (vlc_object_t *obj, + const audio_sample_format_t *restrict infmt, + const audio_sample_format_t *restrict outfmt, + const aout_request_vout_t *request_vout) { - aout_owner_t *owner = aout_owner (aout); + aout_filters_t *filters = malloc (sizeof (*filters)); + if (unlikely(filters == NULL)) + return NULL; + + filters->rate_filter = NULL; + filters->resampler = NULL; + filters->resampling = 0; + filters->count = 0; /* Prepare format structure */ - aout_FormatPrint (aout, "input", infmt); + aout_FormatPrint (obj, "input", infmt); audio_sample_format_t input_format = *infmt; audio_sample_format_t output_format = *outfmt; - /* Now add user filters */ - owner->nb_filters = 0; - owner->rate_filter = NULL; - owner->resampler = NULL; + /* Callbacks (before reading values and also before return statement) */ + if (request_vout != NULL) + { + var_AddCallback (obj, "equalizer", EqualizerCallback, NULL); + var_AddCallback (obj, "equalizer-bands", EqualizerCallback, NULL); + var_AddCallback (obj, "visual", VisualizationCallback, NULL); - var_AddCallback (aout, "visual", VisualizationCallback, NULL); - var_AddCallback (aout, "equalizer", EqualizerCallback, NULL); + var_TriggerCallback( obj, "equalizer-bands" ); + } + /* Now add user filters */ if (!AOUT_FMT_LINEAR(outfmt)) - return 0; - - const char *scaletempo = - var_InheritBool (aout, "audio-time-stretch") ? "scaletempo" : NULL; - char *filters = var_InheritString (aout, "audio-filter"); - char *visual = var_InheritString (aout, "audio-visual"); - - if (request_vout != NULL) - owner->request_vout = *request_vout; - else - { - owner->request_vout.pf_request_vout = RequestVout; - owner->request_vout.p_private = aout; + { /* Non-linear output: just convert formats, no filters/visu */ + if (!AOUT_FMTS_IDENTICAL(infmt, outfmt)) + { + aout_FormatsPrint (obj, "pass-through:", infmt, outfmt); + filters->tab[0] = FindConverter(obj, infmt, outfmt); + if (filters->tab[0] == NULL) + { + msg_Err (obj, "cannot setup pass-through"); + goto error; + } + filters->count++; + } + return filters; } - owner->recycle_vout = (visual != NULL) && *visual; /* parse user filter lists */ - const char *list[AOUT_MAX_FILTERS]; - unsigned n = 0; - - if (scaletempo != NULL) - list[n++] = scaletempo; - if (filters != NULL) + if (var_InheritBool (obj, "audio-time-stretch")) { - char *p = filters, *name; - while ((name = strsep (&p, " :")) != NULL && n < AOUT_MAX_FILTERS) - list[n++] = name; + if (AppendFilter(obj, "audio filter", "scaletempo", + filters, NULL, &input_format, &output_format) == 0) + filters->rate_filter = filters->tab[filters->count - 1]; } - if (visual != NULL && n < AOUT_MAX_FILTERS) - list[n++] = visual; - for (unsigned i = 0; i < n; i++) + char *str = var_InheritString (obj, "audio-filter"); + if (str != NULL) { - const char *name = list[i]; - - if (owner->nb_filters >= AOUT_MAX_FILTERS) + char *p = str, *name; + while ((name = strsep (&p, " :")) != NULL) { - msg_Err (aout, "maximum of %u filters reached", AOUT_MAX_FILTERS); - msg_Err (aout, "cannot add user filter %s (skipped)", name); - break; + AppendFilter(obj, "audio filter", name, filters, + NULL, &input_format, &output_format); } + free (str); + } - filter_t *filter = CreateFilter (VLC_OBJECT(aout), name, - &input_format, &output_format, - name == visual); - if (filter == NULL) - { - msg_Err (aout, "cannot add user filter %s (skipped)", name); - continue; - } - - /* convert to the filter input format if necessary */ - if (aout_FiltersPipelineCreate (aout, owner->filters, - &owner->nb_filters, - AOUT_MAX_FILTERS - 1, - &input_format, &filter->fmt_in.audio)) - { - msg_Err (aout, "cannot add user filter %s (skipped)", name); - module_unneed (filter, filter->p_module); - vlc_object_release (filter); - continue; - } - - assert (owner->nb_filters < AOUT_MAX_FILTERS); - owner->filters[owner->nb_filters++] = filter; - input_format = filter->fmt_out.audio; - - if (name == scaletempo) - owner->rate_filter = filter; + if (request_vout != NULL) + { + char *visual = var_InheritString (obj, "audio-visual"); + if (visual != NULL && strcasecmp (visual, "none")) + AppendFilter(obj, "visualization", visual, filters, + request_vout, &input_format, &output_format); + free (visual); } - free (visual); - free (filters); /* convert to the output format (minus resampling) if necessary */ output_format.i_rate = input_format.i_rate; - if (aout_FiltersPipelineCreate (aout, owner->filters, &owner->nb_filters, - AOUT_MAX_FILTERS, - &input_format, &output_format)) + if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count, + AOUT_MAX_FILTERS, &input_format, &output_format)) { - msg_Err (aout, "cannot setup filtering pipeline"); + msg_Err (obj, "cannot setup filtering pipeline"); goto error; } input_format = output_format; @@ -543,78 +483,69 @@ int aout_FiltersNew (audio_output_t *aout, /* insert the resampler */ output_format.i_rate = outfmt->i_rate; assert (AOUT_FMTS_IDENTICAL(&output_format, outfmt)); - - unsigned rate_bak = input_format.i_rate; - if (output_format.i_rate == input_format.i_rate) - /* For historical reasons, a different rate is required to probe - * resampling filters. */ - input_format.i_rate++; - owner->resampler = FindFilter (VLC_OBJECT(aout), &input_format, - &output_format); - if (owner->resampler == NULL) + filters->resampler = FindResampler (obj, &input_format, + &output_format); + if (filters->resampler == NULL && input_format.i_rate != outfmt->i_rate) { - msg_Err (aout, "cannot setup a resampler"); + msg_Err (obj, "cannot setup a resampler"); goto error; } - owner->resampler->fmt_in.audio.i_rate = rate_bak; - if (owner->rate_filter == NULL) - owner->rate_filter = owner->resampler; - owner->resampling = 0; + if (filters->rate_filter == NULL) + filters->rate_filter = filters->resampler; - return 0; + return filters; error: - aout_FiltersPipelineDestroy (owner->filters, owner->nb_filters); - var_DelCallback (aout, "equalizer", EqualizerCallback, NULL); - var_DelCallback (aout, "visual", VisualizationCallback, NULL); - return -1; + aout_FiltersPipelineDestroy (filters->tab, filters->count); + var_DelCallback (obj, "equalizer", EqualizerCallback, NULL); + var_DelCallback (obj, "equalizer-bands", EqualizerCallback, NULL); + var_DelCallback (obj, "visual", VisualizationCallback, NULL); + free (filters); + return NULL; } +#undef aout_FiltersDelete /** - * Destroys the audio filters. + * Destroys a chain of audio filters. + * \param obj object used with aout_FiltersNew() + * \param filters chain to be destroyed + * \bug + * obj must be NULL iff request_vout was NULL in aout_FiltersNew() + * (this implies obj is an audio_output_t pointer if non NULL). */ -void aout_FiltersDelete (audio_output_t *aout) +void aout_FiltersDelete (vlc_object_t *obj, aout_filters_t *filters) { - aout_owner_t *owner = aout_owner (aout); - - if (owner->resampler != NULL) - aout_FiltersPipelineDestroy (&owner->resampler, 1); - aout_FiltersPipelineDestroy (owner->filters, owner->nb_filters); - var_DelCallback (aout, "equalizer", EqualizerCallback, NULL); - var_DelCallback (aout, "visual", VisualizationCallback, NULL); - - /* XXX We need to update recycle_vout before calling - * aout_FiltersPipelineDestroy(). - * FIXME There may be a race condition if audio-visual is updated between - * aout_FiltersDestroy() and the next aout_FiltersNew(). - */ - char *visual = var_InheritString (aout, "audio-visual"); - owner->recycle_vout = (visual != NULL) && *visual; - free (visual); + if (filters->resampler != NULL) + aout_FiltersPipelineDestroy (&filters->resampler, 1); + aout_FiltersPipelineDestroy (filters->tab, filters->count); + if (obj != NULL) + { + var_DelCallback (obj, "equalizer", EqualizerCallback, NULL); + var_DelCallback (obj, "equalizer-bands", EqualizerCallback, NULL); + var_DelCallback (obj, "visual", VisualizationCallback, NULL); + } + free (filters); } -bool aout_FiltersAdjustResampling (audio_output_t *aout, int adjust) +bool aout_FiltersAdjustResampling (aout_filters_t *filters, int adjust) { - aout_owner_t *owner = aout_owner (aout); - - if (owner->resampler == NULL) + if (filters->resampler == NULL) return false; if (adjust) - owner->resampling += adjust; + filters->resampling += adjust; else - owner->resampling = 0; - return owner->resampling != 0; + filters->resampling = 0; + return filters->resampling != 0; } -block_t *aout_FiltersPlay (audio_output_t *aout, block_t *block, int rate) +block_t *aout_FiltersPlay (aout_filters_t *filters, block_t *block, int rate) { - aout_owner_t *owner = aout_owner (aout); int nominal_rate = 0; if (rate != INPUT_RATE_DEFAULT) { - filter_t *rate_filter = owner->rate_filter; + filter_t *rate_filter = filters->rate_filter; if (rate_filter == NULL) goto drop; /* Without linear, non-nominal rate is impossible. */ @@ -625,20 +556,19 @@ block_t *aout_FiltersPlay (audio_output_t *aout, block_t *block, int rate) (nominal_rate * INPUT_RATE_DEFAULT) / rate; } - block = aout_FiltersPipelinePlay (owner->filters, owner->nb_filters, - block); - if (owner->resampler != NULL) + block = aout_FiltersPipelinePlay (filters->tab, filters->count, block); + if (filters->resampler != NULL) { /* NOTE: the resampler needs to run even if resampling is 0. * The decoder and output rates can still be different. */ - owner->resampler->fmt_in.audio.i_rate += owner->resampling; - block = aout_FiltersPipelinePlay (&owner->resampler, 1, block); - owner->resampler->fmt_in.audio.i_rate -= owner->resampling; + filters->resampler->fmt_in.audio.i_rate += filters->resampling; + block = aout_FiltersPipelinePlay (&filters->resampler, 1, block); + filters->resampler->fmt_in.audio.i_rate -= filters->resampling; } if (nominal_rate != 0) { /* Restore input rate */ - assert (owner->rate_filter != NULL); - owner->rate_filter->fmt_in.audio.i_rate = nominal_rate; + assert (filters->rate_filter != NULL); + filters->rate_filter->fmt_in.audio.i_rate = nominal_rate; } return block;