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