]> code.delx.au - pulseaudio/blob - src/modules/module-equalizer-sink.c
core: Link virtual sinks and sources to their streams.
[pulseaudio] / 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 sink_input_data.origin_sink = u->sink;
1204 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
1205 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1206 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
1207 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
1208
1209 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
1210 pa_sink_input_new_data_done(&sink_input_data);
1211
1212 if (!u->sink_input)
1213 goto fail;
1214
1215 u->sink_input->pop = sink_input_pop_cb;
1216 u->sink_input->process_rewind = sink_input_process_rewind_cb;
1217 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1218 u->sink_input->update_max_request = sink_input_update_max_request_cb;
1219 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
1220 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
1221 u->sink_input->kill = sink_input_kill_cb;
1222 u->sink_input->attach = sink_input_attach_cb;
1223 u->sink_input->detach = sink_input_detach_cb;
1224 u->sink_input->state_change = sink_input_state_change_cb;
1225 u->sink_input->may_move_to = sink_input_may_move_to_cb;
1226 u->sink_input->moving = sink_input_moving_cb;
1227 u->sink_input->volume_changed = sink_input_volume_changed_cb;
1228 u->sink_input->mute_changed = sink_input_mute_changed_cb;
1229 u->sink_input->userdata = u;
1230
1231 u->sink->input_to_master = u->sink_input;
1232
1233 dbus_init(u);
1234
1235 /* default filter to these */
1236 for (c = 0; c< u->channels; ++c) {
1237 a_i = pa_aupdate_write_begin(u->a_H[c]);
1238 H = u->Hs[c][a_i];
1239 u->Xs[c][a_i] = 1.0f;
1240
1241 for(i = 0; i < FILTER_SIZE(u); ++i)
1242 H[i] = 1.0 / sqrtf(2.0f);
1243
1244 fix_filter(H, u->fft_size);
1245 pa_aupdate_write_end(u->a_H[c]);
1246 }
1247
1248 /* load old parameters */
1249 load_state(u);
1250
1251 pa_sink_put(u->sink);
1252 pa_sink_input_put(u->sink_input);
1253
1254 pa_modargs_free(ma);
1255
1256 return 0;
1257
1258 fail:
1259 if (ma)
1260 pa_modargs_free(ma);
1261
1262 pa__done(m);
1263
1264 return -1;
1265 }
1266
1267 int pa__get_n_used(pa_module *m) {
1268 struct userdata *u;
1269
1270 pa_assert(m);
1271 pa_assert_se(u = m->userdata);
1272
1273 return pa_sink_linked_by(u->sink);
1274 }
1275
1276 void pa__done(pa_module*m) {
1277 struct userdata *u;
1278 unsigned c;
1279
1280 pa_assert(m);
1281
1282 if (!(u = m->userdata))
1283 return;
1284
1285 save_state(u);
1286
1287 dbus_done(u);
1288
1289 for(c = 0; c < u->channels; ++c)
1290 pa_xfree(u->base_profiles[c]);
1291 pa_xfree(u->base_profiles);
1292
1293 /* See comments in sink_input_kill_cb() above regarding
1294 * destruction order! */
1295
1296 if (u->sink_input)
1297 pa_sink_input_unlink(u->sink_input);
1298
1299 if (u->sink)
1300 pa_sink_unlink(u->sink);
1301
1302 if (u->sink_input)
1303 pa_sink_input_unref(u->sink_input);
1304
1305 if (u->sink)
1306 pa_sink_unref(u->sink);
1307
1308 pa_xfree(u->output_buffer);
1309 pa_memblockq_free(u->output_q);
1310 pa_memblockq_free(u->input_q);
1311
1312 fftwf_destroy_plan(u->inverse_plan);
1313 fftwf_destroy_plan(u->forward_plan);
1314 pa_xfree(u->output_window);
1315 for (c = 0; c < u->channels; ++c) {
1316 pa_aupdate_free(u->a_H[c]);
1317 pa_xfree(u->overlap_accum[c]);
1318 pa_xfree(u->input[c]);
1319 }
1320 pa_xfree(u->a_H);
1321 pa_xfree(u->overlap_accum);
1322 pa_xfree(u->input);
1323 pa_xfree(u->work_buffer);
1324 pa_xfree(u->W);
1325 for (c = 0; c < u->channels; ++c) {
1326 pa_xfree(u->Xs[c]);
1327 for (size_t i = 0; i < 2; ++i)
1328 pa_xfree(u->Hs[c][i]);
1329 pa_xfree(u->Hs[c]);
1330 }
1331 pa_xfree(u->Xs);
1332 pa_xfree(u->Hs);
1333
1334 pa_xfree(u);
1335 }
1336
1337 /*
1338 * DBus Routines and Callbacks
1339 */
1340 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1341 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1342 #define MANAGER_IFACE EXTNAME ".Manager"
1343 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1344 static void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1345 static void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u);
1346 static void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u);
1347 static void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1348 static void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1349 static void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1350 static void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1351 static void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1352 static void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u);
1353 static void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u);
1354 static void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1355 static void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1356 static void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u);
1357 static void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1358 static void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1359 static void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1360 static void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1361 static void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u);
1362 static void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u);
1363 enum manager_method_index {
1364 MANAGER_METHOD_REMOVE_PROFILE,
1365 MANAGER_METHOD_MAX
1366 };
1367
1368 pa_dbus_arg_info remove_profile_args[]={
1369 {"name", "s","in"},
1370 };
1371
1372 static pa_dbus_method_handler manager_methods[MANAGER_METHOD_MAX]={
1373 [MANAGER_METHOD_REMOVE_PROFILE]{
1374 .method_name="RemoveProfile",
1375 .arguments=remove_profile_args,
1376 .n_arguments=sizeof(remove_profile_args)/sizeof(pa_dbus_arg_info),
1377 .receive_cb=manager_handle_remove_profile}
1378 };
1379
1380 enum manager_handler_index {
1381 MANAGER_HANDLER_REVISION,
1382 MANAGER_HANDLER_EQUALIZED_SINKS,
1383 MANAGER_HANDLER_PROFILES,
1384 MANAGER_HANDLER_MAX
1385 };
1386
1387 static pa_dbus_property_handler manager_handlers[MANAGER_HANDLER_MAX]={
1388 [MANAGER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=manager_get_revision,.set_cb=NULL},
1389 [MANAGER_HANDLER_EQUALIZED_SINKS]={.property_name="EqualizedSinks",.type="ao",.get_cb=manager_get_sinks,.set_cb=NULL},
1390 [MANAGER_HANDLER_PROFILES]={.property_name="Profiles",.type="as",.get_cb=manager_get_profiles,.set_cb=NULL}
1391 };
1392
1393 pa_dbus_arg_info sink_args[]={
1394 {"sink", "o", NULL}
1395 };
1396
1397 enum manager_signal_index{
1398 MANAGER_SIGNAL_SINK_ADDED,
1399 MANAGER_SIGNAL_SINK_REMOVED,
1400 MANAGER_SIGNAL_PROFILES_CHANGED,
1401 MANAGER_SIGNAL_MAX
1402 };
1403
1404 static pa_dbus_signal_info manager_signals[MANAGER_SIGNAL_MAX]={
1405 [MANAGER_SIGNAL_SINK_ADDED]={.name="SinkAdded", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1406 [MANAGER_SIGNAL_SINK_REMOVED]={.name="SinkRemoved", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1407 [MANAGER_SIGNAL_PROFILES_CHANGED]={.name="ProfilesChanged", .arguments=NULL, .n_arguments=0}
1408 };
1409
1410 static pa_dbus_interface_info manager_info={
1411 .name=MANAGER_IFACE,
1412 .method_handlers=manager_methods,
1413 .n_method_handlers=MANAGER_METHOD_MAX,
1414 .property_handlers=manager_handlers,
1415 .n_property_handlers=MANAGER_HANDLER_MAX,
1416 .get_all_properties_cb=manager_get_all,
1417 .signals=manager_signals,
1418 .n_signals=MANAGER_SIGNAL_MAX
1419 };
1420
1421 enum equalizer_method_index {
1422 EQUALIZER_METHOD_FILTER_POINTS,
1423 EQUALIZER_METHOD_SEED_FILTER,
1424 EQUALIZER_METHOD_SAVE_PROFILE,
1425 EQUALIZER_METHOD_LOAD_PROFILE,
1426 EQUALIZER_METHOD_SET_FILTER,
1427 EQUALIZER_METHOD_GET_FILTER,
1428 EQUALIZER_METHOD_SAVE_STATE,
1429 EQUALIZER_METHOD_GET_PROFILE_NAME,
1430 EQUALIZER_METHOD_MAX
1431 };
1432
1433 enum equalizer_handler_index {
1434 EQUALIZER_HANDLER_REVISION,
1435 EQUALIZER_HANDLER_SAMPLERATE,
1436 EQUALIZER_HANDLER_FILTERSAMPLERATE,
1437 EQUALIZER_HANDLER_N_COEFS,
1438 EQUALIZER_HANDLER_N_CHANNELS,
1439 EQUALIZER_HANDLER_MAX
1440 };
1441
1442 pa_dbus_arg_info filter_points_args[]={
1443 {"channel", "u","in"},
1444 {"xs", "au","in"},
1445 {"ys", "ad","out"},
1446 {"preamp", "d","out"}
1447 };
1448 pa_dbus_arg_info seed_filter_args[]={
1449 {"channel", "u","in"},
1450 {"xs", "au","in"},
1451 {"ys", "ad","in"},
1452 {"preamp", "d","in"}
1453 };
1454
1455 pa_dbus_arg_info set_filter_args[]={
1456 {"channel", "u","in"},
1457 {"ys", "ad","in"},
1458 {"preamp", "d","in"}
1459 };
1460 pa_dbus_arg_info get_filter_args[]={
1461 {"channel", "u","in"},
1462 {"ys", "ad","out"},
1463 {"preamp", "d","out"}
1464 };
1465
1466 pa_dbus_arg_info save_profile_args[]={
1467 {"channel", "u","in"},
1468 {"name", "s","in"}
1469 };
1470 pa_dbus_arg_info load_profile_args[]={
1471 {"channel", "u","in"},
1472 {"name", "s","in"}
1473 };
1474 pa_dbus_arg_info base_profile_name_args[]={
1475 {"channel", "u","in"},
1476 {"name", "s","out"}
1477 };
1478
1479 static pa_dbus_method_handler equalizer_methods[EQUALIZER_METHOD_MAX]={
1480 [EQUALIZER_METHOD_SEED_FILTER]{
1481 .method_name="SeedFilter",
1482 .arguments=seed_filter_args,
1483 .n_arguments=sizeof(seed_filter_args)/sizeof(pa_dbus_arg_info),
1484 .receive_cb=equalizer_handle_seed_filter},
1485 [EQUALIZER_METHOD_FILTER_POINTS]{
1486 .method_name="FilterAtPoints",
1487 .arguments=filter_points_args,
1488 .n_arguments=sizeof(filter_points_args)/sizeof(pa_dbus_arg_info),
1489 .receive_cb=equalizer_handle_get_filter_points},
1490 [EQUALIZER_METHOD_SET_FILTER]{
1491 .method_name="SetFilter",
1492 .arguments=set_filter_args,
1493 .n_arguments=sizeof(set_filter_args)/sizeof(pa_dbus_arg_info),
1494 .receive_cb=equalizer_handle_set_filter},
1495 [EQUALIZER_METHOD_GET_FILTER]{
1496 .method_name="GetFilter",
1497 .arguments=get_filter_args,
1498 .n_arguments=sizeof(get_filter_args)/sizeof(pa_dbus_arg_info),
1499 .receive_cb=equalizer_handle_get_filter},
1500 [EQUALIZER_METHOD_SAVE_PROFILE]{
1501 .method_name="SaveProfile",
1502 .arguments=save_profile_args,
1503 .n_arguments=sizeof(save_profile_args)/sizeof(pa_dbus_arg_info),
1504 .receive_cb=equalizer_handle_save_profile},
1505 [EQUALIZER_METHOD_LOAD_PROFILE]{
1506 .method_name="LoadProfile",
1507 .arguments=load_profile_args,
1508 .n_arguments=sizeof(load_profile_args)/sizeof(pa_dbus_arg_info),
1509 .receive_cb=equalizer_handle_load_profile},
1510 [EQUALIZER_METHOD_SAVE_STATE]{
1511 .method_name="SaveState",
1512 .arguments=NULL,
1513 .n_arguments=0,
1514 .receive_cb=equalizer_handle_save_state},
1515 [EQUALIZER_METHOD_GET_PROFILE_NAME]{
1516 .method_name="BaseProfile",
1517 .arguments=base_profile_name_args,
1518 .n_arguments=sizeof(base_profile_name_args)/sizeof(pa_dbus_arg_info),
1519 .receive_cb=equalizer_handle_get_profile_name}
1520 };
1521
1522 static pa_dbus_property_handler equalizer_handlers[EQUALIZER_HANDLER_MAX]={
1523 [EQUALIZER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=equalizer_get_revision,.set_cb=NULL},
1524 [EQUALIZER_HANDLER_SAMPLERATE]{.property_name="SampleRate",.type="u",.get_cb=equalizer_get_sample_rate,.set_cb=NULL},
1525 [EQUALIZER_HANDLER_FILTERSAMPLERATE]{.property_name="FilterSampleRate",.type="u",.get_cb=equalizer_get_filter_rate,.set_cb=NULL},
1526 [EQUALIZER_HANDLER_N_COEFS]{.property_name="NFilterCoefficients",.type="u",.get_cb=equalizer_get_n_coefs,.set_cb=NULL},
1527 [EQUALIZER_HANDLER_N_CHANNELS]{.property_name="NChannels",.type="u",.get_cb=equalizer_get_n_channels,.set_cb=NULL},
1528 };
1529
1530 enum equalizer_signal_index{
1531 EQUALIZER_SIGNAL_FILTER_CHANGED,
1532 EQUALIZER_SIGNAL_SINK_RECONFIGURED,
1533 EQUALIZER_SIGNAL_MAX
1534 };
1535
1536 static pa_dbus_signal_info equalizer_signals[EQUALIZER_SIGNAL_MAX]={
1537 [EQUALIZER_SIGNAL_FILTER_CHANGED]={.name="FilterChanged", .arguments=NULL, .n_arguments=0},
1538 [EQUALIZER_SIGNAL_SINK_RECONFIGURED]={.name="SinkReconfigured", .arguments=NULL, .n_arguments=0},
1539 };
1540
1541 static pa_dbus_interface_info equalizer_info={
1542 .name=EQUALIZER_IFACE,
1543 .method_handlers=equalizer_methods,
1544 .n_method_handlers=EQUALIZER_METHOD_MAX,
1545 .property_handlers=equalizer_handlers,
1546 .n_property_handlers=EQUALIZER_HANDLER_MAX,
1547 .get_all_properties_cb=equalizer_get_all,
1548 .signals=equalizer_signals,
1549 .n_signals=EQUALIZER_SIGNAL_MAX
1550 };
1551
1552 void dbus_init(struct userdata *u){
1553 uint32_t dummy;
1554 DBusMessage *signal = NULL;
1555 pa_idxset *sink_list = NULL;
1556 u->dbus_protocol=pa_dbus_protocol_get(u->sink->core);
1557 u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index);
1558
1559 pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &equalizer_info, u);
1560 sink_list = pa_shared_get(u->sink->core, SINKLIST);
1561 u->database = pa_shared_get(u->sink->core, EQDB);
1562 if(sink_list == NULL){
1563 char *dbname;
1564 sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
1565 pa_shared_set(u->sink->core, SINKLIST, sink_list);
1566 pa_assert_se(dbname = pa_state_path("equalizer-presets", FALSE));
1567 pa_assert_se(u->database = pa_database_open(dbname, TRUE));
1568 pa_xfree(dbname);
1569 pa_shared_set(u->sink->core, EQDB, u->database);
1570 pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
1571 pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
1572 }
1573 pa_idxset_put(sink_list, u, &dummy);
1574
1575 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_ADDED].name)));
1576 dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1577 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1578 dbus_message_unref(signal);
1579 }
1580
1581 void dbus_done(struct userdata *u){
1582 pa_idxset *sink_list;
1583 uint32_t dummy;
1584
1585 DBusMessage *signal = NULL;
1586 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_REMOVED].name)));
1587 dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1588 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1589 dbus_message_unref(signal);
1590
1591 pa_assert_se(sink_list=pa_shared_get(u->sink->core,SINKLIST));
1592 pa_idxset_remove_by_data(sink_list,u,&dummy);
1593 if(pa_idxset_size(sink_list)==0){
1594 pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME);
1595 pa_dbus_protocol_remove_interface(u->dbus_protocol, MANAGER_PATH, manager_info.name);
1596 pa_shared_remove(u->sink->core, EQDB);
1597 pa_database_close(u->database);
1598 pa_shared_remove(u->sink->core, SINKLIST);
1599 pa_xfree(sink_list);
1600 }
1601 pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, equalizer_info.name);
1602 pa_xfree(u->dbus_path);
1603 pa_dbus_protocol_unref(u->dbus_protocol);
1604 }
1605
1606 void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1607 DBusError error;
1608 pa_core *c = (pa_core *)_u;
1609 DBusMessage *signal = NULL;
1610 pa_dbus_protocol *dbus_protocol;
1611 char *name;
1612 pa_assert(conn);
1613 pa_assert(msg);
1614 pa_assert(c);
1615 dbus_error_init(&error);
1616 if(!dbus_message_get_args(msg, &error,
1617 DBUS_TYPE_STRING, &name,
1618 DBUS_TYPE_INVALID)){
1619 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1620 dbus_error_free(&error);
1621 return;
1622 }
1623 remove_profile(c,name);
1624 pa_dbus_send_empty_reply(conn, msg);
1625
1626 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
1627 dbus_protocol = pa_dbus_protocol_get(c);
1628 pa_dbus_protocol_send_signal(dbus_protocol, signal);
1629 pa_dbus_protocol_unref(dbus_protocol);
1630 dbus_message_unref(signal);
1631 }
1632
1633 void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
1634 uint32_t rev=1;
1635 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
1636 }
1637
1638 static void get_sinks(pa_core *u, char ***names, unsigned *n_sinks){
1639 void *iter = NULL;
1640 struct userdata *sink_u = NULL;
1641 uint32_t dummy;
1642 pa_idxset *sink_list;
1643 pa_assert(u);
1644 pa_assert(names);
1645 pa_assert(n_sinks);
1646
1647 pa_assert_se(sink_list = pa_shared_get(u, SINKLIST));
1648 *n_sinks = (unsigned) pa_idxset_size(sink_list);
1649 *names = *n_sinks > 0 ? pa_xnew0(char *,*n_sinks) : NULL;
1650 for(uint32_t i = 0; i < *n_sinks; ++i){
1651 sink_u = (struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy);
1652 (*names)[i] = pa_xstrdup(sink_u->dbus_path);
1653 }
1654 }
1655
1656 void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u){
1657 unsigned n;
1658 char **names = NULL;
1659 pa_assert(conn);
1660 pa_assert(msg);
1661 pa_assert(_u);
1662
1663 get_sinks((pa_core *) _u, &names, &n);
1664 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, names, n);
1665 for(unsigned i = 0; i < n; ++i){
1666 pa_xfree(names[i]);
1667 }
1668 pa_xfree(names);
1669 }
1670
1671 static void get_profiles(pa_core *c, char ***names, unsigned *n){
1672 char *name;
1673 pa_database *database;
1674 pa_datum key, next_key;
1675 pa_strlist *head=NULL, *iter;
1676 pa_bool_t done;
1677 pa_assert_se(database = pa_shared_get(c, EQDB));
1678
1679 pa_assert(c);
1680 pa_assert(names);
1681 pa_assert(n);
1682 done = !pa_database_first(database, &key, NULL);
1683 *n = 0;
1684 while(!done){
1685 done = !pa_database_next(database, &key, &next_key, NULL);
1686 name=pa_xmalloc(key.size + 1);
1687 memcpy(name, key.data, key.size);
1688 name[key.size] = '\0';
1689 pa_datum_free(&key);
1690 head = pa_strlist_prepend(head, name);
1691 pa_xfree(name);
1692 key = next_key;
1693 (*n)++;
1694 }
1695 (*names) = *n > 0 ? pa_xnew0(char *, *n) : NULL;
1696 iter=head;
1697 for(unsigned i = 0; i < *n; ++i){
1698 (*names)[*n - 1 - i] = pa_xstrdup(pa_strlist_data(iter));
1699 iter = pa_strlist_next(iter);
1700 }
1701 pa_strlist_free(head);
1702 }
1703
1704 void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u){
1705 char **names;
1706 unsigned n;
1707 pa_assert(conn);
1708 pa_assert(msg);
1709 pa_assert(_u);
1710
1711 get_profiles((pa_core *)_u, &names, &n);
1712 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, names, n);
1713 for(unsigned i = 0; i < n; ++i){
1714 pa_xfree(names[i]);
1715 }
1716 pa_xfree(names);
1717 }
1718
1719 void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
1720 pa_core *c;
1721 char **names = NULL;
1722 unsigned n;
1723 DBusMessage *reply = NULL;
1724 DBusMessageIter msg_iter, dict_iter;
1725 uint32_t rev;
1726 pa_assert(conn);
1727 pa_assert(msg);
1728 pa_assert_se(c = _u);
1729
1730 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1731 dbus_message_iter_init_append(reply, &msg_iter);
1732 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1733
1734 rev = 1;
1735 pa_dbus_append_basic_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
1736
1737 get_sinks(c, &names, &n);
1738 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter,manager_handlers[MANAGER_HANDLER_EQUALIZED_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, names, n);
1739 for(unsigned i = 0; i < n; ++i){
1740 pa_xfree(names[i]);
1741 }
1742 pa_xfree(names);
1743
1744 get_profiles(c, &names, &n);
1745 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_PROFILES].property_name, DBUS_TYPE_STRING, names, n);
1746 for(unsigned i = 0; i < n; ++i){
1747 pa_xfree(names[i]);
1748 }
1749 pa_xfree(names);
1750 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1751 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1752 dbus_message_unref(reply);
1753 }
1754
1755 void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
1756 struct userdata *u = _u;
1757 DBusError error;
1758 DBusMessage *signal = NULL;
1759 float *ys;
1760 uint32_t *xs, channel, r_channel;
1761 double *_ys, preamp;
1762 unsigned x_npoints, y_npoints, a_i;
1763 float *H;
1764 pa_bool_t points_good = TRUE;
1765
1766 pa_assert(conn);
1767 pa_assert(msg);
1768 pa_assert(u);
1769
1770 dbus_error_init(&error);
1771
1772 if(!dbus_message_get_args(msg, &error,
1773 DBUS_TYPE_UINT32, &channel,
1774 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1775 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &_ys, &y_npoints,
1776 DBUS_TYPE_DOUBLE, &preamp,
1777 DBUS_TYPE_INVALID)){
1778 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1779 dbus_error_free(&error);
1780 return;
1781 }
1782 if(channel > u->channels){
1783 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1784 dbus_error_free(&error);
1785 return;
1786 }
1787 for(size_t i = 0; i < x_npoints; ++i){
1788 if(xs[i] >= FILTER_SIZE(u)){
1789 points_good = FALSE;
1790 break;
1791 }
1792 }
1793 if(!is_monotonic(xs, x_npoints) || !points_good){
1794 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs must be monotonic and 0<=x<=%ld", u->fft_size / 2);
1795 dbus_error_free(&error);
1796 return;
1797 }else if(x_npoints != y_npoints || x_npoints < 2 || x_npoints > FILTER_SIZE(u)){
1798 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));
1799 dbus_error_free(&error);
1800 return;
1801 }else if(xs[0] != 0 || xs[x_npoints - 1] != u->fft_size / 2){
1802 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs[0] must be 0 and xs[-1]=fft_size/2");
1803 dbus_error_free(&error);
1804 return;
1805 }
1806
1807 ys = pa_xmalloc(x_npoints * sizeof(float));
1808 for(uint32_t i = 0; i < x_npoints; ++i){
1809 ys[i] = (float) _ys[i];
1810 }
1811 r_channel = channel == u->channels ? 0 : channel;
1812 a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1813 H = u->Hs[r_channel][a_i];
1814 u->Xs[r_channel][a_i] = preamp;
1815 interpolate(H, FILTER_SIZE(u), xs, ys, x_npoints);
1816 fix_filter(H, u->fft_size);
1817 if(channel == u->channels){
1818 for(size_t c = 1; c < u->channels; ++c){
1819 unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1820 float *H_p = u->Hs[c][b_i];
1821 u->Xs[c][b_i] = preamp;
1822 memcpy(H_p, H, FILTER_SIZE(u) * sizeof(float));
1823 pa_aupdate_write_end(u->a_H[c]);
1824 }
1825 }
1826 pa_aupdate_write_end(u->a_H[r_channel]);
1827 pa_xfree(ys);
1828
1829
1830 pa_dbus_send_empty_reply(conn, msg);
1831
1832 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
1833 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1834 dbus_message_unref(signal);
1835 }
1836
1837 void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u) {
1838 struct userdata *u = (struct userdata *) _u;
1839 uint32_t *xs, channel, r_channel;
1840 double *ys, preamp;
1841 unsigned x_npoints, a_i;
1842 float *H;
1843 pa_bool_t points_good=TRUE;
1844 DBusMessage *reply = NULL;
1845 DBusMessageIter msg_iter;
1846 DBusError error;
1847
1848 pa_assert(conn);
1849 pa_assert(msg);
1850 pa_assert(u);
1851
1852 dbus_error_init(&error);
1853 if(!dbus_message_get_args(msg, &error,
1854 DBUS_TYPE_UINT32, &channel,
1855 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1856 DBUS_TYPE_INVALID)){
1857 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1858 dbus_error_free(&error);
1859 return;
1860 }
1861 if(channel > u->channels){
1862 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1863 dbus_error_free(&error);
1864 return;
1865 }
1866
1867 for(size_t i = 0; i < x_npoints; ++i){
1868 if(xs[i] >= FILTER_SIZE(u)){
1869 points_good=FALSE;
1870 break;
1871 }
1872 }
1873
1874 if(x_npoints > FILTER_SIZE(u) || !points_good){
1875 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs indices/length must be <= %ld!", FILTER_SIZE(u));
1876 dbus_error_free(&error);
1877 return;
1878 }
1879
1880 r_channel = channel == u->channels ? 0 : channel;
1881 ys = pa_xmalloc(x_npoints * sizeof(double));
1882 a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1883 H = u->Hs[r_channel][a_i];
1884 preamp = u->Xs[r_channel][a_i];
1885 for(uint32_t i = 0; i < x_npoints; ++i){
1886 ys[i] = H[xs[i]] * u->fft_size;
1887 }
1888 pa_aupdate_read_end(u->a_H[r_channel]);
1889
1890 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1891 dbus_message_iter_init_append(reply, &msg_iter);
1892
1893 pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, ys, x_npoints);
1894 pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1895
1896 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1897 dbus_message_unref(reply);
1898 pa_xfree(ys);
1899 }
1900
1901 static void get_filter(struct userdata *u, size_t channel, double **H_, double *preamp){
1902 float *H;
1903 unsigned a_i;
1904 size_t r_channel = channel == u->channels ? 0 : channel;
1905 *H_ = pa_xnew0(double, FILTER_SIZE(u));
1906 a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1907 H = u->Hs[r_channel][a_i];
1908 for(size_t i = 0;i < FILTER_SIZE(u); ++i){
1909 (*H_)[i] = H[i] * u->fft_size;
1910 }
1911 *preamp = u->Xs[r_channel][a_i];
1912
1913 pa_aupdate_read_end(u->a_H[r_channel]);
1914 }
1915
1916 void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1917 struct userdata *u;
1918 unsigned n_coefs;
1919 uint32_t channel;
1920 double *H_, preamp;
1921 DBusMessage *reply = NULL;
1922 DBusMessageIter msg_iter;
1923 DBusError error;
1924 pa_assert_se(u = (struct userdata *) _u);
1925 pa_assert(conn);
1926 pa_assert(msg);
1927
1928 dbus_error_init(&error);
1929 if(!dbus_message_get_args(msg, &error,
1930 DBUS_TYPE_UINT32, &channel,
1931 DBUS_TYPE_INVALID)){
1932 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1933 dbus_error_free(&error);
1934 return;
1935 }
1936 if(channel > u->channels){
1937 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1938 dbus_error_free(&error);
1939 return;
1940 }
1941
1942 n_coefs = CHANNEL_PROFILE_SIZE(u);
1943 pa_assert(conn);
1944 pa_assert(msg);
1945 get_filter(u, channel, &H_, &preamp);
1946 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1947 dbus_message_iter_init_append(reply, &msg_iter);
1948
1949 pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, H_, n_coefs);
1950 pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1951
1952 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1953 dbus_message_unref(reply);
1954 pa_xfree(H_);
1955 }
1956
1957 static void set_filter(struct userdata *u, size_t channel, double *H_, double preamp){
1958 unsigned a_i;
1959 size_t r_channel = channel == u->channels ? 0 : channel;
1960 float *H;
1961 //all channels
1962 a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1963 u->Xs[r_channel][a_i] = (float) preamp;
1964 H = u->Hs[r_channel][a_i];
1965 for(size_t i = 0; i < FILTER_SIZE(u); ++i){
1966 H[i] = (float) H_[i];
1967 }
1968 fix_filter(H, u->fft_size);
1969 if(channel == u->channels){
1970 for(size_t c = 1; c < u->channels; ++c){
1971 unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1972 u->Xs[c][b_i] = u->Xs[r_channel][a_i];
1973 memcpy(u->Hs[c][b_i], u->Hs[r_channel][a_i], FILTER_SIZE(u) * sizeof(float));
1974 pa_aupdate_write_end(u->a_H[c]);
1975 }
1976 }
1977 pa_aupdate_write_end(u->a_H[r_channel]);
1978 }
1979
1980 void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1981 struct userdata *u;
1982 double *H, preamp;
1983 uint32_t channel;
1984 unsigned _n_coefs;
1985 DBusMessage *signal = NULL;
1986 DBusError error;
1987 pa_assert_se(u = (struct userdata *) _u);
1988 pa_assert(conn);
1989 pa_assert(msg);
1990
1991 dbus_error_init(&error);
1992 if(!dbus_message_get_args(msg, &error,
1993 DBUS_TYPE_UINT32, &channel,
1994 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &H, &_n_coefs,
1995 DBUS_TYPE_DOUBLE, &preamp,
1996 DBUS_TYPE_INVALID)){
1997 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1998 dbus_error_free(&error);
1999 return;
2000 }
2001 if(channel > u->channels){
2002 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2003 dbus_error_free(&error);
2004 return;
2005 }
2006 if(_n_coefs != FILTER_SIZE(u)){
2007 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE(u), _n_coefs);
2008 return;
2009 }
2010 set_filter(u, channel, H, preamp);
2011
2012 pa_dbus_send_empty_reply(conn, msg);
2013
2014 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2015 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2016 dbus_message_unref(signal);
2017 }
2018
2019 void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
2020 struct userdata *u = (struct userdata *) _u;
2021 char *name;
2022 uint32_t channel, r_channel;
2023 DBusMessage *signal = NULL;
2024 DBusError error;
2025 pa_assert(conn);
2026 pa_assert(msg);
2027 pa_assert(u);
2028 dbus_error_init(&error);
2029
2030 if(!dbus_message_get_args(msg, &error,
2031 DBUS_TYPE_UINT32, &channel,
2032 DBUS_TYPE_STRING, &name,
2033 DBUS_TYPE_INVALID)){
2034 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2035 dbus_error_free(&error);
2036 return;
2037 }
2038 if(channel > u->channels){
2039 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2040 dbus_error_free(&error);
2041 return;
2042 }
2043 r_channel = channel == u->channels ? 0 : channel;
2044 save_profile(u, r_channel, name);
2045 pa_dbus_send_empty_reply(conn, msg);
2046
2047 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
2048 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2049 dbus_message_unref(signal);
2050 }
2051
2052 void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
2053 struct userdata *u = (struct userdata *) _u;
2054 char *name;
2055 DBusError error;
2056 uint32_t channel, r_channel;
2057 const char *err_msg = NULL;
2058 DBusMessage *signal = NULL;
2059
2060 pa_assert(conn);
2061 pa_assert(msg);
2062 pa_assert(u);
2063 dbus_error_init(&error);
2064
2065 if(!dbus_message_get_args(msg, &error,
2066 DBUS_TYPE_UINT32, &channel,
2067 DBUS_TYPE_STRING, &name,
2068 DBUS_TYPE_INVALID)){
2069 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2070 dbus_error_free(&error);
2071 return;
2072 }
2073 if(channel > u->channels){
2074 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2075 dbus_error_free(&error);
2076 return;
2077 }
2078 r_channel = channel == u->channels ? 0 : channel;
2079
2080 err_msg = load_profile(u, r_channel, name);
2081 if(err_msg != NULL){
2082 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "error loading profile %s: %s", name, err_msg);
2083 dbus_error_free(&error);
2084 return;
2085 }
2086 if(channel == u->channels){
2087 for(uint32_t c = 1; c < u->channels; ++c){
2088 load_profile(u, c, name);
2089 }
2090 }
2091 pa_dbus_send_empty_reply(conn, msg);
2092
2093 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2094 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2095 dbus_message_unref(signal);
2096 }
2097
2098 void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u) {
2099 struct userdata *u = (struct userdata *) _u;
2100 pa_assert(conn);
2101 pa_assert(msg);
2102 pa_assert(u);
2103
2104 save_state(u);
2105 pa_dbus_send_empty_reply(conn, msg);
2106 }
2107
2108 void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u){
2109 struct userdata *u = (struct userdata *) _u;
2110 DBusError error;
2111 uint32_t channel, r_channel;
2112
2113 pa_assert(conn);
2114 pa_assert(msg);
2115 pa_assert(u);
2116 dbus_error_init(&error);
2117
2118 if(!dbus_message_get_args(msg, &error,
2119 DBUS_TYPE_UINT32, &channel,
2120 DBUS_TYPE_INVALID)){
2121 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2122 dbus_error_free(&error);
2123 return;
2124 }
2125 if(channel > u->channels){
2126 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2127 dbus_error_free(&error);
2128 return;
2129 }
2130 r_channel = channel == u->channels ? 0 : channel;
2131 pa_assert(u->base_profiles[r_channel]);
2132 pa_dbus_send_basic_value_reply(conn,msg, DBUS_TYPE_STRING, &u->base_profiles[r_channel]);
2133 }
2134
2135 void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
2136 uint32_t rev=1;
2137 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
2138 }
2139
2140 void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u){
2141 struct userdata *u;
2142 uint32_t channels;
2143 pa_assert_se(u = (struct userdata *) _u);
2144 pa_assert(conn);
2145 pa_assert(msg);
2146
2147 channels = (uint32_t) u->channels;
2148 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &channels);
2149 }
2150
2151 void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u){
2152 struct userdata *u;
2153 uint32_t n_coefs;
2154 pa_assert_se(u = (struct userdata *) _u);
2155 pa_assert(conn);
2156 pa_assert(msg);
2157
2158 n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE(u);
2159 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs);
2160 }
2161
2162 void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
2163 struct userdata *u;
2164 uint32_t rate;
2165 pa_assert_se(u = (struct userdata *) _u);
2166 pa_assert(conn);
2167 pa_assert(msg);
2168
2169 rate = (uint32_t) u->sink->sample_spec.rate;
2170 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &rate);
2171 }
2172
2173 void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
2174 struct userdata *u;
2175 uint32_t fft_size;
2176 pa_assert_se(u = (struct userdata *) _u);
2177 pa_assert(conn);
2178 pa_assert(msg);
2179
2180 fft_size = (uint32_t) u->fft_size;
2181 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &fft_size);
2182 }
2183
2184 void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
2185 struct userdata *u;
2186 DBusMessage *reply = NULL;
2187 DBusMessageIter msg_iter, dict_iter;
2188 uint32_t rev, n_coefs, rate, fft_size, channels;
2189
2190 pa_assert_se(u = _u);
2191 pa_assert(msg);
2192
2193 rev = 1;
2194 n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE(u);
2195 rate = (uint32_t) u->sink->sample_spec.rate;
2196 fft_size = (uint32_t) u->fft_size;
2197 channels = (uint32_t) u->channels;
2198
2199 pa_assert_se((reply = dbus_message_new_method_return(msg)));
2200 dbus_message_iter_init_append(reply, &msg_iter);
2201 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
2202
2203 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
2204 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_SAMPLERATE].property_name, DBUS_TYPE_UINT32, &rate);
2205 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_FILTERSAMPLERATE].property_name, DBUS_TYPE_UINT32, &fft_size);
2206 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs);
2207 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_CHANNELS].property_name, DBUS_TYPE_UINT32, &channels);
2208
2209 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
2210 pa_assert_se(dbus_connection_send(conn, reply, NULL));
2211 dbus_message_unref(reply);
2212 }