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