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 //for twiddling with pulseaudio
103 size_t overlap_size
;//window_size-R
104 size_t samples_gathered
;
105 size_t input_buffer_max
;
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
){
201 //ensure's memory allocated is a multiple of v_size
203 static void * alloc(size_t x
,size_t s
){
204 size_t f
= PA_ROUND_UP(x
*s
, sizeof(float)*v_size
);
212 static void alloc_input_buffers(struct userdata
*u
, size_t min_buffer_length
){
213 if(min_buffer_length
<= u
->input_buffer_max
){
216 pa_assert(min_buffer_length
>= u
->window_size
);
217 for(size_t c
= 0; c
< u
->channels
; ++c
){
218 float *tmp
= alloc(min_buffer_length
, sizeof(float));
220 if(!u
->first_iteration
){
221 memcpy(tmp
, u
->input
[c
], u
->overlap_size
* sizeof(float));
227 u
->input_buffer_max
= min_buffer_length
;
230 /* Called from I/O thread context */
231 static int sink_process_msg_cb(pa_msgobject
*o
, int code
, void *data
, int64_t offset
, pa_memchunk
*chunk
) {
232 struct userdata
*u
= PA_SINK(o
)->userdata
;
236 case PA_SINK_MESSAGE_GET_LATENCY
: {
237 //size_t fs=pa_frame_size(&u->sink->sample_spec);
239 /* The sink is _put() before the sink input is, so let's
240 * make sure we don't access it in that time. Also, the
241 * sink input is first shut down, the sink second. */
242 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
243 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
)) {
244 *((pa_usec_t
*) data
) = 0;
248 *((pa_usec_t
*) data
) =
249 /* Get the latency of the master sink */
250 pa_sink_get_latency_within_thread(u
->sink_input
->sink
) +
252 /* Add the latency internal to our sink input on top */
253 pa_bytes_to_usec(pa_memblockq_get_length(u
->sink_input
->thread_info
.render_memblockq
), &u
->sink_input
->sink
->sample_spec
);
254 // pa_bytes_to_usec(u->samples_gathered * fs, &u->sink->sample_spec);
255 //+ pa_bytes_to_usec(u->latency * fs, ss)
256 //+ pa_bytes_to_usec(pa_memblockq_get_length(u->input_q), ss);
261 return pa_sink_process_msg(o
, code
, data
, offset
, chunk
);
265 /* Called from main context */
266 static int sink_set_state_cb(pa_sink
*s
, pa_sink_state_t state
) {
269 pa_sink_assert_ref(s
);
270 pa_assert_se(u
= s
->userdata
);
272 if (!PA_SINK_IS_LINKED(state
) ||
273 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
276 pa_sink_input_cork(u
->sink_input
, state
== PA_SINK_SUSPENDED
);
280 /* Called from I/O thread context */
281 static void sink_request_rewind_cb(pa_sink
*s
) {
284 pa_sink_assert_ref(s
);
285 pa_assert_se(u
= s
->userdata
);
287 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
288 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
291 /* Just hand this one over to the master sink */
292 pa_sink_input_request_rewind(u
->sink_input
, s
->thread_info
.rewind_nbytes
+pa_memblockq_get_length(u
->input_q
), TRUE
, FALSE
, FALSE
);
295 /* Called from I/O thread context */
296 static void sink_update_requested_latency_cb(pa_sink
*s
) {
299 pa_sink_assert_ref(s
);
300 pa_assert_se(u
= s
->userdata
);
302 if (!PA_SINK_IS_LINKED(u
->sink
->thread_info
.state
) ||
303 !PA_SINK_INPUT_IS_LINKED(u
->sink_input
->thread_info
.state
))
306 /* Just hand this one over to the master sink */
307 pa_sink_input_set_requested_latency_within_thread(
309 pa_sink_get_requested_latency_within_thread(s
));
312 /* Called from main context */
313 static void sink_set_volume_cb(pa_sink
*s
) {
316 pa_sink_assert_ref(s
);
317 pa_assert_se(u
= s
->userdata
);
319 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
320 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
323 pa_sink_input_set_volume(u
->sink_input
, &s
->real_volume
, s
->save_volume
, TRUE
);
326 /* Called from main context */
327 static void sink_set_mute_cb(pa_sink
*s
) {
330 pa_sink_assert_ref(s
);
331 pa_assert_se(u
= s
->userdata
);
333 if (!PA_SINK_IS_LINKED(pa_sink_get_state(s
)) ||
334 !PA_SINK_INPUT_IS_LINKED(pa_sink_input_get_state(u
->sink_input
)))
337 pa_sink_input_set_mute(u
->sink_input
, s
->muted
, s
->save_muted
);
341 //reference implementation
342 static void dsp_logic(
343 float * restrict dst
,//used as a temp array too, needs to be fft_length!
344 float * restrict src
,/*input data w/ overlap at start,
345 *automatically cycled in routine
347 float * restrict overlap
,
348 const float X
,//multipliar
349 const float * restrict H
,//The freq. magnitude scalers filter
350 const float * restrict W
,//The windowing function
351 fftwf_complex
* restrict output_window
,//The transformed window'd src
353 //use a linear-phase sliding STFT and overlap-add method (for each channel)
355 memset(dst
+ u
->window_size
, 0, (u
->fft_size
- u
->window_size
) * sizeof(float));
357 for(size_t j
= 0; j
< u
->window_size
; ++j
){
358 dst
[j
] = X
* W
[j
] * src
[j
];
360 //Processing is done here!
362 fftwf_execute_dft_r2c(u
->forward_plan
, dst
, output_window
);
364 for(size_t j
= 0; j
< FILTER_SIZE
; ++j
){
365 u
->output_window
[j
][0] *= H
[j
];
366 u
->output_window
[j
][1] *= H
[j
];
369 fftwf_execute_dft_c2r(u
->inverse_plan
, output_window
, dst
);
370 ////debug: tests overlaping add
371 ////and negates ALL PREVIOUS processing
372 ////yields a perfect reconstruction if COLA is held
373 //for(size_t j = 0; j < u->window_size; ++j){
374 // u->work_buffer[j] = u->W[j] * u->input[c][j];
377 //overlap add and preserve overlap component from this window (linear phase)
378 for(size_t j
= 0; j
< u
->overlap_size
; ++j
){
379 u
->work_buffer
[j
] += overlap
[j
];
380 overlap
[j
] = dst
[u
->R
+ j
];
382 ////debug: tests if basic buffering works
383 ////shouldn't modify the signal AT ALL (beyond roundoff)
384 //for(size_t j = 0; j < u->window_size;++j){
385 // u->work_buffer[j] = u->input[c][j];
388 //preseve the needed input for the next window's overlap
389 memmove(src
, src
+ u
->R
,
390 (u
->samples_gathered
- u
->R
) * sizeof(float)
394 typedef float v4sf
__attribute__ ((__aligned__(v_size
* sizeof(float))));
395 typedef union float_vector
{
403 ////regardless of sse enabled, the loops in here assume
404 ////16 byte aligned addresses and memory allocations divisible by v_size
406 // float * restrict dst,//used as a temp array too, needs to be fft_length!
407 // float * restrict src,/*input data w/ overlap at start,
408 // *automatically cycled in routine
410 // float * restrict overlap,//The size of the overlap
411 // const float X,//multipliar
412 // const float * restrict H,//The freq. magnitude scalers filter
413 // const float * restrict W,//The windowing function
414 // fftwf_complex * restrict output_window,//The transformed window'd src
415 // struct userdata *u){//Collection of constants
416 //float_vector_t x = {X, X, X, X};
417 // const size_t window_size = PA_ROUND_UP(u->window_size,v_size);
418 // const size_t fft_h = PA_ROUND_UP(FILTER_SIZE, v_size / 2);
419 // //const size_t R = PA_ROUND_UP(u->R, v_size);
420 // const size_t overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
421 // overlap_size = PA_ROUND_UP(u->overlap_size, v_size);
423 // //assert(u->samples_gathered >= u->R);
424 // //zero out the bit beyond the real overlap so we don't add garbage
425 // for(size_t j = overlap_size; j > u->overlap_size; --j){
428 // //use a linear-phase sliding STFT and overlap-add method
429 // //zero padd the data
430 // memset(dst + u->window_size, 0, (u->fft_size - u->window_size)*sizeof(float));
432 // for(size_t j = 0; j < window_size; j += v_size){
433 // //dst[j] = W[j]*src[j];
434 // float_vector_t *d = (float_vector_t*) (dst+j);
435 // float_vector_t *w = (float_vector_t*) (W+j);
436 // float_vector_t *s = (float_vector_t*) (src+j);
438 // d->m = _mm_mul_ps(x->m, _mm_mul_ps(w->m, s->m));
440 // d->v = x->v * w->v * s->v;
443 // //Processing is done here!
445 // fftwf_execute_dft_r2c(u->forward_plan, dst, output_window);
448 // //perform filtering - purely magnitude based
449 // for(size_t j = 0;j < fft_h; j+=v_size/2){
450 // //output_window[j][0]*=H[j];
451 // //output_window[j][1]*=H[j];
452 // float_vector_t *d = (float_vector_t*)(output_window+j);
454 // h.f[0] = h.f[1] = H[j];
455 // h.f[2] = h.f[3] = H[j+1];
457 // d->m = _mm_mul_ps(d->m, h.m);
463 // fftwf_execute_dft_c2r(u->inverse_plan, output_window, dst);
465 // ////debug: tests overlaping add
466 // ////and negates ALL PREVIOUS processing
467 // ////yields a perfect reconstruction if COLA is held
468 // //for(size_t j = 0; j < u->window_size; ++j){
469 // // dst[j] = W[j]*src[j];
472 // //overlap add and preserve overlap component from this window (linear phase)
473 // for(size_t j = 0; j < overlap_size; j+=v_size){
474 // //dst[j]+=overlap[j];
475 // //overlap[j]+=dst[j+R];
476 // float_vector_t *d = (float_vector_t*)(dst+j);
477 // float_vector_t *o = (float_vector_t*)(overlap+j);
479 // d->m = _mm_add_ps(d->m, o->m);
480 // o->m = ((float_vector_t*)(dst+u->R+j))->m;
483 // o->v = ((float_vector_t*)(dst+u->R+j))->v;
486 // //memcpy(overlap, dst+u->R, u->overlap_size*sizeof(float));
488 // //////debug: tests if basic buffering works
489 // //////shouldn't modify the signal AT ALL (beyond roundoff)
490 // //for(size_t j = 0; j < u->window_size; ++j){
491 // // dst[j] = src[j];
494 // //preseve the needed input for the next window's overlap
495 // memmove(src, src + u->R,
496 // u->overlap_size * sizeof(float)
500 static void process_samples(struct userdata
*u
, pa_memchunk
*tchunk
){
501 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
505 size_t iterations
, offset
;
506 pa_assert(u
->samples_gathered
>= u
->window_size
);
507 iterations
= (u
->samples_gathered
- u
->overlap_size
) / u
->R
;
509 tchunk
->length
= iterations
* u
->R
* fs
;
510 tchunk
->memblock
= pa_memblock_new(u
->sink
->core
->mempool
, tchunk
->length
);
511 dst
= ((float*) pa_memblock_acquire(tchunk
->memblock
));
512 for(size_t iter
= 0; iter
< iterations
; ++iter
){
513 offset
= iter
* u
->R
* fs
;
514 for(size_t c
= 0;c
< u
->channels
; c
++) {
515 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
528 pa_aupdate_read_end(u
->a_H
[c
]);
529 if(u
->first_iteration
){
530 /* The windowing function will make the audio ramped in, as a cheap fix we can
531 * undo the windowing (for non-zero window values)
533 for(size_t i
= 0; i
< u
->overlap_size
; ++i
){
534 u
->work_buffer
[i
] = u
->W
[i
] <= FLT_EPSILON
? u
->work_buffer
[i
] : u
->work_buffer
[i
] / u
->W
[i
];
537 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, (uint8_t *) (dst
+ c
) + offset
, fs
, u
->work_buffer
, sizeof(float), u
->R
);
539 if(u
->first_iteration
){
540 u
->first_iteration
= FALSE
;
542 u
->samples_gathered
-= u
->R
;
544 pa_memblock_release(tchunk
->memblock
);
547 static void input_buffer(struct userdata
*u
, pa_memchunk
*in
){
548 size_t fs
= pa_frame_size(&(u
->sink
->sample_spec
));
549 size_t samples
= in
->length
/fs
;
550 float *src
= (float*) ((uint8_t*) pa_memblock_acquire(in
->memblock
) + in
->index
);
551 pa_assert(u
->samples_gathered
+ samples
<= u
->input_buffer_max
);
552 for(size_t c
= 0; c
< u
->channels
; c
++) {
553 //buffer with an offset after the overlap from previous
556 u
->input
[c
] + u
->samples_gathered
+ samples
<= u
->input
[c
] + u
->input_buffer_max
558 pa_sample_clamp(PA_SAMPLE_FLOAT32NE
, u
->input
[c
] + u
->samples_gathered
, sizeof(float), src
+ c
, fs
, samples
);
560 u
->samples_gathered
+= samples
;
561 pa_memblock_release(in
->memblock
);
564 /* Called from I/O thread context */
565 static int sink_input_pop_cb(pa_sink_input
*i
, size_t nbytes
, pa_memchunk
*chunk
) {
567 size_t fs
, target_samples
;
568 struct timeval start
, end
;
570 pa_sink_input_assert_ref(i
);
571 pa_assert_se(u
= i
->userdata
);
574 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
575 target_samples
= PA_ROUND_UP(nbytes
/ fs
, u
->R
);
576 if(u
->first_iteration
){
577 //allocate request_size
578 target_samples
= PA_MAX(target_samples
, u
->window_size
);
580 //allocate request_size + overlap
581 target_samples
+= u
->overlap_size
;
582 alloc_input_buffers(u
, target_samples
);
584 alloc_input_buffers(u
, target_samples
);
585 chunk
->memblock
= NULL
;
587 /* Hmm, process any rewind request that might be queued up */
588 pa_sink_process_rewind(u
->sink
, 0);
590 //pa_log_debug("start output-buffered %ld, input-buffered %ld, requested %ld",buffered_samples,u->samples_gathered,samples_requested);
591 pa_rtclock_get(&start
);
593 size_t input_remaining
= target_samples
- u
->samples_gathered
;
594 pa_assert(input_remaining
> 0);
595 while(pa_memblockq_peek(u
->input_q
, &tchunk
) < 0){
596 //pa_sink_render(u->sink, input_remaining * fs, &tchunk);
597 pa_sink_render_full(u
->sink
, input_remaining
* fs
, &tchunk
);
598 pa_assert(tchunk
.memblock
);
599 pa_memblockq_push(u
->input_q
, &tchunk
);
600 pa_memblock_unref(tchunk
.memblock
);
602 pa_assert(tchunk
.memblock
);
603 tchunk
.length
= PA_MIN(input_remaining
* fs
, tchunk
.length
);
604 pa_memblockq_drop(u
->input_q
, tchunk
.length
);
605 //pa_log_debug("asked for %ld input samples, got %ld samples",input_remaining,buffer->length/fs);
607 //pa_rtclock_get(start);
608 input_buffer(u
, &tchunk
);
609 //pa_rtclock_get(&end);
610 //pa_log_debug("Took %0.5f seconds to setup", pa_timeval_diff(end, start) / (double) PA_USEC_PER_SEC);
611 pa_memblock_unref(tchunk
.memblock
);
612 }while(u
->samples_gathered
< target_samples
);
614 pa_rtclock_get(&end
);
615 pa_log_debug("Took %0.6f seconds to get data", (double) pa_timeval_diff(&end
, &start
) / PA_USEC_PER_SEC
);
617 pa_assert(u
->fft_size
>= u
->window_size
);
618 pa_assert(u
->R
< u
->window_size
);
619 /* set the H filter */
620 pa_rtclock_get(&start
);
621 /* process a block */
622 process_samples(u
, chunk
);
623 pa_rtclock_get(&end
);
624 pa_log_debug("Took %0.6f seconds to process", (double) pa_timeval_diff(&end
, &start
) / PA_USEC_PER_SEC
);
626 pa_assert(chunk
->memblock
);
627 //pa_log_debug("gave %ld", chunk->length/fs);
628 //pa_log_debug("end pop");
632 /* Called from main context */
633 static void sink_input_volume_changed_cb(pa_sink_input
*i
) {
636 pa_sink_input_assert_ref(i
);
637 pa_assert_se(u
= i
->userdata
);
639 pa_sink_volume_changed(u
->sink
, &i
->volume
);
642 /* Called from main context */
643 static void sink_input_mute_changed_cb(pa_sink_input
*i
) {
646 pa_sink_input_assert_ref(i
);
647 pa_assert_se(u
= i
->userdata
);
649 pa_sink_mute_changed(u
->sink
, i
->muted
);
652 static void reset_filter(struct userdata
*u
){
653 size_t fs
= pa_frame_size(&u
->sink
->sample_spec
);
655 u
->samples_gathered
= 0;
656 for(size_t i
= 0; i
< u
->channels
; ++i
){
657 memset(u
->overlap_accum
[i
], 0, u
->overlap_size
* sizeof(float));
659 u
->first_iteration
= TRUE
;
660 //set buffer size to max request, no overlap copy
661 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
662 max_request
= PA_MAX(max_request
, u
->window_size
);
663 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
666 /* Called from I/O thread context */
667 static void sink_input_process_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
671 pa_log_debug("Rewind callback!");
672 pa_sink_input_assert_ref(i
);
673 pa_assert_se(u
= i
->userdata
);
675 if (u
->sink
->thread_info
.rewind_nbytes
> 0) {
678 //max_rewrite = nbytes;
679 max_rewrite
= nbytes
+ pa_memblockq_get_length(u
->input_q
);
680 //PA_MIN(pa_memblockq_get_length(u->input_q), nbytes);
681 amount
= PA_MIN(u
->sink
->thread_info
.rewind_nbytes
, max_rewrite
);
682 u
->sink
->thread_info
.rewind_nbytes
= 0;
685 //invalidate the output q
686 pa_memblockq_seek(u
->input_q
, - (int64_t) amount
, PA_SEEK_RELATIVE
, TRUE
);
687 pa_log("Resetting filter");
692 pa_sink_process_rewind(u
->sink
, amount
);
693 pa_memblockq_rewind(u
->input_q
, nbytes
);
696 /* Called from I/O thread context */
697 static void sink_input_update_max_rewind_cb(pa_sink_input
*i
, size_t nbytes
) {
700 pa_sink_input_assert_ref(i
);
701 pa_assert_se(u
= i
->userdata
);
703 pa_memblockq_set_maxrewind(u
->input_q
, nbytes
);
704 pa_sink_set_max_rewind_within_thread(u
->sink
, nbytes
);
707 /* Called from I/O thread context */
708 static void sink_input_update_max_request_cb(pa_sink_input
*i
, size_t nbytes
) {
711 pa_sink_input_assert_ref(i
);
712 pa_assert_se(u
= i
->userdata
);
713 //if(u->first_iteration){
716 fs
= pa_frame_size(&(u
->sink
->sample_spec
));
717 pa_sink_set_max_request_within_thread(u
->sink
, PA_ROUND_UP(nbytes
/ fs
, u
->R
) * fs
);
720 /* Called from I/O thread context */
721 static void sink_input_update_sink_latency_range_cb(pa_sink_input
*i
) {
724 pa_sink_input_assert_ref(i
);
725 pa_assert_se(u
= i
->userdata
);
727 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
730 /* Called from I/O thread context */
731 static void sink_input_update_sink_fixed_latency_cb(pa_sink_input
*i
) {
734 pa_sink_input_assert_ref(i
);
735 pa_assert_se(u
= i
->userdata
);
737 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
740 /* Called from I/O thread context */
741 static void sink_input_detach_cb(pa_sink_input
*i
) {
744 pa_sink_input_assert_ref(i
);
745 pa_assert_se(u
= i
->userdata
);
747 pa_sink_detach_within_thread(u
->sink
);
749 pa_sink_set_rtpoll(u
->sink
, NULL
);
752 /* Called from I/O thread context */
753 static void sink_input_attach_cb(pa_sink_input
*i
) {
755 size_t fs
, max_request
;
756 pa_sink_input_assert_ref(i
);
757 pa_assert_se(u
= i
->userdata
);
759 pa_sink_set_rtpoll(u
->sink
, i
->sink
->thread_info
.rtpoll
);
760 pa_sink_set_latency_range_within_thread(u
->sink
, i
->sink
->thread_info
.min_latency
, i
->sink
->thread_info
.max_latency
);
762 pa_sink_set_fixed_latency_within_thread(u
->sink
, i
->sink
->thread_info
.fixed_latency
);
763 fs
= pa_frame_size(&u
->sink
->sample_spec
);
764 //set buffer size to max request, no overlap copy
765 max_request
= PA_ROUND_UP(pa_sink_input_get_max_request(u
->sink_input
) / fs
, u
->R
);
766 max_request
= PA_MAX(max_request
, u
->window_size
);
767 pa_sink_set_max_request_within_thread(u
->sink
, max_request
* fs
);
768 pa_sink_set_max_rewind_within_thread(u
->sink
, pa_sink_input_get_max_rewind(i
));
769 pa_sink_attach_within_thread(u
->sink
);
771 pa_log_debug("Setting default sink to %s", u
->sink
->name
);
772 pa_namereg_set_default_sink(u
->module
->core
, u
->sink
);
776 /* Called from main context */
777 static void sink_input_kill_cb(pa_sink_input
*i
) {
780 pa_sink_input_assert_ref(i
);
781 pa_assert_se(u
= i
->userdata
);
783 /* The order here matters! We first kill the sink input, followed
784 * by the sink. That means the sink callbacks must be protected
785 * against an unconnected sink input! */
786 pa_sink_input_unlink(u
->sink_input
);
787 pa_sink_unlink(u
->sink
);
789 pa_sink_input_unref(u
->sink_input
);
790 u
->sink_input
= NULL
;
792 pa_sink_unref(u
->sink
);
795 pa_module_unload_request(u
->module
, TRUE
);
798 /* Called from IO thread context */
799 static void sink_input_state_change_cb(pa_sink_input
*i
, pa_sink_input_state_t state
) {
802 pa_sink_input_assert_ref(i
);
803 pa_assert_se(u
= i
->userdata
);
805 /* If we are added for the first time, ask for a rewinding so that
806 * we are heard right-away. */
807 if (PA_SINK_INPUT_IS_LINKED(state
) &&
808 i
->thread_info
.state
== PA_SINK_INPUT_INIT
) {
809 pa_log_debug("Requesting rewind due to state change.");
810 pa_sink_input_request_rewind(i
, 0, FALSE
, TRUE
, TRUE
);
814 static void pack(char **strs
, size_t len
, char **packed
, size_t *length
){
816 size_t headers
= (1+len
) * sizeof(uint16_t);
817 size_t offset
= sizeof(uint16_t);
818 for(size_t i
= 0; i
< len
; ++i
){
819 t_len
+= strlen(strs
[i
]);
821 *length
= headers
+ t_len
;
822 *packed
= pa_xmalloc0(*length
);
823 ((uint16_t *) *packed
)[0] = (uint16_t) len
;
824 for(size_t i
= 0; i
< len
; ++i
){
825 uint16_t l
= strlen(strs
[i
]);
826 *((uint16_t *)(*packed
+ offset
)) = l
;
827 offset
+= sizeof(uint16_t);
828 memcpy(*packed
+ offset
, strs
[i
], l
);
832 static void unpack(char *str
, size_t length
, char ***strs
, size_t *len
){
833 size_t offset
= sizeof(uint16_t);
834 *len
= ((uint16_t *)str
)[0];
835 *strs
= pa_xnew(char *, *len
);
836 for(size_t i
= 0; i
< *len
; ++i
){
837 size_t l
= *((uint16_t *)(str
+offset
));
838 size_t e
= PA_MIN(offset
+ l
, length
) - offset
;
839 offset
= PA_MIN(offset
+ sizeof(uint16_t), length
);
840 (*strs
)[i
] = pa_xnew(char, e
+ 1);
841 memcpy((*strs
)[i
], str
+ offset
, e
);
842 (*strs
)[i
][e
] = '\0';
846 static void save_profile(struct userdata
*u
, size_t channel
, char *name
){
848 const size_t profile_size
= CHANNEL_PROFILE_SIZE
* sizeof(float);
849 float *H_n
, *profile
;
852 profile
= pa_xnew0(float, profile_size
);
853 a_i
= pa_aupdate_read_begin(u
->a_H
[channel
]);
854 profile
[0] = u
->Xs
[a_i
][channel
];
855 H
= u
->Hs
[channel
][a_i
];
857 for(size_t i
= 0 ; i
<= FILTER_SIZE
; ++i
){
858 H_n
[i
] = H
[i
] * u
->fft_size
;
861 pa_aupdate_read_end(u
->a_H
[channel
]);
863 key
.size
= strlen(key
.data
);
865 data
.size
= profile_size
;
866 pa_database_set(u
->database
, &key
, &data
, TRUE
);
867 pa_database_sync(u
->database
);
868 if(u
->base_profiles
[channel
]){
869 pa_xfree(u
->base_profiles
[channel
]);
871 u
->base_profiles
[channel
] = pa_xstrdup(name
);
874 static void save_state(struct userdata
*u
){
876 const size_t filter_state_size
= FILTER_STATE_SIZE
* sizeof(float);
880 pa_database
*database
;
882 char *state_name
= u
->name
;
884 size_t packed_length
;
886 pack(u
->base_profiles
, u
->channels
, &packed
, &packed_length
);
887 state
= (float *) pa_xmalloc0(filter_state_size
+ packed_length
);
889 for(size_t c
= 0; c
< u
->channels
; ++c
){
890 a_i
= pa_aupdate_read_begin(u
->a_H
[c
]);
891 state
[c
* CHANNEL_PROFILE_SIZE
] = u
->Xs
[a_i
][c
];
893 H_n
= state
+ c
* CHANNEL_PROFILE_SIZE
+ 1;
894 memcpy(H_n
, H
, FILTER_SIZE
* sizeof(float));
895 pa_aupdate_read_end(u
->a_H
[c
]);
897 memcpy(((char *)state
) + filter_state_size
, packed
, packed_length
);
900 key
.data
= state_name
;
901 key
.size
= strlen(key
.data
);
903 data
.size
= filter_state_size
+ packed_length
;
904 //thread safety for 0.9.17?
905 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
906 pa_assert_se(database
= pa_database_open(dbname
, TRUE
));
909 pa_database_set(database
, &key
, &data
, TRUE
);
910 pa_database_sync(database
);
911 pa_database_close(database
);
915 static void remove_profile(pa_core
*c
, char *name
){
917 pa_database
*database
;
919 key
.size
= strlen(key
.data
);
920 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
921 pa_database_unset(database
, &key
);
922 pa_database_sync(database
);
925 static const char* load_profile(struct userdata
*u
, size_t channel
, char *name
){
928 const size_t profile_size
= CHANNEL_PROFILE_SIZE
* sizeof(float);
930 key
.size
= strlen(key
.data
);
931 if(pa_database_get(u
->database
, &key
, &value
) != NULL
){
932 if(value
.size
== profile_size
){
933 float *profile
= (float *) value
.data
;
934 a_i
= pa_aupdate_write_begin(u
->a_H
[channel
]);
935 u
->Xs
[channel
][a_i
] = profile
[0];
936 memcpy(u
->Hs
[channel
][a_i
], profile
+ 1, FILTER_SIZE
* sizeof(float));
937 fix_filter(u
->Hs
[channel
][a_i
], u
->fft_size
);
938 pa_aupdate_write_end(u
->a_H
[channel
]);
939 pa_xfree(u
->base_profiles
[channel
]);
940 u
->base_profiles
[channel
] = pa_xstrdup(name
);
942 return "incompatible size";
944 pa_datum_free(&value
);
946 return "profile doesn't exist";
951 static void load_state(struct userdata
*u
){
955 pa_database
*database
;
957 char *state_name
= u
->name
;
958 pa_assert_se(dbname
= pa_state_path(EQ_STATE_DB
, FALSE
));
959 database
= pa_database_open(dbname
, FALSE
);
962 pa_log("No resume state");
966 key
.data
= state_name
;
967 key
.size
= strlen(key
.data
);
969 if(pa_database_get(database
, &key
, &value
) != NULL
){
970 if(value
.size
> FILTER_STATE_SIZE
* sizeof(float) + sizeof(uint16_t)){
971 float *state
= (float *) value
.data
;
974 for(size_t c
= 0; c
< u
->channels
; ++c
){
975 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
976 H
= state
+ c
* CHANNEL_PROFILE_SIZE
+ 1;
977 u
->Xs
[c
][a_i
] = state
[c
* CHANNEL_PROFILE_SIZE
];
978 memcpy(u
->Hs
[c
][a_i
], H
, FILTER_SIZE
* sizeof(float));
979 pa_aupdate_write_end(u
->a_H
[c
]);
981 unpack(((char *)value
.data
) + FILTER_STATE_SIZE
, value
.size
- FILTER_STATE_SIZE
, &names
, &n_profs
);
982 n_profs
= PA_MIN(n_profs
, u
->channels
);
983 for(size_t c
= 0; c
< n_profs
; ++c
){
984 pa_xfree(u
->base_profiles
[c
]);
985 u
->base_profiles
[c
] = names
[c
];
989 pa_datum_free(&value
);
991 pa_log("resume state exists but is wrong size!");
993 pa_database_close(database
);
996 /* Called from main context */
997 static pa_bool_t
sink_input_may_move_to_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1000 pa_sink_input_assert_ref(i
);
1001 pa_assert_se(u
= i
->userdata
);
1003 return u
->sink
!= dest
;
1006 /* Called from main context */
1007 static void sink_input_moving_cb(pa_sink_input
*i
, pa_sink
*dest
) {
1010 pa_sink_input_assert_ref(i
);
1011 pa_assert_se(u
= i
->userdata
);
1013 pa_sink_set_asyncmsgq(u
->sink
, dest
->asyncmsgq
);
1014 pa_sink_update_flags(u
->sink
, PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
, dest
->flags
);
1016 pa_sink_set_asyncmsgq(u
->sink
, NULL
);
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)));//probably unstable near corner cases of powers of 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
->input_buffer_max
= 0;
1072 u
->a_H
= pa_xnew0(pa_aupdate
*, u
->channels
);
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();
1090 u
->overlap_accum
[c
] = alloc(u
->overlap_size
, sizeof(float));
1091 memset(u
->overlap_accum
[c
], 0, u
->overlap_size
*sizeof(float));
1093 u
->output_window
= alloc((FILTER_SIZE
), sizeof(fftwf_complex
));
1094 u
->forward_plan
= fftwf_plan_dft_r2c_1d(u
->fft_size
, u
->work_buffer
, u
->output_window
, FFTW_ESTIMATE
);
1095 u
->inverse_plan
= fftwf_plan_dft_c2r_1d(u
->fft_size
, u
->output_window
, u
->work_buffer
, FFTW_ESTIMATE
);
1097 hanning_window(u
->W
, u
->window_size
);
1098 u
->first_iteration
= TRUE
;
1100 u
->base_profiles
= pa_xnew0(char *, u
->channels
);
1101 for(size_t c
= 0; c
< u
->channels
; ++c
){
1102 u
->base_profiles
[c
] = pa_xstrdup("default");
1106 pa_sink_new_data_init(&sink_data
);
1107 sink_data
.driver
= __FILE__
;
1108 sink_data
.module
= m
;
1109 if (!(sink_data
.name
= pa_xstrdup(pa_modargs_get_value(ma
, "sink_name", NULL
))))
1110 sink_data
.name
= pa_sprintf_malloc("%s.equalizer", master
->name
);
1111 pa_sink_new_data_set_sample_spec(&sink_data
, &ss
);
1112 pa_sink_new_data_set_channel_map(&sink_data
, &map
);
1113 z
= pa_proplist_gets(master
->proplist
, PA_PROP_DEVICE_DESCRIPTION
);
1114 pa_proplist_setf(sink_data
.proplist
, PA_PROP_DEVICE_DESCRIPTION
, "FFT based equalizer on %s",z
? z
: master
->name
);
1115 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_MASTER_DEVICE
, master
->name
);
1116 pa_proplist_sets(sink_data
.proplist
, PA_PROP_DEVICE_CLASS
, "filter");
1118 if (pa_modargs_get_proplist(ma
, "sink_properties", sink_data
.proplist
, PA_UPDATE_REPLACE
) < 0) {
1119 pa_log("Invalid properties");
1120 pa_sink_new_data_done(&sink_data
);
1124 u
->sink
= pa_sink_new(m
->core
, &sink_data
,
1125 PA_SINK_HW_MUTE_CTRL
|PA_SINK_HW_VOLUME_CTRL
|PA_SINK_DECIBEL_VOLUME
|
1126 (master
->flags
& (PA_SINK_LATENCY
|PA_SINK_DYNAMIC_LATENCY
)));
1127 pa_sink_new_data_done(&sink_data
);
1130 pa_log("Failed to create sink.");
1133 u
->name
=pa_xstrdup(u
->sink
->name
);
1134 u
->sink
->parent
.process_msg
= sink_process_msg_cb
;
1135 u
->sink
->set_state
= sink_set_state_cb
;
1136 u
->sink
->update_requested_latency
= sink_update_requested_latency_cb
;
1137 u
->sink
->request_rewind
= sink_request_rewind_cb
;
1138 u
->sink
->set_volume
= sink_set_volume_cb
;
1139 u
->sink
->set_mute
= sink_set_mute_cb
;
1140 u
->sink
->userdata
= u
;
1141 u
->input_q
= pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH
, 0, fs
, 1, 1, 0, &u
->sink
->silence
);
1143 pa_sink_set_asyncmsgq(u
->sink
, master
->asyncmsgq
);
1144 //pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(u->R*fs, &ss));
1146 /* Create sink input */
1147 pa_sink_input_new_data_init(&sink_input_data
);
1148 sink_input_data
.driver
= __FILE__
;
1149 sink_input_data
.module
= m
;
1150 sink_input_data
.sink
= master
;
1151 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_NAME
, "Equalized Stream");
1152 pa_proplist_sets(sink_input_data
.proplist
, PA_PROP_MEDIA_ROLE
, "filter");
1153 pa_sink_input_new_data_set_sample_spec(&sink_input_data
, &ss
);
1154 pa_sink_input_new_data_set_channel_map(&sink_input_data
, &map
);
1156 pa_sink_input_new(&u
->sink_input
, m
->core
, &sink_input_data
);
1157 pa_sink_input_new_data_done(&sink_input_data
);
1162 u
->sink_input
->pop
= sink_input_pop_cb
;
1163 u
->sink_input
->process_rewind
= sink_input_process_rewind_cb
;
1164 u
->sink_input
->update_max_rewind
= sink_input_update_max_rewind_cb
;
1165 u
->sink_input
->update_max_request
= sink_input_update_max_request_cb
;
1166 u
->sink_input
->update_sink_latency_range
= sink_input_update_sink_latency_range_cb
;
1167 u
->sink_input
->update_sink_fixed_latency
= sink_input_update_sink_fixed_latency_cb
;
1168 u
->sink_input
->kill
= sink_input_kill_cb
;
1169 u
->sink_input
->attach
= sink_input_attach_cb
;
1170 u
->sink_input
->detach
= sink_input_detach_cb
;
1171 u
->sink_input
->state_change
= sink_input_state_change_cb
;
1172 u
->sink_input
->may_move_to
= sink_input_may_move_to_cb
;
1173 u
->sink_input
->moving
= sink_input_moving_cb
;
1174 u
->sink_input
->volume_changed
= sink_input_volume_changed_cb
;
1175 u
->sink_input
->mute_changed
= sink_input_mute_changed_cb
;
1177 u
->sink_input
->userdata
= u
;
1179 pa_sink_put(u
->sink
);
1180 pa_sink_input_put(u
->sink_input
);
1182 pa_modargs_free(ma
);
1187 //default filter to these
1188 for(size_t c
= 0; c
< u
->channels
; ++c
){
1189 a_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1191 u
->Xs
[c
][a_i
] = 1.0f
;
1192 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1193 H
[i
] = 1.0 / sqrtf(2.0f
);
1195 fix_filter(H
, u
->fft_size
);
1196 pa_aupdate_write_end(u
->a_H
[c
]);
1198 //load old parameters
1205 pa_modargs_free(ma
);
1213 int pa__get_n_used(pa_module
*m
) {
1217 pa_assert_se(u
= m
->userdata
);
1219 return pa_sink_linked_by(u
->sink
);
1222 void pa__done(pa_module
*m
) {
1227 if (!(u
= m
->userdata
))
1234 for(size_t c
= 0; c
< u
->channels
; ++c
){
1235 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_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1309 static void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
);
1310 enum manager_method_index
{
1311 MANAGER_METHOD_REMOVE_PROFILE
,
1315 pa_dbus_arg_info remove_profile_args
[]={
1319 static pa_dbus_method_handler manager_methods
[MANAGER_METHOD_MAX
]={
1320 [MANAGER_METHOD_REMOVE_PROFILE
]{
1321 .method_name
="RemoveProfile",
1322 .arguments
=remove_profile_args
,
1323 .n_arguments
=sizeof(remove_profile_args
)/sizeof(pa_dbus_arg_info
),
1324 .receive_cb
=manager_handle_remove_profile
}
1327 enum manager_handler_index
{
1328 MANAGER_HANDLER_REVISION
,
1329 MANAGER_HANDLER_EQUALIZED_SINKS
,
1330 MANAGER_HANDLER_PROFILES
,
1334 static pa_dbus_property_handler manager_handlers
[MANAGER_HANDLER_MAX
]={
1335 [MANAGER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=manager_get_revision
,.set_cb
=NULL
},
1336 [MANAGER_HANDLER_EQUALIZED_SINKS
]={.property_name
="EqualizedSinks",.type
="ao",.get_cb
=manager_get_sinks
,.set_cb
=NULL
},
1337 [MANAGER_HANDLER_PROFILES
]={.property_name
="Profiles",.type
="as",.get_cb
=manager_get_profiles
,.set_cb
=NULL
}
1340 pa_dbus_arg_info sink_args
[]={
1344 enum manager_signal_index
{
1345 MANAGER_SIGNAL_SINK_ADDED
,
1346 MANAGER_SIGNAL_SINK_REMOVED
,
1347 MANAGER_SIGNAL_PROFILES_CHANGED
,
1351 static pa_dbus_signal_info manager_signals
[MANAGER_SIGNAL_MAX
]={
1352 [MANAGER_SIGNAL_SINK_ADDED
]={.name
="SinkAdded", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1353 [MANAGER_SIGNAL_SINK_REMOVED
]={.name
="SinkRemoved", .arguments
=sink_args
, .n_arguments
=sizeof(sink_args
)/sizeof(pa_dbus_arg_info
)},
1354 [MANAGER_SIGNAL_PROFILES_CHANGED
]={.name
="ProfilesChanged", .arguments
=NULL
, .n_arguments
=0}
1357 static pa_dbus_interface_info manager_info
={
1358 .name
=MANAGER_IFACE
,
1359 .method_handlers
=manager_methods
,
1360 .n_method_handlers
=MANAGER_METHOD_MAX
,
1361 .property_handlers
=manager_handlers
,
1362 .n_property_handlers
=MANAGER_HANDLER_MAX
,
1363 .get_all_properties_cb
=manager_get_all
,
1364 .signals
=manager_signals
,
1365 .n_signals
=MANAGER_SIGNAL_MAX
1368 enum equalizer_method_index
{
1369 EQUALIZER_METHOD_FILTER_POINTS
,
1370 EQUALIZER_METHOD_SEED_FILTER
,
1371 EQUALIZER_METHOD_SAVE_PROFILE
,
1372 EQUALIZER_METHOD_LOAD_PROFILE
,
1373 EQUALIZER_METHOD_SET_FILTER
,
1374 EQUALIZER_METHOD_GET_FILTER
,
1375 EQUALIZER_METHOD_SAVE_STATE
,
1376 EQUALIZER_METHOD_GET_PROFILE_NAME
,
1377 EQUALIZER_METHOD_MAX
1380 enum equalizer_handler_index
{
1381 EQUALIZER_HANDLER_REVISION
,
1382 EQUALIZER_HANDLER_SAMPLERATE
,
1383 EQUALIZER_HANDLER_FILTERSAMPLERATE
,
1384 EQUALIZER_HANDLER_N_COEFS
,
1385 EQUALIZER_HANDLER_N_CHANNELS
,
1386 EQUALIZER_HANDLER_MAX
1389 pa_dbus_arg_info filter_points_args
[]={
1390 {"channel", "u","in"},
1393 {"preamp", "d","out"}
1395 pa_dbus_arg_info seed_filter_args
[]={
1396 {"channel", "u","in"},
1399 {"preamp", "d","in"}
1402 pa_dbus_arg_info set_filter_args
[]={
1403 {"channel", "u","in"},
1405 {"preamp", "d","in"}
1407 pa_dbus_arg_info get_filter_args
[]={
1408 {"channel", "u","in"},
1410 {"preamp", "d","out"}
1413 pa_dbus_arg_info save_profile_args
[]={
1414 {"channel", "u","in"},
1417 pa_dbus_arg_info load_profile_args
[]={
1418 {"channel", "u","in"},
1421 pa_dbus_arg_info base_profile_name_args
[]={
1422 {"channel", "u","in"},
1426 static pa_dbus_method_handler equalizer_methods
[EQUALIZER_METHOD_MAX
]={
1427 [EQUALIZER_METHOD_SEED_FILTER
]{
1428 .method_name
="SeedFilter",
1429 .arguments
=seed_filter_args
,
1430 .n_arguments
=sizeof(seed_filter_args
)/sizeof(pa_dbus_arg_info
),
1431 .receive_cb
=equalizer_handle_seed_filter
},
1432 [EQUALIZER_METHOD_FILTER_POINTS
]{
1433 .method_name
="FilterAtPoints",
1434 .arguments
=filter_points_args
,
1435 .n_arguments
=sizeof(filter_points_args
)/sizeof(pa_dbus_arg_info
),
1436 .receive_cb
=equalizer_handle_get_filter_points
},
1437 [EQUALIZER_METHOD_SET_FILTER
]{
1438 .method_name
="SetFilter",
1439 .arguments
=set_filter_args
,
1440 .n_arguments
=sizeof(set_filter_args
)/sizeof(pa_dbus_arg_info
),
1441 .receive_cb
=equalizer_handle_set_filter
},
1442 [EQUALIZER_METHOD_GET_FILTER
]{
1443 .method_name
="GetFilter",
1444 .arguments
=get_filter_args
,
1445 .n_arguments
=sizeof(get_filter_args
)/sizeof(pa_dbus_arg_info
),
1446 .receive_cb
=equalizer_handle_get_filter
},
1447 [EQUALIZER_METHOD_SAVE_PROFILE
]{
1448 .method_name
="SaveProfile",
1449 .arguments
=save_profile_args
,
1450 .n_arguments
=sizeof(save_profile_args
)/sizeof(pa_dbus_arg_info
),
1451 .receive_cb
=equalizer_handle_save_profile
},
1452 [EQUALIZER_METHOD_LOAD_PROFILE
]{
1453 .method_name
="LoadProfile",
1454 .arguments
=load_profile_args
,
1455 .n_arguments
=sizeof(load_profile_args
)/sizeof(pa_dbus_arg_info
),
1456 .receive_cb
=equalizer_handle_load_profile
},
1457 [EQUALIZER_METHOD_SAVE_STATE
]{
1458 .method_name
="SaveState",
1461 .receive_cb
=equalizer_handle_save_state
},
1462 [EQUALIZER_METHOD_GET_PROFILE_NAME
]{
1463 .method_name
="BaseProfile",
1464 .arguments
=base_profile_name_args
,
1465 .n_arguments
=sizeof(base_profile_name_args
)/sizeof(pa_dbus_arg_info
),
1466 .receive_cb
=equalizer_handle_get_profile_name
}
1469 static pa_dbus_property_handler equalizer_handlers
[EQUALIZER_HANDLER_MAX
]={
1470 [EQUALIZER_HANDLER_REVISION
]={.property_name
="InterfaceRevision",.type
="u",.get_cb
=equalizer_get_revision
,.set_cb
=NULL
},
1471 [EQUALIZER_HANDLER_SAMPLERATE
]{.property_name
="SampleRate",.type
="u",.get_cb
=equalizer_get_sample_rate
,.set_cb
=NULL
},
1472 [EQUALIZER_HANDLER_FILTERSAMPLERATE
]{.property_name
="FilterSampleRate",.type
="u",.get_cb
=equalizer_get_filter_rate
,.set_cb
=NULL
},
1473 [EQUALIZER_HANDLER_N_COEFS
]{.property_name
="NFilterCoefficients",.type
="u",.get_cb
=equalizer_get_n_coefs
,.set_cb
=NULL
},
1474 [EQUALIZER_HANDLER_N_CHANNELS
]{.property_name
="NChannels",.type
="u",.get_cb
=equalizer_get_n_channels
,.set_cb
=NULL
},
1477 enum equalizer_signal_index
{
1478 EQUALIZER_SIGNAL_FILTER_CHANGED
,
1479 EQUALIZER_SIGNAL_SINK_RECONFIGURED
,
1480 EQUALIZER_SIGNAL_MAX
1483 static pa_dbus_signal_info equalizer_signals
[EQUALIZER_SIGNAL_MAX
]={
1484 [EQUALIZER_SIGNAL_FILTER_CHANGED
]={.name
="FilterChanged", .arguments
=NULL
, .n_arguments
=0},
1485 [EQUALIZER_SIGNAL_SINK_RECONFIGURED
]={.name
="SinkReconfigured", .arguments
=NULL
, .n_arguments
=0},
1488 static pa_dbus_interface_info equalizer_info
={
1489 .name
=EQUALIZER_IFACE
,
1490 .method_handlers
=equalizer_methods
,
1491 .n_method_handlers
=EQUALIZER_METHOD_MAX
,
1492 .property_handlers
=equalizer_handlers
,
1493 .n_property_handlers
=EQUALIZER_HANDLER_MAX
,
1494 .get_all_properties_cb
=equalizer_get_all
,
1495 .signals
=equalizer_signals
,
1496 .n_signals
=EQUALIZER_SIGNAL_MAX
1499 void dbus_init(struct userdata
*u
){
1501 DBusMessage
*signal
= NULL
;
1502 pa_idxset
*sink_list
= NULL
;
1503 u
->dbus_protocol
=pa_dbus_protocol_get(u
->sink
->core
);
1504 u
->dbus_path
=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u
->sink
->index
);
1506 pa_dbus_protocol_add_interface(u
->dbus_protocol
, u
->dbus_path
, &equalizer_info
, u
);
1507 sink_list
= pa_shared_get(u
->sink
->core
, SINKLIST
);
1508 u
->database
= pa_shared_get(u
->sink
->core
, EQDB
);
1509 if(sink_list
== NULL
){
1511 sink_list
=pa_idxset_new(&pa_idxset_trivial_hash_func
, &pa_idxset_trivial_compare_func
);
1512 pa_shared_set(u
->sink
->core
, SINKLIST
, sink_list
);
1513 pa_assert_se(dbname
= pa_state_path("equalizer-presets", FALSE
));
1514 pa_assert_se(u
->database
= pa_database_open(dbname
, TRUE
));
1516 pa_shared_set(u
->sink
->core
, EQDB
, u
->database
);
1517 pa_dbus_protocol_add_interface(u
->dbus_protocol
, MANAGER_PATH
, &manager_info
, u
->sink
->core
);
1518 pa_dbus_protocol_register_extension(u
->dbus_protocol
, EXTNAME
);
1520 pa_idxset_put(sink_list
, u
, &dummy
);
1522 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_ADDED
].name
)));
1523 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1524 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1525 dbus_message_unref(signal
);
1528 void dbus_done(struct userdata
*u
){
1529 pa_idxset
*sink_list
;
1532 DBusMessage
*signal
= NULL
;
1533 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_SINK_REMOVED
].name
)));
1534 dbus_message_append_args(signal
, DBUS_TYPE_OBJECT_PATH
, &u
->dbus_path
, DBUS_TYPE_INVALID
);
1535 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1536 dbus_message_unref(signal
);
1538 pa_assert_se(sink_list
=pa_shared_get(u
->sink
->core
,SINKLIST
));
1539 pa_idxset_remove_by_data(sink_list
,u
,&dummy
);
1540 if(pa_idxset_size(sink_list
)==0){
1541 pa_dbus_protocol_unregister_extension(u
->dbus_protocol
, EXTNAME
);
1542 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, MANAGER_PATH
, manager_info
.name
);
1543 pa_shared_remove(u
->sink
->core
, EQDB
);
1544 pa_database_close(u
->database
);
1545 pa_shared_remove(u
->sink
->core
, SINKLIST
);
1546 pa_xfree(sink_list
);
1548 pa_dbus_protocol_remove_interface(u
->dbus_protocol
, u
->dbus_path
, equalizer_info
.name
);
1549 pa_xfree(u
->dbus_path
);
1550 pa_dbus_protocol_unref(u
->dbus_protocol
);
1553 void manager_handle_remove_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1555 pa_core
*c
= (pa_core
*)_u
;
1556 DBusMessage
*signal
= NULL
;
1557 pa_dbus_protocol
*dbus_protocol
;
1562 dbus_error_init(&error
);
1563 if(!dbus_message_get_args(msg
, &error
,
1564 DBUS_TYPE_STRING
, &name
,
1565 DBUS_TYPE_INVALID
)){
1566 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1567 dbus_error_free(&error
);
1570 remove_profile(c
,name
);
1571 pa_dbus_send_empty_reply(conn
, msg
);
1573 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1574 dbus_protocol
= pa_dbus_protocol_get(c
);
1575 pa_dbus_protocol_send_signal(dbus_protocol
, signal
);
1576 pa_dbus_protocol_unref(dbus_protocol
);
1577 dbus_message_unref(signal
);
1580 void manager_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1582 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
1585 static void get_sinks(pa_core
*u
, char ***names
, unsigned *n_sinks
){
1587 struct userdata
*sink_u
= NULL
;
1589 pa_idxset
*sink_list
;
1594 pa_assert_se(sink_list
= pa_shared_get(u
, SINKLIST
));
1595 *n_sinks
= (unsigned) pa_idxset_size(sink_list
);
1596 *names
= *n_sinks
> 0 ? pa_xnew0(char *,*n_sinks
) : NULL
;
1597 for(uint32_t i
= 0; i
< *n_sinks
; ++i
){
1598 sink_u
= (struct userdata
*) pa_idxset_iterate(sink_list
, &iter
, &dummy
);
1599 (*names
)[i
] = pa_xstrdup(sink_u
->dbus_path
);
1603 void manager_get_sinks(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1605 char **names
= NULL
;
1610 get_sinks((pa_core
*) _u
, &names
, &n
);
1611 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1612 for(unsigned i
= 0; i
< n
; ++i
){
1618 static void get_profiles(pa_core
*c
, char ***names
, unsigned *n
){
1620 pa_database
*database
;
1621 pa_datum key
, next_key
;
1622 pa_strlist
*head
=NULL
, *iter
;
1624 pa_assert_se(database
= pa_shared_get(c
, EQDB
));
1629 done
= !pa_database_first(database
, &key
, NULL
);
1632 done
= !pa_database_next(database
, &key
, &next_key
, NULL
);
1633 name
=pa_xmalloc(key
.size
+ 1);
1634 memcpy(name
, key
.data
, key
.size
);
1635 name
[key
.size
] = '\0';
1636 pa_datum_free(&key
);
1637 head
= pa_strlist_prepend(head
, name
);
1642 (*names
) = *n
> 0 ? pa_xnew0(char *, *n
) : NULL
;
1644 for(unsigned i
= 0; i
< *n
; ++i
){
1645 (*names
)[*n
- 1 - i
] = pa_xstrdup(pa_strlist_data(iter
));
1646 iter
= pa_strlist_next(iter
);
1648 pa_strlist_free(head
);
1651 void manager_get_profiles(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1658 get_profiles((pa_core
*)_u
, &names
, &n
);
1659 pa_dbus_send_basic_array_variant_reply(conn
, msg
, DBUS_TYPE_STRING
, names
, n
);
1660 for(unsigned i
= 0; i
< n
; ++i
){
1666 void manager_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1668 char **names
= NULL
;
1670 DBusMessage
*reply
= NULL
;
1671 DBusMessageIter msg_iter
, dict_iter
;
1675 pa_assert_se(c
= _u
);
1677 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1678 dbus_message_iter_init_append(reply
, &msg_iter
);
1679 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
1682 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
1684 get_sinks(c
, &names
, &n
);
1685 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
,manager_handlers
[MANAGER_HANDLER_EQUALIZED_SINKS
].property_name
, DBUS_TYPE_OBJECT_PATH
, names
, n
);
1686 for(unsigned i
= 0; i
< n
; ++i
){
1691 get_profiles(c
, &names
, &n
);
1692 pa_dbus_append_basic_array_variant_dict_entry(&dict_iter
, manager_handlers
[MANAGER_HANDLER_PROFILES
].property_name
, DBUS_TYPE_STRING
, names
, n
);
1693 for(unsigned i
= 0; i
< n
; ++i
){
1697 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
1698 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1699 dbus_message_unref(reply
);
1702 void equalizer_handle_seed_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1703 struct userdata
*u
=(struct userdata
*) _u
;
1705 DBusMessage
*signal
= NULL
;
1707 uint32_t *xs
, channel
, r_channel
;
1708 double *_ys
, preamp
;
1709 unsigned x_npoints
, y_npoints
, a_i
;
1711 pa_bool_t points_good
= TRUE
;
1716 dbus_error_init(&error
);
1718 if(!dbus_message_get_args(msg
, &error
,
1719 DBUS_TYPE_UINT32
, &channel
,
1720 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1721 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &_ys
, &y_npoints
,
1722 DBUS_TYPE_DOUBLE
, &preamp
,
1723 DBUS_TYPE_INVALID
)){
1724 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1725 dbus_error_free(&error
);
1728 if(channel
> u
->channels
){
1729 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1730 dbus_error_free(&error
);
1733 for(size_t i
= 0; i
< x_npoints
; ++i
){
1734 if(xs
[i
] >= FILTER_SIZE
){
1735 points_good
= FALSE
;
1739 if(!is_monotonic(xs
, x_npoints
) || !points_good
){
1740 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs must be monotonic and 0<=x<=%ld", u
->fft_size
/ 2);
1741 dbus_error_free(&error
);
1743 }else if(x_npoints
!= y_npoints
|| x_npoints
< 2 || x_npoints
> FILTER_SIZE
){
1744 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs and ys must be the same length and 2<=l<=%ld!", FILTER_SIZE
);
1745 dbus_error_free(&error
);
1747 }else if(xs
[0] != 0 || xs
[x_npoints
- 1] != u
->fft_size
/ 2){
1748 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs[0] must be 0 and xs[-1]=fft_size/2");
1749 dbus_error_free(&error
);
1753 ys
= pa_xmalloc(x_npoints
* sizeof(float));
1754 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1755 ys
[i
] = (float) _ys
[i
];
1757 r_channel
= channel
== u
->channels
? 0 : channel
;
1758 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1759 H
= u
->Hs
[r_channel
][a_i
];
1760 u
->Xs
[r_channel
][a_i
] = preamp
;
1761 interpolate(H
, FILTER_SIZE
, xs
, ys
, x_npoints
);
1762 fix_filter(H
, u
->fft_size
);
1763 if(channel
== u
->channels
){
1764 for(size_t c
= 1; c
< u
->channels
; ++c
){
1765 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1766 float *H_p
= u
->Hs
[c
][b_i
];
1767 u
->Xs
[c
][b_i
] = preamp
;
1768 memcpy(H_p
, H
, FILTER_SIZE
* sizeof(float));
1769 pa_aupdate_write_end(u
->a_H
[c
]);
1772 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1776 pa_dbus_send_empty_reply(conn
, msg
);
1778 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1779 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1780 dbus_message_unref(signal
);
1783 void equalizer_handle_get_filter_points(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1784 struct userdata
*u
= (struct userdata
*) _u
;
1785 uint32_t *xs
, channel
, r_channel
;
1787 unsigned x_npoints
, a_i
;
1789 pa_bool_t points_good
=TRUE
;
1790 DBusMessage
*reply
= NULL
;
1791 DBusMessageIter msg_iter
;
1798 dbus_error_init(&error
);
1799 if(!dbus_message_get_args(msg
, &error
,
1800 DBUS_TYPE_UINT32
, &channel
,
1801 DBUS_TYPE_ARRAY
, DBUS_TYPE_UINT32
, &xs
, &x_npoints
,
1802 DBUS_TYPE_INVALID
)){
1803 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1804 dbus_error_free(&error
);
1807 if(channel
> u
->channels
){
1808 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1809 dbus_error_free(&error
);
1813 for(size_t i
= 0; i
< x_npoints
; ++i
){
1814 if(xs
[i
] >= FILTER_SIZE
){
1820 if(x_npoints
> FILTER_SIZE
|| !points_good
){
1821 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "xs indices/length must be <= %ld!", FILTER_SIZE
);
1822 dbus_error_free(&error
);
1826 r_channel
= channel
== u
->channels
? 0 : channel
;
1827 ys
= pa_xmalloc(x_npoints
* sizeof(double));
1828 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1829 H
= u
->Hs
[r_channel
][a_i
];
1830 preamp
= u
->Xs
[r_channel
][a_i
];
1831 for(uint32_t i
= 0; i
< x_npoints
; ++i
){
1832 ys
[i
] = H
[xs
[i
]] * u
->fft_size
;
1834 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1836 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1837 dbus_message_iter_init_append(reply
, &msg_iter
);
1839 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, ys
, x_npoints
);
1840 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1842 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1843 dbus_message_unref(reply
);
1847 static void get_filter(struct userdata
*u
, size_t channel
, double **H_
, double *preamp
){
1850 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1851 *H_
= pa_xnew0(double, FILTER_SIZE
);
1852 a_i
= pa_aupdate_read_begin(u
->a_H
[r_channel
]);
1853 H
= u
->Hs
[r_channel
][a_i
];
1854 for(size_t i
= 0;i
< FILTER_SIZE
; ++i
){
1855 (*H_
)[i
] = H
[i
] * u
->fft_size
;
1857 *preamp
= u
->Xs
[r_channel
][a_i
];
1859 pa_aupdate_read_end(u
->a_H
[r_channel
]);
1862 void equalizer_handle_get_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1867 DBusMessage
*reply
= NULL
;
1868 DBusMessageIter msg_iter
;
1870 pa_assert_se(u
= (struct userdata
*) _u
);
1874 dbus_error_init(&error
);
1875 if(!dbus_message_get_args(msg
, &error
,
1876 DBUS_TYPE_UINT32
, &channel
,
1877 DBUS_TYPE_INVALID
)){
1878 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1879 dbus_error_free(&error
);
1882 if(channel
> u
->channels
){
1883 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1884 dbus_error_free(&error
);
1888 n_coefs
= CHANNEL_PROFILE_SIZE
;
1891 get_filter(u
, channel
, &H_
, &preamp
);
1892 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
1893 dbus_message_iter_init_append(reply
, &msg_iter
);
1895 pa_dbus_append_basic_array(&msg_iter
, DBUS_TYPE_DOUBLE
, H_
, n_coefs
);
1896 pa_dbus_append_basic_variant(&msg_iter
, DBUS_TYPE_DOUBLE
, &preamp
);
1898 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
1899 dbus_message_unref(reply
);
1903 static void set_filter(struct userdata
*u
, size_t channel
, double *H_
, double preamp
){
1905 size_t r_channel
= channel
== u
->channels
? 0 : channel
;
1908 a_i
= pa_aupdate_write_begin(u
->a_H
[r_channel
]);
1909 u
->Xs
[r_channel
][a_i
] = (float) preamp
;
1910 H
= u
->Hs
[r_channel
][a_i
];
1911 for(size_t i
= 0; i
< FILTER_SIZE
; ++i
){
1912 H
[i
] = (float) H_
[i
];
1914 fix_filter(H
, u
->fft_size
);
1915 if(channel
== u
->channels
){
1916 for(size_t c
= 1; c
< u
->channels
; ++c
){
1917 unsigned b_i
= pa_aupdate_write_begin(u
->a_H
[c
]);
1918 u
->Xs
[c
][b_i
] = u
->Xs
[r_channel
][a_i
];
1919 memcpy(u
->Hs
[c
][b_i
], u
->Hs
[r_channel
][a_i
], FILTER_SIZE
* sizeof(float));
1920 pa_aupdate_write_end(u
->a_H
[c
]);
1923 pa_aupdate_write_end(u
->a_H
[r_channel
]);
1926 void equalizer_handle_set_filter(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
1931 DBusMessage
*signal
= NULL
;
1933 pa_assert_se(u
= (struct userdata
*) _u
);
1937 dbus_error_init(&error
);
1938 if(!dbus_message_get_args(msg
, &error
,
1939 DBUS_TYPE_UINT32
, &channel
,
1940 DBUS_TYPE_ARRAY
, DBUS_TYPE_DOUBLE
, &H
, &_n_coefs
,
1941 DBUS_TYPE_DOUBLE
, &preamp
,
1942 DBUS_TYPE_INVALID
)){
1943 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1944 dbus_error_free(&error
);
1947 if(channel
> u
->channels
){
1948 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1949 dbus_error_free(&error
);
1952 if(_n_coefs
!= FILTER_SIZE
){
1953 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "This filter takes exactly %ld coefficients, you gave %d", FILTER_SIZE
, _n_coefs
);
1956 set_filter(u
, channel
, H
, preamp
);
1958 pa_dbus_send_empty_reply(conn
, msg
);
1960 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
1961 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1962 dbus_message_unref(signal
);
1965 void equalizer_handle_save_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1966 struct userdata
*u
= (struct userdata
*) _u
;
1968 uint32_t channel
, r_channel
;
1969 DBusMessage
*signal
= NULL
;
1974 dbus_error_init(&error
);
1976 if(!dbus_message_get_args(msg
, &error
,
1977 DBUS_TYPE_UINT32
, &channel
,
1978 DBUS_TYPE_STRING
, &name
,
1979 DBUS_TYPE_INVALID
)){
1980 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
1981 dbus_error_free(&error
);
1984 if(channel
> u
->channels
){
1985 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
1986 dbus_error_free(&error
);
1989 r_channel
= channel
== u
->channels
? 0 : channel
;
1990 save_profile(u
, r_channel
, name
);
1991 pa_dbus_send_empty_reply(conn
, msg
);
1993 pa_assert_se((signal
= dbus_message_new_signal(MANAGER_PATH
, MANAGER_IFACE
, manager_signals
[MANAGER_SIGNAL_PROFILES_CHANGED
].name
)));
1994 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
1995 dbus_message_unref(signal
);
1998 void equalizer_handle_load_profile(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
1999 struct userdata
*u
= (struct userdata
*) _u
;
2002 uint32_t channel
, r_channel
;
2003 const char *err_msg
= NULL
;
2004 DBusMessage
*signal
= NULL
;
2009 dbus_error_init(&error
);
2011 if(!dbus_message_get_args(msg
, &error
,
2012 DBUS_TYPE_UINT32
, &channel
,
2013 DBUS_TYPE_STRING
, &name
,
2014 DBUS_TYPE_INVALID
)){
2015 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2016 dbus_error_free(&error
);
2019 if(channel
> u
->channels
){
2020 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2021 dbus_error_free(&error
);
2024 r_channel
= channel
== u
->channels
? 0 : channel
;
2026 err_msg
= load_profile(u
, r_channel
, name
);
2027 if(err_msg
!= NULL
){
2028 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_FAILED
, "error loading profile %s: %s", name
, err_msg
);
2029 dbus_error_free(&error
);
2032 if(channel
== u
->channels
){
2033 for(uint32_t c
= 1; c
< u
->channels
; ++c
){
2034 load_profile(u
, c
, name
);
2037 pa_dbus_send_empty_reply(conn
, msg
);
2039 pa_assert_se((signal
= dbus_message_new_signal(u
->dbus_path
, EQUALIZER_IFACE
, equalizer_signals
[EQUALIZER_SIGNAL_FILTER_CHANGED
].name
)));
2040 pa_dbus_protocol_send_signal(u
->dbus_protocol
, signal
);
2041 dbus_message_unref(signal
);
2044 void equalizer_handle_save_state(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
) {
2045 struct userdata
*u
= (struct userdata
*) _u
;
2051 pa_dbus_send_empty_reply(conn
, msg
);
2054 void equalizer_handle_get_profile_name(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2055 struct userdata
*u
= (struct userdata
*) _u
;
2057 uint32_t channel
, r_channel
;
2062 dbus_error_init(&error
);
2064 if(!dbus_message_get_args(msg
, &error
,
2065 DBUS_TYPE_UINT32
, &channel
,
2066 DBUS_TYPE_INVALID
)){
2067 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "%s", error
.message
);
2068 dbus_error_free(&error
);
2071 if(channel
> u
->channels
){
2072 pa_dbus_send_error(conn
, msg
, DBUS_ERROR_INVALID_ARGS
, "invalid channel: %d", channel
);
2073 dbus_error_free(&error
);
2076 r_channel
= channel
== u
->channels
? 0 : channel
;
2077 pa_assert(u
->base_profiles
[r_channel
]);
2078 pa_dbus_send_basic_value_reply(conn
,msg
, DBUS_TYPE_STRING
, &u
->base_profiles
[r_channel
]);
2081 void equalizer_get_revision(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2083 pa_dbus_send_basic_value_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rev
);
2086 void equalizer_get_n_channels(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2089 pa_assert_se(u
= (struct userdata
*) _u
);
2093 channels
= (uint32_t) u
->channels
;
2094 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &channels
);
2097 void equalizer_get_n_coefs(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2100 pa_assert_se(u
= (struct userdata
*) _u
);
2104 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2105 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &n_coefs
);
2108 void equalizer_get_sample_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2111 pa_assert_se(u
= (struct userdata
*) _u
);
2115 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2116 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &rate
);
2119 void equalizer_get_filter_rate(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2122 pa_assert_se(u
= (struct userdata
*) _u
);
2126 fft_size
= (uint32_t) u
->fft_size
;
2127 pa_dbus_send_basic_variant_reply(conn
, msg
, DBUS_TYPE_UINT32
, &fft_size
);
2130 void equalizer_get_all(DBusConnection
*conn
, DBusMessage
*msg
, void *_u
){
2132 DBusMessage
*reply
= NULL
;
2133 DBusMessageIter msg_iter
, dict_iter
;
2134 uint32_t rev
, n_coefs
, rate
, fft_size
, channels
;
2135 pa_assert_se(u
= (struct userdata
*) _u
);
2139 n_coefs
= (uint32_t) CHANNEL_PROFILE_SIZE
;
2140 rate
= (uint32_t) u
->sink
->sample_spec
.rate
;
2141 fft_size
= (uint32_t) u
->fft_size
;
2142 channels
= (uint32_t) u
->channels
;
2144 pa_assert_se((reply
= dbus_message_new_method_return(msg
)));
2145 dbus_message_iter_init_append(reply
, &msg_iter
);
2146 pa_assert_se(dbus_message_iter_open_container(&msg_iter
, DBUS_TYPE_ARRAY
, "{sv}", &dict_iter
));
2148 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_REVISION
].property_name
, DBUS_TYPE_UINT32
, &rev
);
2149 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_SAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &rate
);
2150 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_FILTERSAMPLERATE
].property_name
, DBUS_TYPE_UINT32
, &fft_size
);
2151 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_COEFS
].property_name
, DBUS_TYPE_UINT32
, &n_coefs
);
2152 pa_dbus_append_basic_variant_dict_entry(&dict_iter
, equalizer_handlers
[EQUALIZER_HANDLER_N_CHANNELS
].property_name
, DBUS_TYPE_UINT32
, &channels
);
2154 pa_assert_se(dbus_message_iter_close_container(&msg_iter
, &dict_iter
));
2155 pa_assert_se(dbus_connection_send(conn
, reply
, NULL
));
2156 dbus_message_unref(reply
);