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
);
1006 //ensure's memory allocated is a multiple of v_size
1008 static void * alloc(size_t x
,size_t s
){
1009 size_t f
= PA_ROUND_UP(x
*s
, sizeof(float)*v_size
);
1011 pa_assert(f
>= x
*s
);
1012 t
= fftwf_malloc(f
);
1017 int pa__init(pa_module
*m
) {
1024 pa_sink_input_new_data sink_input_data
;
1025 pa_sink_new_data sink_data
;
1032 if (!(ma
= pa_modargs_new(m
->argument
, valid_modargs
))) {
1033 pa_log("Failed to parse module arguments.");
1037 if (!(master
= pa_namereg_get(m
->core
, pa_modargs_get_value(ma
, "master", NULL
), PA_NAMEREG_SINK
))) {
1038 pa_log("Master sink not found, trying default");
1039 master
= pa_namereg_get_default_sink(m
->core
);
1041 pa_log("no default sink found!");
1046 ss
= master
->sample_spec
;
1047 ss
.format
= PA_SAMPLE_FLOAT32
;
1048 map
= master
->channel_map
;
1049 if (pa_modargs_get_sample_spec_and_channel_map(ma
, &ss
, &map
, PA_CHANNEL_MAP_DEFAULT
) < 0) {
1050 pa_log("Invalid sample format specification or channel map");
1053 fs
= pa_frame_size(&ss
);
1055 u
= pa_xnew0(struct userdata
, 1);
1059 u
->set_default
= TRUE
;
1060 pa_modargs_get_value_boolean(ma
, "set_default", &u
->set_default
);
1062 u
->channels
= ss
.channels
;
1063 u
->fft_size
= pow(2, ceil(log(ss
.rate
)/log(2)));
1064 pa_log_debug("fft size: %ld", u
->fft_size
);
1065 u
->window_size
= 15999;
1066 u
->R
= (u
->window_size
+ 1) / 2;
1067 u
->overlap_size
= u
->window_size
- u
->R
;
1068 u
->samples_gathered
= 0;
1069 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
1070 u
->latency
= u
->window_size
- u
->R
;
1071 u
->Xs
= pa_xnew0(float *, u
->channels
);
1072 u
->Hs
= pa_xnew0(float **, u
->channels
);
1073 for(size_t c
= 0; c
< u
->channels
; ++c
){
1074 u
->Xs
[c
] = pa_xnew0(float, 2);
1075 u
->Hs
[c
] = pa_xnew0(float *, 2);
1076 for(size_t i
= 0; i
< 2; ++i
){
1077 u
->Hs
[c
][i
] = alloc((FILTER_SIZE
), sizeof(float));
1080 u
->W
= alloc(u
->window_size
, sizeof(float));
1081 u
->work_buffer
= alloc(u
->fft_size
, sizeof(float));
1082 memset(u
->work_buffer
, 0, u
->fft_size
*sizeof(float));
1083 u
->input
= pa_xnew0(float *, u
->channels
);
1084 u
->overlap_accum
= pa_xnew0(float *, u
->channels
);
1085 for(size_t c
= 0; c
< u
->channels
; ++c
){
1086 u
->a_H
[c
] = pa_aupdate_new();
1087 u
->input
[c
] = alloc(u
->window_size
, sizeof(float));
1088 memset(u
->input
[c
], 0, (u
->window_size
)*sizeof(float));
1089 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1090 memset(u
->overlap_accum
[c
], 0, u
->overlap_size
*sizeof(float));
1092 u
->output_window
= alloc((FILTER_SIZE
), sizeof(fftwf_complex
));
1093 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1094 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1096 hanning_window(u
->W
, u
->window_size
);
1097 u
->first_iteration
= TRUE
;
1099 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1102 pa_sink_new_data_init(&sink_data
);
1103 sink_data
.driver
= __FILE__
;
1104 sink_data
.module
= m
;
1105 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1106 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1107 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1108 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1109 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1110 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s",z
? z
: master
->name
);
1111 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1112 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1114 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1115 pa_log("Invalid properties");
1116 pa_sink_new_data_done(&sink_data
);
1120 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
1121 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
1122 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
1123 pa_sink_new_data_done(&sink_data
);
1126 pa_log("Failed to create sink.");
1129 u
->name
=pa_xstrdup(u
->sink
->name
);
1130 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1131 u
->sink
->set_state
= sink_set_state_cb
;
1132 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1133 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1134 u
->sink
->set_volume
= sink_set_volume_cb
;
1135 u
->sink
->set_mute
= sink_set_mute_cb
;
1136 u
->sink
->userdata
= u
;
1137 u
->input_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, &u
->sink
->silence
);
1139 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1140 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1142 /* Create sink input */
1143 pa_sink_input_new_data_init(&sink_input_data
);
1144 sink_input_data
.driver
= __FILE__
;
1145 sink_input_data
.module
= m
;
1146 sink_input_data
.sink
= master
;
1147 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1148 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1149 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1150 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1152 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
, 0);
1153 pa_sink_input_new_data_done(&sink_input_data
);
1158 u
->sink_input
->pop
= sink_input_pop_cb
;
1159 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1160 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1161 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1162 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1163 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1164 u
->sink_input
->kill
= sink_input_kill_cb
;
1165 u
->sink_input
->attach
= sink_input_attach_cb
;
1166 u
->sink_input
->detach
= sink_input_detach_cb
;
1167 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1168 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1169 u
->sink_input
->moving
= sink_input_moving_cb
;
1170 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1171 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1173 u
->sink_input
->userdata
= u
;
1175 pa_sink_put(u
->sink
);
1176 pa_sink_input_put(u
->sink_input
);
1178 pa_modargs_free(ma
);
1183 //default filter to these
1184 for(size_t c
= 0; c
< u
->channels
; ++c
){
1185 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1187 u
->Xs
[c
][a_i
] = 1.0f
;
1188 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1189 H
[i
] = 1.0 / sqrtf(2.0f
);
1191 fix_filter(H
, u
->fft_size
);
1192 pa_aupdate_write_end(u
->a_H
[c
]);
1194 //load old parameters
1201 pa_modargs_free(ma
);
1209 int pa__get_n_used(pa_module
*m
) {
1213 pa_assert_se(u
= m
->userdata
);
1215 return pa_sink_linked_by(u
->sink
);
1218 void pa__done(pa_module
*m
) {
1223 if (!(u
= m
->userdata
))
1230 for(size_t c
= 0; c
< u
->channels
; ++c
){
1231 if(u
->base_profiles
[c
]){
1232 pa_xfree(u
->base_profiles
[c
]);
1235 pa_xfree(u
->base_profiles
);
1237 /* See comments in sink_input_kill_cb() above regarding
1238 * destruction order! */
1241 pa_sink_input_unlink(u
->sink_input
);
1244 pa_sink_unlink(u
->sink
);
1247 pa_sink_input_unref(u
->sink_input
);
1250 pa_sink_unref(u
->sink
);
1252 pa_memblockq_free(u
->input_q
);
1254 fftwf_destroy_plan(u
->inverse_plan
);
1255 fftwf_destroy_plan(u
->forward_plan
);
1256 pa_xfree(u
->output_window
);
1257 for(size_t c
=0; c
< u
->channels
; ++c
){
1258 pa_aupdate_free(u
->a_H
[c
]);
1259 pa_xfree(u
->overlap_accum
[c
]);
1260 pa_xfree(u
->input
[c
]);
1263 pa_xfree(u
->overlap_accum
);
1265 pa_xfree(u
->work_buffer
);
1267 for(size_t c
= 0; c
< u
->channels
; ++c
){
1269 for(size_t i
= 0; i
< 2; ++i
){
1270 pa_xfree(u
->Hs
[c
][i
]);
1283 * DBus Routines and Callbacks
1285 #define EXTNAME "org.PulseAudio.Ext.Equalizing1"
1286 #define MANAGER_PATH "/org/pulseaudio/equalizing1"
1287 #define MANAGER_IFACE EXTNAME ".Manager"
1288 #define EQUALIZER_IFACE EXTNAME ".Equalizer"
1289 static void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1290 static void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1291 static void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1292 static void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1293 static void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1294 static void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1295 static void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1296 static void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1297 static void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1298 static void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1299 static void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1300 static void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1301 static void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1302 static void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1303 static void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1304 static void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1305 static void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1306 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1307 enum manager_method_index
{
1308 MANAGER_METHOD_REMOVE_PROFILE
,
1312 pa_dbus_arg_info remove_profile_args
[]={
1316 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1317 [MANAGER_METHOD_REMOVE_PROFILE
]{
1318 .method_name
="RemoveProfile",
1319 .arguments
=remove_profile_args
,
1320 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1321 .receive_cb
=manager_handle_remove_profile
}
1324 enum manager_handler_index
{
1325 MANAGER_HANDLER_REVISION
,
1326 MANAGER_HANDLER_EQUALIZED_SINKS
,
1327 MANAGER_HANDLER_PROFILES
,
1331 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1332 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1333 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1334 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1337 pa_dbus_arg_info sink_args
[]={
1341 enum manager_signal_index
{
1342 MANAGER_SIGNAL_SINK_ADDED
,
1343 MANAGER_SIGNAL_SINK_REMOVED
,
1344 MANAGER_SIGNAL_PROFILES_CHANGED
,
1348 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1349 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1350 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1351 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1354 static pa_dbus_interface_info manager_info
={
1355 .name
=MANAGER_IFACE
,
1356 .method_handlers
=manager_methods
,
1357 .n_method_handlers
=MANAGER_METHOD_MAX
,
1358 .property_handlers
=manager_handlers
,
1359 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1360 .get_all_properties_cb
=manager_get_all
,
1361 .signals
=manager_signals
,
1362 .n_signals
=MANAGER_SIGNAL_MAX
1365 enum equalizer_method_index
{
1366 EQUALIZER_METHOD_FILTER_POINTS
,
1367 EQUALIZER_METHOD_SEED_FILTER
,
1368 EQUALIZER_METHOD_SAVE_PROFILE
,
1369 EQUALIZER_METHOD_LOAD_PROFILE
,
1370 EQUALIZER_METHOD_SET_FILTER
,
1371 EQUALIZER_METHOD_GET_FILTER
,
1372 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1373 EQUALIZER_METHOD_MAX
1376 enum equalizer_handler_index
{
1377 EQUALIZER_HANDLER_REVISION
,
1378 EQUALIZER_HANDLER_SAMPLERATE
,
1379 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1380 EQUALIZER_HANDLER_N_COEFS
,
1381 EQUALIZER_HANDLER_N_CHANNELS
,
1382 EQUALIZER_HANDLER_MAX
1385 pa_dbus_arg_info filter_points_args
[]={
1386 {"channel", "u","in"},
1389 {"preamp", "d","out"}
1391 pa_dbus_arg_info seed_filter_args
[]={
1392 {"channel", "u","in"},
1395 {"preamp", "d","in"}
1398 pa_dbus_arg_info set_filter_args
[]={
1399 {"channel", "u","in"},
1401 {"preamp", "d","in"}
1403 pa_dbus_arg_info get_filter_args
[]={
1404 {"channel", "u","in"},
1406 {"preamp", "d","out"}
1409 pa_dbus_arg_info save_profile_args
[]={
1410 {"channel", "u","in"},
1413 pa_dbus_arg_info load_profile_args
[]={
1414 {"channel", "u","in"},
1417 pa_dbus_arg_info base_profile_name_args
[]={
1418 {"channel", "u","in"},
1422 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1423 [EQUALIZER_METHOD_SEED_FILTER
]{
1424 .method_name
="SeedFilter",
1425 .arguments
=seed_filter_args
,
1426 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1427 .receive_cb
=equalizer_handle_seed_filter
},
1428 [EQUALIZER_METHOD_FILTER_POINTS
]{
1429 .method_name
="FilterAtPoints",
1430 .arguments
=filter_points_args
,
1431 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1432 .receive_cb
=equalizer_handle_get_filter_points
},
1433 [EQUALIZER_METHOD_SET_FILTER
]{
1434 .method_name
="SetFilter",
1435 .arguments
=set_filter_args
,
1436 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1437 .receive_cb
=equalizer_handle_set_filter
},
1438 [EQUALIZER_METHOD_GET_FILTER
]{
1439 .method_name
="GetFilter",
1440 .arguments
=get_filter_args
,
1441 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1442 .receive_cb
=equalizer_handle_get_filter
},
1443 [EQUALIZER_METHOD_SAVE_PROFILE
]{
1444 .method_name
="SaveProfile",
1445 .arguments
=save_profile_args
,
1446 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1447 .receive_cb
=equalizer_handle_save_profile
},
1448 [EQUALIZER_METHOD_LOAD_PROFILE
]{
1449 .method_name
="LoadProfile",
1450 .arguments
=load_profile_args
,
1451 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1452 .receive_cb
=equalizer_handle_load_profile
},
1453 [EQUALIZER_METHOD_GET_PROFILE_NAME
]{
1454 .method_name
="BaseProfile",
1455 .arguments
=base_profile_name_args
,
1456 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1457 .receive_cb
=equalizer_handle_get_profile_name
}
1460 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1461 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1462 [EQUALIZER_HANDLER_SAMPLERATE
]{.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1463 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]{.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1464 [EQUALIZER_HANDLER_N_COEFS
]{.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1465 [EQUALIZER_HANDLER_N_CHANNELS
]{.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1468 enum equalizer_signal_index
{
1469 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1470 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1471 EQUALIZER_SIGNAL_MAX
1474 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1475 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1476 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1479 static pa_dbus_interface_info equalizer_info
={
1480 .name
=EQUALIZER_IFACE
,
1481 .method_handlers
=equalizer_methods
,
1482 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1483 .property_handlers
=equalizer_handlers
,
1484 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1485 .get_all_properties_cb
=equalizer_get_all
,
1486 .signals
=equalizer_signals
,
1487 .n_signals
=EQUALIZER_SIGNAL_MAX
1490 void dbus_init(struct userdata
*u
){
1492 DBusMessage
*signal
= NULL
;
1493 pa_idxset
*sink_list
= NULL
;
1494 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1495 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1497 pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
);
1498 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1499 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1500 if(sink_list
== NULL
){
1502 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1503 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1504 pa_assert_se(dbname
= pa_state_path("equalizer-presets", FALSE
));
1505 pa_assert_se(u
->database
= pa_database_open(dbname
, TRUE
));
1507 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1508 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1509 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1511 pa_idxset_put(sink_list
, u
, &dummy
);
1513 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1514 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1515 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1516 dbus_message_unref(signal
);
1519 void dbus_done(struct userdata
*u
){
1520 pa_idxset
*sink_list
;
1523 DBusMessage
*signal
= NULL
;
1524 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1525 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1526 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1527 dbus_message_unref(signal
);
1529 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1530 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1531 if(pa_idxset_size(sink_list
)==0){
1532 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1533 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1534 pa_shared_remove(u
->sink
->core
, EQDB
);
1535 pa_database_close(u
->database
);
1536 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1537 pa_xfree(sink_list
);
1539 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1540 pa_xfree(u
->dbus_path
);
1541 pa_dbus_protocol_unref(u
->dbus_protocol
);
1544 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1546 pa_core
*c
= (pa_core
*)_u
;
1547 DBusMessage
*signal
= NULL
;
1548 pa_dbus_protocol
*dbus_protocol
;
1553 dbus_error_init(&error
);
1554 if(!dbus_message_get_args(msg
, &error
,
1555 DBUS_TYPE_STRING
, &name
,
1556 DBUS_TYPE_INVALID
)){
1557 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1558 dbus_error_free(&error
);
1561 remove_profile(c
,name
);
1562 pa_dbus_send_empty_reply(conn
, msg
);
1564 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1565 dbus_protocol
= pa_dbus_protocol_get(c
);
1566 pa_dbus_protocol_send_signal(dbus_protocol
, signal
);
1567 pa_dbus_protocol_unref(dbus_protocol
);
1568 dbus_message_unref(signal
);
1571 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1573 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1576 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
){
1578 struct userdata
*sink_u
= NULL
;
1580 pa_idxset
*sink_list
;
1585 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1586 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1587 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1588 for(uint32_t i
= 0; i
< *n_sinks
; ++i
){
1589 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1590 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1594 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1596 char **names
= NULL
;
1601 get_sinks((pa_core
*) _u
, &names
, &n
);
1602 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1603 for(unsigned i
= 0; i
< n
; ++i
){
1609 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
){
1611 pa_database
*database
;
1612 pa_datum key
, next_key
;
1613 pa_strlist
*head
=NULL
, *iter
;
1615 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1620 done
= !pa_database_first(database
, &key
, NULL
);
1623 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1624 name
=pa_xmalloc(key
.size
+ 1);
1625 memcpy(name
, key
.data
, key
.size
);
1626 name
[key
.size
] = '\0';
1627 pa_datum_free(&key
);
1628 head
= pa_strlist_prepend(head
, name
);
1633 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1635 for(unsigned i
= 0; i
< *n
; ++i
){
1636 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1637 iter
= pa_strlist_next(iter
);
1639 pa_strlist_free(head
);
1642 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1649 get_profiles((pa_core
*)_u
, &names
, &n
);
1650 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1651 for(unsigned i
= 0; i
< n
; ++i
){
1657 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1659 char **names
= NULL
;
1661 DBusMessage
*reply
= NULL
;
1662 DBusMessageIter msg_iter
, dict_iter
;
1666 pa_assert_se(c
= _u
);
1668 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1669 dbus_message_iter_init_append(reply
, &msg_iter
);
1670 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1673 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1675 get_sinks(c
, &names
, &n
);
1676 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1677 for(unsigned i
= 0; i
< n
; ++i
){
1682 get_profiles(c
, &names
, &n
);
1683 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1684 for(unsigned i
= 0; i
< n
; ++i
){
1688 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1689 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1690 dbus_message_unref(reply
);
1693 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1694 struct userdata
*u
=(struct userdata
*) _u
;
1696 DBusMessage
*signal
= NULL
;
1698 uint32_t *xs
, channel
, r_channel
;
1699 double *_ys
, preamp
;
1700 unsigned x_npoints
, y_npoints
, a_i
;
1702 pa_bool_t points_good
= TRUE
;
1707 dbus_error_init(&error
);
1709 if(!dbus_message_get_args(msg
, &error
,
1710 DBUS_TYPE_UINT32
, &channel
,
1711 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1712 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1713 DBUS_TYPE_DOUBLE
, &preamp
,
1714 DBUS_TYPE_INVALID
)){
1715 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1716 dbus_error_free(&error
);
1719 if(channel
> u
->channels
){
1720 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1721 dbus_error_free(&error
);
1724 for(size_t i
= 0; i
< x_npoints
; ++i
){
1725 if(xs
[i
] >= FILTER_SIZE
){
1726 points_good
= FALSE
;
1730 if(!is_monotonic(xs
, x_npoints
) || !points_good
){
1731 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%ld", u
->fft_size
/ 2);
1732 dbus_error_free(&error
);
1734 }else if(x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE
){
1735 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE
);
1736 dbus_error_free(&error
);
1738 }else if(xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2){
1739 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1740 dbus_error_free(&error
);
1744 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1745 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1746 ys
[i
] = (float) _ys
[i
];
1748 r_channel
= channel
== u
->channels
? 0 : channel
;
1749 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1750 H
= u
->Hs
[r_channel
][a_i
];
1751 u
->Xs
[r_channel
][a_i
] = preamp
;
1752 interpolate(H
, FILTER_SIZE
, xs
, ys
, x_npoints
);
1753 fix_filter(H
, u
->fft_size
);
1754 if(channel
== u
->channels
){
1755 for(size_t c
= 1; c
< u
->channels
; ++c
){
1756 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1757 float *H_p
= u
->Hs
[c
][b_i
];
1758 u
->Xs
[c
][b_i
] = preamp
;
1759 memcpy(H_p
, H
, FILTER_SIZE
* sizeof(float));
1760 pa_aupdate_write_end(u
->a_H
[c
]);
1763 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1767 pa_dbus_send_empty_reply(conn
, msg
);
1769 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1770 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1771 dbus_message_unref(signal
);
1774 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1775 struct userdata
*u
= (struct userdata
*) _u
;
1776 uint32_t *xs
, channel
, r_channel
;
1778 unsigned x_npoints
, a_i
;
1780 pa_bool_t points_good
=TRUE
;
1781 DBusMessage
*reply
= NULL
;
1782 DBusMessageIter msg_iter
;
1789 dbus_error_init(&error
);
1790 if(!dbus_message_get_args(msg
, &error
,
1791 DBUS_TYPE_UINT32
, &channel
,
1792 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1793 DBUS_TYPE_INVALID
)){
1794 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1795 dbus_error_free(&error
);
1798 if(channel
> u
->channels
){
1799 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1800 dbus_error_free(&error
);
1804 for(size_t i
= 0; i
< x_npoints
; ++i
){
1805 if(xs
[i
] >= FILTER_SIZE
){
1811 if(x_npoints
> FILTER_SIZE
|| !points_good
){
1812 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %ld!", FILTER_SIZE
);
1813 dbus_error_free(&error
);
1817 r_channel
= channel
== u
->channels
? 0 : channel
;
1818 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1819 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1820 H
= u
->Hs
[r_channel
][a_i
];
1821 preamp
= u
->Xs
[r_channel
][a_i
];
1822 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1823 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1825 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1827 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1828 dbus_message_iter_init_append(reply
, &msg_iter
);
1830 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1831 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1833 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1834 dbus_message_unref(reply
);
1838 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
){
1841 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1842 *H_
= pa_xnew0(double, FILTER_SIZE
);
1843 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1844 H
= u
->Hs
[r_channel
][a_i
];
1845 for(size_t i
= 0;i
< FILTER_SIZE
; ++i
){
1846 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1848 *preamp
= u
->Xs
[r_channel
][a_i
];
1850 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1853 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1858 DBusMessage
*reply
= NULL
;
1859 DBusMessageIter msg_iter
;
1861 pa_assert_se(u
= (struct userdata
*) _u
);
1865 dbus_error_init(&error
);
1866 if(!dbus_message_get_args(msg
, &error
,
1867 DBUS_TYPE_UINT32
, &channel
,
1868 DBUS_TYPE_INVALID
)){
1869 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1870 dbus_error_free(&error
);
1873 if(channel
> u
->channels
){
1874 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1875 dbus_error_free(&error
);
1879 n_coefs
= CHANNEL_PROFILE_SIZE
;
1882 get_filter(u
, channel
, &H_
, &preamp
);
1883 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1884 dbus_message_iter_init_append(reply
, &msg_iter
);
1886 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1887 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1889 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1890 dbus_message_unref(reply
);
1894 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
){
1896 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1899 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1900 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1901 H
= u
->Hs
[r_channel
][a_i
];
1902 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1903 H
[i
] = (float) H_
[i
];
1905 fix_filter(H
, u
->fft_size
);
1906 if(channel
== u
->channels
){
1907 for(size_t c
= 1; c
< u
->channels
; ++c
){
1908 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1909 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
1910 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE
* sizeof(float));
1911 pa_aupdate_write_end(u
->a_H
[c
]);
1914 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1917 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1922 DBusMessage
*signal
= NULL
;
1924 pa_assert_se(u
= (struct userdata
*) _u
);
1928 dbus_error_init(&error
);
1929 if(!dbus_message_get_args(msg
, &error
,
1930 DBUS_TYPE_UINT32
, &channel
,
1931 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
1932 DBUS_TYPE_DOUBLE
, &preamp
,
1933 DBUS_TYPE_INVALID
)){
1934 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1935 dbus_error_free(&error
);
1938 if(channel
> u
->channels
){
1939 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1940 dbus_error_free(&error
);
1943 if(_n_coefs
!= FILTER_SIZE
){
1944 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE
, _n_coefs
);
1947 set_filter(u
, channel
, H
, preamp
);
1949 pa_dbus_send_empty_reply(conn
, msg
);
1951 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1952 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1953 dbus_message_unref(signal
);
1956 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1957 struct userdata
*u
= (struct userdata
*) _u
;
1959 uint32_t channel
, r_channel
;
1960 DBusMessage
*signal
= NULL
;
1965 dbus_error_init(&error
);
1967 if(!dbus_message_get_args(msg
, &error
,
1968 DBUS_TYPE_UINT32
, &channel
,
1969 DBUS_TYPE_STRING
, &name
,
1970 DBUS_TYPE_INVALID
)){
1971 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1972 dbus_error_free(&error
);
1975 if(channel
> u
->channels
){
1976 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1977 dbus_error_free(&error
);
1980 r_channel
= channel
== u
->channels
? 0 : channel
;
1981 save_profile(u
, r_channel
, name
);
1982 pa_dbus_send_empty_reply(conn
, msg
);
1984 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1985 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1986 dbus_message_unref(signal
);
1989 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1990 struct userdata
*u
= (struct userdata
*) _u
;
1993 uint32_t channel
, r_channel
;
1994 const char *err_msg
= NULL
;
1995 DBusMessage
*signal
= NULL
;
2000 dbus_error_init(&error
);
2002 if(!dbus_message_get_args(msg
, &error
,
2003 DBUS_TYPE_UINT32
, &channel
,
2004 DBUS_TYPE_STRING
, &name
,
2005 DBUS_TYPE_INVALID
)){
2006 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2007 dbus_error_free(&error
);
2010 if(channel
> u
->channels
){
2011 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2012 dbus_error_free(&error
);
2015 r_channel
= channel
== u
->channels
? 0 : channel
;
2017 err_msg
= load_profile(u
, r_channel
, name
);
2018 if(err_msg
!= NULL
){
2019 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2020 dbus_error_free(&error
);
2023 if(channel
== u
->channels
){
2024 for(uint32_t c
= 1; c
< u
->channels
; ++c
){
2025 load_profile(u
, c
, name
);
2028 pa_dbus_send_empty_reply(conn
, msg
);
2030 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2031 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2032 dbus_message_unref(signal
);
2035 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2036 struct userdata
*u
= (struct userdata
*) _u
;
2038 uint32_t channel
, r_channel
;
2043 dbus_error_init(&error
);
2045 if(!dbus_message_get_args(msg
, &error
,
2046 DBUS_TYPE_UINT32
, &channel
,
2047 DBUS_TYPE_INVALID
)){
2048 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2049 dbus_error_free(&error
);
2052 if(channel
> u
->channels
){
2053 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2054 dbus_error_free(&error
);
2057 r_channel
= channel
== u
->channels
? 0 : channel
;
2058 if(u
->base_profiles
[r_channel
]){
2059 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2061 pa_dbus_send_empty_reply(conn
, msg
);
2065 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2067 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2070 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2073 pa_assert_se(u
= (struct userdata
*) _u
);
2077 channels
= (uint32_t) u
->channels
;
2078 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2081 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2084 pa_assert_se(u
= (struct userdata
*) _u
);
2088 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2089 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2092 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2095 pa_assert_se(u
= (struct userdata
*) _u
);
2099 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2100 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2103 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2106 pa_assert_se(u
= (struct userdata
*) _u
);
2110 fft_size
= (uint32_t) u
->fft_size
;
2111 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2114 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2116 DBusMessage
*reply
= NULL
;
2117 DBusMessageIter msg_iter
, dict_iter
;
2118 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2119 pa_assert_se(u
= (struct userdata
*) _u
);
2123 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2124 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2125 fft_size
= (uint32_t) u
->fft_size
;
2126 channels
= (uint32_t) u
->channels
;
2128 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2129 dbus_message_iter_init_append(reply
, &msg_iter
);
2130 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2132 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2133 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2134 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2135 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2136 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2138 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2139 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2140 dbus_message_unref(reply
);