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