]> code.delx.au - pulseaudio/blob - src/modules/module-equalizer-sink.c
Move i18n.[ch] to src/pulsecore
[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 (magintude 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,//multipliar
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 window'd 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 padd 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 overlaping 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 //preseve 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,//multipliar
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 window'd 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 padd 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 overlaping 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 //preseve 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 static void reset_filter(struct userdata *u){
704 size_t fs = pa_frame_size(&u->sink->sample_spec);
705 size_t max_request;
706
707 u->samples_gathered = 0;
708
709 for(size_t i = 0; i < u->channels; ++i)
710 pa_memzero(u->overlap_accum[i], u->overlap_size * sizeof(float));
711
712 u->first_iteration = TRUE;
713 //set buffer size to max request, no overlap copy
714 max_request = PA_ROUND_UP(pa_sink_input_get_max_request(u->sink_input) / fs , u->R);
715 max_request = PA_MAX(max_request, u->window_size);
716 pa_sink_set_max_request_within_thread(u->sink, max_request * fs);
717 }
718
719 /* Called from I/O thread context */
720 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
721 struct userdata *u;
722 size_t amount = 0;
723
724 pa_log_debug("Rewind callback!");
725 pa_sink_input_assert_ref(i);
726 pa_assert_se(u = i->userdata);
727
728 if (u->sink->thread_info.rewind_nbytes > 0) {
729 size_t max_rewrite;
730
731 //max_rewrite = nbytes;
732 max_rewrite = nbytes + pa_memblockq_get_length(u->input_q);
733 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
734 amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
735 u->sink->thread_info.rewind_nbytes = 0;
736
737 if (amount > 0) {
738 //invalidate the output q
739 pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
740 pa_log("Resetting filter");
741 //reset_filter(u); //this is the "proper" thing to do...
742 }
743 }
744
745 pa_sink_process_rewind(u->sink, amount);
746 pa_memblockq_rewind(u->input_q, nbytes);
747 }
748
749 /* Called from I/O thread context */
750 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
751 struct userdata *u;
752
753 pa_sink_input_assert_ref(i);
754 pa_assert_se(u = i->userdata);
755
756 pa_memblockq_set_maxrewind(u->input_q, nbytes);
757 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
758 }
759
760 /* Called from I/O thread context */
761 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
762 struct userdata *u;
763 size_t fs;
764
765 pa_sink_input_assert_ref(i);
766 pa_assert_se(u = i->userdata);
767
768 fs = pa_frame_size(&u->sink_input->sample_spec);
769 pa_sink_set_max_request_within_thread(u->sink, PA_ROUND_UP(nbytes / fs, u->R) * fs);
770 }
771
772 /* Called from I/O thread context */
773 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
774 struct userdata *u;
775
776 pa_sink_input_assert_ref(i);
777 pa_assert_se(u = i->userdata);
778
779 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
780 }
781
782 /* Called from I/O thread context */
783 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
784 struct userdata *u;
785
786 pa_sink_input_assert_ref(i);
787 pa_assert_se(u = i->userdata);
788
789 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
790 }
791
792 /* Called from I/O thread context */
793 static void sink_input_detach_cb(pa_sink_input *i) {
794 struct userdata *u;
795
796 pa_sink_input_assert_ref(i);
797 pa_assert_se(u = i->userdata);
798
799 pa_sink_detach_within_thread(u->sink);
800
801 pa_sink_set_rtpoll(u->sink, NULL);
802 }
803
804 /* Called from I/O thread context */
805 static void sink_input_attach_cb(pa_sink_input *i) {
806 struct userdata *u;
807 size_t fs, max_request;
808
809 pa_sink_input_assert_ref(i);
810 pa_assert_se(u = i->userdata);
811
812 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
813 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
814 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
815
816 fs = pa_frame_size(&u->sink_input->sample_spec);
817 /* set buffer size to max request, no overlap copy */
818 max_request = PA_ROUND_UP(pa_sink_input_get_max_request(u->sink_input) / fs, u->R);
819 max_request = PA_MAX(max_request, u->window_size);
820
821 pa_sink_set_max_request_within_thread(u->sink, max_request * fs);
822 pa_sink_set_max_rewind_within_thread(u->sink, pa_sink_input_get_max_rewind(i));
823
824 pa_sink_attach_within_thread(u->sink);
825 }
826
827 /* Called from main context */
828 static void sink_input_kill_cb(pa_sink_input *i) {
829 struct userdata *u;
830
831 pa_sink_input_assert_ref(i);
832 pa_assert_se(u = i->userdata);
833
834 /* The order here matters! We first kill the sink input, followed
835 * by the sink. That means the sink callbacks must be protected
836 * against an unconnected sink input! */
837 pa_sink_input_unlink(u->sink_input);
838 pa_sink_unlink(u->sink);
839
840 pa_sink_input_unref(u->sink_input);
841 u->sink_input = NULL;
842
843 pa_sink_unref(u->sink);
844 u->sink = NULL;
845
846 pa_module_unload_request(u->module, TRUE);
847 }
848
849 /* Called from IO thread context */
850 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
851 struct userdata *u;
852
853 pa_sink_input_assert_ref(i);
854 pa_assert_se(u = i->userdata);
855
856 /* If we are added for the first time, ask for a rewinding so that
857 * we are heard right-away. */
858 if (PA_SINK_INPUT_IS_LINKED(state) &&
859 i->thread_info.state == PA_SINK_INPUT_INIT) {
860 pa_log_debug("Requesting rewind due to state change.");
861 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
862 }
863 }
864
865 static void pack(char **strs, size_t len, char **packed, size_t *length){
866 size_t t_len = 0;
867 size_t headers = (1+len) * sizeof(uint16_t);
868 char *p;
869 for(size_t i = 0; i < len; ++i){
870 t_len += strlen(strs[i]);
871 }
872 *length = headers + t_len;
873 p = *packed = pa_xmalloc0(*length);
874 *((uint16_t *) p) = (uint16_t) len;
875 p += sizeof(uint16_t);
876 for(size_t i = 0; i < len; ++i){
877 uint16_t l = strlen(strs[i]);
878 *((uint16_t *) p) = (uint16_t) l;
879 p += sizeof(uint16_t);
880 memcpy(p, strs[i], l);
881 p += l;
882 }
883 }
884 static void unpack(char *str, size_t length, char ***strs, size_t *len){
885 char *p = str;
886 *len = *((uint16_t *) p);
887 p += sizeof(uint16_t);
888 *strs = pa_xnew(char *, *len);
889
890 for(size_t i = 0; i < *len; ++i){
891 size_t l = *((uint16_t *) p);
892 p += sizeof(uint16_t);
893 (*strs)[i] = pa_xnew(char, l + 1);
894 memcpy((*strs)[i], p, l);
895 (*strs)[i][l] = '\0';
896 p += l;
897 }
898 }
899 static void save_profile(struct userdata *u, size_t channel, char *name){
900 unsigned a_i;
901 const size_t profile_size = CHANNEL_PROFILE_SIZE(u) * sizeof(float);
902 float *H_n, *profile;
903 const float *H;
904 pa_datum key, data;
905 profile = pa_xnew0(float, profile_size);
906 a_i = pa_aupdate_read_begin(u->a_H[channel]);
907 profile[0] = u->Xs[a_i][channel];
908 H = u->Hs[channel][a_i];
909 H_n = profile + 1;
910 for(size_t i = 0 ; i <= FILTER_SIZE(u); ++i){
911 H_n[i] = H[i] * u->fft_size;
912 //H_n[i] = H[i];
913 }
914 pa_aupdate_read_end(u->a_H[channel]);
915 key.data=name;
916 key.size = strlen(key.data);
917 data.data = profile;
918 data.size = profile_size;
919 pa_database_set(u->database, &key, &data, TRUE);
920 pa_database_sync(u->database);
921 if(u->base_profiles[channel]){
922 pa_xfree(u->base_profiles[channel]);
923 }
924 u->base_profiles[channel] = pa_xstrdup(name);
925 }
926
927 static void save_state(struct userdata *u){
928 unsigned a_i;
929 const size_t filter_state_size = FILTER_STATE_SIZE(u) * sizeof(float);
930 float *H_n, *state;
931 float *H;
932 pa_datum key, data;
933 pa_database *database;
934 char *dbname;
935 char *packed;
936 size_t packed_length;
937
938 pack(u->base_profiles, u->channels, &packed, &packed_length);
939 state = (float *) pa_xmalloc0(filter_state_size + packed_length);
940 memcpy(state + FILTER_STATE_SIZE(u), packed, packed_length);
941 pa_xfree(packed);
942
943 for(size_t c = 0; c < u->channels; ++c){
944 a_i = pa_aupdate_read_begin(u->a_H[c]);
945 state[c * CHANNEL_PROFILE_SIZE(u)] = u->Xs[c][a_i];
946 H = u->Hs[c][a_i];
947 H_n = &state[c * CHANNEL_PROFILE_SIZE(u) + 1];
948 memcpy(H_n, H, FILTER_SIZE(u) * sizeof(float));
949 pa_aupdate_read_end(u->a_H[c]);
950 }
951
952 key.data = u->sink->name;
953 key.size = strlen(key.data);
954 data.data = state;
955 data.size = filter_state_size + packed_length;
956 //thread safety for 0.9.17?
957 pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, FALSE));
958 pa_assert_se(database = pa_database_open(dbname, TRUE));
959 pa_xfree(dbname);
960
961 pa_database_set(database, &key, &data, TRUE);
962 pa_database_sync(database);
963 pa_database_close(database);
964 pa_xfree(state);
965 }
966
967 static void remove_profile(pa_core *c, char *name){
968 pa_datum key;
969 pa_database *database;
970 key.data = name;
971 key.size = strlen(key.data);
972 pa_assert_se(database = pa_shared_get(c, EQDB));
973 pa_database_unset(database, &key);
974 pa_database_sync(database);
975 }
976
977 static const char* load_profile(struct userdata *u, size_t channel, char *name){
978 unsigned a_i;
979 pa_datum key, value;
980 const size_t profile_size = CHANNEL_PROFILE_SIZE(u) * sizeof(float);
981 key.data = name;
982 key.size = strlen(key.data);
983 if(pa_database_get(u->database, &key, &value) != NULL){
984 if(value.size == profile_size){
985 float *profile = (float *) value.data;
986 a_i = pa_aupdate_write_begin(u->a_H[channel]);
987 u->Xs[channel][a_i] = profile[0];
988 memcpy(u->Hs[channel][a_i], profile + 1, FILTER_SIZE(u) * sizeof(float));
989 fix_filter(u->Hs[channel][a_i], u->fft_size);
990 pa_aupdate_write_end(u->a_H[channel]);
991 pa_xfree(u->base_profiles[channel]);
992 u->base_profiles[channel] = pa_xstrdup(name);
993 }else{
994 return "incompatible size";
995 }
996 pa_datum_free(&value);
997 }else{
998 return "profile doesn't exist";
999 }
1000 return NULL;
1001 }
1002
1003 static void load_state(struct userdata *u){
1004 unsigned a_i;
1005 float *H;
1006 pa_datum key, value;
1007 pa_database *database;
1008 char *dbname;
1009 pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, FALSE));
1010 database = pa_database_open(dbname, FALSE);
1011 pa_xfree(dbname);
1012 if(!database){
1013 pa_log("No resume state");
1014 return;
1015 }
1016
1017 key.data = u->sink->name;
1018 key.size = strlen(key.data);
1019
1020 if(pa_database_get(database, &key, &value) != NULL){
1021 if(value.size > FILTER_STATE_SIZE(u) * sizeof(float) + sizeof(uint16_t)){
1022 float *state = (float *) value.data;
1023 size_t n_profs;
1024 char **names;
1025 for(size_t c = 0; c < u->channels; ++c){
1026 a_i = pa_aupdate_write_begin(u->a_H[c]);
1027 H = state + c * CHANNEL_PROFILE_SIZE(u) + 1;
1028 u->Xs[c][a_i] = state[c * CHANNEL_PROFILE_SIZE(u)];
1029 memcpy(u->Hs[c][a_i], H, FILTER_SIZE(u) * sizeof(float));
1030 pa_aupdate_write_end(u->a_H[c]);
1031 }
1032 unpack(((char *)value.data) + FILTER_STATE_SIZE(u) * sizeof(float), value.size - FILTER_STATE_SIZE(u) * sizeof(float), &names, &n_profs);
1033 n_profs = PA_MIN(n_profs, u->channels);
1034 for(size_t c = 0; c < n_profs; ++c){
1035 pa_xfree(u->base_profiles[c]);
1036 u->base_profiles[c] = names[c];
1037 }
1038 pa_xfree(names);
1039 }
1040 pa_datum_free(&value);
1041 }else{
1042 pa_log("resume state exists but is wrong size!");
1043 }
1044 pa_database_close(database);
1045 }
1046
1047 /* Called from main context */
1048 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
1049 struct userdata *u;
1050
1051 pa_sink_input_assert_ref(i);
1052 pa_assert_se(u = i->userdata);
1053
1054 return u->sink != dest;
1055 }
1056
1057 /* Called from main context */
1058 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
1059 struct userdata *u;
1060
1061 pa_sink_input_assert_ref(i);
1062 pa_assert_se(u = i->userdata);
1063
1064 if (dest) {
1065 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
1066 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
1067 } else
1068 pa_sink_set_asyncmsgq(u->sink, NULL);
1069 }
1070
1071 int pa__init(pa_module*m) {
1072 struct userdata *u;
1073 pa_sample_spec ss;
1074 pa_channel_map map;
1075 pa_modargs *ma;
1076 const char *z;
1077 pa_sink *master;
1078 pa_sink_input_new_data sink_input_data;
1079 pa_sink_new_data sink_data;
1080 size_t fs, i;
1081 unsigned c;
1082 float *H;
1083 unsigned a_i;
1084
1085 pa_assert(m);
1086
1087 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1088 pa_log("Failed to parse module arguments.");
1089 goto fail;
1090 }
1091
1092 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) {
1093 pa_log("Master sink not found");
1094 goto fail;
1095 }
1096
1097 ss = master->sample_spec;
1098 ss.format = PA_SAMPLE_FLOAT32;
1099 map = master->channel_map;
1100 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1101 pa_log("Invalid sample format specification or channel map");
1102 goto fail;
1103 }
1104
1105 fs = pa_frame_size(&ss);
1106
1107 u = pa_xnew0(struct userdata, 1);
1108 u->module = m;
1109 m->userdata = u;
1110
1111 u->channels = ss.channels;
1112 u->fft_size = pow(2, ceil(log(ss.rate) / log(2)));//probably unstable near corner cases of powers of 2
1113 pa_log_debug("fft size: %ld", u->fft_size);
1114 u->window_size = 15999;
1115 if (u->window_size % 2 == 0)
1116 u->window_size--;
1117 u->R = (u->window_size + 1) / 2;
1118 u->overlap_size = u->window_size - u->R;
1119 u->samples_gathered = 0;
1120 u->input_buffer_max = 0;
1121
1122 u->a_H = pa_xnew0(pa_aupdate *, u->channels);
1123 u->Xs = pa_xnew0(float *, u->channels);
1124 u->Hs = pa_xnew0(float **, u->channels);
1125
1126 for (c = 0; c < u->channels; ++c) {
1127 u->Xs[c] = pa_xnew0(float, 2);
1128 u->Hs[c] = pa_xnew0(float *, 2);
1129 for (i = 0; i < 2; ++i)
1130 u->Hs[c][i] = alloc(FILTER_SIZE(u), sizeof(float));
1131 }
1132
1133 u->W = alloc(u->window_size, sizeof(float));
1134 u->work_buffer = alloc(u->fft_size, sizeof(float));
1135 u->input = pa_xnew0(float *, u->channels);
1136 u->overlap_accum = pa_xnew0(float *, u->channels);
1137 for (c = 0; c < u->channels; ++c) {
1138 u->a_H[c] = pa_aupdate_new();
1139 u->input[c] = NULL;
1140 u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float));
1141 }
1142 u->output_window = alloc(FILTER_SIZE(u), sizeof(fftwf_complex));
1143 u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
1144 u->inverse_plan = fftwf_plan_dft_c2r_1d(u->fft_size, u->output_window, u->work_buffer, FFTW_ESTIMATE);
1145
1146 hanning_window(u->W, u->window_size);
1147 u->first_iteration = TRUE;
1148
1149 u->base_profiles = pa_xnew0(char *, u->channels);
1150 for (c = 0; c < u->channels; ++c)
1151 u->base_profiles[c] = pa_xstrdup("default");
1152
1153 /* Create sink */
1154 pa_sink_new_data_init(&sink_data);
1155 sink_data.driver = __FILE__;
1156 sink_data.module = m;
1157 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
1158 sink_data.name = pa_sprintf_malloc("%s.equalizer", master->name);
1159 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
1160 pa_sink_new_data_set_channel_map(&sink_data, &map);
1161
1162 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1163 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "FFT based equalizer on %s", z ? z : master->name);
1164
1165 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
1166 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1167
1168 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
1169 pa_log("Invalid properties");
1170 pa_sink_new_data_done(&sink_data);
1171 goto fail;
1172 }
1173
1174 u->autoloaded = DEFAULT_AUTOLOADED;
1175 if (pa_modargs_get_value_boolean(ma, "autoloaded", &u->autoloaded) < 0) {
1176 pa_log("Failed to parse autoloaded value");
1177 goto fail;
1178 }
1179
1180 u->sink = pa_sink_new(m->core, &sink_data,
1181 (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
1182 pa_sink_new_data_done(&sink_data);
1183
1184 if (!u->sink) {
1185 pa_log("Failed to create sink.");
1186 goto fail;
1187 }
1188
1189 u->sink->parent.process_msg = sink_process_msg_cb;
1190 u->sink->set_state = sink_set_state_cb;
1191 u->sink->update_requested_latency = sink_update_requested_latency_cb;
1192 u->sink->request_rewind = sink_request_rewind_cb;
1193 pa_sink_enable_decibel_volume(u->sink, TRUE);
1194 pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb);
1195 pa_sink_set_set_mute_callback(u->sink, sink_set_mute_cb);
1196 u->sink->userdata = u;
1197
1198 u->input_q = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, &u->sink->silence);
1199 u->output_q = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, NULL);
1200 u->output_buffer = NULL;
1201 u->output_buffer_length = 0;
1202 u->output_buffer_max_length = 0;
1203
1204 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
1205 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1206
1207 /* Create sink input */
1208 pa_sink_input_new_data_init(&sink_input_data);
1209 sink_input_data.driver = __FILE__;
1210 sink_input_data.module = m;
1211 pa_sink_input_new_data_set_sink(&sink_input_data, master, FALSE);
1212 sink_input_data.origin_sink = u->sink;
1213 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
1214 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1215 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
1216 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
1217
1218 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data);
1219 pa_sink_input_new_data_done(&sink_input_data);
1220
1221 if (!u->sink_input)
1222 goto fail;
1223
1224 u->sink_input->pop = sink_input_pop_cb;
1225 u->sink_input->process_rewind = sink_input_process_rewind_cb;
1226 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1227 u->sink_input->update_max_request = sink_input_update_max_request_cb;
1228 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
1229 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
1230 u->sink_input->kill = sink_input_kill_cb;
1231 u->sink_input->attach = sink_input_attach_cb;
1232 u->sink_input->detach = sink_input_detach_cb;
1233 u->sink_input->state_change = sink_input_state_change_cb;
1234 u->sink_input->may_move_to = sink_input_may_move_to_cb;
1235 u->sink_input->moving = sink_input_moving_cb;
1236 u->sink_input->volume_changed = sink_input_volume_changed_cb;
1237 u->sink_input->mute_changed = sink_input_mute_changed_cb;
1238 u->sink_input->userdata = u;
1239
1240 u->sink->input_to_master = u->sink_input;
1241
1242 dbus_init(u);
1243
1244 /* default filter to these */
1245 for (c = 0; c< u->channels; ++c) {
1246 a_i = pa_aupdate_write_begin(u->a_H[c]);
1247 H = u->Hs[c][a_i];
1248 u->Xs[c][a_i] = 1.0f;
1249
1250 for(i = 0; i < FILTER_SIZE(u); ++i)
1251 H[i] = 1.0 / sqrtf(2.0f);
1252
1253 fix_filter(H, u->fft_size);
1254 pa_aupdate_write_end(u->a_H[c]);
1255 }
1256
1257 /* load old parameters */
1258 load_state(u);
1259
1260 pa_sink_put(u->sink);
1261 pa_sink_input_put(u->sink_input);
1262
1263 pa_modargs_free(ma);
1264
1265 return 0;
1266
1267 fail:
1268 if (ma)
1269 pa_modargs_free(ma);
1270
1271 pa__done(m);
1272
1273 return -1;
1274 }
1275
1276 int pa__get_n_used(pa_module *m) {
1277 struct userdata *u;
1278
1279 pa_assert(m);
1280 pa_assert_se(u = m->userdata);
1281
1282 return pa_sink_linked_by(u->sink);
1283 }
1284
1285 void pa__done(pa_module*m) {
1286 struct userdata *u;
1287 unsigned c;
1288
1289 pa_assert(m);
1290
1291 if (!(u = m->userdata))
1292 return;
1293
1294 save_state(u);
1295
1296 dbus_done(u);
1297
1298 for(c = 0; c < u->channels; ++c)
1299 pa_xfree(u->base_profiles[c]);
1300 pa_xfree(u->base_profiles);
1301
1302 /* See comments in sink_input_kill_cb() above regarding
1303 * destruction order! */
1304
1305 if (u->sink_input)
1306 pa_sink_input_unlink(u->sink_input);
1307
1308 if (u->sink)
1309 pa_sink_unlink(u->sink);
1310
1311 if (u->sink_input)
1312 pa_sink_input_unref(u->sink_input);
1313
1314 if (u->sink)
1315 pa_sink_unref(u->sink);
1316
1317 pa_xfree(u->output_buffer);
1318 pa_memblockq_free(u->output_q);
1319 pa_memblockq_free(u->input_q);
1320
1321 fftwf_destroy_plan(u->inverse_plan);
1322 fftwf_destroy_plan(u->forward_plan);
1323 pa_xfree(u->output_window);
1324 for (c = 0; c < u->channels; ++c) {
1325 pa_aupdate_free(u->a_H[c]);
1326 pa_xfree(u->overlap_accum[c]);
1327 pa_xfree(u->input[c]);
1328 }
1329 pa_xfree(u->a_H);
1330 pa_xfree(u->overlap_accum);
1331 pa_xfree(u->input);
1332 pa_xfree(u->work_buffer);
1333 pa_xfree(u->W);
1334 for (c = 0; c < u->channels; ++c) {
1335 pa_xfree(u->Xs[c]);
1336 for (size_t i = 0; i < 2; ++i)
1337 pa_xfree(u->Hs[c][i]);
1338 pa_xfree(u->Hs[c]);
1339 }
1340 pa_xfree(u->Xs);
1341 pa_xfree(u->Hs);
1342
1343 pa_xfree(u);
1344 }
1345
1346 /*
1347 * DBus Routines and Callbacks
1348 */
1349 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1350 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1351 #define MANAGER_IFACE EXTNAME ".Manager"
1352 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1353 static void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1354 static void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u);
1355 static void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u);
1356 static void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1357 static void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1358 static void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1359 static void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1360 static void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1361 static void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u);
1362 static void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u);
1363 static void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1364 static void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1365 static void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u);
1366 static void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1367 static void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1368 static void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1369 static void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1370 static void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u);
1371 static void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u);
1372 enum manager_method_index {
1373 MANAGER_METHOD_REMOVE_PROFILE,
1374 MANAGER_METHOD_MAX
1375 };
1376
1377 pa_dbus_arg_info remove_profile_args[]={
1378 {"name", "s","in"},
1379 };
1380
1381 static pa_dbus_method_handler manager_methods[MANAGER_METHOD_MAX]={
1382 [MANAGER_METHOD_REMOVE_PROFILE]{
1383 .method_name="RemoveProfile",
1384 .arguments=remove_profile_args,
1385 .n_arguments=sizeof(remove_profile_args)/sizeof(pa_dbus_arg_info),
1386 .receive_cb=manager_handle_remove_profile}
1387 };
1388
1389 enum manager_handler_index {
1390 MANAGER_HANDLER_REVISION,
1391 MANAGER_HANDLER_EQUALIZED_SINKS,
1392 MANAGER_HANDLER_PROFILES,
1393 MANAGER_HANDLER_MAX
1394 };
1395
1396 static pa_dbus_property_handler manager_handlers[MANAGER_HANDLER_MAX]={
1397 [MANAGER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=manager_get_revision,.set_cb=NULL},
1398 [MANAGER_HANDLER_EQUALIZED_SINKS]={.property_name="EqualizedSinks",.type="ao",.get_cb=manager_get_sinks,.set_cb=NULL},
1399 [MANAGER_HANDLER_PROFILES]={.property_name="Profiles",.type="as",.get_cb=manager_get_profiles,.set_cb=NULL}
1400 };
1401
1402 pa_dbus_arg_info sink_args[]={
1403 {"sink", "o", NULL}
1404 };
1405
1406 enum manager_signal_index{
1407 MANAGER_SIGNAL_SINK_ADDED,
1408 MANAGER_SIGNAL_SINK_REMOVED,
1409 MANAGER_SIGNAL_PROFILES_CHANGED,
1410 MANAGER_SIGNAL_MAX
1411 };
1412
1413 static pa_dbus_signal_info manager_signals[MANAGER_SIGNAL_MAX]={
1414 [MANAGER_SIGNAL_SINK_ADDED]={.name="SinkAdded", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1415 [MANAGER_SIGNAL_SINK_REMOVED]={.name="SinkRemoved", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1416 [MANAGER_SIGNAL_PROFILES_CHANGED]={.name="ProfilesChanged", .arguments=NULL, .n_arguments=0}
1417 };
1418
1419 static pa_dbus_interface_info manager_info={
1420 .name=MANAGER_IFACE,
1421 .method_handlers=manager_methods,
1422 .n_method_handlers=MANAGER_METHOD_MAX,
1423 .property_handlers=manager_handlers,
1424 .n_property_handlers=MANAGER_HANDLER_MAX,
1425 .get_all_properties_cb=manager_get_all,
1426 .signals=manager_signals,
1427 .n_signals=MANAGER_SIGNAL_MAX
1428 };
1429
1430 enum equalizer_method_index {
1431 EQUALIZER_METHOD_FILTER_POINTS,
1432 EQUALIZER_METHOD_SEED_FILTER,
1433 EQUALIZER_METHOD_SAVE_PROFILE,
1434 EQUALIZER_METHOD_LOAD_PROFILE,
1435 EQUALIZER_METHOD_SET_FILTER,
1436 EQUALIZER_METHOD_GET_FILTER,
1437 EQUALIZER_METHOD_SAVE_STATE,
1438 EQUALIZER_METHOD_GET_PROFILE_NAME,
1439 EQUALIZER_METHOD_MAX
1440 };
1441
1442 enum equalizer_handler_index {
1443 EQUALIZER_HANDLER_REVISION,
1444 EQUALIZER_HANDLER_SAMPLERATE,
1445 EQUALIZER_HANDLER_FILTERSAMPLERATE,
1446 EQUALIZER_HANDLER_N_COEFS,
1447 EQUALIZER_HANDLER_N_CHANNELS,
1448 EQUALIZER_HANDLER_MAX
1449 };
1450
1451 pa_dbus_arg_info filter_points_args[]={
1452 {"channel", "u","in"},
1453 {"xs", "au","in"},
1454 {"ys", "ad","out"},
1455 {"preamp", "d","out"}
1456 };
1457 pa_dbus_arg_info seed_filter_args[]={
1458 {"channel", "u","in"},
1459 {"xs", "au","in"},
1460 {"ys", "ad","in"},
1461 {"preamp", "d","in"}
1462 };
1463
1464 pa_dbus_arg_info set_filter_args[]={
1465 {"channel", "u","in"},
1466 {"ys", "ad","in"},
1467 {"preamp", "d","in"}
1468 };
1469 pa_dbus_arg_info get_filter_args[]={
1470 {"channel", "u","in"},
1471 {"ys", "ad","out"},
1472 {"preamp", "d","out"}
1473 };
1474
1475 pa_dbus_arg_info save_profile_args[]={
1476 {"channel", "u","in"},
1477 {"name", "s","in"}
1478 };
1479 pa_dbus_arg_info load_profile_args[]={
1480 {"channel", "u","in"},
1481 {"name", "s","in"}
1482 };
1483 pa_dbus_arg_info base_profile_name_args[]={
1484 {"channel", "u","in"},
1485 {"name", "s","out"}
1486 };
1487
1488 static pa_dbus_method_handler equalizer_methods[EQUALIZER_METHOD_MAX]={
1489 [EQUALIZER_METHOD_SEED_FILTER]{
1490 .method_name="SeedFilter",
1491 .arguments=seed_filter_args,
1492 .n_arguments=sizeof(seed_filter_args)/sizeof(pa_dbus_arg_info),
1493 .receive_cb=equalizer_handle_seed_filter},
1494 [EQUALIZER_METHOD_FILTER_POINTS]{
1495 .method_name="FilterAtPoints",
1496 .arguments=filter_points_args,
1497 .n_arguments=sizeof(filter_points_args)/sizeof(pa_dbus_arg_info),
1498 .receive_cb=equalizer_handle_get_filter_points},
1499 [EQUALIZER_METHOD_SET_FILTER]{
1500 .method_name="SetFilter",
1501 .arguments=set_filter_args,
1502 .n_arguments=sizeof(set_filter_args)/sizeof(pa_dbus_arg_info),
1503 .receive_cb=equalizer_handle_set_filter},
1504 [EQUALIZER_METHOD_GET_FILTER]{
1505 .method_name="GetFilter",
1506 .arguments=get_filter_args,
1507 .n_arguments=sizeof(get_filter_args)/sizeof(pa_dbus_arg_info),
1508 .receive_cb=equalizer_handle_get_filter},
1509 [EQUALIZER_METHOD_SAVE_PROFILE]{
1510 .method_name="SaveProfile",
1511 .arguments=save_profile_args,
1512 .n_arguments=sizeof(save_profile_args)/sizeof(pa_dbus_arg_info),
1513 .receive_cb=equalizer_handle_save_profile},
1514 [EQUALIZER_METHOD_LOAD_PROFILE]{
1515 .method_name="LoadProfile",
1516 .arguments=load_profile_args,
1517 .n_arguments=sizeof(load_profile_args)/sizeof(pa_dbus_arg_info),
1518 .receive_cb=equalizer_handle_load_profile},
1519 [EQUALIZER_METHOD_SAVE_STATE]{
1520 .method_name="SaveState",
1521 .arguments=NULL,
1522 .n_arguments=0,
1523 .receive_cb=equalizer_handle_save_state},
1524 [EQUALIZER_METHOD_GET_PROFILE_NAME]{
1525 .method_name="BaseProfile",
1526 .arguments=base_profile_name_args,
1527 .n_arguments=sizeof(base_profile_name_args)/sizeof(pa_dbus_arg_info),
1528 .receive_cb=equalizer_handle_get_profile_name}
1529 };
1530
1531 static pa_dbus_property_handler equalizer_handlers[EQUALIZER_HANDLER_MAX]={
1532 [EQUALIZER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=equalizer_get_revision,.set_cb=NULL},
1533 [EQUALIZER_HANDLER_SAMPLERATE]{.property_name="SampleRate",.type="u",.get_cb=equalizer_get_sample_rate,.set_cb=NULL},
1534 [EQUALIZER_HANDLER_FILTERSAMPLERATE]{.property_name="FilterSampleRate",.type="u",.get_cb=equalizer_get_filter_rate,.set_cb=NULL},
1535 [EQUALIZER_HANDLER_N_COEFS]{.property_name="NFilterCoefficients",.type="u",.get_cb=equalizer_get_n_coefs,.set_cb=NULL},
1536 [EQUALIZER_HANDLER_N_CHANNELS]{.property_name="NChannels",.type="u",.get_cb=equalizer_get_n_channels,.set_cb=NULL},
1537 };
1538
1539 enum equalizer_signal_index{
1540 EQUALIZER_SIGNAL_FILTER_CHANGED,
1541 EQUALIZER_SIGNAL_SINK_RECONFIGURED,
1542 EQUALIZER_SIGNAL_MAX
1543 };
1544
1545 static pa_dbus_signal_info equalizer_signals[EQUALIZER_SIGNAL_MAX]={
1546 [EQUALIZER_SIGNAL_FILTER_CHANGED]={.name="FilterChanged", .arguments=NULL, .n_arguments=0},
1547 [EQUALIZER_SIGNAL_SINK_RECONFIGURED]={.name="SinkReconfigured", .arguments=NULL, .n_arguments=0},
1548 };
1549
1550 static pa_dbus_interface_info equalizer_info={
1551 .name=EQUALIZER_IFACE,
1552 .method_handlers=equalizer_methods,
1553 .n_method_handlers=EQUALIZER_METHOD_MAX,
1554 .property_handlers=equalizer_handlers,
1555 .n_property_handlers=EQUALIZER_HANDLER_MAX,
1556 .get_all_properties_cb=equalizer_get_all,
1557 .signals=equalizer_signals,
1558 .n_signals=EQUALIZER_SIGNAL_MAX
1559 };
1560
1561 void dbus_init(struct userdata *u){
1562 uint32_t dummy;
1563 DBusMessage *signal = NULL;
1564 pa_idxset *sink_list = NULL;
1565 u->dbus_protocol=pa_dbus_protocol_get(u->sink->core);
1566 u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index);
1567
1568 pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &equalizer_info, u);
1569 sink_list = pa_shared_get(u->sink->core, SINKLIST);
1570 u->database = pa_shared_get(u->sink->core, EQDB);
1571 if(sink_list == NULL){
1572 char *dbname;
1573 sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
1574 pa_shared_set(u->sink->core, SINKLIST, sink_list);
1575 pa_assert_se(dbname = pa_state_path("equalizer-presets", FALSE));
1576 pa_assert_se(u->database = pa_database_open(dbname, TRUE));
1577 pa_xfree(dbname);
1578 pa_shared_set(u->sink->core, EQDB, u->database);
1579 pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
1580 pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
1581 }
1582 pa_idxset_put(sink_list, u, &dummy);
1583
1584 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_ADDED].name)));
1585 dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1586 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1587 dbus_message_unref(signal);
1588 }
1589
1590 void dbus_done(struct userdata *u){
1591 pa_idxset *sink_list;
1592 uint32_t dummy;
1593
1594 DBusMessage *signal = NULL;
1595 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_REMOVED].name)));
1596 dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1597 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1598 dbus_message_unref(signal);
1599
1600 pa_assert_se(sink_list=pa_shared_get(u->sink->core,SINKLIST));
1601 pa_idxset_remove_by_data(sink_list,u,&dummy);
1602 if(pa_idxset_size(sink_list)==0){
1603 pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME);
1604 pa_dbus_protocol_remove_interface(u->dbus_protocol, MANAGER_PATH, manager_info.name);
1605 pa_shared_remove(u->sink->core, EQDB);
1606 pa_database_close(u->database);
1607 pa_shared_remove(u->sink->core, SINKLIST);
1608 pa_xfree(sink_list);
1609 }
1610 pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, equalizer_info.name);
1611 pa_xfree(u->dbus_path);
1612 pa_dbus_protocol_unref(u->dbus_protocol);
1613 }
1614
1615 void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1616 DBusError error;
1617 pa_core *c = (pa_core *)_u;
1618 DBusMessage *signal = NULL;
1619 pa_dbus_protocol *dbus_protocol;
1620 char *name;
1621 pa_assert(conn);
1622 pa_assert(msg);
1623 pa_assert(c);
1624 dbus_error_init(&error);
1625 if(!dbus_message_get_args(msg, &error,
1626 DBUS_TYPE_STRING, &name,
1627 DBUS_TYPE_INVALID)){
1628 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1629 dbus_error_free(&error);
1630 return;
1631 }
1632 remove_profile(c,name);
1633 pa_dbus_send_empty_reply(conn, msg);
1634
1635 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
1636 dbus_protocol = pa_dbus_protocol_get(c);
1637 pa_dbus_protocol_send_signal(dbus_protocol, signal);
1638 pa_dbus_protocol_unref(dbus_protocol);
1639 dbus_message_unref(signal);
1640 }
1641
1642 void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
1643 uint32_t rev=1;
1644 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
1645 }
1646
1647 static void get_sinks(pa_core *u, char ***names, unsigned *n_sinks){
1648 void *iter = NULL;
1649 struct userdata *sink_u = NULL;
1650 uint32_t dummy;
1651 pa_idxset *sink_list;
1652 pa_assert(u);
1653 pa_assert(names);
1654 pa_assert(n_sinks);
1655
1656 pa_assert_se(sink_list = pa_shared_get(u, SINKLIST));
1657 *n_sinks = (unsigned) pa_idxset_size(sink_list);
1658 *names = *n_sinks > 0 ? pa_xnew0(char *,*n_sinks) : NULL;
1659 for(uint32_t i = 0; i < *n_sinks; ++i){
1660 sink_u = (struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy);
1661 (*names)[i] = pa_xstrdup(sink_u->dbus_path);
1662 }
1663 }
1664
1665 void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u){
1666 unsigned n;
1667 char **names = NULL;
1668 pa_assert(conn);
1669 pa_assert(msg);
1670 pa_assert(_u);
1671
1672 get_sinks((pa_core *) _u, &names, &n);
1673 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, names, n);
1674 for(unsigned i = 0; i < n; ++i){
1675 pa_xfree(names[i]);
1676 }
1677 pa_xfree(names);
1678 }
1679
1680 static void get_profiles(pa_core *c, char ***names, unsigned *n){
1681 char *name;
1682 pa_database *database;
1683 pa_datum key, next_key;
1684 pa_strlist *head=NULL, *iter;
1685 pa_bool_t done;
1686 pa_assert_se(database = pa_shared_get(c, EQDB));
1687
1688 pa_assert(c);
1689 pa_assert(names);
1690 pa_assert(n);
1691 done = !pa_database_first(database, &key, NULL);
1692 *n = 0;
1693 while(!done){
1694 done = !pa_database_next(database, &key, &next_key, NULL);
1695 name=pa_xmalloc(key.size + 1);
1696 memcpy(name, key.data, key.size);
1697 name[key.size] = '\0';
1698 pa_datum_free(&key);
1699 head = pa_strlist_prepend(head, name);
1700 pa_xfree(name);
1701 key = next_key;
1702 (*n)++;
1703 }
1704 (*names) = *n > 0 ? pa_xnew0(char *, *n) : NULL;
1705 iter=head;
1706 for(unsigned i = 0; i < *n; ++i){
1707 (*names)[*n - 1 - i] = pa_xstrdup(pa_strlist_data(iter));
1708 iter = pa_strlist_next(iter);
1709 }
1710 pa_strlist_free(head);
1711 }
1712
1713 void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u){
1714 char **names;
1715 unsigned n;
1716 pa_assert(conn);
1717 pa_assert(msg);
1718 pa_assert(_u);
1719
1720 get_profiles((pa_core *)_u, &names, &n);
1721 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, names, n);
1722 for(unsigned i = 0; i < n; ++i){
1723 pa_xfree(names[i]);
1724 }
1725 pa_xfree(names);
1726 }
1727
1728 void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
1729 pa_core *c;
1730 char **names = NULL;
1731 unsigned n;
1732 DBusMessage *reply = NULL;
1733 DBusMessageIter msg_iter, dict_iter;
1734 uint32_t rev;
1735 pa_assert(conn);
1736 pa_assert(msg);
1737 pa_assert_se(c = _u);
1738
1739 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1740 dbus_message_iter_init_append(reply, &msg_iter);
1741 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1742
1743 rev = 1;
1744 pa_dbus_append_basic_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
1745
1746 get_sinks(c, &names, &n);
1747 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter,manager_handlers[MANAGER_HANDLER_EQUALIZED_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, names, n);
1748 for(unsigned i = 0; i < n; ++i){
1749 pa_xfree(names[i]);
1750 }
1751 pa_xfree(names);
1752
1753 get_profiles(c, &names, &n);
1754 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_PROFILES].property_name, DBUS_TYPE_STRING, names, n);
1755 for(unsigned i = 0; i < n; ++i){
1756 pa_xfree(names[i]);
1757 }
1758 pa_xfree(names);
1759 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1760 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1761 dbus_message_unref(reply);
1762 }
1763
1764 void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
1765 struct userdata *u = _u;
1766 DBusError error;
1767 DBusMessage *signal = NULL;
1768 float *ys;
1769 uint32_t *xs, channel, r_channel;
1770 double *_ys, preamp;
1771 unsigned x_npoints, y_npoints, a_i;
1772 float *H;
1773 pa_bool_t points_good = TRUE;
1774
1775 pa_assert(conn);
1776 pa_assert(msg);
1777 pa_assert(u);
1778
1779 dbus_error_init(&error);
1780
1781 if(!dbus_message_get_args(msg, &error,
1782 DBUS_TYPE_UINT32, &channel,
1783 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1784 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &_ys, &y_npoints,
1785 DBUS_TYPE_DOUBLE, &preamp,
1786 DBUS_TYPE_INVALID)){
1787 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1788 dbus_error_free(&error);
1789 return;
1790 }
1791 if(channel > u->channels){
1792 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1793 dbus_error_free(&error);
1794 return;
1795 }
1796 for(size_t i = 0; i < x_npoints; ++i){
1797 if(xs[i] >= FILTER_SIZE(u)){
1798 points_good = FALSE;
1799 break;
1800 }
1801 }
1802 if(!is_monotonic(xs, x_npoints) || !points_good){
1803 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs must be monotonic and 0<=x<=%ld", u->fft_size / 2);
1804 dbus_error_free(&error);
1805 return;
1806 }else if(x_npoints != y_npoints || x_npoints < 2 || x_npoints > FILTER_SIZE(u)){
1807 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));
1808 dbus_error_free(&error);
1809 return;
1810 }else if(xs[0] != 0 || xs[x_npoints - 1] != u->fft_size / 2){
1811 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs[0] must be 0 and xs[-1]=fft_size/2");
1812 dbus_error_free(&error);
1813 return;
1814 }
1815
1816 ys = pa_xmalloc(x_npoints * sizeof(float));
1817 for(uint32_t i = 0; i < x_npoints; ++i){
1818 ys[i] = (float) _ys[i];
1819 }
1820 r_channel = channel == u->channels ? 0 : channel;
1821 a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1822 H = u->Hs[r_channel][a_i];
1823 u->Xs[r_channel][a_i] = preamp;
1824 interpolate(H, FILTER_SIZE(u), xs, ys, x_npoints);
1825 fix_filter(H, u->fft_size);
1826 if(channel == u->channels){
1827 for(size_t c = 1; c < u->channels; ++c){
1828 unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1829 float *H_p = u->Hs[c][b_i];
1830 u->Xs[c][b_i] = preamp;
1831 memcpy(H_p, H, FILTER_SIZE(u) * sizeof(float));
1832 pa_aupdate_write_end(u->a_H[c]);
1833 }
1834 }
1835 pa_aupdate_write_end(u->a_H[r_channel]);
1836 pa_xfree(ys);
1837
1838
1839 pa_dbus_send_empty_reply(conn, msg);
1840
1841 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
1842 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1843 dbus_message_unref(signal);
1844 }
1845
1846 void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u) {
1847 struct userdata *u = (struct userdata *) _u;
1848 uint32_t *xs, channel, r_channel;
1849 double *ys, preamp;
1850 unsigned x_npoints, a_i;
1851 float *H;
1852 pa_bool_t points_good=TRUE;
1853 DBusMessage *reply = NULL;
1854 DBusMessageIter msg_iter;
1855 DBusError error;
1856
1857 pa_assert(conn);
1858 pa_assert(msg);
1859 pa_assert(u);
1860
1861 dbus_error_init(&error);
1862 if(!dbus_message_get_args(msg, &error,
1863 DBUS_TYPE_UINT32, &channel,
1864 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1865 DBUS_TYPE_INVALID)){
1866 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1867 dbus_error_free(&error);
1868 return;
1869 }
1870 if(channel > u->channels){
1871 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1872 dbus_error_free(&error);
1873 return;
1874 }
1875
1876 for(size_t i = 0; i < x_npoints; ++i){
1877 if(xs[i] >= FILTER_SIZE(u)){
1878 points_good=FALSE;
1879 break;
1880 }
1881 }
1882
1883 if(x_npoints > FILTER_SIZE(u) || !points_good){
1884 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs indices/length must be <= %ld!", FILTER_SIZE(u));
1885 dbus_error_free(&error);
1886 return;
1887 }
1888
1889 r_channel = channel == u->channels ? 0 : channel;
1890 ys = pa_xmalloc(x_npoints * sizeof(double));
1891 a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1892 H = u->Hs[r_channel][a_i];
1893 preamp = u->Xs[r_channel][a_i];
1894 for(uint32_t i = 0; i < x_npoints; ++i){
1895 ys[i] = H[xs[i]] * u->fft_size;
1896 }
1897 pa_aupdate_read_end(u->a_H[r_channel]);
1898
1899 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1900 dbus_message_iter_init_append(reply, &msg_iter);
1901
1902 pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, ys, x_npoints);
1903 pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1904
1905 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1906 dbus_message_unref(reply);
1907 pa_xfree(ys);
1908 }
1909
1910 static void get_filter(struct userdata *u, size_t channel, double **H_, double *preamp){
1911 float *H;
1912 unsigned a_i;
1913 size_t r_channel = channel == u->channels ? 0 : channel;
1914 *H_ = pa_xnew0(double, FILTER_SIZE(u));
1915 a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1916 H = u->Hs[r_channel][a_i];
1917 for(size_t i = 0;i < FILTER_SIZE(u); ++i){
1918 (*H_)[i] = H[i] * u->fft_size;
1919 }
1920 *preamp = u->Xs[r_channel][a_i];
1921
1922 pa_aupdate_read_end(u->a_H[r_channel]);
1923 }
1924
1925 void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1926 struct userdata *u;
1927 unsigned n_coefs;
1928 uint32_t channel;
1929 double *H_, preamp;
1930 DBusMessage *reply = NULL;
1931 DBusMessageIter msg_iter;
1932 DBusError error;
1933 pa_assert_se(u = (struct userdata *) _u);
1934 pa_assert(conn);
1935 pa_assert(msg);
1936
1937 dbus_error_init(&error);
1938 if(!dbus_message_get_args(msg, &error,
1939 DBUS_TYPE_UINT32, &channel,
1940 DBUS_TYPE_INVALID)){
1941 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1942 dbus_error_free(&error);
1943 return;
1944 }
1945 if(channel > u->channels){
1946 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1947 dbus_error_free(&error);
1948 return;
1949 }
1950
1951 n_coefs = CHANNEL_PROFILE_SIZE(u);
1952 pa_assert(conn);
1953 pa_assert(msg);
1954 get_filter(u, channel, &H_, &preamp);
1955 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1956 dbus_message_iter_init_append(reply, &msg_iter);
1957
1958 pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, H_, n_coefs);
1959 pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1960
1961 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1962 dbus_message_unref(reply);
1963 pa_xfree(H_);
1964 }
1965
1966 static void set_filter(struct userdata *u, size_t channel, double *H_, double preamp){
1967 unsigned a_i;
1968 size_t r_channel = channel == u->channels ? 0 : channel;
1969 float *H;
1970 //all channels
1971 a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1972 u->Xs[r_channel][a_i] = (float) preamp;
1973 H = u->Hs[r_channel][a_i];
1974 for(size_t i = 0; i < FILTER_SIZE(u); ++i){
1975 H[i] = (float) H_[i];
1976 }
1977 fix_filter(H, u->fft_size);
1978 if(channel == u->channels){
1979 for(size_t c = 1; c < u->channels; ++c){
1980 unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1981 u->Xs[c][b_i] = u->Xs[r_channel][a_i];
1982 memcpy(u->Hs[c][b_i], u->Hs[r_channel][a_i], FILTER_SIZE(u) * sizeof(float));
1983 pa_aupdate_write_end(u->a_H[c]);
1984 }
1985 }
1986 pa_aupdate_write_end(u->a_H[r_channel]);
1987 }
1988
1989 void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1990 struct userdata *u;
1991 double *H, preamp;
1992 uint32_t channel;
1993 unsigned _n_coefs;
1994 DBusMessage *signal = NULL;
1995 DBusError error;
1996 pa_assert_se(u = (struct userdata *) _u);
1997 pa_assert(conn);
1998 pa_assert(msg);
1999
2000 dbus_error_init(&error);
2001 if(!dbus_message_get_args(msg, &error,
2002 DBUS_TYPE_UINT32, &channel,
2003 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &H, &_n_coefs,
2004 DBUS_TYPE_DOUBLE, &preamp,
2005 DBUS_TYPE_INVALID)){
2006 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2007 dbus_error_free(&error);
2008 return;
2009 }
2010 if(channel > u->channels){
2011 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2012 dbus_error_free(&error);
2013 return;
2014 }
2015 if(_n_coefs != FILTER_SIZE(u)){
2016 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE(u), _n_coefs);
2017 return;
2018 }
2019 set_filter(u, channel, H, preamp);
2020
2021 pa_dbus_send_empty_reply(conn, msg);
2022
2023 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2024 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2025 dbus_message_unref(signal);
2026 }
2027
2028 void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
2029 struct userdata *u = (struct userdata *) _u;
2030 char *name;
2031 uint32_t channel, r_channel;
2032 DBusMessage *signal = NULL;
2033 DBusError error;
2034 pa_assert(conn);
2035 pa_assert(msg);
2036 pa_assert(u);
2037 dbus_error_init(&error);
2038
2039 if(!dbus_message_get_args(msg, &error,
2040 DBUS_TYPE_UINT32, &channel,
2041 DBUS_TYPE_STRING, &name,
2042 DBUS_TYPE_INVALID)){
2043 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2044 dbus_error_free(&error);
2045 return;
2046 }
2047 if(channel > u->channels){
2048 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2049 dbus_error_free(&error);
2050 return;
2051 }
2052 r_channel = channel == u->channels ? 0 : channel;
2053 save_profile(u, r_channel, name);
2054 pa_dbus_send_empty_reply(conn, msg);
2055
2056 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
2057 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2058 dbus_message_unref(signal);
2059 }
2060
2061 void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
2062 struct userdata *u = (struct userdata *) _u;
2063 char *name;
2064 DBusError error;
2065 uint32_t channel, r_channel;
2066 const char *err_msg = NULL;
2067 DBusMessage *signal = NULL;
2068
2069 pa_assert(conn);
2070 pa_assert(msg);
2071 pa_assert(u);
2072 dbus_error_init(&error);
2073
2074 if(!dbus_message_get_args(msg, &error,
2075 DBUS_TYPE_UINT32, &channel,
2076 DBUS_TYPE_STRING, &name,
2077 DBUS_TYPE_INVALID)){
2078 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2079 dbus_error_free(&error);
2080 return;
2081 }
2082 if(channel > u->channels){
2083 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2084 dbus_error_free(&error);
2085 return;
2086 }
2087 r_channel = channel == u->channels ? 0 : channel;
2088
2089 err_msg = load_profile(u, r_channel, name);
2090 if(err_msg != NULL){
2091 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "error loading profile %s: %s", name, err_msg);
2092 dbus_error_free(&error);
2093 return;
2094 }
2095 if(channel == u->channels){
2096 for(uint32_t c = 1; c < u->channels; ++c){
2097 load_profile(u, c, name);
2098 }
2099 }
2100 pa_dbus_send_empty_reply(conn, msg);
2101
2102 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2103 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2104 dbus_message_unref(signal);
2105 }
2106
2107 void equalizer_handle_save_state(DBusConnection *conn, DBusMessage *msg, void *_u) {
2108 struct userdata *u = (struct userdata *) _u;
2109 pa_assert(conn);
2110 pa_assert(msg);
2111 pa_assert(u);
2112
2113 save_state(u);
2114 pa_dbus_send_empty_reply(conn, msg);
2115 }
2116
2117 void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u){
2118 struct userdata *u = (struct userdata *) _u;
2119 DBusError error;
2120 uint32_t channel, r_channel;
2121
2122 pa_assert(conn);
2123 pa_assert(msg);
2124 pa_assert(u);
2125 dbus_error_init(&error);
2126
2127 if(!dbus_message_get_args(msg, &error,
2128 DBUS_TYPE_UINT32, &channel,
2129 DBUS_TYPE_INVALID)){
2130 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2131 dbus_error_free(&error);
2132 return;
2133 }
2134 if(channel > u->channels){
2135 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2136 dbus_error_free(&error);
2137 return;
2138 }
2139 r_channel = channel == u->channels ? 0 : channel;
2140 pa_assert(u->base_profiles[r_channel]);
2141 pa_dbus_send_basic_value_reply(conn,msg, DBUS_TYPE_STRING, &u->base_profiles[r_channel]);
2142 }
2143
2144 void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
2145 uint32_t rev=1;
2146 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
2147 }
2148
2149 void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u){
2150 struct userdata *u;
2151 uint32_t channels;
2152 pa_assert_se(u = (struct userdata *) _u);
2153 pa_assert(conn);
2154 pa_assert(msg);
2155
2156 channels = (uint32_t) u->channels;
2157 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &channels);
2158 }
2159
2160 void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u){
2161 struct userdata *u;
2162 uint32_t n_coefs;
2163 pa_assert_se(u = (struct userdata *) _u);
2164 pa_assert(conn);
2165 pa_assert(msg);
2166
2167 n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE(u);
2168 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs);
2169 }
2170
2171 void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
2172 struct userdata *u;
2173 uint32_t rate;
2174 pa_assert_se(u = (struct userdata *) _u);
2175 pa_assert(conn);
2176 pa_assert(msg);
2177
2178 rate = (uint32_t) u->sink->sample_spec.rate;
2179 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &rate);
2180 }
2181
2182 void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
2183 struct userdata *u;
2184 uint32_t fft_size;
2185 pa_assert_se(u = (struct userdata *) _u);
2186 pa_assert(conn);
2187 pa_assert(msg);
2188
2189 fft_size = (uint32_t) u->fft_size;
2190 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &fft_size);
2191 }
2192
2193 void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
2194 struct userdata *u;
2195 DBusMessage *reply = NULL;
2196 DBusMessageIter msg_iter, dict_iter;
2197 uint32_t rev, n_coefs, rate, fft_size, channels;
2198
2199 pa_assert_se(u = _u);
2200 pa_assert(msg);
2201
2202 rev = 1;
2203 n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE(u);
2204 rate = (uint32_t) u->sink->sample_spec.rate;
2205 fft_size = (uint32_t) u->fft_size;
2206 channels = (uint32_t) u->channels;
2207
2208 pa_assert_se((reply = dbus_message_new_method_return(msg)));
2209 dbus_message_iter_init_append(reply, &msg_iter);
2210 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
2211
2212 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
2213 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_SAMPLERATE].property_name, DBUS_TYPE_UINT32, &rate);
2214 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_FILTERSAMPLERATE].property_name, DBUS_TYPE_UINT32, &fft_size);
2215 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs);
2216 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_CHANNELS].property_name, DBUS_TYPE_UINT32, &channels);
2217
2218 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
2219 pa_assert_se(dbus_connection_send(conn, reply, NULL));
2220 dbus_message_unref(reply);
2221 }