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