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