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