+ return block;
+}
+
+/** Callback for visualization selection */
+static int VisualizationCallback (vlc_object_t *obj, char const *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
+ {
+ 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);
+ }
+
+ aout_InputRequestRestart (aout);
+ (void) var; (void) oldval; (void) data;
+ return VLC_SUCCESS;
+}
+
+static int EqualizerCallback (vlc_object_t *obj, char const *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
+ {
+ var_Create (obj, "equalizer-preset", VLC_VAR_STRING);
+ var_SetString (obj, "equalizer-preset", mode);
+ ret = ChangeFiltersString (obj, "audio-filter", "equalizer", true);
+ }
+
+ /* That sucks */
+ if (ret)
+ aout_InputRequestRestart (aout);
+ (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.
+ * 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;
+
+ return req->pf_request_vout (req->p_private, vout, fmt,
+ owner->recycle_vout);
+}
+
+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)
+{
+ 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)
+ {
+ filter->p_module = module_need (filter, "audio filter", name, true);
+ if (filter->p_module != NULL)
+ return filter;
+
+ /* 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->p_module = module_need (filter, "visualization2", name, true);
+ if (filter->p_module != NULL)
+ return filter;
+
+ vlc_object_release (filter);
+ return NULL;