+
+enum property_handler_index {
+ PROPERTY_HANDLER_N_COEFS,
+ PROPERTY_HANDLER_COEFS,
+ PROPERTY_HANDLER_MAX
+};
+
+static pa_dbus_property_handler property_handlers[PROPERTY_HANDLER_MAX]={
+ [PROPERTY_HANDLER_N_COEFS]{.property_name="n_filter_coefficients",.type="u",.get_cb=get_n_coefs,.set_cb=NULL},
+ [PROPERTY_HANDLER_COEFS]{.property_name="filter_coefficients",.type="ai",.get_cb=get_filter,.set_cb=set_filter}
+};
+
+//static pa_dbus_arg_info new_equalizer_args[] = { { "path","o",NULL} };
+//static pa_dbus_signal_info signals[SIGNAL_MAX] = {
+// [SIGNAL_NEW_EQUALIZER]={.name="NewEqualizer",.arguments=new_equalizer_args,.n_arguments=1}
+//};
+
+#define EXTNAME "org.PulseAudio.Ext.Equalizing1"
+
+static pa_dbus_interface_info interface_info={
+ .name=EXTNAME ".Equalizer",
+ .method_handlers=NULL,
+ .n_method_handlers=0,
+ .property_handlers=property_handlers,
+ .n_property_handlers=PROPERTY_HANDLER_MAX,
+ .get_all_properties_cb=handle_get_all,
+ .signals=NULL,
+ .n_signals=0
+};
+
+
+void dbus_init(struct userdata *u){
+ u->dbus_protocol=pa_dbus_protocol_get(u->core);
+ u->dbus_path=pa_sprintf_malloc("/org/pulseaudio/core1/sink%d", u->sink->index);
+
+ pa_dbus_protocol_add_interface(u->dbus_protocol, u->dbus_path, &interface_info, u);
+ pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
+}
+
+void dbus_done(struct userdata *u){
+ pa_dbus_protocol_unregister_extension(u->dbus_protocol, EXTNAME);
+ pa_dbus_protocol_remove_interface(u->dbus_protocol, u->dbus_path, EXTNAME);
+
+ pa_xfree(u->dbus_path);
+ pa_dbus_protocol_unref(u->dbus_protocol);
+}
+
+void get_n_coefs(DBusConnection *conn, DBusMessage *msg, void *_u){
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(_u);
+
+ struct userdata *u=(struct userdata *)_u;
+
+ uint32_t n_coefs=(uint32_t)(u->fft_size / 2 + 1);
+ pa_dbus_send_basic_variant_reply(conn, msg, DBUS_TYPE_UINT32, &n_coefs);
+}
+
+void get_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(_u);
+
+ struct userdata *u=(struct userdata *)_u;
+
+ unsigned n_coefs=(unsigned)(u->fft_size / 2 + 1);
+ double *H_=(double *)pa_xmalloc0(n_coefs*sizeof(double));
+
+ unsigned H_i=pa_aupdate_read_begin(u->a_H);
+ float *H=u->Hs[H_i];
+ for(size_t i = 0;i < u->fft_size / 2 + 1; ++i){
+ H_[i]=H[i];
+ }
+ pa_aupdate_read_end(u->a_H);
+ pa_dbus_send_basic_array_variant_reply(conn, msg, DBUS_TYPE_DOUBLE, &H_, n_coefs);
+ pa_xfree(H_);
+}
+
+void set_filter(DBusConnection *conn, DBusMessage *msg, void *_u){
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(_u);
+
+ struct userdata *u=(struct userdata *)_u;
+ double *H_;
+ unsigned _n_coefs;
+ pa_dbus_get_fixed_array_set_property_arg(conn, msg, DBUS_TYPE_DOUBLE, &H_, &_n_coefs);
+ if(_n_coefs!=u->fft_size / 2 + 1){
+ pa_dbus_send_error(conn, msg, DBUS_ERROR_INVALID_ARGS, "This filter takes exactly %ld coefficients, you gave %d", u->fft_size / 2 + 1, _n_coefs);
+ return;
+ }
+ unsigned H_i = pa_aupdate_write_begin(u->a_H);
+ float *H = u->Hs[H_i];
+ for(size_t i = 0; i < u->fft_size / 2 + 1; ++i){
+ H[i] = (float)H_[i];
+ }
+ pa_aupdate_write_swap(u->a_H);
+ pa_aupdate_write_end(u->a_H);
+
+ pa_dbus_send_empty_reply(conn, msg);
+}
+
+void handle_get_all(DBusConnection *conn, DBusMessage *msg, void *_u){
+ pa_assert(conn);
+ pa_assert(msg);
+ pa_assert(_u);
+
+ struct userdata *u = (struct userdata *)_u;
+ DBusMessage *reply = NULL;
+ DBusMessageIter msg_iter, dict_iter;
+
+ int n_coefs=(unsigned)(u->fft_size / 2 + 1);
+ double *H_=(double *)pa_xmalloc0(n_coefs*sizeof(double));
+
+ unsigned H_i=pa_aupdate_read_begin(u->a_H);
+ float *H=u->Hs[H_i];
+ for(size_t i = 0; i < u->fft_size / 2 + 1; ++i){
+ H_[i] = H[i];
+ }
+ pa_aupdate_read_end(u->a_H);
+
+ pa_assert_se((reply = dbus_message_new_method_return(msg)));
+ dbus_message_iter_init_append(reply, &msg_iter);
+ pa_assert_se(dbus_message_iter_open_container(&msg_iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter));
+
+ pa_dbus_append_basic_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_N_COEFS].property_name, DBUS_TYPE_UINT32, &n_coefs);
+ pa_dbus_append_basic_array_variant_dict_entry(&dict_iter, property_handlers[PROPERTY_HANDLER_COEFS].property_name, DBUS_TYPE_DOUBLE, H_, n_coefs);
+
+ pa_assert_se(dbus_message_iter_close_container(&msg_iter, &dict_iter));
+ pa_assert_se(dbus_connection_send(conn, reply, NULL));
+ dbus_message_unref(reply);
+
+ pa_xfree(H_);
+}