• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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