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