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