1/***
2  This file is part of PulseAudio.
3
4  This module is based off Lennart Poettering's LADSPA sink and swaps out
5  LADSPA functionality for a dbus-aware STFT OLA based digital equalizer.
6  All new work is published under PulseAudio's original license.
7
8  Copyright 2009 Jason Newton <nevion@gmail.com>
9
10  Original Author:
11  Copyright 2004-2008 Lennart Poettering
12
13  PulseAudio is free software; you can redistribute it and/or modify
14  it under the terms of the GNU Lesser General Public License as
15  published by the Free Software Foundation; either version 2.1 of the
16  License, or (at your option) any later version.
17
18  PulseAudio is distributed in the hope that it will be useful, but
19  WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  General Public License for more details.
22
23  You should have received a copy of the GNU Lesser General Public
24  License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
25***/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31#include <stdlib.h>
32#include <stdio.h>
33#include <float.h>
34#include <math.h>
35#include <string.h>
36#include <stdint.h>
37
38//#undef __SSE2__
39#ifdef __SSE2__
40#include <xmmintrin.h>
41#include <emmintrin.h>
42#endif
43
44#include <fftw3.h>
45
46#include <pulse/xmalloc.h>
47#include <pulse/timeval.h>
48
49#include <pulsecore/core-rtclock.h>
50#include <pulsecore/i18n.h>
51#include <pulsecore/aupdate.h>
52#include <pulsecore/namereg.h>
53#include <pulsecore/sink.h>
54#include <pulsecore/module.h>
55#include <pulsecore/core-util.h>
56#include <pulsecore/modargs.h>
57#include <pulsecore/log.h>
58#include <pulsecore/rtpoll.h>
59#include <pulsecore/sample-util.h>
60#include <pulsecore/shared.h>
61#include <pulsecore/idxset.h>
62#include <pulsecore/strlist.h>
63#include <pulsecore/database.h>
64#include <pulsecore/protocol-dbus.h>
65#include <pulsecore/dbus-util.h>
66
67PA_MODULE_AUTHOR("Jason Newton");
68PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
69PA_MODULE_VERSION(PACKAGE_VERSION);
70PA_MODULE_LOAD_ONCE(false);
71PA_MODULE_USAGE(
72        _("sink_name=<name of the sink> "
73          "sink_properties=<properties for the sink> "
74          "sink_master=<sink to connect to> "
75          "format=<sample format> "
76          "rate=<sample rate> "
77          "channels=<number of channels> "
78          "channel_map=<channel map> "
79          "autoloaded=<set if this module is being loaded automatically> "
80          "use_volume_sharing=<yes or no> "
81         ));
82
83#define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
84#define DEFAULT_AUTOLOADED false
85
86struct userdata {
87    pa_module *module;
88    pa_sink *sink;
89    pa_sink_input *sink_input;
90    bool autoloaded;
91
92    size_t channels;
93    size_t fft_size;//length (res) of fft
94    size_t window_size;/*
95                        *sliding window size
96                        *effectively chooses R
97                        */
98    size_t R;/* the hop size between overlapping windows
99              * the latency of the filter, calculated from window_size
100              * based on constraints of COLA and window function
101              */
102    //for twiddling with pulseaudio
103    size_t overlap_size;//window_size-R
104    size_t samples_gathered;
105    size_t input_buffer_max;
106    //message
107    float *W;//windowing function (time domain)
108    float *work_buffer, **input, **overlap_accum;
109    fftwf_complex *output_window;
110    fftwf_plan forward_plan, inverse_plan;
111    //size_t samplings;
112
113    float **Xs;
114    float ***Hs;//thread updatable copies of the freq response filters (magnitude based)
115    pa_aupdate **a_H;
116    pa_memblockq *input_q;
117    char *output_buffer;
118    size_t output_buffer_length;
119    size_t output_buffer_max_length;
120    pa_memblockq *output_q;
121    bool first_iteration;
122
123    pa_dbus_protocol *dbus_protocol;
124    char *dbus_path;
125
126    pa_database *database;
127    char **base_profiles;
128
129    bool automatic_description;
130};
131
132static const char* const valid_modargs[] = {
133    "sink_name",
134    "sink_properties",
135    "sink_master",
136    "format",
137    "rate",
138    "channels",
139    "channel_map",
140    "autoloaded",
141    "use_volume_sharing",
142    NULL
143};
144
145#define v_size 4
146#define SINKLIST "equalized_sinklist"
147#define EQDB "equalizer_db"
148#define EQ_STATE_DB "equalizer-state"
149#define FILTER_SIZE(u) ((u)->fft_size / 2 + 1)
150#define CHANNEL_PROFILE_SIZE(u) (FILTER_SIZE(u) + 1)
151#define FILTER_STATE_SIZE(u) (CHANNEL_PROFILE_SIZE(u) * (u)->channels)
152
153static void dbus_init(struct userdata *u);
154static void dbus_done(struct userdata *u);
155
156static void hanning_window(float *W, size_t window_size) {
157    /* h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2 */
158    for (size_t i = 0; i < window_size; ++i)
159        W[i] = (float).5 * (1 - cos(2*M_PI*i / (window_size+1)));
160}
161
162static void fix_filter(float *H, size_t fft_size) {
163    /* divide out the fft gain */
164    for (size_t i = 0; i < fft_size / 2 + 1; ++i)
165        H[i] /= fft_size;
166}
167
168static void interpolate(float *samples, size_t length, uint32_t *xs, float *ys, size_t n_points) {
169    /* Note that xs must be monotonically increasing! */
170    float x_range_lower, x_range_upper, c0;
171
172    pa_assert(n_points >= 2);
173    pa_assert(xs[0] == 0);
174    pa_assert(xs[n_points - 1] == length - 1);
175
176    for (size_t x = 0, x_range_lower_i = 0; x < length-1; ++x) {
177        pa_assert(x_range_lower_i < n_points-1);
178
179        x_range_lower = (float) xs[x_range_lower_i];
180        x_range_upper = (float) xs[x_range_lower_i+1];
181
182        pa_assert_se(x_range_lower < x_range_upper);
183        pa_assert_se(x >= x_range_lower);
184        pa_assert_se(x <= x_range_upper);
185
186        /* bilinear-interpolation of coefficients specified */
187        c0 = (x-x_range_lower) / (x_range_upper-x_range_lower);
188        pa_assert(c0 >= 0 && c0 <= 1.0);
189
190        samples[x] = ((1.0f - c0) * ys[x_range_lower_i] + c0 * ys[x_range_lower_i + 1]);
191        while(x >= xs[x_range_lower_i + 1])
192            x_range_lower_i++;
193    }
194
195    samples[length-1] = ys[n_points-1];
196}
197
198static bool is_monotonic(const uint32_t *xs, size_t length) {
199    pa_assert(xs);
200
201    if (length < 2)
202        return true;
203
204    for(size_t i = 1; i < length; ++i)
205        if (xs[i] <= xs[i-1])
206            return false;
207
208    return true;
209}
210
211/* ensures memory allocated is a multiple of v_size and aligned */
212static void * alloc(size_t x, size_t s) {
213    size_t f;
214    float *t;
215
216    f = PA_ROUND_UP(x*s, sizeof(float)*v_size);
217    pa_assert_se(t = fftwf_malloc(f));
218    pa_memzero(t, f);
219
220    return t;
221}
222
223static void alloc_input_buffers(struct userdata *u, size_t min_buffer_length) {
224    if (min_buffer_length <= u->input_buffer_max)
225        return;
226
227    pa_assert(min_buffer_length >= u->window_size);
228    for (size_t c = 0; c < u->channels; ++c) {
229        float *tmp = alloc(min_buffer_length, sizeof(float));
230        if (u->input[c]) {
231            if (!u->first_iteration)
232                memcpy(tmp, u->input[c], u->overlap_size * sizeof(float));
233            fftwf_free(u->input[c]);
234        }
235        u->input[c] = tmp;
236    }
237    u->input_buffer_max = min_buffer_length;
238}
239
240/* Called from I/O thread context */
241static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
242    struct userdata *u = PA_SINK(o)->userdata;
243
244    switch (code) {
245
246        case PA_SINK_MESSAGE_GET_LATENCY: {
247            //size_t fs=pa_frame_size(&u->sink->sample_spec);
248
249            /* The sink is _put() before the sink input is, so let's
250             * make sure we don't access it in that time. Also, the
251             * sink input is first shut down, the sink second. */
252            if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
253                !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
254                *((int64_t*) data) = 0;
255                return 0;
256            }
257
258            *((int64_t*) data) =
259                /* Get the latency of the master sink */
260                pa_sink_get_latency_within_thread(u->sink_input->sink, true) +
261
262                /* Add the latency internal to our sink input on top */
263                pa_bytes_to_usec(pa_memblockq_get_length(u->output_q) +
264                                 pa_memblockq_get_length(u->input_q), &u->sink_input->sink->sample_spec) +
265                pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);
266            //    pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
267            //+ pa_bytes_to_usec(u->latency * fs, ss)
268
269            /* Add resampler latency */
270            *((int64_t*) data) += pa_resampler_get_delay_usec(u->sink_input->thread_info.resampler);
271            return 0;
272        }
273    }
274
275    return pa_sink_process_msg(o, code, data, offset, chunk);
276}
277
278/* Called from main context */
279static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) {
280    struct userdata *u;
281
282    pa_sink_assert_ref(s);
283    pa_assert_se(u = s->userdata);
284
285    if (!PA_SINK_IS_LINKED(state) ||
286        !PA_SINK_INPUT_IS_LINKED(u->sink_input->state))
287        return 0;
288
289    pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
290    return 0;
291}
292
293/* Called from the IO thread. */
294static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
295    struct userdata *u;
296
297    pa_assert(s);
298    pa_assert_se(u = s->userdata);
299
300    /* When set to running or idle for the first time, request a rewind
301     * of the master sink to make sure we are heard immediately */
302    if (PA_SINK_IS_OPENED(new_state) && s->thread_info.state == PA_SINK_INIT) {
303        pa_log_debug("Requesting rewind due to state change.");
304        pa_sink_input_request_rewind(u->sink_input, 0, false, true, true);
305    }
306
307    return 0;
308}
309
310/* Called from I/O thread context */
311static void sink_request_rewind_cb(pa_sink *s) {
312    struct userdata *u;
313
314    pa_sink_assert_ref(s);
315    pa_assert_se(u = s->userdata);
316
317    if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
318        !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
319        return;
320
321    /* Just hand this one over to the master sink */
322    pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes+pa_memblockq_get_length(u->input_q), true, false, false);
323}
324
325/* Called from I/O thread context */
326static void sink_update_requested_latency_cb(pa_sink *s) {
327    struct userdata *u;
328
329    pa_sink_assert_ref(s);
330    pa_assert_se(u = s->userdata);
331
332    if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
333        !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
334        return;
335
336    /* Just hand this one over to the master sink */
337    pa_sink_input_set_requested_latency_within_thread(
338            u->sink_input,
339            pa_sink_get_requested_latency_within_thread(s));
340}
341
342/* Called from main context */
343static void sink_set_volume_cb(pa_sink *s) {
344    struct userdata *u;
345
346    pa_sink_assert_ref(s);
347    pa_assert_se(u = s->userdata);
348
349    if (!PA_SINK_IS_LINKED(s->state) ||
350        !PA_SINK_INPUT_IS_LINKED(u->sink_input->state))
351        return;
352
353    pa_sink_input_set_volume(u->sink_input, &s->real_volume, s->save_volume, true);
354}
355
356/* Called from main context */
357static void sink_set_mute_cb(pa_sink *s) {
358    struct userdata *u;
359
360    pa_sink_assert_ref(s);
361    pa_assert_se(u = s->userdata);
362
363    if (!PA_SINK_IS_LINKED(s->state) ||
364        !PA_SINK_INPUT_IS_LINKED(u->sink_input->state))
365        return;
366
367    pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);
368}
369
370#if 1
371//reference implementation
372static void dsp_logic(
373    float * restrict dst,//used as a temp array too, needs to be fft_length!
374    float * restrict src,/*input data w/ overlap at start,
375                               *automatically cycled in routine
376                               */
377    float * restrict overlap,
378    const float X,//multiplier
379    const float * restrict H,//The freq. magnitude scalers filter
380    const float * restrict W,//The windowing function
381    fftwf_complex * restrict output_window,//The transformed windowed src
382    struct userdata *u) {
383
384    //use a linear-phase sliding STFT and overlap-add method (for each channel)
385    //window the data
386    for(size_t j = 0; j < u->window_size; ++j) {
387        dst[j] = X * W[j] * src[j];
388    }
389    //zero pad the remaining fft window
390    memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
391    //Processing is done here!
392    //do fft
393    fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
394    //perform filtering
395    for(size_t j = 0; j < FILTER_SIZE(u); ++j) {
396        u->output_window[j][0] *= H[j];
397        u->output_window[j][1] *= H[j];
398    }
399    //inverse fft
400    fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
401    ////debug: tests overlapping add
402    ////and negates ALL PREVIOUS processing
403    ////yields a perfect reconstruction if COLA is held
404    //for(size_t j = 0; j < u->window_size; ++j) {
405    //    u->work_buffer[j] = u->W[j] * u->input[c][j];
406    //}
407
408    //overlap add and preserve overlap component from this window (linear phase)
409    for(size_t j = 0; j < u->overlap_size; ++j) {
410        u->work_buffer[j] += overlap[j];
411        overlap[j] = dst[u->R + j];
412    }
413    ////debug: tests if basic buffering works
414    ////shouldn't modify the signal AT ALL (beyond roundoff)
415    //for(size_t j = 0; j < u->window_size;++j) {
416    //    u->work_buffer[j] = u->input[c][j];
417    //}
418
419    //preserve the needed input for the next window's overlap
420    memmove(src, src + u->R,
421        (u->samples_gathered - u->R) * sizeof(float)
422    );
423}
424#else
425typedef float v4sf __attribute__ ((__aligned__(v_size * sizeof(float))));
426typedef union float_vector {
427    float f[v_size];
428    v4sf v;
429    __m128 m;
430} float_vector_t;
431
432//regardless of sse enabled, the loops in here assume
433//16 byte aligned addresses and memory allocations divisible by v_size
434static void dsp_logic(
435    float * restrict dst,//used as a temp array too, needs to be fft_length!
436    float * restrict src,/*input data w/ overlap at start,
437                               *automatically cycled in routine
438                               */
439    float * restrict overlap,//The size of the overlap
440    const float X,//multiplier
441    const float * restrict H,//The freq. magnitude scalers filter
442    const float * restrict W,//The windowing function
443    fftwf_complex * restrict output_window,//The transformed windowed src
444    struct userdata *u) {//Collection of constants
445    const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
446    float_vector_t x;
447    x.f[0] = x.f[1] = x.f[2] = x.f[3] = X;
448
449    //assert(u->samples_gathered >= u->R);
450    //use a linear-phase sliding STFT and overlap-add method
451    for(size_t j = 0; j < u->window_size; j += v_size) {
452        //dst[j] = W[j] * src[j];
453        float_vector_t *d = (float_vector_t*) (dst + j);
454        float_vector_t *w = (float_vector_t*) (W + j);
455        float_vector_t *s = (float_vector_t*) (src + j);
456//#if __SSE2__
457        d->m = _mm_mul_ps(x.m, _mm_mul_ps(w->m, s->m));
458//        d->v = x->v * w->v * s->v;
459//#endif
460    }
461    //zero pad the remaining fft window
462    memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
463
464    //Processing is done here!
465    //do fft
466    fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
467    //perform filtering - purely magnitude based
468    for(size_t j = 0; j < FILTER_SIZE; j += v_size / 2) {
469        //output_window[j][0]*=H[j];
470        //output_window[j][1]*=H[j];
471        float_vector_t *d = (float_vector_t*)( ((float *) output_window) + 2 * j);
472        float_vector_t h;
473        h.f[0] = h.f[1] = H[j];
474        h.f[2] = h.f[3] = H[j + 1];
475//#if __SSE2__
476        d->m = _mm_mul_ps(d->m, h.m);
477//#else
478//        d->v = d->v * h.v;
479//#endif
480    }
481
482    //inverse fft
483    fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
484
485    ////debug: tests overlapping add
486    ////and negates ALL PREVIOUS processing
487    ////yields a perfect reconstruction if COLA is held
488    //for(size_t j = 0; j < u->window_size; ++j) {
489    //    dst[j] = W[j] * src[j];
490    //}
491
492    //overlap add and preserve overlap component from this window (linear phase)
493    for(size_t j = 0; j < overlap_size; j += v_size) {
494        //dst[j]+=overlap[j];
495        //overlap[j]+=dst[j+R];
496        float_vector_t *d = (float_vector_t*)(dst + j);
497        float_vector_t *o = (float_vector_t*)(overlap + j);
498//#if __SSE2__
499        d->m = _mm_add_ps(d->m, o->m);
500        o->m = ((float_vector_t*)(dst + u->R + j))->m;
501//#else
502//        d->v = d->v + o->v;
503//        o->v = ((float_vector_t*)(dst + u->R + j))->v;
504//#endif
505    }
506    //memcpy(overlap, dst+u->R, u->overlap_size * sizeof(float)); //overlap preserve (debug)
507    //zero out the bit beyond the real overlap so we don't add garbage next iteration
508    memset(overlap + u->overlap_size, 0, overlap_size - u->overlap_size);
509
510    ////debug: tests if basic buffering works
511    ////shouldn't modify the signal AT ALL (beyond roundoff)
512    //for(size_t j = 0; j < u->window_size; ++j) {
513    //    dst[j] = src[j];
514    //}
515
516    //preserve the needed input for the next window's overlap
517    memmove(src, src + u->R,
518        (u->samples_gathered - u->R) * sizeof(float)
519    );
520}
521#endif
522
523static void flatten_to_memblockq(struct userdata *u) {
524    size_t mbs = pa_mempool_block_size_max(u->sink->core->mempool);
525    pa_memchunk tchunk;
526    char *dst;
527    size_t i = 0;
528    while(i < u->output_buffer_length) {
529        tchunk.index = 0;
530        tchunk.length = PA_MIN((u->output_buffer_length - i), mbs);
531        tchunk.memblock = pa_memblock_new(u->sink->core->mempool, tchunk.length);
532        //pa_log_debug("pushing %ld into the q", tchunk.length);
533        dst = pa_memblock_acquire(tchunk.memblock);
534        memcpy(dst, u->output_buffer + i, tchunk.length);
535        pa_memblock_release(tchunk.memblock);
536        pa_memblockq_push(u->output_q, &tchunk);
537        pa_memblock_unref(tchunk.memblock);
538        i += tchunk.length;
539    }
540}
541
542static void process_samples(struct userdata *u) {
543    size_t fs = pa_frame_size(&(u->sink->sample_spec));
544    unsigned a_i;
545    float *H, X;
546    size_t iterations, offset;
547    pa_assert(u->samples_gathered >= u->window_size);
548    iterations = (u->samples_gathered - u->overlap_size) / u->R;
549    //make sure there is enough buffer memory allocated
550    if (iterations * u->R * fs > u->output_buffer_max_length) {
551        u->output_buffer_max_length = iterations * u->R * fs;
552        pa_xfree(u->output_buffer);
553        u->output_buffer = pa_xmalloc(u->output_buffer_max_length);
554    }
555    u->output_buffer_length = iterations * u->R * fs;
556
557    for(size_t iter = 0; iter < iterations; ++iter) {
558        offset = iter * u->R * fs;
559        for(size_t c = 0;c < u->channels; c++) {
560            a_i = pa_aupdate_read_begin(u->a_H[c]);
561            X = u->Xs[c][a_i];
562            H = u->Hs[c][a_i];
563            dsp_logic(
564                u->work_buffer,
565                u->input[c],
566                u->overlap_accum[c],
567                X,
568                H,
569                u->W,
570                u->output_window,
571                u
572            );
573            pa_aupdate_read_end(u->a_H[c]);
574            if (u->first_iteration) {
575                /* The windowing function will make the audio ramped in, as a cheap fix we can
576                 * undo the windowing (for non-zero window values)
577                 */
578                for(size_t i = 0; i < u->overlap_size; ++i) {
579                    u->work_buffer[i] = u->W[i] <= FLT_EPSILON ? u->work_buffer[i] : u->work_buffer[i] / u->W[i];
580                }
581            }
582            pa_sample_clamp(PA_SAMPLE_FLOAT32NE, (uint8_t *) (((float *)u->output_buffer) + c) + offset, fs, u->work_buffer, sizeof(float), u->R);
583        }
584        if (u->first_iteration) {
585            u->first_iteration = false;
586        }
587        u->samples_gathered -= u->R;
588    }
589    flatten_to_memblockq(u);
590}
591
592static void input_buffer(struct userdata *u, pa_memchunk *in) {
593    size_t fs = pa_frame_size(&(u->sink->sample_spec));
594    size_t samples = in->length/fs;
595    float *src = pa_memblock_acquire_chunk(in);
596    pa_assert(u->samples_gathered + samples <= u->input_buffer_max);
597    for(size_t c = 0; c < u->channels; c++) {
598        //buffer with an offset after the overlap from previous
599        //iterations
600        pa_assert_se(
601            u->input[c] + u->samples_gathered + samples <= u->input[c] + u->input_buffer_max
602        );
603        pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c] + u->samples_gathered, sizeof(float), src + c, fs, samples);
604    }
605    u->samples_gathered += samples;
606    pa_memblock_release(in->memblock);
607}
608
609/* Called from I/O thread context */
610static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
611    struct userdata *u;
612    size_t fs, target_samples;
613    size_t mbs;
614    //struct timeval start, end;
615    pa_memchunk tchunk;
616
617    pa_sink_input_assert_ref(i);
618    pa_assert_se(u = i->userdata);
619    pa_assert(chunk);
620    pa_assert(u->sink);
621
622    if (!PA_SINK_IS_LINKED(u->sink->thread_info.state))
623        return -1;
624
625    /* FIXME: Please clean this up. I see more commented code lines
626     * than uncommented code lines. I am sorry, but I am too dumb to
627     * understand this. */
628
629    fs = pa_frame_size(&(u->sink->sample_spec));
630    mbs = pa_mempool_block_size_max(u->sink->core->mempool);
631    if (pa_memblockq_get_length(u->output_q) > 0) {
632        //pa_log_debug("qsize is %ld", pa_memblockq_get_length(u->output_q));
633        goto END;
634    }
635    //nbytes = PA_MIN(nbytes, pa_mempool_block_size_max(u->sink->core->mempool));
636    target_samples = PA_ROUND_UP(nbytes / fs, u->R);
637    ////pa_log_debug("vanilla mbs = %ld",mbs);
638    //mbs = PA_ROUND_DOWN(mbs / fs, u->R);
639    //mbs = PA_MAX(mbs, u->R);
640    //target_samples = PA_MAX(target_samples, mbs);
641    //pa_log_debug("target samples: %ld", target_samples);
642    if (u->first_iteration) {
643        //allocate request_size
644        target_samples = PA_MAX(target_samples, u->window_size);
645    }else{
646        //allocate request_size + overlap
647        target_samples += u->overlap_size;
648    }
649    alloc_input_buffers(u, target_samples);
650    //pa_log_debug("post target samples: %ld", target_samples);
651    chunk->memblock = NULL;
652
653    /* Hmm, process any rewind request that might be queued up */
654    pa_sink_process_rewind(u->sink, 0);
655
656    //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
657    //pa_rtclock_get(&start);
658    do{
659        size_t input_remaining = target_samples - u->samples_gathered;
660       // pa_log_debug("input remaining %ld samples", input_remaining);
661        pa_assert(input_remaining > 0);
662        while (pa_memblockq_peek(u->input_q, &tchunk) < 0) {
663            //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
664            pa_sink_render_full(u->sink, PA_MIN(input_remaining * fs, mbs), &tchunk);
665            pa_memblockq_push(u->input_q, &tchunk);
666            pa_memblock_unref(tchunk.memblock);
667        }
668        pa_assert(tchunk.memblock);
669
670        tchunk.length = PA_MIN(input_remaining * fs, tchunk.length);
671
672        pa_memblockq_drop(u->input_q, tchunk.length);
673        //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
674        /* copy new input */
675        //pa_rtclock_get(start);
676       // pa_log_debug("buffering %ld bytes", tchunk.length);
677        input_buffer(u, &tchunk);
678        //pa_rtclock_get(&end);
679        //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
680        pa_memblock_unref(tchunk.memblock);
681    } while(u->samples_gathered < target_samples);
682
683    //pa_rtclock_get(&end);
684    //pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
685
686    pa_assert(u->fft_size >= u->window_size);
687    pa_assert(u->R < u->window_size);
688    //pa_rtclock_get(&start);
689    /* process a block */
690    process_samples(u);
691    //pa_rtclock_get(&end);
692    //pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
693END:
694    pa_assert_se(pa_memblockq_peek(u->output_q, chunk) >= 0);
695    pa_assert(chunk->memblock);
696    pa_memblockq_drop(u->output_q, chunk->length);
697
698    //pa_log_debug("gave %ld", chunk->length/fs);
699    //pa_log_debug("end pop");
700    return 0;
701}
702
703/* Called from main context */
704static void sink_input_volume_changed_cb(pa_sink_input *i) {
705    struct userdata *u;
706
707    pa_sink_input_assert_ref(i);
708    pa_assert_se(u = i->userdata);
709
710    pa_sink_volume_changed(u->sink, &i->volume);
711}
712
713/* Called from main context */
714static void sink_input_mute_changed_cb(pa_sink_input *i) {
715    struct userdata *u;
716
717    pa_sink_input_assert_ref(i);
718    pa_assert_se(u = i->userdata);
719
720    pa_sink_mute_changed(u->sink, i->muted);
721}
722
723#if 0
724static void reset_filter(struct userdata *u) {
725    size_t fs = pa_frame_size(&u->sink->sample_spec);
726    size_t max_request;
727
728    u->samples_gathered = 0;
729
730    for(size_t i = 0; i < u->channels; ++i)
731        pa_memzero(u->overlap_accum[i], u->overlap_size * sizeof(float));
732
733    u->first_iteration = true;
734    //set buffer size to max request, no overlap copy
735    max_request = PA_ROUND_UP(pa_sink_input_get_max_request(u->sink_input) / fs , u->R);
736    max_request = PA_MAX(max_request, u->window_size);
737    pa_sink_set_max_request_within_thread(u->sink, max_request * fs);
738}
739#endif
740
741/* Called from I/O thread context */
742static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
743    struct userdata *u;
744    size_t amount = 0;
745
746    pa_log_debug("Rewind callback!");
747    pa_sink_input_assert_ref(i);
748    pa_assert_se(u = i->userdata);
749
750    /* If the sink is not yet linked, there is nothing to rewind */
751    if (!PA_SINK_IS_LINKED(u->sink->thread_info.state))
752        return;
753
754    if (u->sink->thread_info.rewind_nbytes > 0) {
755        size_t max_rewrite;
756
757        //max_rewrite = nbytes;
758        max_rewrite = nbytes + pa_memblockq_get_length(u->input_q);
759        //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
760        amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
761        u->sink->thread_info.rewind_nbytes = 0;
762
763        if (amount > 0) {
764            //invalidate the output q
765            pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, true);
766            pa_log("Resetting filter");
767            //reset_filter(u); //this is the "proper" thing to do...
768        }
769    }
770
771    pa_sink_process_rewind(u->sink, amount);
772    pa_memblockq_rewind(u->input_q, nbytes);
773}
774
775/* Called from I/O thread context */
776static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
777    struct userdata *u;
778
779    pa_sink_input_assert_ref(i);
780    pa_assert_se(u = i->userdata);
781
782    /* FIXME: Too small max_rewind:
783     * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
784    pa_memblockq_set_maxrewind(u->input_q, nbytes);
785    pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
786}
787
788/* Called from I/O thread context */
789static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
790    struct userdata *u;
791    size_t fs;
792
793    pa_sink_input_assert_ref(i);
794    pa_assert_se(u = i->userdata);
795
796    fs = pa_frame_size(&u->sink_input->sample_spec);
797    pa_sink_set_max_request_within_thread(u->sink, PA_ROUND_UP(nbytes / fs, u->R) * fs);
798}
799
800/* Called from I/O thread context */
801static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
802    struct userdata *u;
803
804    pa_sink_input_assert_ref(i);
805    pa_assert_se(u = i->userdata);
806
807    pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
808}
809
810/* Called from I/O thread context */
811static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
812    struct userdata *u;
813
814    pa_sink_input_assert_ref(i);
815    pa_assert_se(u = i->userdata);
816
817    pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
818}
819
820/* Called from I/O thread context */
821static void sink_input_detach_cb(pa_sink_input *i) {
822    struct userdata *u;
823
824    pa_sink_input_assert_ref(i);
825    pa_assert_se(u = i->userdata);
826
827    if (PA_SINK_IS_LINKED(u->sink->thread_info.state))
828        pa_sink_detach_within_thread(u->sink);
829
830    pa_sink_set_rtpoll(u->sink, NULL);
831}
832
833/* Called from I/O thread context */
834static void sink_input_attach_cb(pa_sink_input *i) {
835    struct userdata *u;
836    size_t fs, max_request;
837
838    pa_sink_input_assert_ref(i);
839    pa_assert_se(u = i->userdata);
840
841    pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
842    pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
843    pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
844
845    fs = pa_frame_size(&u->sink_input->sample_spec);
846    /* set buffer size to max request, no overlap copy */
847    max_request = PA_ROUND_UP(pa_sink_input_get_max_request(u->sink_input) / fs, u->R);
848    max_request = PA_MAX(max_request, u->window_size);
849
850    pa_sink_set_max_request_within_thread(u->sink, max_request * fs);
851
852    /* FIXME: Too small max_rewind:
853     * https://bugs.freedesktop.org/show_bug.cgi?id=53709 */
854    pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
855
856    if (PA_SINK_IS_LINKED(u->sink->thread_info.state))
857        pa_sink_attach_within_thread(u->sink);
858}
859
860/* Called from main context */
861static void sink_input_kill_cb(pa_sink_input *i) {
862    struct userdata *u;
863
864    pa_sink_input_assert_ref(i);
865    pa_assert_se(u = i->userdata);
866
867    /* The order here matters! We first kill the sink so that streams
868     * can properly be moved away while the sink input is still connected
869     * to the master. */
870    pa_sink_input_cork(u->sink_input, true);
871    pa_sink_unlink(u->sink);
872    pa_sink_input_unlink(u->sink_input);
873
874    pa_sink_input_unref(u->sink_input);
875    u->sink_input = NULL;
876
877    /* Leave u->sink alone for now, it will be cleaned up on module
878     * unload (and it is needed during unload as well). */
879
880    pa_module_unload_request(u->module, true);
881}
882
883static void pack(char **strs, size_t len, char **packed, size_t *length) {
884    size_t t_len = 0;
885    size_t headers = (1+len) * sizeof(uint16_t);
886    char *p;
887    for(size_t i = 0; i < len; ++i) {
888        t_len += strlen(strs[i]);
889    }
890    *length = headers + t_len;
891    p = *packed = pa_xmalloc0(*length);
892    *((uint16_t *) p) = (uint16_t) len;
893    p += sizeof(uint16_t);
894    for(size_t i = 0; i < len; ++i) {
895        uint16_t l = strlen(strs[i]);
896        *((uint16_t *) p) = (uint16_t) l;
897        p += sizeof(uint16_t);
898        memcpy(p, strs[i], l);
899        p += l;
900    }
901}
902static void unpack(char *str, size_t length, char ***strs, size_t *len) {
903    char *p = str;
904    *len = *((uint16_t *) p);
905    p += sizeof(uint16_t);
906    *strs = pa_xnew(char *, *len);
907
908    for(size_t i = 0; i < *len; ++i) {
909        size_t l = *((uint16_t *) p);
910        p += sizeof(uint16_t);
911        (*strs)[i] = pa_xnew(char, l + 1);
912        memcpy((*strs)[i], p, l);
913        (*strs)[i][l] = '\0';
914        p += l;
915    }
916}
917static void save_profile(struct userdata *u, size_t channel, char *name) {
918    unsigned a_i;
919    const size_t profile_size = CHANNEL_PROFILE_SIZE(u) * sizeof(float);
920    float *H_n, *profile;
921    const float *H;
922    pa_datum key, data;
923    profile = pa_xnew0(float, profile_size);
924    a_i = pa_aupdate_read_begin(u->a_H[channel]);
925    profile[0] = u->Xs[a_i][channel];
926    H = u->Hs[channel][a_i];
927    H_n = profile + 1;
928    for(size_t i = 0 ; i < FILTER_SIZE(u); ++i) {
929        H_n[i] = H[i] * u->fft_size;
930        //H_n[i] = H[i];
931    }
932    pa_aupdate_read_end(u->a_H[channel]);
933    key.data=name;
934    key.size = strlen(key.data);
935    data.data = profile;
936    data.size = profile_size;
937    pa_database_set(u->database, &key, &data, true);
938    pa_database_sync(u->database);
939    if (u->base_profiles[channel]) {
940        pa_xfree(u->base_profiles[channel]);
941    }
942    u->base_profiles[channel] = pa_xstrdup(name);
943}
944
945static void save_state(struct userdata *u) {
946    unsigned a_i;
947    const size_t filter_state_size = FILTER_STATE_SIZE(u) * sizeof(float);
948    float *H_n, *state;
949    float *H;
950    pa_datum key, data;
951    pa_database *database;
952    char *state_path;
953    char *packed;
954    size_t packed_length;
955
956    pack(u->base_profiles, u->channels, &packed, &packed_length);
957    state = (float *) pa_xmalloc0(filter_state_size + packed_length);
958    memcpy(state + FILTER_STATE_SIZE(u), packed, packed_length);
959    pa_xfree(packed);
960
961    for(size_t c = 0; c < u->channels; ++c) {
962        a_i = pa_aupdate_read_begin(u->a_H[c]);
963        state[c * CHANNEL_PROFILE_SIZE(u)] = u->Xs[c][a_i];
964        H = u->Hs[c][a_i];
965        H_n = &state[c * CHANNEL_PROFILE_SIZE(u) + 1];
966        memcpy(H_n, H, FILTER_SIZE(u) * sizeof(float));
967        pa_aupdate_read_end(u->a_H[c]);
968    }
969
970    key.data = u->sink->name;
971    key.size = strlen(key.data);
972    data.data = state;
973    data.size = filter_state_size + packed_length;
974    //thread safety for 0.9.17?
975    pa_assert_se(state_path = pa_state_path(NULL, false));
976    pa_assert_se(database = pa_database_open(state_path, EQ_STATE_DB, false, true));
977    pa_xfree(state_path);
978
979    pa_database_set(database, &key, &data, true);
980    pa_database_sync(database);
981    pa_database_close(database);
982    pa_xfree(state);
983}
984
985static void remove_profile(pa_core *c, char *name) {
986    pa_datum key;
987    pa_database *database;
988    key.data = name;
989    key.size = strlen(key.data);
990    pa_assert_se(database = pa_shared_get(c, EQDB));
991    pa_database_unset(database, &key);
992    pa_database_sync(database);
993}
994
995static const char* load_profile(struct userdata *u, size_t channel, char *name) {
996    unsigned a_i;
997    pa_datum key, value;
998    const size_t profile_size = CHANNEL_PROFILE_SIZE(u) * sizeof(float);
999    key.data = name;
1000    key.size = strlen(key.data);
1001    if (pa_database_get(u->database, &key, &value) != NULL) {
1002        if (value.size == profile_size) {
1003            float *profile = (float *) value.data;
1004            a_i = pa_aupdate_write_begin(u->a_H[channel]);
1005            u->Xs[channel][a_i] = profile[0];
1006            memcpy(u->Hs[channel][a_i], profile + 1, FILTER_SIZE(u) * sizeof(float));
1007            fix_filter(u->Hs[channel][a_i], u->fft_size);
1008            pa_aupdate_write_end(u->a_H[channel]);
1009            pa_xfree(u->base_profiles[channel]);
1010            u->base_profiles[channel] = pa_xstrdup(name);
1011        }else{
1012            return "incompatible size";
1013        }
1014        pa_datum_free(&value);
1015    }else{
1016        return "profile doesn't exist";
1017    }
1018    return NULL;
1019}
1020
1021static void load_state(struct userdata *u) {
1022    unsigned a_i;
1023    float *H;
1024    pa_datum key, value;
1025    pa_database *database;
1026    char *state_path;
1027    pa_assert_se(state_path = pa_state_path(NULL, false));
1028    database = pa_database_open(state_path, EQ_STATE_DB, false, false);
1029    pa_xfree(state_path);
1030    if (!database) {
1031        pa_log("No resume state");
1032        return;
1033    }
1034
1035    key.data = u->sink->name;
1036    key.size = strlen(key.data);
1037
1038    if (pa_database_get(database, &key, &value) != NULL) {
1039        if (value.size > FILTER_STATE_SIZE(u) * sizeof(float) + sizeof(uint16_t)) {
1040            float *state = (float *) value.data;
1041            size_t n_profs;
1042            char **names;
1043            for(size_t c = 0; c < u->channels; ++c) {
1044                a_i = pa_aupdate_write_begin(u->a_H[c]);
1045                H = state + c * CHANNEL_PROFILE_SIZE(u) + 1;
1046                u->Xs[c][a_i] = state[c * CHANNEL_PROFILE_SIZE(u)];
1047                memcpy(u->Hs[c][a_i], H, FILTER_SIZE(u) * sizeof(float));
1048                pa_aupdate_write_end(u->a_H[c]);
1049            }
1050            unpack(((char *)value.data) + FILTER_STATE_SIZE(u) * sizeof(float), value.size - FILTER_STATE_SIZE(u) * sizeof(float), &names, &n_profs);
1051            n_profs = PA_MIN(n_profs, u->channels);
1052            for(size_t c = 0; c < n_profs; ++c) {
1053                pa_xfree(u->base_profiles[c]);
1054                u->base_profiles[c] = names[c];
1055            }
1056            pa_xfree(names);
1057        }
1058        pa_datum_free(&value);
1059    }else{
1060        pa_log("resume state exists but is wrong size!");
1061    }
1062    pa_database_close(database);
1063}
1064
1065/* Called from main context */
1066static bool sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
1067    struct userdata *u;
1068
1069    pa_sink_input_assert_ref(i);
1070    pa_assert_se(u = i->userdata);
1071
1072    return u->sink != dest;
1073}
1074
1075/* Called from main context */
1076static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1077    struct userdata *u;
1078
1079    pa_sink_input_assert_ref(i);
1080    pa_assert_se(u = i->userdata);
1081
1082    if (u->autoloaded) {
1083        /* We were autoloaded, and don't support moving. Let's unload ourselves. */
1084        pa_log_debug("Can't move autoloaded stream, unloading");
1085        pa_module_unload_request(u->module, true);
1086    }
1087
1088    if (dest) {
1089        pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
1090        pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
1091
1092        if (u->automatic_description) {
1093            const char *master_description;
1094            char *new_description;
1095
1096            master_description = pa_proplist_gets(dest->proplist, PA_PROP_DEVICE_DESCRIPTION);
1097            new_description = pa_sprintf_malloc(_("FFT based equalizer on %s"),
1098                                                master_description ? master_description : dest->name);
1099            pa_sink_set_description(u->sink, new_description);
1100            pa_xfree(new_description);
1101        }
1102    } else
1103        pa_sink_set_asyncmsgq(u->sink, NULL);
1104}
1105
1106int pa__init(pa_module*m) {
1107    struct userdata *u;
1108    pa_sample_spec ss;
1109    pa_channel_map map;
1110    pa_modargs *ma;
1111    pa_sink *master;
1112    pa_sink_input_new_data sink_input_data;
1113    pa_sink_new_data sink_data;
1114    size_t i;
1115    unsigned c;
1116    float *H;
1117    unsigned a_i;
1118    bool use_volume_sharing = true;
1119
1120    pa_assert(m);
1121
1122    pa_log_warn("module-equalizer-sink is currently unsupported, and can sometimes cause "
1123                "PulseAudio crashes, increased latency or audible artifacts.");
1124    pa_log_warn("If you're facing audio problems, try unloading this module as a potential workaround.");
1125
1126    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1127        pa_log("Failed to parse module arguments.");
1128        goto fail;
1129    }
1130
1131    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) {
1132        pa_log("Master sink not found");
1133        goto fail;
1134    }
1135
1136    ss = master->sample_spec;
1137    ss.format = PA_SAMPLE_FLOAT32;
1138    map = master->channel_map;
1139    if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1140        pa_log("Invalid sample format specification or channel map");
1141        goto fail;
1142    }
1143
1144    //fs = pa_frame_size(&ss);
1145
1146    if (pa_modargs_get_value_boolean(ma, "use_volume_sharing", &use_volume_sharing) < 0) {
1147        pa_log("use_volume_sharing= expects a boolean argument");
1148        goto fail;
1149    }
1150
1151    u = pa_xnew0(struct userdata, 1);
1152    u->module = m;
1153    m->userdata = u;
1154
1155    u->channels = ss.channels;
1156    u->fft_size = pow(2, ceil(log(ss.rate) / log(2)));//probably unstable near corner cases of powers of 2
1157    pa_log_debug("fft size: %zd", u->fft_size);
1158    u->window_size = 15999;
1159    if (u->window_size % 2 == 0)
1160        u->window_size--;
1161    u->R = (u->window_size + 1) / 2;
1162    u->overlap_size = u->window_size - u->R;
1163    u->samples_gathered = 0;
1164    u->input_buffer_max = 0;
1165
1166    u->a_H = pa_xnew0(pa_aupdate *, u->channels);
1167    u->Xs = pa_xnew0(float *, u->channels);
1168    u->Hs = pa_xnew0(float **, u->channels);
1169
1170    for (c = 0; c < u->channels; ++c) {
1171        u->Xs[c] = pa_xnew0(float, 2);
1172        u->Hs[c] = pa_xnew0(float *, 2);
1173        for (i = 0; i < 2; ++i)
1174            u->Hs[c][i] = alloc(FILTER_SIZE(u), sizeof(float));
1175    }
1176
1177    u->W = alloc(u->window_size, sizeof(float));
1178    u->work_buffer = alloc(u->fft_size, sizeof(float));
1179    u->input = pa_xnew0(float *, u->channels);
1180    u->overlap_accum = pa_xnew0(float *, u->channels);
1181    for (c = 0; c < u->channels; ++c) {
1182        u->a_H[c] = pa_aupdate_new();
1183        u->input[c] = NULL;
1184        u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float));
1185    }
1186    u->output_window = alloc(FILTER_SIZE(u), sizeof(fftwf_complex));
1187    u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
1188    u->inverse_plan = fftwf_plan_dft_c2r_1d(u->fft_size, u->output_window, u->work_buffer, FFTW_ESTIMATE);
1189
1190    hanning_window(u->W, u->window_size);
1191    u->first_iteration = true;
1192
1193    u->base_profiles = pa_xnew0(char *, u->channels);
1194    for (c = 0; c < u->channels; ++c)
1195        u->base_profiles[c] = pa_xstrdup("default");
1196
1197    /* Create sink */
1198    pa_sink_new_data_init(&sink_data);
1199    sink_data.driver = __FILE__;
1200    sink_data.module = m;
1201    if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
1202        sink_data.name = pa_sprintf_malloc("%s.equalizer", master->name);
1203    pa_sink_new_data_set_sample_spec(&sink_data, &ss);
1204    pa_sink_new_data_set_channel_map(&sink_data, &map);
1205
1206    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
1207    pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1208
1209    if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
1210        pa_log("Invalid properties");
1211        pa_sink_new_data_done(&sink_data);
1212        goto fail;
1213    }
1214
1215    if (!pa_proplist_contains(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION)) {
1216        const char *master_description;
1217
1218        master_description = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1219        pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION,
1220                         _("FFT based equalizer on %s"), master_description ? master_description : master->name);
1221        u->automatic_description = true;
1222    }
1223
1224    u->autoloaded = DEFAULT_AUTOLOADED;
1225    if (pa_modargs_get_value_boolean(ma, "autoloaded", &u->autoloaded) < 0) {
1226        pa_log("Failed to parse autoloaded value");
1227        goto fail;
1228    }
1229
1230    u->sink = pa_sink_new(m->core, &sink_data, (master->flags & (PA_SINK_LATENCY | PA_SINK_DYNAMIC_LATENCY))
1231                                               | (use_volume_sharing ? PA_SINK_SHARE_VOLUME_WITH_MASTER : 0));
1232    pa_sink_new_data_done(&sink_data);
1233
1234    if (!u->sink) {
1235        pa_log("Failed to create sink.");
1236        goto fail;
1237    }
1238
1239    u->sink->parent.process_msg = sink_process_msg_cb;
1240    u->sink->set_state_in_main_thread = sink_set_state_in_main_thread_cb;
1241    u->sink->set_state_in_io_thread = sink_set_state_in_io_thread_cb;
1242    u->sink->update_requested_latency = sink_update_requested_latency_cb;
1243    u->sink->request_rewind = sink_request_rewind_cb;
1244    pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
1245    if (!use_volume_sharing) {
1246        pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
1247        pa_sink_enable_decibel_volume(u->sink, true);
1248    }
1249    u->sink->userdata = u;
1250
1251    u->input_q = pa_memblockq_new("module-equalizer-sink input_q", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, &u->sink->silence);
1252    u->output_q = pa_memblockq_new("module-equalizer-sink output_q", 0, MEMBLOCKQ_MAXLENGTH, 0, &ss, 1, 1, 0, NULL);
1253    u->output_buffer = NULL;
1254    u->output_buffer_length = 0;
1255    u->output_buffer_max_length = 0;
1256
1257    pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
1258    //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1259
1260    /* Create sink input */
1261    pa_sink_input_new_data_init(&sink_input_data);
1262    sink_input_data.driver = __FILE__;
1263    sink_input_data.module = m;
1264    pa_sink_input_new_data_set_sink(&sink_input_data, master, false, true);
1265    sink_input_data.origin_sink = u->sink;
1266    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
1267    pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1268    pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
1269    pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
1270    sink_input_data.flags |= PA_SINK_INPUT_START_CORKED;
1271
1272    pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
1273    pa_sink_input_new_data_done(&sink_input_data);
1274
1275    if (!u->sink_input)
1276        goto fail;
1277
1278    u->sink_input->pop = sink_input_pop_cb;
1279    u->sink_input->process_rewind = sink_input_process_rewind_cb;
1280    u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1281    u->sink_input->update_max_request = sink_input_update_max_request_cb;
1282    u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
1283    u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
1284    u->sink_input->kill = sink_input_kill_cb;
1285    u->sink_input->attach = sink_input_attach_cb;
1286    u->sink_input->detach = sink_input_detach_cb;
1287    u->sink_input->may_move_to = sink_input_may_move_to_cb;
1288    u->sink_input->moving = sink_input_moving_cb;
1289    if (!use_volume_sharing)
1290        u->sink_input->volume_changed = sink_input_volume_changed_cb;
1291    u->sink_input->mute_changed = sink_input_mute_changed_cb;
1292    u->sink_input->userdata = u;
1293
1294    u->sink->input_to_master = u->sink_input;
1295
1296    dbus_init(u);
1297
1298    /* default filter to these */
1299    for (c = 0; c< u->channels; ++c) {
1300        a_i = pa_aupdate_write_begin(u->a_H[c]);
1301        H = u->Hs[c][a_i];
1302        u->Xs[c][a_i] = 1.0f;
1303
1304        for(i = 0; i < FILTER_SIZE(u); ++i)
1305            H[i] = 1.0 / sqrtf(2.0f);
1306
1307        fix_filter(H, u->fft_size);
1308        pa_aupdate_write_end(u->a_H[c]);
1309    }
1310
1311    /* load old parameters */
1312    load_state(u);
1313
1314    /* The order here is important. The input must be put first,
1315     * otherwise streams might attach to the sink before the sink
1316     * input is attached to the master. */
1317    pa_sink_input_put(u->sink_input);
1318    pa_sink_put(u->sink);
1319    pa_sink_input_cork(u->sink_input, false);
1320
1321    pa_modargs_free(ma);
1322
1323    return 0;
1324
1325fail:
1326    if (ma)
1327        pa_modargs_free(ma);
1328
1329    pa__done(m);
1330
1331    return -1;
1332}
1333
1334int pa__get_n_used(pa_module *m) {
1335    struct userdata *u;
1336
1337    pa_assert(m);
1338    pa_assert_se(u = m->userdata);
1339
1340    return pa_sink_linked_by(u->sink);
1341}
1342
1343void pa__done(pa_module*m) {
1344    struct userdata *u;
1345    unsigned c;
1346
1347    pa_assert(m);
1348
1349    if (!(u = m->userdata))
1350        return;
1351
1352    save_state(u);
1353
1354    dbus_done(u);
1355
1356    for(c = 0; c < u->channels; ++c)
1357        pa_xfree(u->base_profiles[c]);
1358    pa_xfree(u->base_profiles);
1359
1360    /* See comments in sink_input_kill_cb() above regarding
1361     * destruction order! */
1362
1363    if (u->sink_input)
1364        pa_sink_input_cork(u->sink_input, true);
1365
1366    if (u->sink)
1367        pa_sink_unlink(u->sink);
1368
1369    if (u->sink_input) {
1370        pa_sink_input_unlink(u->sink_input);
1371        pa_sink_input_unref(u->sink_input);
1372}
1373
1374    if (u->sink)
1375        pa_sink_unref(u->sink);
1376
1377    pa_xfree(u->output_buffer);
1378    pa_memblockq_free(u->output_q);
1379    pa_memblockq_free(u->input_q);
1380
1381    fftwf_destroy_plan(u->inverse_plan);
1382    fftwf_destroy_plan(u->forward_plan);
1383    fftwf_free(u->output_window);
1384    for (c = 0; c < u->channels; ++c) {
1385        pa_aupdate_free(u->a_H[c]);
1386        fftwf_free(u->overlap_accum[c]);
1387        fftwf_free(u->input[c]);
1388    }
1389    pa_xfree(u->a_H);
1390    pa_xfree(u->overlap_accum);
1391    pa_xfree(u->input);
1392    fftwf_free(u->work_buffer);
1393    fftwf_free(u->W);
1394    for (c = 0; c < u->channels; ++c) {
1395        pa_xfree(u->Xs[c]);
1396        for (size_t i = 0; i < 2; ++i)
1397            fftwf_free(u->Hs[c][i]);
1398        fftwf_free(u->Hs[c]);
1399    }
1400    pa_xfree(u->Xs);
1401    pa_xfree(u->Hs);
1402
1403    pa_xfree(u);
1404}
1405
1406/*
1407 * DBus Routines and Callbacks
1408 */
1409#define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1410#define MANAGER_PATH "/org/pulseaudio/equalizing1"
1411#define MANAGER_IFACE EXTNAME ".Manager"
1412#define EQUALIZER_IFACE EXTNAME ".Equalizer"
1413static void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1414static void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u);
1415static void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u);
1416static void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1417static void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1418static void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1419static void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1420static void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1421static void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u);
1422static void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u);
1423static void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1424static void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1425static void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u);
1426static void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1427static void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1428static void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1429static void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1430static void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u);
1431static void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u);
1432enum manager_method_index {
1433    MANAGER_METHOD_REMOVE_PROFILE,
1434    MANAGER_METHOD_MAX
1435};
1436
1437pa_dbus_arg_info remove_profile_args[]={
1438    {"name", "s","in"},
1439};
1440
1441static pa_dbus_method_handler manager_methods[MANAGER_METHOD_MAX]={
1442    [MANAGER_METHOD_REMOVE_PROFILE]={
1443        .method_name="RemoveProfile",
1444        .arguments=remove_profile_args,
1445        .n_arguments=sizeof(remove_profile_args)/sizeof(pa_dbus_arg_info),
1446        .receive_cb=manager_handle_remove_profile}
1447};
1448
1449enum manager_handler_index {
1450    MANAGER_HANDLER_REVISION,
1451    MANAGER_HANDLER_EQUALIZED_SINKS,
1452    MANAGER_HANDLER_PROFILES,
1453    MANAGER_HANDLER_MAX
1454};
1455
1456static pa_dbus_property_handler manager_handlers[MANAGER_HANDLER_MAX]={
1457    [MANAGER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=manager_get_revision,.set_cb=NULL},
1458    [MANAGER_HANDLER_EQUALIZED_SINKS]={.property_name="EqualizedSinks",.type="ao",.get_cb=manager_get_sinks,.set_cb=NULL},
1459    [MANAGER_HANDLER_PROFILES]={.property_name="Profiles",.type="as",.get_cb=manager_get_profiles,.set_cb=NULL}
1460};
1461
1462pa_dbus_arg_info sink_args[]={
1463    {"sink", "o", NULL}
1464};
1465
1466enum manager_signal_index{
1467    MANAGER_SIGNAL_SINK_ADDED,
1468    MANAGER_SIGNAL_SINK_REMOVED,
1469    MANAGER_SIGNAL_PROFILES_CHANGED,
1470    MANAGER_SIGNAL_MAX
1471};
1472
1473static pa_dbus_signal_info manager_signals[MANAGER_SIGNAL_MAX]={
1474    [MANAGER_SIGNAL_SINK_ADDED]={.name="SinkAdded", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1475    [MANAGER_SIGNAL_SINK_REMOVED]={.name="SinkRemoved", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1476    [MANAGER_SIGNAL_PROFILES_CHANGED]={.name="ProfilesChanged", .arguments=NULL, .n_arguments=0}
1477};
1478
1479static pa_dbus_interface_info manager_info={
1480    .name=MANAGER_IFACE,
1481    .method_handlers=manager_methods,
1482    .n_method_handlers=MANAGER_METHOD_MAX,
1483    .property_handlers=manager_handlers,
1484    .n_property_handlers=MANAGER_HANDLER_MAX,
1485    .get_all_properties_cb=manager_get_all,
1486    .signals=manager_signals,
1487    .n_signals=MANAGER_SIGNAL_MAX
1488};
1489
1490enum equalizer_method_index {
1491    EQUALIZER_METHOD_FILTER_POINTS,
1492    EQUALIZER_METHOD_SEED_FILTER,
1493    EQUALIZER_METHOD_SAVE_PROFILE,
1494    EQUALIZER_METHOD_LOAD_PROFILE,
1495    EQUALIZER_METHOD_SET_FILTER,
1496    EQUALIZER_METHOD_GET_FILTER,
1497    EQUALIZER_METHOD_SAVE_STATE,
1498    EQUALIZER_METHOD_GET_PROFILE_NAME,
1499    EQUALIZER_METHOD_MAX
1500};
1501
1502enum equalizer_handler_index {
1503    EQUALIZER_HANDLER_REVISION,
1504    EQUALIZER_HANDLER_SAMPLERATE,
1505    EQUALIZER_HANDLER_FILTERSAMPLERATE,
1506    EQUALIZER_HANDLER_N_COEFS,
1507    EQUALIZER_HANDLER_N_CHANNELS,
1508    EQUALIZER_HANDLER_MAX
1509};
1510
1511pa_dbus_arg_info filter_points_args[]={
1512    {"channel", "u","in"},
1513    {"xs", "au","in"},
1514    {"ys", "ad","out"},
1515    {"preamp", "d","out"}
1516};
1517pa_dbus_arg_info seed_filter_args[]={
1518    {"channel", "u","in"},
1519    {"xs", "au","in"},
1520    {"ys", "ad","in"},
1521    {"preamp", "d","in"}
1522};
1523
1524pa_dbus_arg_info set_filter_args[]={
1525    {"channel", "u","in"},
1526    {"ys", "ad","in"},
1527    {"preamp", "d","in"}
1528};
1529pa_dbus_arg_info get_filter_args[]={
1530    {"channel", "u","in"},
1531    {"ys", "ad","out"},
1532    {"preamp", "d","out"}
1533};
1534
1535pa_dbus_arg_info save_profile_args[]={
1536    {"channel", "u","in"},
1537    {"name", "s","in"}
1538};
1539pa_dbus_arg_info load_profile_args[]={
1540    {"channel", "u","in"},
1541    {"name", "s","in"}
1542};
1543pa_dbus_arg_info base_profile_name_args[]={
1544    {"channel", "u","in"},
1545    {"name", "s","out"}
1546};
1547
1548static pa_dbus_method_handler equalizer_methods[EQUALIZER_METHOD_MAX]={
1549    [EQUALIZER_METHOD_SEED_FILTER]={
1550        .method_name="SeedFilter",
1551        .arguments=seed_filter_args,
1552        .n_arguments=sizeof(seed_filter_args)/sizeof(pa_dbus_arg_info),
1553        .receive_cb=equalizer_handle_seed_filter},
1554    [EQUALIZER_METHOD_FILTER_POINTS]={
1555        .method_name="FilterAtPoints",
1556        .arguments=filter_points_args,
1557        .n_arguments=sizeof(filter_points_args)/sizeof(pa_dbus_arg_info),
1558        .receive_cb=equalizer_handle_get_filter_points},
1559    [EQUALIZER_METHOD_SET_FILTER]={
1560        .method_name="SetFilter",
1561        .arguments=set_filter_args,
1562        .n_arguments=sizeof(set_filter_args)/sizeof(pa_dbus_arg_info),
1563        .receive_cb=equalizer_handle_set_filter},
1564    [EQUALIZER_METHOD_GET_FILTER]={
1565        .method_name="GetFilter",
1566        .arguments=get_filter_args,
1567        .n_arguments=sizeof(get_filter_args)/sizeof(pa_dbus_arg_info),
1568        .receive_cb=equalizer_handle_get_filter},
1569    [EQUALIZER_METHOD_SAVE_PROFILE]={
1570        .method_name="SaveProfile",
1571        .arguments=save_profile_args,
1572        .n_arguments=sizeof(save_profile_args)/sizeof(pa_dbus_arg_info),
1573        .receive_cb=equalizer_handle_save_profile},
1574    [EQUALIZER_METHOD_LOAD_PROFILE]={
1575        .method_name="LoadProfile",
1576        .arguments=load_profile_args,
1577        .n_arguments=sizeof(load_profile_args)/sizeof(pa_dbus_arg_info),
1578        .receive_cb=equalizer_handle_load_profile},
1579    [EQUALIZER_METHOD_SAVE_STATE]={
1580        .method_name="SaveState",
1581        .arguments=NULL,
1582        .n_arguments=0,
1583        .receive_cb=equalizer_handle_save_state},
1584    [EQUALIZER_METHOD_GET_PROFILE_NAME]={
1585        .method_name="BaseProfile",
1586        .arguments=base_profile_name_args,
1587        .n_arguments=sizeof(base_profile_name_args)/sizeof(pa_dbus_arg_info),
1588        .receive_cb=equalizer_handle_get_profile_name}
1589};
1590
1591static pa_dbus_property_handler equalizer_handlers[EQUALIZER_HANDLER_MAX]={
1592    [EQUALIZER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=equalizer_get_revision,.set_cb=NULL},
1593    [EQUALIZER_HANDLER_SAMPLERATE]={.property_name="SampleRate",.type="u",.get_cb=equalizer_get_sample_rate,.set_cb=NULL},
1594    [EQUALIZER_HANDLER_FILTERSAMPLERATE]={.property_name="FilterSampleRate",.type="u",.get_cb=equalizer_get_filter_rate,.set_cb=NULL},
1595    [EQUALIZER_HANDLER_N_COEFS]={.property_name="NFilterCoefficients",.type="u",.get_cb=equalizer_get_n_coefs,.set_cb=NULL},
1596    [EQUALIZER_HANDLER_N_CHANNELS]={.property_name="NChannels",.type="u",.get_cb=equalizer_get_n_channels,.set_cb=NULL},
1597};
1598
1599enum equalizer_signal_index{
1600    EQUALIZER_SIGNAL_FILTER_CHANGED,
1601    EQUALIZER_SIGNAL_SINK_RECONFIGURED,
1602    EQUALIZER_SIGNAL_MAX
1603};
1604
1605static pa_dbus_signal_info equalizer_signals[EQUALIZER_SIGNAL_MAX]={
1606    [EQUALIZER_SIGNAL_FILTER_CHANGED]={.name="FilterChanged", .arguments=NULL, .n_arguments=0},
1607    [EQUALIZER_SIGNAL_SINK_RECONFIGURED]={.name="SinkReconfigured", .arguments=NULL, .n_arguments=0},
1608};
1609
1610static pa_dbus_interface_info equalizer_info={
1611    .name=EQUALIZER_IFACE,
1612    .method_handlers=equalizer_methods,
1613    .n_method_handlers=EQUALIZER_METHOD_MAX,
1614    .property_handlers=equalizer_handlers,
1615    .n_property_handlers=EQUALIZER_HANDLER_MAX,
1616    .get_all_properties_cb=equalizer_get_all,
1617    .signals=equalizer_signals,
1618    .n_signals=EQUALIZER_SIGNAL_MAX
1619};
1620
1621void dbus_init(struct userdata *u) {
1622    uint32_t dummy;
1623    DBusMessage *message = NULL;
1624    pa_idxset *sink_list = NULL;
1625    u->dbus_protocol=pa_dbus_protocol_get(u->sink->core);
1626    u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index);
1627
1628    pa_assert_se(pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &equalizer_info, u) >= 0);
1629    sink_list = pa_shared_get(u->sink->core, SINKLIST);
1630    u->database = pa_shared_get(u->sink->core, EQDB);
1631    if (sink_list == NULL) {
1632        char *state_path;
1633        sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
1634        pa_shared_set(u->sink->core, SINKLIST, sink_list);
1635        pa_assert_se(state_path = pa_state_path(NULL, false));
1636        pa_assert_se(u->database = pa_database_open(state_path, "equalizer-presets", false, true));
1637        pa_xfree(state_path);
1638        pa_shared_set(u->sink->core, EQDB, u->database);
1639        pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
1640        pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
1641    }
1642    pa_idxset_put(sink_list, u, &dummy);
1643
1644    pa_assert_se((message = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_ADDED].name)));
1645    dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1646    pa_dbus_protocol_send_signal(u->dbus_protocol, message);
1647    dbus_message_unref(message);
1648}
1649
1650void dbus_done(struct userdata *u) {
1651    pa_idxset *sink_list;
1652    uint32_t dummy;
1653
1654    DBusMessage *message = NULL;
1655    pa_assert_se((message = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_REMOVED].name)));
1656    dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1657    pa_dbus_protocol_send_signal(u->dbus_protocol, message);
1658    dbus_message_unref(message);
1659
1660    pa_assert_se(sink_list=pa_shared_get(u->sink->core,SINKLIST));
1661    pa_idxset_remove_by_data(sink_list,u,&dummy);
1662    if (pa_idxset_size(sink_list) == 0) {
1663        pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME);
1664        pa_dbus_protocol_remove_interface(u->dbus_protocol, MANAGER_PATH, manager_info.name);
1665        pa_shared_remove(u->sink->core, EQDB);
1666        pa_database_close(u->database);
1667        pa_shared_remove(u->sink->core, SINKLIST);
1668        pa_xfree(sink_list);
1669    }
1670    pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, equalizer_info.name);
1671    pa_xfree(u->dbus_path);
1672    pa_dbus_protocol_unref(u->dbus_protocol);
1673}
1674
1675void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1676    DBusError error;
1677    pa_core *c = (pa_core *)_u;
1678    DBusMessage *message = NULL;
1679    pa_dbus_protocol *dbus_protocol;
1680    char *name;
1681    pa_assert(conn);
1682    pa_assert(msg);
1683    pa_assert(c);
1684    dbus_error_init(&error);
1685    if (!dbus_message_get_args(msg, &error,
1686                 DBUS_TYPE_STRING, &name,
1687                DBUS_TYPE_INVALID)) {
1688        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1689        dbus_error_free(&error);
1690        return;
1691    }
1692    remove_profile(c,name);
1693    pa_dbus_send_empty_reply(conn, msg);
1694
1695    pa_assert_se((message = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
1696    dbus_protocol = pa_dbus_protocol_get(c);
1697    pa_dbus_protocol_send_signal(dbus_protocol, message);
1698    pa_dbus_protocol_unref(dbus_protocol);
1699    dbus_message_unref(message);
1700}
1701
1702void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u) {
1703    uint32_t rev=1;
1704    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
1705}
1706
1707static void get_sinks(pa_core *u, char ***names, unsigned *n_sinks) {
1708    void *iter = NULL;
1709    struct userdata *sink_u = NULL;
1710    uint32_t dummy;
1711    pa_idxset *sink_list;
1712    pa_assert(u);
1713    pa_assert(names);
1714    pa_assert(n_sinks);
1715
1716    pa_assert_se(sink_list = pa_shared_get(u, SINKLIST));
1717    *n_sinks = (unsigned) pa_idxset_size(sink_list);
1718    *names = *n_sinks > 0 ? pa_xnew0(char *,*n_sinks) : NULL;
1719    for(uint32_t i = 0; i < *n_sinks; ++i) {
1720        sink_u = (struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy);
1721        (*names)[i] = pa_xstrdup(sink_u->dbus_path);
1722    }
1723}
1724
1725void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u) {
1726    unsigned n;
1727    char **names = NULL;
1728    pa_assert(conn);
1729    pa_assert(msg);
1730    pa_assert(_u);
1731
1732    get_sinks((pa_core *) _u, &names, &n);
1733    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, names, n);
1734    for(unsigned i = 0; i < n; ++i) {
1735        pa_xfree(names[i]);
1736    }
1737    pa_xfree(names);
1738}
1739
1740static void get_profiles(pa_core *c, char ***names, unsigned *n) {
1741    char *name;
1742    pa_database *database;
1743    pa_datum key, next_key;
1744    pa_strlist *head=NULL, *iter;
1745    bool done;
1746    pa_assert_se(database = pa_shared_get(c, EQDB));
1747
1748    pa_assert(c);
1749    pa_assert(names);
1750    pa_assert(n);
1751    done = !pa_database_first(database, &key, NULL);
1752    *n = 0;
1753    while(!done) {
1754        done = !pa_database_next(database, &key, &next_key, NULL);
1755        name=pa_xmalloc(key.size + 1);
1756        memcpy(name, key.data, key.size);
1757        name[key.size] = '\0';
1758        pa_datum_free(&key);
1759        head = pa_strlist_prepend(head, name);
1760        pa_xfree(name);
1761        key = next_key;
1762        (*n)++;
1763    }
1764    (*names) = *n > 0 ? pa_xnew0(char *, *n) : NULL;
1765    iter=head;
1766    for(unsigned i = 0; i < *n; ++i) {
1767        (*names)[*n - 1 - i] = pa_xstrdup(pa_strlist_data(iter));
1768        iter = pa_strlist_next(iter);
1769    }
1770    pa_strlist_free(head);
1771}
1772
1773void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u) {
1774    char **names;
1775    unsigned n;
1776    pa_assert(conn);
1777    pa_assert(msg);
1778    pa_assert(_u);
1779
1780    get_profiles((pa_core *)_u, &names, &n);
1781    pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, names, n);
1782    for(unsigned i = 0; i < n; ++i) {
1783        pa_xfree(names[i]);
1784    }
1785    pa_xfree(names);
1786}
1787
1788void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u) {
1789    pa_core *c;
1790    char **names = NULL;
1791    unsigned n;
1792    DBusMessage *reply = NULL;
1793    DBusMessageIter msg_iter, dict_iter;
1794    uint32_t rev;
1795    pa_assert(conn);
1796    pa_assert(msg);
1797    pa_assert_se(c = _u);
1798
1799    pa_assert_se((reply = dbus_message_new_method_return(msg)));
1800    dbus_message_iter_init_append(reply, &msg_iter);
1801    pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1802
1803    rev = 1;
1804    pa_dbus_append_basic_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
1805
1806    get_sinks(c, &names, &n);
1807    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter,manager_handlers[MANAGER_HANDLER_EQUALIZED_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, names, n);
1808    for(unsigned i = 0; i < n; ++i) {
1809        pa_xfree(names[i]);
1810    }
1811    pa_xfree(names);
1812
1813    get_profiles(c, &names, &n);
1814    pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_PROFILES].property_name, DBUS_TYPE_STRING, names, n);
1815    for(unsigned i = 0; i < n; ++i) {
1816        pa_xfree(names[i]);
1817    }
1818    pa_xfree(names);
1819    pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1820    pa_assert_se(dbus_connection_send(conn, reply, NULL));
1821    dbus_message_unref(reply);
1822}
1823
1824void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
1825    struct userdata *u = _u;
1826    DBusError error;
1827    DBusMessage *message = NULL;
1828    float *ys;
1829    uint32_t *xs, channel, r_channel;
1830    double *_ys, preamp;
1831    unsigned x_npoints, y_npoints, a_i;
1832    float *H;
1833    bool points_good = true;
1834
1835    pa_assert(conn);
1836    pa_assert(msg);
1837    pa_assert(u);
1838
1839    dbus_error_init(&error);
1840
1841    if (!dbus_message_get_args(msg, &error,
1842                DBUS_TYPE_UINT32, &channel,
1843                DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1844                DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &_ys, &y_npoints,
1845                DBUS_TYPE_DOUBLE, &preamp,
1846                DBUS_TYPE_INVALID)) {
1847        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1848        dbus_error_free(&error);
1849        return;
1850    }
1851    if (channel > u->channels) {
1852        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1853        dbus_error_free(&error);
1854        return;
1855    }
1856    for(size_t i = 0; i < x_npoints; ++i) {
1857        if (xs[i] >= FILTER_SIZE(u)) {
1858            points_good = false;
1859            break;
1860        }
1861    }
1862    if (!is_monotonic(xs, x_npoints) || !points_good) {
1863        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs must be monotonic and 0<=x<=%zd", u->fft_size / 2);
1864        dbus_error_free(&error);
1865        return;
1866    }else if (x_npoints != y_npoints || x_npoints < 2 || x_npoints > FILTER_SIZE(u)) {
1867        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs and ys must be the same length and 2<=l<=%zd!", FILTER_SIZE(u));
1868        dbus_error_free(&error);
1869        return;
1870    }else if (xs[0] != 0 || xs[x_npoints - 1] != u->fft_size / 2) {
1871        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs[0] must be 0 and xs[-1]=fft_size/2");
1872        dbus_error_free(&error);
1873        return;
1874    }
1875
1876    ys = pa_xmalloc(x_npoints * sizeof(float));
1877    for(uint32_t i = 0; i < x_npoints; ++i) {
1878        ys[i] = (float) _ys[i];
1879    }
1880    r_channel = channel == u->channels ? 0 : channel;
1881    a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1882    H = u->Hs[r_channel][a_i];
1883    u->Xs[r_channel][a_i] = preamp;
1884    interpolate(H, FILTER_SIZE(u), xs, ys, x_npoints);
1885    fix_filter(H, u->fft_size);
1886    if (channel == u->channels) {
1887        for(size_t c = 1; c < u->channels; ++c) {
1888            unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1889            float *H_p = u->Hs[c][b_i];
1890            u->Xs[c][b_i] = preamp;
1891            memcpy(H_p, H, FILTER_SIZE(u) * sizeof(float));
1892            pa_aupdate_write_end(u->a_H[c]);
1893        }
1894    }
1895    pa_aupdate_write_end(u->a_H[r_channel]);
1896    pa_xfree(ys);
1897
1898    pa_dbus_send_empty_reply(conn, msg);
1899
1900    pa_assert_se((message = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
1901    pa_dbus_protocol_send_signal(u->dbus_protocol, message);
1902    dbus_message_unref(message);
1903}
1904
1905void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u) {
1906    struct userdata *u = (struct userdata *) _u;
1907    uint32_t *xs, channel, r_channel;
1908    double *ys, preamp;
1909    unsigned x_npoints, a_i;
1910    float *H;
1911    bool points_good=true;
1912    DBusMessage *reply = NULL;
1913    DBusMessageIter msg_iter;
1914    DBusError error;
1915
1916    pa_assert(conn);
1917    pa_assert(msg);
1918    pa_assert(u);
1919
1920    dbus_error_init(&error);
1921    if (!dbus_message_get_args(msg, &error,
1922                DBUS_TYPE_UINT32, &channel,
1923                DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1924                DBUS_TYPE_INVALID)) {
1925        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1926        dbus_error_free(&error);
1927        return;
1928    }
1929    if (channel > u->channels) {
1930        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1931        dbus_error_free(&error);
1932        return;
1933    }
1934
1935    for(size_t i = 0; i < x_npoints; ++i) {
1936        if (xs[i] >= FILTER_SIZE(u)) {
1937            points_good=false;
1938            break;
1939        }
1940    }
1941
1942    if (x_npoints > FILTER_SIZE(u) || !points_good) {
1943        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs indices/length must be <= %zd!", FILTER_SIZE(u));
1944        dbus_error_free(&error);
1945        return;
1946    }
1947
1948    r_channel = channel == u->channels ? 0 : channel;
1949    ys = pa_xmalloc(x_npoints * sizeof(double));
1950    a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1951    H = u->Hs[r_channel][a_i];
1952    preamp = u->Xs[r_channel][a_i];
1953    for(uint32_t i = 0; i < x_npoints; ++i) {
1954        ys[i] = H[xs[i]] * u->fft_size;
1955    }
1956    pa_aupdate_read_end(u->a_H[r_channel]);
1957
1958    pa_assert_se((reply = dbus_message_new_method_return(msg)));
1959    dbus_message_iter_init_append(reply, &msg_iter);
1960
1961    pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, ys, x_npoints);
1962    pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1963
1964    pa_assert_se(dbus_connection_send(conn, reply, NULL));
1965    dbus_message_unref(reply);
1966    pa_xfree(ys);
1967}
1968
1969static void get_filter(struct userdata *u, size_t channel, double **H_, double *preamp) {
1970    float *H;
1971    unsigned a_i;
1972    size_t r_channel = channel == u->channels ? 0 : channel;
1973    *H_ = pa_xnew0(double, FILTER_SIZE(u));
1974    a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1975    H = u->Hs[r_channel][a_i];
1976    for(size_t i = 0;i < FILTER_SIZE(u); ++i) {
1977        (*H_)[i] = H[i] * u->fft_size;
1978    }
1979    *preamp = u->Xs[r_channel][a_i];
1980
1981    pa_aupdate_read_end(u->a_H[r_channel]);
1982}
1983
1984void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
1985    struct userdata *u;
1986    unsigned n_coefs;
1987    uint32_t channel;
1988    double *H_, preamp;
1989    DBusMessage *reply = NULL;
1990    DBusMessageIter msg_iter;
1991    DBusError error;
1992    pa_assert_se(u = (struct userdata *) _u);
1993    pa_assert(conn);
1994    pa_assert(msg);
1995
1996    dbus_error_init(&error);
1997    if (!dbus_message_get_args(msg, &error,
1998                DBUS_TYPE_UINT32, &channel,
1999                DBUS_TYPE_INVALID)) {
2000        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2001        dbus_error_free(&error);
2002        return;
2003    }
2004    if (channel > u->channels) {
2005        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2006        dbus_error_free(&error);
2007        return;
2008    }
2009
2010    n_coefs = CHANNEL_PROFILE_SIZE(u);
2011    pa_assert(conn);
2012    pa_assert(msg);
2013    get_filter(u, channel, &H_, &preamp);
2014    pa_assert_se((reply = dbus_message_new_method_return(msg)));
2015    dbus_message_iter_init_append(reply, &msg_iter);
2016
2017    pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, H_, n_coefs);
2018    pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
2019
2020    pa_assert_se(dbus_connection_send(conn, reply, NULL));
2021    dbus_message_unref(reply);
2022    pa_xfree(H_);
2023}
2024
2025static void set_filter(struct userdata *u, size_t channel, double *H_, double preamp) {
2026    unsigned a_i;
2027    size_t r_channel = channel == u->channels ? 0 : channel;
2028    float *H;
2029    //all channels
2030    a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
2031    u->Xs[r_channel][a_i] = (float) preamp;
2032    H = u->Hs[r_channel][a_i];
2033    for(size_t i = 0; i < FILTER_SIZE(u); ++i) {
2034        H[i] = (float) H_[i];
2035    }
2036    fix_filter(H, u->fft_size);
2037    if (channel == u->channels) {
2038        for(size_t c = 1; c < u->channels; ++c) {
2039            unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
2040            u->Xs[c][b_i] = u->Xs[r_channel][a_i];
2041            memcpy(u->Hs[c][b_i], u->Hs[r_channel][a_i], FILTER_SIZE(u) * sizeof(float));
2042            pa_aupdate_write_end(u->a_H[c]);
2043        }
2044    }
2045    pa_aupdate_write_end(u->a_H[r_channel]);
2046}
2047
2048void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
2049    struct userdata *u;
2050    double *H, preamp;
2051    uint32_t channel;
2052    unsigned _n_coefs;
2053    DBusMessage *message = NULL;
2054    DBusError error;
2055    pa_assert_se(u = (struct userdata *) _u);
2056    pa_assert(conn);
2057    pa_assert(msg);
2058
2059    dbus_error_init(&error);
2060    if (!dbus_message_get_args(msg, &error,
2061                DBUS_TYPE_UINT32, &channel,
2062                DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &H, &_n_coefs,
2063                DBUS_TYPE_DOUBLE, &preamp,
2064                DBUS_TYPE_INVALID)) {
2065        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2066        dbus_error_free(&error);
2067        return;
2068    }
2069    if (channel > u->channels) {
2070        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2071        dbus_error_free(&error);
2072        return;
2073    }
2074    if (_n_coefs != FILTER_SIZE(u)) {
2075        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %zd coefficients, you gave %d", FILTER_SIZE(u), _n_coefs);
2076        return;
2077    }
2078    set_filter(u, channel, H, preamp);
2079
2080    pa_dbus_send_empty_reply(conn, msg);
2081
2082    pa_assert_se((message = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2083    pa_dbus_protocol_send_signal(u->dbus_protocol, message);
2084    dbus_message_unref(message);
2085}
2086
2087void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
2088    struct userdata *u = (struct userdata *) _u;
2089    char *name;
2090    uint32_t channel, r_channel;
2091    DBusMessage *message = NULL;
2092    DBusError error;
2093    pa_assert(conn);
2094    pa_assert(msg);
2095    pa_assert(u);
2096    dbus_error_init(&error);
2097
2098    if (!dbus_message_get_args(msg, &error,
2099                DBUS_TYPE_UINT32, &channel,
2100                DBUS_TYPE_STRING, &name,
2101                DBUS_TYPE_INVALID)) {
2102        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2103        dbus_error_free(&error);
2104        return;
2105    }
2106    if (channel > u->channels) {
2107        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2108        dbus_error_free(&error);
2109        return;
2110    }
2111    r_channel = channel == u->channels ? 0 : channel;
2112    save_profile(u, r_channel, name);
2113    pa_dbus_send_empty_reply(conn, msg);
2114
2115    pa_assert_se((message = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
2116    pa_dbus_protocol_send_signal(u->dbus_protocol, message);
2117    dbus_message_unref(message);
2118}
2119
2120void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
2121    struct userdata *u = (struct userdata *) _u;
2122    char *name;
2123    DBusError error;
2124    uint32_t channel, r_channel;
2125    const char *err_msg = NULL;
2126    DBusMessage *message = NULL;
2127
2128    pa_assert(conn);
2129    pa_assert(msg);
2130    pa_assert(u);
2131    dbus_error_init(&error);
2132
2133    if (!dbus_message_get_args(msg, &error,
2134                DBUS_TYPE_UINT32, &channel,
2135                DBUS_TYPE_STRING, &name,
2136                DBUS_TYPE_INVALID)) {
2137        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2138        dbus_error_free(&error);
2139        return;
2140    }
2141    if (channel > u->channels) {
2142        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2143        dbus_error_free(&error);
2144        return;
2145    }
2146    r_channel = channel == u->channels ? 0 : channel;
2147
2148    err_msg = load_profile(u, r_channel, name);
2149    if (err_msg != NULL) {
2150        pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "error loading profile %s: %s", name, err_msg);
2151        dbus_error_free(&error);
2152        return;
2153    }
2154    if (channel == u->channels) {
2155        for(uint32_t c = 1; c < u->channels; ++c) {
2156            load_profile(u, c, name);
2157        }
2158    }
2159    pa_dbus_send_empty_reply(conn, msg);
2160
2161    pa_assert_se((message = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2162    pa_dbus_protocol_send_signal(u->dbus_protocol, message);
2163    dbus_message_unref(message);
2164}
2165
2166void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u) {
2167    struct userdata *u = (struct userdata *) _u;
2168    pa_assert(conn);
2169    pa_assert(msg);
2170    pa_assert(u);
2171
2172    save_state(u);
2173    pa_dbus_send_empty_reply(conn, msg);
2174}
2175
2176void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u) {
2177    struct userdata *u = (struct userdata *) _u;
2178    DBusError error;
2179    uint32_t channel, r_channel;
2180
2181    pa_assert(conn);
2182    pa_assert(msg);
2183    pa_assert(u);
2184    dbus_error_init(&error);
2185
2186    if (!dbus_message_get_args(msg, &error,
2187                DBUS_TYPE_UINT32, &channel,
2188                DBUS_TYPE_INVALID)) {
2189        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2190        dbus_error_free(&error);
2191        return;
2192    }
2193    if (channel > u->channels) {
2194        pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2195        dbus_error_free(&error);
2196        return;
2197    }
2198    r_channel = channel == u->channels ? 0 : channel;
2199    pa_assert(u->base_profiles[r_channel]);
2200    pa_dbus_send_basic_value_reply(conn,msg, DBUS_TYPE_STRING, &u->base_profiles[r_channel]);
2201}
2202
2203void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u) {
2204    uint32_t rev=1;
2205    pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
2206}
2207
2208void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u) {
2209    struct userdata *u;
2210    uint32_t channels;
2211    pa_assert_se(u = (struct userdata *) _u);
2212    pa_assert(conn);
2213    pa_assert(msg);
2214
2215    channels = (uint32_t) u->channels;
2216    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &channels);
2217}
2218
2219void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u) {
2220    struct userdata *u;
2221    uint32_t n_coefs;
2222    pa_assert_se(u = (struct userdata *) _u);
2223    pa_assert(conn);
2224    pa_assert(msg);
2225
2226    n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE(u);
2227    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs);
2228}
2229
2230void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u) {
2231    struct userdata *u;
2232    uint32_t rate;
2233    pa_assert_se(u = (struct userdata *) _u);
2234    pa_assert(conn);
2235    pa_assert(msg);
2236
2237    rate = (uint32_t) u->sink->sample_spec.rate;
2238    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &rate);
2239}
2240
2241void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u) {
2242    struct userdata *u;
2243    uint32_t fft_size;
2244    pa_assert_se(u = (struct userdata *) _u);
2245    pa_assert(conn);
2246    pa_assert(msg);
2247
2248    fft_size = (uint32_t) u->fft_size;
2249    pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &fft_size);
2250}
2251
2252void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u) {
2253    struct userdata *u;
2254    DBusMessage *reply = NULL;
2255    DBusMessageIter msg_iter, dict_iter;
2256    uint32_t rev, n_coefs, rate, fft_size, channels;
2257
2258    pa_assert_se(u = _u);
2259    pa_assert(msg);
2260
2261    rev = 1;
2262    n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE(u);
2263    rate = (uint32_t) u->sink->sample_spec.rate;
2264    fft_size = (uint32_t) u->fft_size;
2265    channels = (uint32_t) u->channels;
2266
2267    pa_assert_se((reply = dbus_message_new_method_return(msg)));
2268    dbus_message_iter_init_append(reply, &msg_iter);
2269    pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
2270
2271    pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
2272    pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_SAMPLERATE].property_name, DBUS_TYPE_UINT32, &rate);
2273    pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_FILTERSAMPLERATE].property_name, DBUS_TYPE_UINT32, &fft_size);
2274    pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs);
2275    pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_CHANNELS].property_name, DBUS_TYPE_UINT32, &channels);
2276
2277    pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
2278    pa_assert_se(dbus_connection_send(conn, reply, NULL));
2279    dbus_message_unref(reply);
2280}
2281