2 This file is part of PulseAudio.
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 Copyright 2009 Jason Newton <nevion@gmail.com>
10 Copyright 2004-2008 Lennart Poettering
12 PulseAudio is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published
14 by the Free Software Foundation; either version 2.1 of the License,
15 or (at your option) any later version.
17 PulseAudio is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with PulseAudio; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39 #include <pulse/xmalloc.h>
40 #include <pulse/i18n.h>
41 #include <pulse/timeval.h>
43 #include <pulsecore/core-rtclock.h>
44 #include <pulsecore/aupdate.h>
45 #include <pulsecore/core-error.h>
46 #include <pulsecore/namereg.h>
47 #include <pulsecore/sink.h>
48 #include <pulsecore/module.h>
49 #include <pulsecore/core-util.h>
50 #include <pulsecore/modargs.h>
51 #include <pulsecore/log.h>
52 #include <pulsecore/thread.h>
53 #include <pulsecore/thread-mq.h>
54 #include <pulsecore/rtpoll.h>
55 #include <pulsecore/sample-util.h>
56 #include <pulsecore/shared.h>
57 #include <pulsecore/idxset.h>
58 #include <pulsecore/strlist.h>
59 #include <pulsecore/database.h>
60 #include <pulsecore/protocol-dbus.h>
61 #include <pulsecore/dbus-util.h>
69 #include <xmmintrin.h>
70 #include <emmintrin.h>
75 #include "module-equalizer-sink-symdef.h"
77 PA_MODULE_AUTHOR("Jason Newton");
78 PA_MODULE_DESCRIPTION(_("General Purpose Equalizer"));
79 PA_MODULE_VERSION(PACKAGE_VERSION);
80 PA_MODULE_LOAD_ONCE(FALSE);
81 PA_MODULE_USAGE(_("sink=<sink to connect to> "));
83 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
89 pa_sink_input *sink_input;
93 size_t fft_size;//length (res) of fft
96 *effectively chooses R
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
102 size_t latency;//Really just R but made into it's own variable
103 //for twiddling with pulseaudio
104 size_t overlap_size;//window_size-R
105 size_t samples_gathered;
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;
114 float ***Hs;//thread updatable copies of the freq response filters (magintude based)
116 pa_memchunk conv_buffer;
117 pa_memblockq *input_q;
118 pa_bool_t first_iteration;
120 pa_dbus_protocol *dbus_protocol;
122 pa_bool_t set_default;
124 pa_database *database;
125 char **base_profiles;
128 static const char* const valid_modargs[] = {
142 #define SINKLIST "equalized_sinklist"
143 #define EQDB "equalizer_db"
144 #define EQ_STATE_DB "equalizer-state"
145 #define FILTER_SIZE (u->fft_size / 2 + 1)
146 #define CHANNEL_PROFILE_SIZE (FILTER_SIZE + 1)
147 #define FILTER_STATE_SIZE (CHANNEL_PROFILE_SIZE * u->channels)
148 static void dbus_init(struct userdata *u);
149 static void dbus_done(struct userdata *u);
151 static void hanning_window(float *W, size_t window_size){
152 //h=.5*(1-cos(2*pi*j/(window_size+1)), COLA for R=(M+1)/2
153 for(size_t i=0; i < window_size;++i){
154 W[i] = (float).5*(1-cos(2*M_PI*i/(window_size+1)));
158 static void fix_filter(float *H, size_t fft_size){
159 //divide out the fft gain
160 for(size_t i = 0; i < fft_size / 2 + 1; ++i){
165 static void interpolate(float *signal, size_t length, uint32_t *xs, float *ys, size_t n_points){
166 //Note that xs must be monotonically increasing!
167 float x_range_lower, x_range_upper, c0;
168 pa_assert_se(n_points>=2);
169 pa_assert_se(xs[0] == 0);
170 pa_assert_se(xs[n_points - 1] == length - 1);
171 for(size_t x = 0, x_range_lower_i = 0; x < length-1; ++x){
172 pa_assert(x_range_lower_i < n_points-1);
173 x_range_lower = (float) (xs[x_range_lower_i]);
174 x_range_upper = (float) (xs[x_range_lower_i+1]);
175 pa_assert_se(x_range_lower < x_range_upper);
176 pa_assert_se(x >= x_range_lower);
177 pa_assert_se(x <= x_range_upper);
178 //bilinear-interpolation of coefficients specified
179 c0 = (x-x_range_lower)/(x_range_upper-x_range_lower);
180 pa_assert_se(c0 >= 0&&c0 <= 1.0);
181 signal[x] = ((1.0f - c0) * ys[x_range_lower_i] + c0 * ys[x_range_lower_i + 1]);
182 while(x >= xs[x_range_lower_i + 1]){
186 signal[length-1]=ys[n_points-1];
189 static int is_monotonic(const uint32_t *xs,size_t length){
193 for(size_t i = 1; i < length; ++i){
202 /* Called from I/O thread context */
203 static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) {
204 struct userdata *u = PA_SINK(o)->userdata;
208 case PA_SINK_MESSAGE_GET_LATENCY: {
209 //size_t fs=pa_frame_size(&u->sink->sample_spec);
211 /* The sink is _put() before the sink input is, so let's
212 * make sure we don't access it in that time. Also, the
213 * sink input is first shut down, the sink second. */
214 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
215 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state)) {
216 *((pa_usec_t*) data) = 0;
220 *((pa_usec_t*) data) =
221 /* Get the latency of the master sink */
222 pa_sink_get_latency_within_thread(u->sink_input->sink) +
224 /* Add the latency internal to our sink input on top */
225 pa_bytes_to_usec(pa_memblockq_get_length(u->sink_input->thread_info.render_memblockq), &u->sink_input->sink->sample_spec);
226 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
227 //+ pa_bytes_to_usec(u->latency * fs, ss)
228 //+ pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss);
233 return pa_sink_process_msg(o, code, data, offset, chunk);
237 /* Called from main context */
238 static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) {
241 pa_sink_assert_ref(s);
242 pa_assert_se(u = s->userdata);
244 if (!PA_SINK_IS_LINKED(state) ||
245 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
248 pa_sink_input_cork(u->sink_input, state == PA_SINK_SUSPENDED);
252 /* Called from I/O thread context */
253 static void sink_request_rewind_cb(pa_sink *s) {
256 pa_sink_assert_ref(s);
257 pa_assert_se(u = s->userdata);
259 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
260 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
263 /* Just hand this one over to the master sink */
264 pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes+pa_memblockq_get_length(u->input_q), TRUE, FALSE, FALSE);
267 /* Called from I/O thread context */
268 static void sink_update_requested_latency_cb(pa_sink *s) {
271 pa_sink_assert_ref(s);
272 pa_assert_se(u = s->userdata);
274 if (!PA_SINK_IS_LINKED(u->sink->thread_info.state) ||
275 !PA_SINK_INPUT_IS_LINKED(u->sink_input->thread_info.state))
278 /* Just hand this one over to the master sink */
279 pa_sink_input_set_requested_latency_within_thread(
281 pa_sink_get_requested_latency_within_thread(s));
284 /* Called from main context */
285 static void sink_set_volume_cb(pa_sink *s) {
288 pa_sink_assert_ref(s);
289 pa_assert_se(u = s->userdata);
291 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) ||
292 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
295 pa_sink_input_set_volume(u->sink_input, &s->real_volume, s->save_volume, TRUE);
298 /* Called from main context */
299 static void sink_set_mute_cb(pa_sink *s) {
302 pa_sink_assert_ref(s);
303 pa_assert_se(u = s->userdata);
305 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s)) ||
306 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u->sink_input)))
309 pa_sink_input_set_mute(u->sink_input, s->muted, s->save_muted);
313 //reference implementation
314 static void dsp_logic(
315 float * restrict dst,//used as a temp array too, needs to be fft_length!
316 float * restrict src,/*input data w/ overlap at start,
317 *automatically cycled in routine
319 float * restrict overlap,
320 const float X,//multipliar
321 const float * restrict H,//The freq. magnitude scalers filter
322 const float * restrict W,//The windowing function
323 fftwf_complex * restrict output_window,//The transformed window'd src
325 //use a linear-phase sliding STFT and overlap-add method (for each channel)
327 memset(dst + u->window_size, 0, (u->fft_size - u->window_size) * sizeof(float));
329 for(size_t j = 0; j < u->window_size; ++j){
330 dst[j] = X * W[j] * src[j];
332 //Processing is done here!
334 fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
336 for(size_t j = 0; j < FILTER_SIZE; ++j){
337 u->output_window[j][0] *= H[j];
338 u->output_window[j][1] *= H[j];
341 fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
342 ////debug: tests overlaping add
343 ////and negates ALL PREVIOUS processing
344 ////yields a perfect reconstruction if COLA is held
345 //for(size_t j = 0; j < u->window_size; ++j){
346 // u->work_buffer[j] = u->W[j] * u->input[c][j];
349 //overlap add and preserve overlap component from this window (linear phase)
350 for(size_t j = 0; j < u->overlap_size; ++j){
351 u->work_buffer[j] += overlap[j];
352 overlap[j] = dst[u->R + j];
354 ////debug: tests if basic buffering works
355 ////shouldn't modify the signal AT ALL (beyond roundoff)
356 //for(size_t j = 0; j < u->window_size;++j){
357 // u->work_buffer[j] = u->input[c][j];
360 //preseve the needed input for the next window's overlap
361 memmove(src, src + u->R,
362 u->overlap_size * sizeof(float)
366 typedef float v4sf __attribute__ ((__aligned__(v_size * sizeof(float))));
367 typedef union float_vector {
375 ////regardless of sse enabled, the loops in here assume
376 ////16 byte aligned addresses and memory allocations divisible by v_size
378 // float * restrict dst,//used as a temp array too, needs to be fft_length!
379 // float * restrict src,/*input data w/ overlap at start,
380 // *automatically cycled in routine
382 // float * restrict overlap,//The size of the overlap
383 // const float X,//multipliar
384 // const float * restrict H,//The freq. magnitude scalers filter
385 // const float * restrict W,//The windowing function
386 // fftwf_complex * restrict output_window,//The transformed window'd src
387 // struct userdata *u){//Collection of constants
388 //float_vector_t x = {X, X, X, X};
389 // const size_t window_size = PA_ROUND_UP(u->window_size,v_size);
390 // const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2);
391 // //const size_t R = PA_ROUND_UP(u->R, v_size);
392 // const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
393 // overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
395 // //assert(u->samples_gathered >= u->R);
396 // //zero out the bit beyond the real overlap so we don't add garbage
397 // for(size_t j = overlap_size; j > u->overlap_size; --j){
400 // //use a linear-phase sliding STFT and overlap-add method
401 // //zero padd the data
402 // memset(dst + u->window_size, 0, (u->fft_size - u->window_size)*sizeof(float));
404 // for(size_t j = 0; j < window_size; j += v_size){
405 // //dst[j] = W[j]*src[j];
406 // float_vector_t *d = (float_vector_t*) (dst+j);
407 // float_vector_t *w = (float_vector_t*) (W+j);
408 // float_vector_t *s = (float_vector_t*) (src+j);
410 // d->m = _mm_mul_ps(x->m, _mm_mul_ps(w->m, s->m));
412 // d->v = x->v * w->v * s->v;
415 // //Processing is done here!
417 // fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
420 // //perform filtering - purely magnitude based
421 // for(size_t j = 0;j < fft_h; j+=v_size/2){
422 // //output_window[j][0]*=H[j];
423 // //output_window[j][1]*=H[j];
424 // float_vector_t *d = (float_vector_t*)(output_window+j);
426 // h.f[0] = h.f[1] = H[j];
427 // h.f[2] = h.f[3] = H[j+1];
429 // d->m = _mm_mul_ps(d->m, h.m);
435 // fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
437 // ////debug: tests overlaping add
438 // ////and negates ALL PREVIOUS processing
439 // ////yields a perfect reconstruction if COLA is held
440 // //for(size_t j = 0; j < u->window_size; ++j){
441 // // dst[j] = W[j]*src[j];
444 // //overlap add and preserve overlap component from this window (linear phase)
445 // for(size_t j = 0; j < overlap_size; j+=v_size){
446 // //dst[j]+=overlap[j];
447 // //overlap[j]+=dst[j+R];
448 // float_vector_t *d = (float_vector_t*)(dst+j);
449 // float_vector_t *o = (float_vector_t*)(overlap+j);
451 // d->m = _mm_add_ps(d->m, o->m);
452 // o->m = ((float_vector_t*)(dst+u->R+j))->m;
455 // o->v = ((float_vector_t*)(dst+u->R+j))->v;
458 // //memcpy(overlap, dst+u->R, u->overlap_size*sizeof(float));
460 // //////debug: tests if basic buffering works
461 // //////shouldn't modify the signal AT ALL (beyond roundoff)
462 // //for(size_t j = 0; j < u->window_size; ++j){
463 // // dst[j] = src[j];
466 // //preseve the needed input for the next window's overlap
467 // memmove(src, src + u->R,
468 // u->overlap_size * sizeof(float)
472 static void process_samples(struct userdata *u, pa_memchunk *tchunk){
473 size_t fs=pa_frame_size(&(u->sink->sample_spec));
477 pa_assert(u->samples_gathered >= u->R);
479 tchunk->length = u->R * fs;
480 tchunk->memblock = pa_memblock_new(u->sink->core->mempool, tchunk->length);
481 dst = ((float*)pa_memblock_acquire(tchunk->memblock));
483 for(size_t c=0;c < u->channels; c++) {
484 a_i = pa_aupdate_read_begin(u->a_H[c]);
497 pa_aupdate_read_end(u->a_H[c]);
498 if(u->first_iteration){
499 /* The windowing function will make the audio ramped in, as a cheap fix we can
500 * undo the windowing (for non-zero window values)
502 for(size_t i = 0;i < u->overlap_size; ++i){
503 u->work_buffer[i] = u->W[i] <= FLT_EPSILON ? u->work_buffer[i] : u->work_buffer[i] / u->W[i];
506 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, dst + c, fs, u->work_buffer, sizeof(float), u->R);
508 pa_memblock_release(tchunk->memblock);
509 u->samples_gathered -= u->R;
512 static void initialize_buffer(struct userdata *u, pa_memchunk *in){
513 size_t fs = pa_frame_size(&u->sink->sample_spec);
514 size_t samples = in->length / fs;
515 float *src = (float*) ((uint8_t*) pa_memblock_acquire(in->memblock) + in->index);
516 pa_assert_se(u->samples_gathered + samples <= u->window_size);
517 for(size_t c = 0; c < u->channels; c++) {
518 //buffer with an offset after the overlap from previous
520 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c] + u->samples_gathered, sizeof(float), src + c, fs, samples);
522 u->samples_gathered += samples;
523 pa_memblock_release(in->memblock);
526 static void input_buffer(struct userdata *u, pa_memchunk *in){
527 size_t fs = pa_frame_size(&(u->sink->sample_spec));
528 size_t samples = in->length/fs;
529 float *src = (float*) ((uint8_t*) pa_memblock_acquire(in->memblock) + in->index);
530 pa_assert_se(samples <= u->window_size - u->samples_gathered);
531 for(size_t c = 0; c < u->channels; c++) {
532 //buffer with an offset after the overlap from previous
535 u->input[c]+u->samples_gathered+samples <= u->input[c]+u->window_size
537 pa_sample_clamp(PA_SAMPLE_FLOAT32NE, u->input[c]+u->samples_gathered, sizeof(float), src + c, fs, samples);
539 u->samples_gathered += samples;
540 pa_memblock_release(in->memblock);
543 /* Called from I/O thread context */
544 static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
547 struct timeval start, end;
549 pa_sink_input_assert_ref(i);
550 pa_assert_se(u = i->userdata);
553 fs = pa_frame_size(&(u->sink->sample_spec));
554 chunk->memblock = NULL;
556 /* Hmm, process any rewind request that might be queued up */
557 pa_sink_process_rewind(u->sink, 0);
559 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
560 pa_rtclock_get(&start);
562 size_t input_remaining = u->window_size - u->samples_gathered;
563 pa_assert(input_remaining > 0);
566 //buffer = &u->conv_buffer;
567 //buffer->length = input_remaining*fs;
569 //pa_memblock_ref(buffer->memblock);
570 //pa_sink_render_into(u->sink, buffer);
571 while(pa_memblockq_peek(u->input_q, &tchunk) < 0){
572 pa_sink_render(u->sink, input_remaining*fs, &tchunk);
573 //pa_sink_render_full(u->sink, input_remaining*fs, &tchunk);
574 pa_assert(tchunk.memblock);
575 pa_memblockq_push(u->input_q, &tchunk);
576 pa_memblock_unref(tchunk.memblock);
578 pa_assert(tchunk.memblock);
579 tchunk.length = PA_MIN(input_remaining * fs, tchunk.length);
580 pa_memblockq_drop(u->input_q, tchunk.length);
581 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
583 //pa_rtclock_get(start);
584 if(u->first_iteration){
585 initialize_buffer(u, &tchunk);
587 input_buffer(u, &tchunk);
589 //pa_rtclock_get(&end);
590 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
591 pa_memblock_unref(tchunk.memblock);
592 }while(u->samples_gathered < u->window_size);
593 pa_rtclock_get(&end);
594 pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
596 pa_assert(u->fft_size >= u->window_size);
597 pa_assert(u->R < u->window_size);
598 /* set the H filter */
599 pa_rtclock_get(&start);
600 /* process a block */
601 process_samples(u, chunk);
602 pa_rtclock_get(&end);
603 pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end, &start) / PA_USEC_PER_SEC);
605 pa_assert(chunk->memblock);
606 //pa_log_debug("gave %ld", chunk->length/fs);
607 //pa_log_debug("end pop");
608 if(u->first_iteration){
609 u->first_iteration = FALSE;
614 /* Called from main context */
615 static void sink_input_volume_changed_cb(pa_sink_input *i) {
618 pa_sink_input_assert_ref(i);
619 pa_assert_se(u = i->userdata);
621 pa_sink_volume_changed(u->sink, &i->volume);
624 /* Called from main context */
625 static void sink_input_mute_changed_cb(pa_sink_input *i) {
628 pa_sink_input_assert_ref(i);
629 pa_assert_se(u = i->userdata);
631 pa_sink_mute_changed(u->sink, i->muted);
634 static void reset_filter(struct userdata *u){
635 u->samples_gathered = 0;
636 for(size_t i = 0;i < u->channels; ++i){
637 memset(u->overlap_accum[i], 0, u->overlap_size * sizeof(float));
639 u->first_iteration = TRUE;
642 /* Called from I/O thread context */
643 static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) {
647 pa_log_debug("Rewind callback!");
648 pa_sink_input_assert_ref(i);
649 pa_assert_se(u = i->userdata);
651 if (u->sink->thread_info.rewind_nbytes > 0) {
654 //max_rewrite = nbytes;
655 max_rewrite = nbytes + pa_memblockq_get_length(u->input_q);
656 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
657 amount = PA_MIN(u->sink->thread_info.rewind_nbytes, max_rewrite);
658 u->sink->thread_info.rewind_nbytes = 0;
661 //pa_sample_spec *ss = &u->sink->sample_spec;
662 //invalidate the output q
663 pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
664 //pa_memblockq_drop(u->input_q, pa_memblockq_get_length(u->input_q));
665 //pa_memblockq_seek(u->input_q, - (int64_t) amount, PA_SEEK_RELATIVE, TRUE);
666 pa_log("Resetting filter");
671 pa_sink_process_rewind(u->sink, amount);
672 pa_memblockq_rewind(u->input_q, nbytes);
675 /* Called from I/O thread context */
676 static void sink_input_update_max_rewind_cb(pa_sink_input *i, size_t nbytes) {
679 pa_sink_input_assert_ref(i);
680 pa_assert_se(u = i->userdata);
682 pa_memblockq_set_maxrewind(u->input_q, nbytes);
683 pa_sink_set_max_rewind_within_thread(u->sink, nbytes);
686 /* Called from I/O thread context */
687 static void sink_input_update_max_request_cb(pa_sink_input *i, size_t nbytes) {
690 pa_sink_input_assert_ref(i);
691 pa_assert_se(u = i->userdata);
693 fs = pa_frame_size(&(u->sink->sample_spec));
694 //pa_sink_set_max_request_within_thread(u->sink, nbytes);
695 //pa_sink_set_max_request_within_thread(u->sink, u->R*fs);
696 pa_sink_set_max_request_within_thread(u->sink, ((nbytes+u->R*fs-1)/(u->R*fs))*(u->R*fs));
699 /* Called from I/O thread context */
700 static void sink_input_update_sink_latency_range_cb(pa_sink_input *i) {
703 pa_sink_input_assert_ref(i);
704 pa_assert_se(u = i->userdata);
706 //pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->latency*fs);
707 //pa_sink_set_latency_range_within_thread(u->sink, u->latency*fs, u->latency*fs );
708 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
711 /* Called from I/O thread context */
712 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input *i) {
715 pa_sink_input_assert_ref(i);
716 pa_assert_se(u = i->userdata);
718 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
721 /* Called from I/O thread context */
722 static void sink_input_detach_cb(pa_sink_input *i) {
725 pa_sink_input_assert_ref(i);
726 pa_assert_se(u = i->userdata);
728 pa_sink_detach_within_thread(u->sink);
730 pa_sink_set_rtpoll(u->sink, NULL);
733 /* Called from I/O thread context */
734 static void sink_input_attach_cb(pa_sink_input *i) {
737 pa_sink_input_assert_ref(i);
738 pa_assert_se(u = i->userdata);
740 pa_sink_set_rtpoll(u->sink, i->sink->thread_info.rtpoll);
741 pa_sink_set_latency_range_within_thread(u->sink, i->sink->thread_info.min_latency, i->sink->thread_info.max_latency);
743 pa_sink_set_fixed_latency_within_thread(u->sink, i->sink->thread_info.fixed_latency);
744 fs = pa_frame_size(&(u->sink->sample_spec));
745 pa_sink_set_max_request_within_thread(u->sink, PA_ROUND_UP(pa_sink_input_get_max_request(i), u->R*fs));
747 //pa_sink_set_latency_range_within_thread(u->sink, u->latency*fs, u->latency*fs);
748 //pa_sink_set_latency_range_within_thread(u->sink, u->latency*fs, u->master->thread_info.max_latency);
749 //TODO: setting this guy minimizes drop outs but doesn't get rid
750 //of them completely, figure out why
751 //pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->latency*fs);
752 //TODO: this guy causes dropouts constantly+rewinds, it's unusable
753 //pa_sink_set_latency_range_within_thread(u->sink, u->master->thread_info.min_latency, u->master->thread_info.max_latency);
754 pa_sink_attach_within_thread(u->sink);
756 pa_log("Setting default sink to %s", u->sink->name);
757 pa_namereg_set_default_sink(u->module->core, u->sink);
761 /* Called from main context */
762 static void sink_input_kill_cb(pa_sink_input *i) {
765 pa_sink_input_assert_ref(i);
766 pa_assert_se(u = i->userdata);
768 /* The order here matters! We first kill the sink input, followed
769 * by the sink. That means the sink callbacks must be protected
770 * against an unconnected sink input! */
771 pa_sink_input_unlink(u->sink_input);
772 pa_sink_unlink(u->sink);
774 pa_sink_input_unref(u->sink_input);
775 u->sink_input = NULL;
777 pa_sink_unref(u->sink);
780 pa_module_unload_request(u->module, TRUE);
783 /* Called from IO thread context */
784 static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t state) {
787 pa_sink_input_assert_ref(i);
788 pa_assert_se(u = i->userdata);
790 /* If we are added for the first time, ask for a rewinding so that
791 * we are heard right-away. */
792 if (PA_SINK_INPUT_IS_LINKED(state) &&
793 i->thread_info.state == PA_SINK_INPUT_INIT) {
794 pa_log_debug("Requesting rewind due to state change.");
795 pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
799 static void pack(char **strs, size_t len, char **packed, size_t *length){
801 size_t headers = (1+len) * sizeof(uint16_t);
802 size_t offset = sizeof(uint16_t);
803 for(size_t i = 0; i < len; ++i){
804 t_len += strlen(strs[i]);
806 *length = headers + t_len;
807 *packed = pa_xmalloc0(*length);
808 ((uint16_t *) *packed)[0] = (uint16_t) len;
809 for(size_t i = 0; i < len; ++i){
810 uint16_t l = strlen(strs[i]);
811 *((uint16_t *)(*packed + offset)) = l;
812 offset += sizeof(uint16_t);
813 memcpy(*packed + offset, strs[i], l);
817 static void unpack(char *str, size_t length, char ***strs, size_t *len){
818 size_t offset = sizeof(uint16_t);
819 *len = ((uint16_t *)str)[0];
820 *strs = pa_xnew(char *, *len);
821 for(size_t i = 0; i < *len; ++i){
822 size_t l = *((uint16_t *)(str+offset));
823 size_t e = PA_MIN(offset + l, length) - offset;
824 offset = PA_MIN(offset + sizeof(uint16_t), length);
826 (*strs)[i] = pa_xnew(char, e + 1);
827 memcpy((*strs)[i], strs + offset, e);
828 (*strs)[i][e] = '\0';
834 static void save_profile(struct userdata *u, size_t channel, char *name){
836 const size_t profile_size = CHANNEL_PROFILE_SIZE * sizeof(float);
837 float *H_n, *profile;
840 profile = pa_xnew0(float, profile_size);
841 a_i = pa_aupdate_read_begin(u->a_H[channel]);
842 profile[0] = u->Xs[a_i][channel];
843 H = u->Hs[channel][a_i];
845 for(size_t i = 0 ; i <= FILTER_SIZE; ++i){
846 H_n[i] = H[i] * u->fft_size;
849 pa_aupdate_read_end(u->a_H[channel]);
851 key.size = strlen(key.data);
853 data.size = profile_size;
854 pa_database_set(u->database, &key, &data, TRUE);
855 pa_database_sync(u->database);
856 if(u->base_profiles[channel]){
857 pa_xfree(u->base_profiles[channel]);
859 u->base_profiles[channel] = pa_xstrdup(name);
862 static void save_state(struct userdata *u){
864 const size_t filter_state_size = FILTER_STATE_SIZE * sizeof(float);
868 pa_database *database;
870 char *state_name = u->name;
872 size_t packed_length;
874 pack(u->base_profiles, u->channels, &packed, &packed_length);
875 state = (float *) pa_xmalloc0(filter_state_size + packed_length);
877 for(size_t c = 0; c < u->channels; ++c){
878 a_i = pa_aupdate_read_begin(u->a_H[c]);
879 state[c * CHANNEL_PROFILE_SIZE] = u->Xs[a_i][c];
881 H_n = state + c * CHANNEL_PROFILE_SIZE + 1;
882 memcpy(H_n, H, FILTER_SIZE * sizeof(float));
883 pa_aupdate_read_end(u->a_H[c]);
885 memcpy(((char *)state) + filter_state_size, packed, packed_length);
888 key.data = state_name;
889 key.size = strlen(key.data);
891 data.size = filter_state_size + packed_length;
892 //thread safety for 0.9.17?
893 pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, TRUE));
894 pa_assert_se(database = pa_database_open(dbname, TRUE));
897 pa_database_set(database, &key, &data, TRUE);
898 pa_database_sync(database);
899 pa_database_close(database);
903 static void remove_profile(pa_core *c, char *name){
905 pa_database *database;
907 key.size = strlen(key.data);
908 pa_assert_se(database = pa_shared_get(c, EQDB));
909 pa_database_unset(database, &key);
910 pa_database_sync(database);
913 static const char* load_profile(struct userdata *u, size_t channel, char *name){
916 const size_t profile_size = CHANNEL_PROFILE_SIZE * sizeof(float);
918 key.size = strlen(key.data);
919 if(pa_database_get(u->database, &key, &value) != NULL){
920 if(value.size == profile_size){
921 float *profile = (float *) value.data;
922 a_i = pa_aupdate_write_begin(u->a_H[channel]);
923 u->Xs[channel][a_i] = profile[0];
924 memcpy(u->Hs[channel][a_i], profile + 1, CHANNEL_PROFILE_SIZE * sizeof(float));
925 fix_filter(u->Hs[channel][a_i], u->fft_size);
926 pa_aupdate_write_end(u->a_H[channel]);
927 if(u->base_profiles[channel]){
928 pa_xfree(u->base_profiles[channel]);
930 u->base_profiles[channel] = pa_xstrdup(name);
932 return "incompatible size";
934 pa_datum_free(&value);
936 return "profile doesn't exist";
941 static void load_state(struct userdata *u){
945 pa_database *database;
947 char *state_name = u->name;
948 pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, FALSE));
949 database = pa_database_open(dbname, FALSE);
955 key.data = state_name;
956 key.size = strlen(key.data);
958 if(pa_database_get(database, &key, &value) != NULL){
959 if(value.size > FILTER_STATE_SIZE * sizeof(float) + sizeof(uint16_t)){
960 float *state = (float *) value.data;
963 for(size_t c = 0; c < u->channels; ++c){
964 a_i = pa_aupdate_write_begin(u->a_H[c]);
965 H = state + c * CHANNEL_PROFILE_SIZE + 1;
966 u->Xs[c][a_i] = state[c * CHANNEL_PROFILE_SIZE];
967 memcpy(u->Hs[c][a_i], H, FILTER_SIZE * sizeof(float));
968 pa_aupdate_write_end(u->a_H[c]);
970 unpack(((char *)value.data) + FILTER_STATE_SIZE, value.size - FILTER_STATE_SIZE, &names, &n_profs);
971 n_profs = PA_MIN(n_profs, u->channels);
972 for(size_t c = 0; c < n_profs; ++c){
973 if(u->base_profiles[c]){
974 pa_xfree(u->base_profiles[c]);
976 u->base_profiles[c] = names[c];
980 pa_datum_free(&value);
982 pa_database_close(database);
985 /* Called from main context */
986 static pa_bool_t sink_input_may_move_to_cb(pa_sink_input *i, pa_sink *dest) {
989 pa_sink_input_assert_ref(i);
990 pa_assert_se(u = i->userdata);
992 return u->sink != dest;
995 /* Called from main context */
996 static void sink_input_moving_cb(pa_sink_input *i, pa_sink *dest) {
999 pa_sink_input_assert_ref(i);
1000 pa_assert_se(u = i->userdata);
1002 pa_sink_set_asyncmsgq(u->sink, dest->asyncmsgq);
1003 pa_sink_update_flags(u->sink, PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY, dest->flags);
1005 pa_sink_set_asyncmsgq(u->sink, NULL);
1008 //ensure's memory allocated is a multiple of v_size
1010 static void * alloc(size_t x,size_t s){
1011 size_t f = PA_ROUND_UP(x*s, sizeof(float)*v_size);
1013 pa_assert(f >= x*s);
1014 t = fftwf_malloc(f);
1019 int pa__init(pa_module*m) {
1026 pa_sink_input_new_data sink_input_data;
1027 pa_sink_new_data sink_data;
1034 if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
1035 pa_log("Failed to parse module arguments.");
1039 if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
1040 pa_log("Master sink not found, trying default");
1041 master = pa_namereg_get_default_sink(m->core);
1043 pa_log("no default sink found!");
1048 ss = master->sample_spec;
1049 ss.format = PA_SAMPLE_FLOAT32;
1050 map = master->channel_map;
1051 if (pa_modargs_get_sample_spec_and_channel_map(ma, &ss, &map, PA_CHANNEL_MAP_DEFAULT) < 0) {
1052 pa_log("Invalid sample format specification or channel map");
1055 fs = pa_frame_size(&ss);
1057 u = pa_xnew0(struct userdata, 1);
1061 u->set_default = TRUE;
1062 pa_modargs_get_value_boolean(ma, "set_default", &u->set_default);
1064 u->channels = ss.channels;
1065 u->fft_size = pow(2, ceil(log(ss.rate)/log(2)));
1066 pa_log_debug("fft size: %ld", u->fft_size);
1067 u->window_size = 15999;
1068 u->R = (u->window_size + 1) / 2;
1069 u->overlap_size = u->window_size - u->R;
1070 u->samples_gathered = 0;
1071 u->a_H = pa_xnew0(pa_aupdate *, u->channels);
1072 u->latency = u->window_size - u->R;
1073 u->Xs = pa_xnew0(float *, u->channels);
1074 u->Hs = pa_xnew0(float **, u->channels);
1075 for(size_t c = 0; c < u->channels; ++c){
1076 u->Xs[c] = pa_xnew0(float, 2);
1077 u->Hs[c] = pa_xnew0(float *, 2);
1078 for(size_t i = 0; i < 2; ++i){
1079 u->Hs[c][i] = alloc((FILTER_SIZE), sizeof(float));
1082 u->W = alloc(u->window_size, sizeof(float));
1083 u->work_buffer = alloc(u->fft_size, sizeof(float));
1084 memset(u->work_buffer, 0, u->fft_size*sizeof(float));
1085 u->input = pa_xnew0(float *, u->channels);
1086 u->overlap_accum = pa_xnew0(float *, u->channels);
1087 for(size_t c = 0; c < u->channels; ++c){
1088 u->a_H[c] = pa_aupdate_new();
1089 u->input[c] = alloc(u->window_size, sizeof(float));
1090 memset(u->input[c], 0, (u->window_size)*sizeof(float));
1091 u->overlap_accum[c] = alloc(u->overlap_size, sizeof(float));
1092 memset(u->overlap_accum[c], 0, u->overlap_size*sizeof(float));
1094 u->output_window = alloc((FILTER_SIZE), sizeof(fftwf_complex));
1095 u->forward_plan = fftwf_plan_dft_r2c_1d(u->fft_size, u->work_buffer, u->output_window, FFTW_ESTIMATE);
1096 u->inverse_plan = fftwf_plan_dft_c2r_1d(u->fft_size, u->output_window, u->work_buffer, FFTW_ESTIMATE);
1098 hanning_window(u->W, u->window_size);
1099 u->first_iteration = TRUE;
1101 u->base_profiles = pa_xnew0(char *, u->channels);
1104 pa_sink_new_data_init(&sink_data);
1105 sink_data.driver = __FILE__;
1106 sink_data.module = m;
1107 if (!(sink_data.name = pa_xstrdup(pa_modargs_get_value(ma, "sink_name", NULL))))
1108 sink_data.name = pa_sprintf_malloc("%s.equalizer", master->name);
1109 pa_sink_new_data_set_sample_spec(&sink_data, &ss);
1110 pa_sink_new_data_set_channel_map(&sink_data, &map);
1111 z = pa_proplist_gets(master->proplist, PA_PROP_DEVICE_DESCRIPTION);
1112 pa_proplist_setf(sink_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "FFT based equalizer on %s",z? z: master->name);
1113 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_MASTER_DEVICE, master->name);
1114 pa_proplist_sets(sink_data.proplist, PA_PROP_DEVICE_CLASS, "filter");
1116 if (pa_modargs_get_proplist(ma, "sink_properties", sink_data.proplist, PA_UPDATE_REPLACE) < 0) {
1117 pa_log("Invalid properties");
1118 pa_sink_new_data_done(&sink_data);
1122 u->sink = pa_sink_new(m->core, &sink_data,
1123 PA_SINK_HW_MUTE_CTRL|PA_SINK_HW_VOLUME_CTRL|PA_SINK_DECIBEL_VOLUME|
1124 (master->flags & (PA_SINK_LATENCY|PA_SINK_DYNAMIC_LATENCY)));
1125 pa_sink_new_data_done(&sink_data);
1128 pa_log("Failed to create sink.");
1131 u->name=pa_xstrdup(u->sink->name);
1132 u->sink->parent.process_msg = sink_process_msg_cb;
1133 u->sink->set_state = sink_set_state_cb;
1134 u->sink->update_requested_latency = sink_update_requested_latency_cb;
1135 u->sink->request_rewind = sink_request_rewind_cb;
1136 u->sink->set_volume = sink_set_volume_cb;
1137 u->sink->set_mute = sink_set_mute_cb;
1138 u->sink->userdata = u;
1139 u->input_q = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, fs, 1, 1, 0, &u->sink->silence);
1141 pa_sink_set_asyncmsgq(u->sink, master->asyncmsgq);
1142 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1144 /* Create sink input */
1145 pa_sink_input_new_data_init(&sink_input_data);
1146 sink_input_data.driver = __FILE__;
1147 sink_input_data.module = m;
1148 sink_input_data.sink = master;
1149 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_NAME, "Equalized Stream");
1150 pa_proplist_sets(sink_input_data.proplist, PA_PROP_MEDIA_ROLE, "filter");
1151 pa_sink_input_new_data_set_sample_spec(&sink_input_data, &ss);
1152 pa_sink_input_new_data_set_channel_map(&sink_input_data, &map);
1154 pa_sink_input_new(&u->sink_input, m->core, &sink_input_data, 0);
1155 pa_sink_input_new_data_done(&sink_input_data);
1160 u->sink_input->pop = sink_input_pop_cb;
1161 u->sink_input->process_rewind = sink_input_process_rewind_cb;
1162 u->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
1163 u->sink_input->update_max_request = sink_input_update_max_request_cb;
1164 u->sink_input->update_sink_latency_range = sink_input_update_sink_latency_range_cb;
1165 u->sink_input->update_sink_fixed_latency = sink_input_update_sink_fixed_latency_cb;
1166 u->sink_input->kill = sink_input_kill_cb;
1167 u->sink_input->attach = sink_input_attach_cb;
1168 u->sink_input->detach = sink_input_detach_cb;
1169 u->sink_input->state_change = sink_input_state_change_cb;
1170 u->sink_input->may_move_to = sink_input_may_move_to_cb;
1171 u->sink_input->moving = sink_input_moving_cb;
1172 u->sink_input->volume_changed = sink_input_volume_changed_cb;
1173 u->sink_input->mute_changed = sink_input_mute_changed_cb;
1175 u->sink_input->userdata = u;
1177 pa_sink_put(u->sink);
1178 pa_sink_input_put(u->sink_input);
1180 pa_modargs_free(ma);
1185 //default filter to these
1186 for(size_t c = 0; c< u->channels; ++c){
1187 a_i = pa_aupdate_write_begin(u->a_H[c]);
1189 u->Xs[c][a_i] = 1.0f;
1190 for(size_t i = 0; i < FILTER_SIZE; ++i){
1191 H[i] = 1.0 / sqrtf(2.0f);
1193 fix_filter(H, u->fft_size);
1194 pa_aupdate_write_end(u->a_H[c]);
1196 //load old parameters
1203 pa_modargs_free(ma);
1211 int pa__get_n_used(pa_module *m) {
1215 pa_assert_se(u = m->userdata);
1217 return pa_sink_linked_by(u->sink);
1220 void pa__done(pa_module*m) {
1225 if (!(u = m->userdata))
1232 for(size_t c = 0; c < u->channels; ++c){
1233 if(u->base_profiles[c]){
1234 pa_xfree(u->base_profiles[c]);
1237 pa_xfree(u->base_profiles);
1239 /* See comments in sink_input_kill_cb() above regarding
1240 * destruction order! */
1243 pa_sink_input_unlink(u->sink_input);
1246 pa_sink_unlink(u->sink);
1249 pa_sink_input_unref(u->sink_input);
1252 pa_sink_unref(u->sink);
1254 pa_memblockq_free(u->input_q);
1256 fftwf_destroy_plan(u->inverse_plan);
1257 fftwf_destroy_plan(u->forward_plan);
1258 pa_xfree(u->output_window);
1259 for(size_t c=0; c < u->channels; ++c){
1260 pa_aupdate_free(u->a_H[c]);
1261 pa_xfree(u->overlap_accum[c]);
1262 pa_xfree(u->input[c]);
1265 pa_xfree(u->overlap_accum);
1267 pa_xfree(u->work_buffer);
1269 for(size_t c = 0; c < u->channels; ++c){
1271 for(size_t i = 0; i < 2; ++i){
1272 pa_xfree(u->Hs[c][i]);
1285 * DBus Routines and Callbacks
1287 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1288 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1289 #define MANAGER_IFACE EXTNAME ".Manager"
1290 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1291 static void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1292 static void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u);
1293 static void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u);
1294 static void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1295 static void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1296 static void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u);
1297 static void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1298 static void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u);
1299 static void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u);
1300 static void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u);
1301 static void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u);
1302 static void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1303 static void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u);
1304 static void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1305 static void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u);
1306 static void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1307 static void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u);
1308 static void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u);
1309 enum manager_method_index {
1310 MANAGER_METHOD_REMOVE_PROFILE,
1314 pa_dbus_arg_info remove_profile_args[]={
1318 static pa_dbus_method_handler manager_methods[MANAGER_METHOD_MAX]={
1319 [MANAGER_METHOD_REMOVE_PROFILE]{
1320 .method_name="RemoveProfile",
1321 .arguments=remove_profile_args,
1322 .n_arguments=sizeof(remove_profile_args)/sizeof(pa_dbus_arg_info),
1323 .receive_cb=manager_handle_remove_profile}
1326 enum manager_handler_index {
1327 MANAGER_HANDLER_REVISION,
1328 MANAGER_HANDLER_EQUALIZED_SINKS,
1329 MANAGER_HANDLER_PROFILES,
1333 static pa_dbus_property_handler manager_handlers[MANAGER_HANDLER_MAX]={
1334 [MANAGER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=manager_get_revision,.set_cb=NULL},
1335 [MANAGER_HANDLER_EQUALIZED_SINKS]={.property_name="EqualizedSinks",.type="ao",.get_cb=manager_get_sinks,.set_cb=NULL},
1336 [MANAGER_HANDLER_PROFILES]={.property_name="Profiles",.type="as",.get_cb=manager_get_profiles,.set_cb=NULL}
1339 pa_dbus_arg_info sink_args[]={
1343 enum manager_signal_index{
1344 MANAGER_SIGNAL_SINK_ADDED,
1345 MANAGER_SIGNAL_SINK_REMOVED,
1346 MANAGER_SIGNAL_PROFILES_CHANGED,
1350 static pa_dbus_signal_info manager_signals[MANAGER_SIGNAL_MAX]={
1351 [MANAGER_SIGNAL_SINK_ADDED]={.name="SinkAdded", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1352 [MANAGER_SIGNAL_SINK_REMOVED]={.name="SinkRemoved", .arguments=sink_args, .n_arguments=sizeof(sink_args)/sizeof(pa_dbus_arg_info)},
1353 [MANAGER_SIGNAL_PROFILES_CHANGED]={.name="ProfilesChanged", .arguments=NULL, .n_arguments=0}
1356 static pa_dbus_interface_info manager_info={
1357 .name=MANAGER_IFACE,
1358 .method_handlers=manager_methods,
1359 .n_method_handlers=MANAGER_METHOD_MAX,
1360 .property_handlers=manager_handlers,
1361 .n_property_handlers=MANAGER_HANDLER_MAX,
1362 .get_all_properties_cb=manager_get_all,
1363 .signals=manager_signals,
1364 .n_signals=MANAGER_SIGNAL_MAX
1367 enum equalizer_method_index {
1368 EQUALIZER_METHOD_FILTER_POINTS,
1369 EQUALIZER_METHOD_SEED_FILTER,
1370 EQUALIZER_METHOD_SAVE_PROFILE,
1371 EQUALIZER_METHOD_LOAD_PROFILE,
1372 EQUALIZER_METHOD_SET_FILTER,
1373 EQUALIZER_METHOD_GET_FILTER,
1374 EQUALIZER_METHOD_GET_PROFILE_NAME,
1375 EQUALIZER_METHOD_MAX
1378 enum equalizer_handler_index {
1379 EQUALIZER_HANDLER_REVISION,
1380 EQUALIZER_HANDLER_SAMPLERATE,
1381 EQUALIZER_HANDLER_FILTERSAMPLERATE,
1382 EQUALIZER_HANDLER_N_COEFS,
1383 EQUALIZER_HANDLER_N_CHANNELS,
1384 EQUALIZER_HANDLER_MAX
1387 pa_dbus_arg_info filter_points_args[]={
1388 {"channel", "u","in"},
1391 {"preamp", "d","out"}
1393 pa_dbus_arg_info seed_filter_args[]={
1394 {"channel", "u","in"},
1397 {"preamp", "d","in"}
1400 pa_dbus_arg_info set_filter_args[]={
1401 {"channel", "u","in"},
1403 {"preamp", "d","in"}
1405 pa_dbus_arg_info get_filter_args[]={
1406 {"channel", "u","in"},
1408 {"preamp", "d","out"}
1411 pa_dbus_arg_info save_profile_args[]={
1412 {"channel", "u","in"},
1415 pa_dbus_arg_info load_profile_args[]={
1416 {"channel", "u","in"},
1419 pa_dbus_arg_info base_profile_name_args[]={
1420 {"channel", "u","in"},
1424 static pa_dbus_method_handler equalizer_methods[EQUALIZER_METHOD_MAX]={
1425 [EQUALIZER_METHOD_SEED_FILTER]{
1426 .method_name="SeedFilter",
1427 .arguments=seed_filter_args,
1428 .n_arguments=sizeof(seed_filter_args)/sizeof(pa_dbus_arg_info),
1429 .receive_cb=equalizer_handle_seed_filter},
1430 [EQUALIZER_METHOD_FILTER_POINTS]{
1431 .method_name="FilterAtPoints",
1432 .arguments=filter_points_args,
1433 .n_arguments=sizeof(filter_points_args)/sizeof(pa_dbus_arg_info),
1434 .receive_cb=equalizer_handle_get_filter_points},
1435 [EQUALIZER_METHOD_SET_FILTER]{
1436 .method_name="SetFilter",
1437 .arguments=set_filter_args,
1438 .n_arguments=sizeof(set_filter_args)/sizeof(pa_dbus_arg_info),
1439 .receive_cb=equalizer_handle_set_filter},
1440 [EQUALIZER_METHOD_GET_FILTER]{
1441 .method_name="GetFilter",
1442 .arguments=get_filter_args,
1443 .n_arguments=sizeof(get_filter_args)/sizeof(pa_dbus_arg_info),
1444 .receive_cb=equalizer_handle_get_filter},
1445 [EQUALIZER_METHOD_SAVE_PROFILE]{
1446 .method_name="SaveProfile",
1447 .arguments=save_profile_args,
1448 .n_arguments=sizeof(save_profile_args)/sizeof(pa_dbus_arg_info),
1449 .receive_cb=equalizer_handle_save_profile},
1450 [EQUALIZER_METHOD_LOAD_PROFILE]{
1451 .method_name="LoadProfile",
1452 .arguments=load_profile_args,
1453 .n_arguments=sizeof(load_profile_args)/sizeof(pa_dbus_arg_info),
1454 .receive_cb=equalizer_handle_load_profile},
1455 [EQUALIZER_METHOD_GET_PROFILE_NAME]{
1456 .method_name="BaseProfile",
1457 .arguments=base_profile_name_args,
1458 .n_arguments=sizeof(base_profile_name_args)/sizeof(pa_dbus_arg_info),
1459 .receive_cb=equalizer_handle_get_profile_name}
1462 static pa_dbus_property_handler equalizer_handlers[EQUALIZER_HANDLER_MAX]={
1463 [EQUALIZER_HANDLER_REVISION]={.property_name="InterfaceRevision",.type="u",.get_cb=equalizer_get_revision,.set_cb=NULL},
1464 [EQUALIZER_HANDLER_SAMPLERATE]{.property_name="SampleRate",.type="u",.get_cb=equalizer_get_sample_rate,.set_cb=NULL},
1465 [EQUALIZER_HANDLER_FILTERSAMPLERATE]{.property_name="FilterSampleRate",.type="u",.get_cb=equalizer_get_filter_rate,.set_cb=NULL},
1466 [EQUALIZER_HANDLER_N_COEFS]{.property_name="NFilterCoefficients",.type="u",.get_cb=equalizer_get_n_coefs,.set_cb=NULL},
1467 [EQUALIZER_HANDLER_N_CHANNELS]{.property_name="NChannels",.type="u",.get_cb=equalizer_get_n_channels,.set_cb=NULL},
1470 enum equalizer_signal_index{
1471 EQUALIZER_SIGNAL_FILTER_CHANGED,
1472 EQUALIZER_SIGNAL_SINK_RECONFIGURED,
1473 EQUALIZER_SIGNAL_MAX
1476 static pa_dbus_signal_info equalizer_signals[EQUALIZER_SIGNAL_MAX]={
1477 [EQUALIZER_SIGNAL_FILTER_CHANGED]={.name="FilterChanged", .arguments=NULL, .n_arguments=0},
1478 [EQUALIZER_SIGNAL_SINK_RECONFIGURED]={.name="SinkReconfigured", .arguments=NULL, .n_arguments=0},
1481 static pa_dbus_interface_info equalizer_info={
1482 .name=EQUALIZER_IFACE,
1483 .method_handlers=equalizer_methods,
1484 .n_method_handlers=EQUALIZER_METHOD_MAX,
1485 .property_handlers=equalizer_handlers,
1486 .n_property_handlers=EQUALIZER_HANDLER_MAX,
1487 .get_all_properties_cb=equalizer_get_all,
1488 .signals=equalizer_signals,
1489 .n_signals=EQUALIZER_SIGNAL_MAX
1492 void dbus_init(struct userdata *u){
1494 DBusMessage *signal = NULL;
1495 pa_idxset *sink_list = NULL;
1496 u->dbus_protocol=pa_dbus_protocol_get(u->sink->core);
1497 u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index);
1499 pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &equalizer_info, u);
1500 sink_list = pa_shared_get(u->sink->core, SINKLIST);
1501 u->database = pa_shared_get(u->sink->core, EQDB);
1502 if(sink_list == NULL){
1504 sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
1505 pa_shared_set(u->sink->core, SINKLIST, sink_list);
1506 pa_assert_se(dbname = pa_state_path("equalizer-presets", FALSE));
1507 pa_assert_se(u->database = pa_database_open(dbname, TRUE));
1509 pa_shared_set(u->sink->core, EQDB, u->database);
1510 pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
1511 pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
1513 pa_idxset_put(sink_list, u, &dummy);
1515 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_ADDED].name)));
1516 dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1517 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1518 dbus_message_unref(signal);
1521 void dbus_done(struct userdata *u){
1522 pa_idxset *sink_list;
1525 DBusMessage *signal = NULL;
1526 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_SINK_REMOVED].name)));
1527 dbus_message_append_args(signal, DBUS_TYPE_OBJECT_PATH, &u->dbus_path, DBUS_TYPE_INVALID);
1528 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1529 dbus_message_unref(signal);
1531 pa_assert_se(sink_list=pa_shared_get(u->sink->core,SINKLIST));
1532 pa_idxset_remove_by_data(sink_list,u,&dummy);
1533 if(pa_idxset_size(sink_list)==0){
1534 pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME);
1535 pa_dbus_protocol_remove_interface(u->dbus_protocol, MANAGER_PATH, manager_info.name);
1536 pa_shared_remove(u->sink->core, EQDB);
1537 pa_database_close(u->database);
1538 pa_shared_remove(u->sink->core, SINKLIST);
1539 pa_xfree(sink_list);
1541 pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, equalizer_info.name);
1542 pa_xfree(u->dbus_path);
1543 pa_dbus_protocol_unref(u->dbus_protocol);
1546 void manager_handle_remove_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1548 pa_core *c = (pa_core *)_u;
1549 DBusMessage *signal = NULL;
1550 pa_dbus_protocol *dbus_protocol;
1555 dbus_error_init(&error);
1556 if(!dbus_message_get_args(msg, &error,
1557 DBUS_TYPE_STRING, &name,
1558 DBUS_TYPE_INVALID)){
1559 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1560 dbus_error_free(&error);
1563 remove_profile(c,name);
1564 pa_dbus_send_empty_reply(conn, msg);
1566 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
1567 dbus_protocol = pa_dbus_protocol_get(c);
1568 pa_dbus_protocol_send_signal(dbus_protocol, signal);
1569 pa_dbus_protocol_unref(dbus_protocol);
1570 dbus_message_unref(signal);
1573 void manager_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
1575 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
1578 static void get_sinks(pa_core *u, char ***names, unsigned *n_sinks){
1580 struct userdata *sink_u = NULL;
1582 pa_idxset *sink_list;
1587 pa_assert_se(sink_list = pa_shared_get(u, SINKLIST));
1588 *n_sinks = (unsigned) pa_idxset_size(sink_list);
1589 *names = *n_sinks > 0 ? pa_xnew0(char *,*n_sinks) : NULL;
1590 for(uint32_t i = 0; i < *n_sinks; ++i){
1591 sink_u = (struct userdata *) pa_idxset_iterate(sink_list, &iter, &dummy);
1592 (*names)[i] = pa_xstrdup(sink_u->dbus_path);
1596 void manager_get_sinks(DBusConnection *conn, DBusMessage *msg, void *_u){
1598 char **names = NULL;
1603 get_sinks((pa_core *) _u, &names, &n);
1604 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_OBJECT_PATH, names, n);
1605 for(unsigned i = 0; i < n; ++i){
1611 static void get_profiles(pa_core *c, char ***names, unsigned *n){
1613 pa_database *database;
1614 pa_datum key, next_key;
1615 pa_strlist *head=NULL, *iter;
1617 pa_assert_se(database = pa_shared_get(c, EQDB));
1622 done = !pa_database_first(database, &key, NULL);
1625 done = !pa_database_next(database, &key, &next_key, NULL);
1626 name=pa_xmalloc(key.size + 1);
1627 memcpy(name, key.data, key.size);
1628 name[key.size] = '\0';
1629 pa_datum_free(&key);
1630 head = pa_strlist_prepend(head, name);
1635 (*names) = *n > 0 ? pa_xnew0(char *, *n) : NULL;
1637 for(unsigned i = 0; i < *n; ++i){
1638 (*names)[*n - 1 - i] = pa_xstrdup(pa_strlist_data(iter));
1639 iter = pa_strlist_next(iter);
1641 pa_strlist_free(head);
1644 void manager_get_profiles(DBusConnection *conn, DBusMessage *msg, void *_u){
1651 get_profiles((pa_core *)_u, &names, &n);
1652 pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_STRING, names, n);
1653 for(unsigned i = 0; i < n; ++i){
1659 void manager_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
1661 char **names = NULL;
1663 DBusMessage *reply = NULL;
1664 DBusMessageIter msg_iter, dict_iter;
1668 pa_assert_se(c = _u);
1670 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1671 dbus_message_iter_init_append(reply, &msg_iter);
1672 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
1675 pa_dbus_append_basic_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
1677 get_sinks(c, &names, &n);
1678 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter,manager_handlers[MANAGER_HANDLER_EQUALIZED_SINKS].property_name, DBUS_TYPE_OBJECT_PATH, names, n);
1679 for(unsigned i = 0; i < n; ++i){
1684 get_profiles(c, &names, &n);
1685 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, manager_handlers[MANAGER_HANDLER_PROFILES].property_name, DBUS_TYPE_STRING, names, n);
1686 for(unsigned i = 0; i < n; ++i){
1690 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
1691 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1692 dbus_message_unref(reply);
1695 void equalizer_handle_seed_filter(DBusConnection *conn, DBusMessage *msg, void *_u) {
1696 struct userdata *u=(struct userdata *) _u;
1698 DBusMessage *signal = NULL;
1700 uint32_t *xs, channel, r_channel;
1701 double *_ys, preamp;
1702 unsigned x_npoints, y_npoints, a_i;
1704 pa_bool_t points_good = TRUE;
1709 dbus_error_init(&error);
1711 if(!dbus_message_get_args(msg, &error,
1712 DBUS_TYPE_UINT32, &channel,
1713 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1714 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &_ys, &y_npoints,
1715 DBUS_TYPE_DOUBLE, &preamp,
1716 DBUS_TYPE_INVALID)){
1717 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1718 dbus_error_free(&error);
1721 if(channel > u->channels){
1722 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1723 dbus_error_free(&error);
1726 for(size_t i = 0; i < x_npoints; ++i){
1727 if(xs[i] >= FILTER_SIZE){
1728 points_good = FALSE;
1732 if(!is_monotonic(xs, x_npoints) || !points_good){
1733 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs must be monotonic and 0<=x<=%ld", u->fft_size / 2);
1734 dbus_error_free(&error);
1736 }else if(x_npoints != y_npoints || x_npoints < 2 || x_npoints > FILTER_SIZE ){
1737 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE);
1738 dbus_error_free(&error);
1740 }else if(xs[0] != 0 || xs[x_npoints - 1] != u->fft_size / 2){
1741 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs[0] must be 0 and xs[-1]=fft_size/2");
1742 dbus_error_free(&error);
1746 ys = pa_xmalloc(x_npoints * sizeof(float));
1747 for(uint32_t i = 0; i < x_npoints; ++i){
1748 ys[i] = (float) _ys[i];
1750 r_channel = channel == u->channels ? 0 : channel;
1751 a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1752 H = u->Hs[r_channel][a_i];
1753 u->Xs[r_channel][a_i] = preamp;
1754 interpolate(H, FILTER_SIZE, xs, ys, x_npoints);
1755 fix_filter(H, u->fft_size);
1756 if(channel == u->channels){
1757 for(size_t c = 1; c < u->channels; ++c){
1758 unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1759 float *H_p = u->Hs[c][b_i];
1760 u->Xs[c][b_i] = preamp;
1761 memcpy(H_p, H, FILTER_SIZE * sizeof(float));
1762 pa_aupdate_write_end(u->a_H[c]);
1765 pa_aupdate_write_end(u->a_H[r_channel]);
1769 pa_dbus_send_empty_reply(conn, msg);
1771 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
1772 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1773 dbus_message_unref(signal);
1776 void equalizer_handle_get_filter_points(DBusConnection *conn, DBusMessage *msg, void *_u) {
1777 struct userdata *u = (struct userdata *) _u;
1778 uint32_t *xs, channel, r_channel;
1780 unsigned x_npoints, a_i;
1782 pa_bool_t points_good=TRUE;
1783 DBusMessage *reply = NULL;
1784 DBusMessageIter msg_iter;
1791 dbus_error_init(&error);
1792 if(!dbus_message_get_args(msg, &error,
1793 DBUS_TYPE_UINT32, &channel,
1794 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &xs, &x_npoints,
1795 DBUS_TYPE_INVALID)){
1796 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1797 dbus_error_free(&error);
1800 if(channel > u->channels){
1801 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1802 dbus_error_free(&error);
1806 for(size_t i = 0; i < x_npoints; ++i){
1807 if(xs[i] >= FILTER_SIZE){
1813 if(x_npoints > FILTER_SIZE || !points_good){
1814 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "xs indices/length must be <= %ld!", FILTER_SIZE);
1815 dbus_error_free(&error);
1819 r_channel = channel == u->channels ? 0 : channel;
1820 ys = pa_xmalloc(x_npoints * sizeof(double));
1821 a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1822 H = u->Hs[r_channel][a_i];
1823 preamp = u->Xs[r_channel][a_i];
1824 for(uint32_t i = 0; i < x_npoints; ++i){
1825 ys[i] = H[xs[i]] * u->fft_size;
1827 pa_aupdate_read_end(u->a_H[r_channel]);
1829 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1830 dbus_message_iter_init_append(reply, &msg_iter);
1832 pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, ys, x_npoints);
1833 pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1835 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1836 dbus_message_unref(reply);
1840 static void get_filter(struct userdata *u, size_t channel, double **H_, double *preamp){
1843 size_t r_channel = channel == u->channels ? 0 : channel;
1844 *H_ = pa_xnew0(double, FILTER_SIZE);
1845 a_i = pa_aupdate_read_begin(u->a_H[r_channel]);
1846 H = u->Hs[r_channel][a_i];
1847 for(size_t i = 0;i < FILTER_SIZE; ++i){
1848 (*H_)[i] = H[i] * u->fft_size;
1850 *preamp = u->Xs[r_channel][a_i];
1852 pa_aupdate_read_end(u->a_H[r_channel]);
1855 void equalizer_handle_get_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1860 DBusMessage *reply = NULL;
1861 DBusMessageIter msg_iter;
1863 pa_assert_se(u = (struct userdata *) _u);
1867 dbus_error_init(&error);
1868 if(!dbus_message_get_args(msg, &error,
1869 DBUS_TYPE_UINT32, &channel,
1870 DBUS_TYPE_INVALID)){
1871 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1872 dbus_error_free(&error);
1875 if(channel > u->channels){
1876 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1877 dbus_error_free(&error);
1881 n_coefs = CHANNEL_PROFILE_SIZE;
1884 get_filter(u, channel, &H_, &preamp);
1885 pa_assert_se((reply = dbus_message_new_method_return(msg)));
1886 dbus_message_iter_init_append(reply, &msg_iter);
1888 pa_dbus_append_basic_array(&msg_iter, DBUS_TYPE_DOUBLE, H_, n_coefs);
1889 pa_dbus_append_basic_variant(&msg_iter, DBUS_TYPE_DOUBLE, &preamp);
1891 pa_assert_se(dbus_connection_send(conn, reply, NULL));
1892 dbus_message_unref(reply);
1896 static void set_filter(struct userdata *u, size_t channel, double *H_, double preamp){
1898 size_t r_channel = channel == u->channels ? 0 : channel;
1901 a_i = pa_aupdate_write_begin(u->a_H[r_channel]);
1902 u->Xs[r_channel][a_i] = (float) preamp;
1903 H = u->Hs[r_channel][a_i];
1904 for(size_t i = 0; i < FILTER_SIZE; ++i){
1905 H[i] = (float) H_[i];
1907 fix_filter(H, u->fft_size);
1908 if(channel == u->channels){
1909 for(size_t c = 1; c < u->channels; ++c){
1910 unsigned b_i = pa_aupdate_write_begin(u->a_H[c]);
1911 u->Xs[c][b_i] = u->Xs[r_channel][a_i];
1912 memcpy(u->Hs[c][b_i], u->Hs[r_channel][a_i], FILTER_SIZE * sizeof(float));
1913 pa_aupdate_write_end(u->a_H[c]);
1916 pa_aupdate_write_end(u->a_H[r_channel]);
1919 void equalizer_handle_set_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
1924 DBusMessage *signal = NULL;
1926 pa_assert_se(u = (struct userdata *) _u);
1930 dbus_error_init(&error);
1931 if(!dbus_message_get_args(msg, &error,
1932 DBUS_TYPE_UINT32, &channel,
1933 DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &H, &_n_coefs,
1934 DBUS_TYPE_DOUBLE, &preamp,
1935 DBUS_TYPE_INVALID)){
1936 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1937 dbus_error_free(&error);
1940 if(channel > u->channels){
1941 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1942 dbus_error_free(&error);
1945 if(_n_coefs != FILTER_SIZE){
1946 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE, _n_coefs);
1949 set_filter(u, channel, H, preamp);
1951 pa_dbus_send_empty_reply(conn, msg);
1953 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
1954 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1955 dbus_message_unref(signal);
1958 void equalizer_handle_save_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1959 struct userdata *u = (struct userdata *) _u;
1961 uint32_t channel, r_channel;
1962 DBusMessage *signal = NULL;
1967 dbus_error_init(&error);
1969 if(!dbus_message_get_args(msg, &error,
1970 DBUS_TYPE_UINT32, &channel,
1971 DBUS_TYPE_STRING, &name,
1972 DBUS_TYPE_INVALID)){
1973 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
1974 dbus_error_free(&error);
1977 if(channel > u->channels){
1978 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
1979 dbus_error_free(&error);
1982 r_channel = channel == u->channels ? 0 : channel;
1983 save_profile(u, r_channel, name);
1984 pa_dbus_send_empty_reply(conn, msg);
1986 pa_assert_se((signal = dbus_message_new_signal(MANAGER_PATH, MANAGER_IFACE, manager_signals[MANAGER_SIGNAL_PROFILES_CHANGED].name)));
1987 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
1988 dbus_message_unref(signal);
1991 void equalizer_handle_load_profile(DBusConnection *conn, DBusMessage *msg, void *_u) {
1992 struct userdata *u = (struct userdata *) _u;
1995 uint32_t channel, r_channel;
1996 const char *err_msg = NULL;
1997 DBusMessage *signal = NULL;
2002 dbus_error_init(&error);
2004 if(!dbus_message_get_args(msg, &error,
2005 DBUS_TYPE_UINT32, &channel,
2006 DBUS_TYPE_STRING, &name,
2007 DBUS_TYPE_INVALID)){
2008 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2009 dbus_error_free(&error);
2012 if(channel > u->channels){
2013 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2014 dbus_error_free(&error);
2017 r_channel = channel == u->channels ? 0 : channel;
2019 err_msg = load_profile(u, r_channel, name);
2020 if(err_msg != NULL){
2021 pa_dbus_send_error(conn, msg, DBUS_ERROR_FAILED, "error loading profile %s: %s", name, err_msg);
2022 dbus_error_free(&error);
2025 if(channel == u->channels){
2026 for(uint32_t c = 1; c < u->channels; ++c){
2027 load_profile(u, c, name);
2030 pa_dbus_send_empty_reply(conn, msg);
2032 pa_assert_se((signal = dbus_message_new_signal(u->dbus_path, EQUALIZER_IFACE, equalizer_signals[EQUALIZER_SIGNAL_FILTER_CHANGED].name)));
2033 pa_dbus_protocol_send_signal(u->dbus_protocol, signal);
2034 dbus_message_unref(signal);
2037 void equalizer_handle_get_profile_name(DBusConnection *conn, DBusMessage *msg, void *_u){
2038 struct userdata *u = (struct userdata *) _u;
2040 uint32_t channel, r_channel;
2045 dbus_error_init(&error);
2047 if(!dbus_message_get_args(msg, &error,
2048 DBUS_TYPE_UINT32, &channel,
2049 DBUS_TYPE_INVALID)){
2050 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "%s", error.message);
2051 dbus_error_free(&error);
2054 if(channel > u->channels){
2055 pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "invalid channel: %d", channel);
2056 dbus_error_free(&error);
2059 r_channel = channel == u->channels ? 0 : channel;
2060 if(u->base_profiles[r_channel]){
2061 pa_dbus_send_basic_value_reply(conn,msg, DBUS_TYPE_STRING, &u->base_profiles[r_channel]);
2063 pa_dbus_send_empty_reply(conn, msg);
2067 void equalizer_get_revision(DBusConnection *conn, DBusMessage *msg, void *_u){
2069 pa_dbus_send_basic_value_reply(conn, msg, DBUS_TYPE_UINT32, &rev);
2072 void equalizer_get_n_channels(DBusConnection *conn, DBusMessage *msg, void *_u){
2075 pa_assert_se(u = (struct userdata *) _u);
2079 channels = (uint32_t) u->channels;
2080 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &channels);
2083 void equalizer_get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u){
2086 pa_assert_se(u = (struct userdata *) _u);
2090 n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE;
2091 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs);
2094 void equalizer_get_sample_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
2097 pa_assert_se(u = (struct userdata *) _u);
2101 rate = (uint32_t) u->sink->sample_spec.rate;
2102 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &rate);
2105 void equalizer_get_filter_rate(DBusConnection *conn, DBusMessage *msg, void *_u){
2108 pa_assert_se(u = (struct userdata *) _u);
2112 fft_size = (uint32_t) u->fft_size;
2113 pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &fft_size);
2116 void equalizer_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
2118 DBusMessage *reply = NULL;
2119 DBusMessageIter msg_iter, dict_iter;
2120 uint32_t rev, n_coefs, rate, fft_size, channels;
2121 pa_assert_se(u = (struct userdata *) _u);
2125 n_coefs = (uint32_t) CHANNEL_PROFILE_SIZE;
2126 rate = (uint32_t) u->sink->sample_spec.rate;
2127 fft_size = (uint32_t) u->fft_size;
2128 channels = (uint32_t) u->channels;
2130 pa_assert_se((reply = dbus_message_new_method_return(msg)));
2131 dbus_message_iter_init_append(reply, &msg_iter);
2132 pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
2134 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_REVISION].property_name, DBUS_TYPE_UINT32, &rev);
2135 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_SAMPLERATE].property_name, DBUS_TYPE_UINT32, &rate);
2136 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_FILTERSAMPLERATE].property_name, DBUS_TYPE_UINT32, &fft_size);
2137 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs);
2138 pa_dbus_append_basic_variant_dict_entry(&dict_iter, equalizer_handlers[EQUALIZER_HANDLER_N_CHANNELS].property_name, DBUS_TYPE_UINT32, &channels);
2140 pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
2141 pa_assert_se(dbus_connection_send(conn, reply, NULL));
2142 dbus_message_unref(reply);