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