From 3ff35e42210fbcf76312bb16455b93fa135ed7cd Mon Sep 17 00:00:00 2001 From: kotontrion Date: Sun, 29 Sep 2024 14:08:19 +0200 Subject: new lib: cava --- lib/cava/cava.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 lib/cava/cava.c (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c new file mode 100644 index 0000000..46931f3 --- /dev/null +++ b/lib/cava/cava.c @@ -0,0 +1,213 @@ +#include "astal-cava.h" +#include "cava/common.h" +#include "cava/config.h" +#include "glib-object.h" +#include "glib.h" + +#include +#include +#include + +struct _AstalCavaCava { + GObject parent_instance; + + gint bars; + gchar* config_path; + + GArray* values; +}; + +typedef struct { + struct cava_plan plan; + struct config_params cfg; + struct audio_data audio_data; + struct audio_raw audio_raw; + ptr input_src; + + GThread* input_thread; + guint timer_id; + +} AstalCavaCavaPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE(AstalCavaCava, astal_cava_cava, G_TYPE_OBJECT) + +typedef enum { + ASTAL_CAVA_CAVA_PROP_VALUES = 1, + ASTAL_CAVA_CAVA_PROP_BARS, + ASTAL_CAVA_CAVA_PROP_CONFIG_PATH, + ASTAL_CAVA_CAVA_N_PROPERTIES +} AstalCavaProperties; + +static GParamSpec* astal_cava_cava_properties[ASTAL_CAVA_CAVA_N_PROPERTIES] = { + NULL, +}; + +/** + * astal_cava_cava_get_values + * @self: the AstalCavaCava object + * + * Returns: (transfer none) (element-type gdouble): a list of values + * + */ +GArray* astal_cava_cava_get_values(AstalCavaCava* self) { return self->values; } + +static void astal_cava_cava_set_property(GObject* object, guint property_id, const GValue* value, + GParamSpec* pspec) { + AstalCavaCava* self = ASTAL_CAVA_CAVA(object); + + switch (property_id) { + case ASTAL_CAVA_CAVA_PROP_BARS: + self->bars = g_value_get_int(value); + break; + case ASTAL_CAVA_CAVA_PROP_CONFIG_PATH: + self->config_path = g_strdup(g_value_get_string(value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static void astal_cava_cava_get_property(GObject* object, guint property_id, GValue* value, + GParamSpec* pspec) { + AstalCavaCava* self = ASTAL_CAVA_CAVA(object); + + switch (property_id) { + case ASTAL_CAVA_CAVA_PROP_BARS: + g_value_set_int(value, self->bars); + break; + case ASTAL_CAVA_CAVA_PROP_VALUES: + g_value_set_pointer(value, self->values); + break; + case ASTAL_CAVA_CAVA_PROP_CONFIG_PATH: + g_value_set_string(value, self->config_path); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); + break; + } +} + +static gboolean exec_cava(AstalCavaCava* self) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + pthread_mutex_lock(&priv->audio_data.lock); + cava_execute(priv->audio_data.cava_in, priv->audio_data.samples_counter, + priv->audio_raw.cava_out, &priv->plan); + if (priv->audio_data.samples_counter > 0) priv->audio_data.samples_counter = 0; + pthread_mutex_unlock(&priv->audio_data.lock); + + g_array_remove_range(self->values, 0, priv->audio_raw.number_of_bars); + g_array_insert_vals(self->values, 0, priv->audio_raw.cava_out, priv->audio_raw.number_of_bars); + + g_object_notify(G_OBJECT(self), "values"); + + return G_SOURCE_CONTINUE; +} + +static void astal_cava_cava_constructed(GObject* object) { + AstalCavaCava* self = ASTAL_CAVA_CAVA(object); + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + struct error_s error = {}; + + if (!load_config(self->config_path, &priv->cfg, false, &error)) { + g_critical("Error loading config. %s", error.message); + return; + } + + priv->cfg.inAtty = 0; + priv->cfg.output = OUTPUT_RAW; + priv->cfg.raw_target = strdup("/dev/stdout"); + priv->cfg.data_format = strdup("binary"); + + if(self->bars > 0) priv->cfg.fixedbars = self->bars; + else self->bars = priv->cfg.fixedbars; + + priv->audio_data = (struct audio_data) { + .cava_in = calloc(BUFFER_SIZE * priv->cfg.channels * 8, sizeof(gdouble)), + .input_buffer_size = BUFFER_SIZE * priv->cfg.channels, + .cava_buffer_size = BUFFER_SIZE * priv->cfg.channels * 8, + .format = -1, + .rate = 0, + .channels = priv->cfg.channels, + .source = g_strdup(priv->cfg.audio_source), + .terminate = 0, + .samples_counter = 0, + .IEEE_FLOAT = 0, + .suspendFlag = false, + }; + + priv->input_src = get_input(&priv->audio_data, &priv->cfg); + + audio_raw_init(&priv->audio_data, &priv->audio_raw, &priv->cfg, &priv->plan); + + self->values = g_array_sized_new(TRUE, TRUE, sizeof(gdouble), priv->audio_raw.number_of_bars); + g_array_set_size(self->values, priv->audio_raw.number_of_bars); + + priv->input_thread = g_thread_new("cava_input", priv->input_src, &priv->audio_data); + + priv->timer_id = g_timeout_add(1000 / priv->cfg.framerate, G_SOURCE_FUNC(exec_cava), self); +} + +static void astal_cava_cava_init(AstalCavaCava* self) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); +} + +/** + * astal_cava_cava_get_default + * + * Returns: (nullable) (transfer none): gets the default Cava object. + */ +AstalCavaCava* astal_cava_cava_get_default() { + static AstalCavaCava* self = NULL; + + if (self == NULL) self = g_object_new(ASTAL_CAVA_TYPE_CAVA, NULL); + + return self; +} + +static void astal_cava_cava_dispose(GObject* object) { + AstalCavaCava* self = ASTAL_CAVA_CAVA(object); + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + g_source_remove(priv->timer_id); + pthread_mutex_lock(&priv->audio_data.lock); + priv->audio_data.terminate = 1; + pthread_mutex_unlock(&priv->audio_data.lock); + g_thread_join(priv->input_thread); +} + +static void astal_cava_cava_finalize(GObject* object) { + AstalCavaCava* self = ASTAL_CAVA_CAVA(object); + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + cava_destroy(&priv->plan); + g_array_free(self->values, TRUE); + + G_OBJECT_CLASS(astal_cava_cava_parent_class)->finalize(object); +} + +static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { + GObjectClass* object_class = G_OBJECT_CLASS(class); + object_class->get_property = astal_cava_cava_get_property; + object_class->set_property = astal_cava_cava_set_property; + object_class->constructed = astal_cava_cava_constructed; + object_class->dispose = astal_cava_cava_dispose; + object_class->finalize = astal_cava_cava_finalize; + + /** + * AstalCava:values: (type GList(gdouble)) + * + * A list of values + */ + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_VALUES] = + g_param_spec_pointer("values", "values", "a list of values", G_PARAM_READABLE); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_BARS] = + g_param_spec_int("bars", "bars", "number of bars per channel", 0, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_CONFIG_PATH] = + g_param_spec_string("config-path", "config-path", "config-path", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, + astal_cava_cava_properties); +} -- cgit v1.2.3 From 10a06596c33a4e64a9aa7321680fdfcff8c05173 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Thu, 3 Oct 2024 15:09:52 +0200 Subject: cava: don't use config file --- lib/cava/cava.c | 96 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 26 deletions(-) (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c index 46931f3..a2f7aa3 100644 --- a/lib/cava/cava.c +++ b/lib/cava/cava.c @@ -7,12 +7,12 @@ #include #include #include +#include struct _AstalCavaCava { GObject parent_instance; gint bars; - gchar* config_path; GArray* values; }; @@ -34,7 +34,6 @@ G_DEFINE_TYPE_WITH_PRIVATE(AstalCavaCava, astal_cava_cava, G_TYPE_OBJECT) typedef enum { ASTAL_CAVA_CAVA_PROP_VALUES = 1, ASTAL_CAVA_CAVA_PROP_BARS, - ASTAL_CAVA_CAVA_PROP_CONFIG_PATH, ASTAL_CAVA_CAVA_N_PROPERTIES } AstalCavaProperties; @@ -59,9 +58,6 @@ static void astal_cava_cava_set_property(GObject* object, guint property_id, con case ASTAL_CAVA_CAVA_PROP_BARS: self->bars = g_value_get_int(value); break; - case ASTAL_CAVA_CAVA_PROP_CONFIG_PATH: - self->config_path = g_strdup(g_value_get_string(value)); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -79,9 +75,6 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa case ASTAL_CAVA_CAVA_PROP_VALUES: g_value_set_pointer(value, self->values); break; - case ASTAL_CAVA_CAVA_PROP_CONFIG_PATH: - g_value_set_string(value, self->config_path); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -109,20 +102,73 @@ static void astal_cava_cava_constructed(GObject* object) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); - struct error_s error = {}; - - if (!load_config(self->config_path, &priv->cfg, false, &error)) { - g_critical("Error loading config. %s", error.message); - return; - } - - priv->cfg.inAtty = 0; - priv->cfg.output = OUTPUT_RAW; - priv->cfg.raw_target = strdup("/dev/stdout"); - priv->cfg.data_format = strdup("binary"); - - if(self->bars > 0) priv->cfg.fixedbars = self->bars; - else self->bars = priv->cfg.fixedbars; + priv->cfg = (struct config_params) { + .inAtty = 0, + .output = OUTPUT_RAW, + .raw_target = strdup("/dev/stdout"), + .data_format = strdup("binary"), + + .fixedbars = self->bars, + + //TODO: make more of those configurable + .audio_source = strdup("auto"), + .input = INPUT_PIPEWIRE, + + .monstercat = 0, + .sens = 1, + .noise_reduction = 0.77, + .lower_cut_off = 50, + .upper_cut_off = 10000, + .mono_opt = AVERAGE, + .stereo = 0, + .framerate = 60, + .autosens = 1, + .channels = 2, + .waves = 0, + .userEQ = NULL, + .userEQ_keys = 0, + .userEQ_enabled = 0, + .samplerate = 44100, + .samplebits = 16, + .autoconnect = 2, + .waveform = 0, + + //not needed in this lib + .sleep_timer = 0, + .show_idle_bar_heads = 1, + .continuous_rendering = 0, + .sdl_width = 1000, + .sdl_height = 500, + .sdl_x = -1, + .sdl_y = -1, + .sdl_full_screen = 0, + .draw_and_quit = 0, + .zero_test = 0, + .non_zero_test = 0, + .reverse = 0, + .sync_updates = 0, + .disable_blanking = 0, + .bar_height = 32, + .col = 0, + .bgcol = 0, + .autobars = 0, + .raw_format = FORMAT_BINARY, + .ascii_range = 1000, + .bit_format = 16, + .gradient = 0, + .gradient_count = 0, + .bar_width = 2, + .bar_spacing = 1, + .xaxis = NONE, + .orientation = ORIENT_BOTTOM, + .color = NULL, + .bcolor = NULL, + .gradient_colors = NULL, + .vertex_shader = NULL, + .fragment_shader = NULL, + .bar_delim = ';', + .frame_delim = '\n', + }; priv->audio_data = (struct audio_data) { .cava_in = calloc(BUFFER_SIZE * priv->cfg.channels * 8, sizeof(gdouble)), @@ -197,17 +243,15 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { object_class->finalize = astal_cava_cava_finalize; /** - * AstalCava:values: (type GList(gdouble)) + * AstalCava:values: (type GArray(gdouble)) * * A list of values */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_VALUES] = g_param_spec_pointer("values", "values", "a list of values", G_PARAM_READABLE); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_BARS] = - g_param_spec_int("bars", "bars", "number of bars per channel", 0, G_MAXINT, 0, + g_param_spec_int("bars", "bars", "number of bars per channel", 1, G_MAXINT, 20, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_CONFIG_PATH] = - g_param_spec_string("config-path", "config-path", "config-path", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, astal_cava_cava_properties); } -- cgit v1.2.3 From 7f7d05362dae3f2262560b9e7303ae8eb9a2ad78 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Wed, 9 Oct 2024 09:52:40 +0200 Subject: cava: add more properties --- lib/cava/cava.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 89 insertions(+), 14 deletions(-) (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c index a2f7aa3..2298229 100644 --- a/lib/cava/cava.c +++ b/lib/cava/cava.c @@ -3,6 +3,7 @@ #include "cava/config.h" #include "glib-object.h" #include "glib.h" +#include "glibconfig.h" #include #include @@ -13,6 +14,12 @@ struct _AstalCavaCava { GObject parent_instance; gint bars; + gboolean autosens; + gdouble sens; + gboolean stereo; + gboolean monstercat; + gdouble noise_reduction; + gint framerate; GArray* values; }; @@ -34,6 +41,12 @@ G_DEFINE_TYPE_WITH_PRIVATE(AstalCavaCava, astal_cava_cava, G_TYPE_OBJECT) typedef enum { ASTAL_CAVA_CAVA_PROP_VALUES = 1, ASTAL_CAVA_CAVA_PROP_BARS, + ASTAL_CAVA_CAVA_PROP_AUTOSENS, + ASTAL_CAVA_CAVA_PROP_SENS, + ASTAL_CAVA_CAVA_PROP_STEREO, + ASTAL_CAVA_CAVA_PROP_MONSTERCAT, + ASTAL_CAVA_CAVA_PROP_NOISE, + ASTAL_CAVA_CAVA_PROP_FRAMERATE, ASTAL_CAVA_CAVA_N_PROPERTIES } AstalCavaProperties; @@ -41,6 +54,8 @@ static GParamSpec* astal_cava_cava_properties[ASTAL_CAVA_CAVA_N_PROPERTIES] = { NULL, }; + + /** * astal_cava_cava_get_values * @self: the AstalCavaCava object @@ -50,6 +65,14 @@ static GParamSpec* astal_cava_cava_properties[ASTAL_CAVA_CAVA_N_PROPERTIES] = { */ GArray* astal_cava_cava_get_values(AstalCavaCava* self) { return self->values; } +gint astal_cava_cava_get_bars(AstalCavaCava* self) { return self->bars; } +gboolean astal_cava_cava_get_autosens(AstalCavaCava* self) { return self->autosens; } +gboolean astal_cava_cava_get_stereo(AstalCavaCava* self) { return self->stereo; } +gboolean astal_cava_cava_get_monstercat(AstalCavaCava* self) { return self->monstercat; } +gdouble astal_cava_cava_get_sensitivity(AstalCavaCava* self) { return self->sens; } +gdouble astal_cava_cava_get_noise_reduction(AstalCavaCava* self) { return self->noise_reduction; } +gint astal_cava_cava_get_framerate(AstalCavaCava* self) { return self->framerate; } + static void astal_cava_cava_set_property(GObject* object, guint property_id, const GValue* value, GParamSpec* pspec) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); @@ -58,6 +81,24 @@ static void astal_cava_cava_set_property(GObject* object, guint property_id, con case ASTAL_CAVA_CAVA_PROP_BARS: self->bars = g_value_get_int(value); break; + case ASTAL_CAVA_CAVA_PROP_AUTOSENS: + self->autosens = g_value_get_boolean(value); + break; + case ASTAL_CAVA_CAVA_PROP_SENS: + self->sens = g_value_get_double(value); + break; + case ASTAL_CAVA_CAVA_PROP_NOISE: + self->noise_reduction = g_value_get_double(value); + break; + case ASTAL_CAVA_CAVA_PROP_STEREO: + self->stereo = g_value_get_boolean(value); + break; + case ASTAL_CAVA_CAVA_PROP_MONSTERCAT: + self->monstercat = g_value_get_boolean(value); + break; + case ASTAL_CAVA_CAVA_PROP_FRAMERATE: + self->framerate = g_value_get_int(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -75,6 +116,24 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa case ASTAL_CAVA_CAVA_PROP_VALUES: g_value_set_pointer(value, self->values); break; + case ASTAL_CAVA_CAVA_PROP_AUTOSENS: + g_value_set_boolean(value, self->autosens); + break; + case ASTAL_CAVA_CAVA_PROP_SENS: + g_value_set_double(value, self->sens); + break; + case ASTAL_CAVA_CAVA_PROP_NOISE: + g_value_set_double(value, self->noise_reduction); + break; + case ASTAL_CAVA_CAVA_PROP_STEREO: + g_value_set_boolean(value, self->stereo); + break; + case ASTAL_CAVA_CAVA_PROP_MONSTERCAT: + g_value_set_boolean(value, self->monstercat); + break; + case ASTAL_CAVA_CAVA_PROP_FRAMERATE: + g_value_set_int(value, self->framerate); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -109,31 +168,33 @@ static void astal_cava_cava_constructed(GObject* object) { .data_format = strdup("binary"), .fixedbars = self->bars, - - //TODO: make more of those configurable + .autosens = self->autosens, + .sens = self->sens, + .stereo = self->stereo, + .channels = self->stereo + 1, + .monstercat = self->monstercat, + .noise_reduction = self->noise_reduction, + .framerate = self->framerate, + + //TODO: make these configurable .audio_source = strdup("auto"), .input = INPUT_PIPEWIRE, - .monstercat = 0, - .sens = 1, - .noise_reduction = 0.77, + //maybe make some of them configurable .lower_cut_off = 50, .upper_cut_off = 10000, .mono_opt = AVERAGE, - .stereo = 0, - .framerate = 60, - .autosens = 1, - .channels = 2, .waves = 0, .userEQ = NULL, .userEQ_keys = 0, .userEQ_enabled = 0, .samplerate = 44100, .samplebits = 16, - .autoconnect = 2, .waveform = 0, //not needed in this lib + .autoconnect = 2, + .reverse = 0, .sleep_timer = 0, .show_idle_bar_heads = 1, .continuous_rendering = 0, @@ -145,7 +206,6 @@ static void astal_cava_cava_constructed(GObject* object) { .draw_and_quit = 0, .zero_test = 0, .non_zero_test = 0, - .reverse = 0, .sync_updates = 0, .disable_blanking = 0, .bar_height = 32, @@ -196,9 +256,7 @@ static void astal_cava_cava_constructed(GObject* object) { priv->timer_id = g_timeout_add(1000 / priv->cfg.framerate, G_SOURCE_FUNC(exec_cava), self); } -static void astal_cava_cava_init(AstalCavaCava* self) { - AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); -} +static void astal_cava_cava_init(AstalCavaCava* self) { } /** * astal_cava_cava_get_default @@ -252,6 +310,23 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_BARS] = g_param_spec_int("bars", "bars", "number of bars per channel", 1, G_MAXINT, 20, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_AUTOSENS] = + g_param_spec_boolean("autosens", "autosens", "dynamically adjust sensitivity", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SENS] = + g_param_spec_double("sensitivity", "sensitivity", "sensitivity", 0, G_MAXDOUBLE, 1, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_STEREO] = + g_param_spec_boolean("stereo", "stereo", "stereo", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_MONSTERCAT] = + g_param_spec_boolean("monstercat", "monstercat", "monstercat smoothing", FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_NOISE] = + g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, G_MAXDOUBLE, 0.77, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_FRAMERATE] = + g_param_spec_int("framerate", "framerate", "framerate", 1, G_MAXINT, 60, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, astal_cava_cava_properties); } -- cgit v1.2.3 From f36feb00bcde39e9edded0f1df410eee0d3a85cb Mon Sep 17 00:00:00 2001 From: kotontrion Date: Wed, 9 Oct 2024 19:13:29 +0200 Subject: cava: add audio selection --- lib/cava/cava.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 5 deletions(-) (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c index 2298229..30d7bc7 100644 --- a/lib/cava/cava.c +++ b/lib/cava/cava.c @@ -20,6 +20,8 @@ struct _AstalCavaCava { gboolean monstercat; gdouble noise_reduction; gint framerate; + AstalCavaInput input; + gchar* audio_source; GArray* values; }; @@ -36,6 +38,16 @@ typedef struct { } AstalCavaCavaPrivate; +G_DEFINE_ENUM_TYPE(AstalCavaInput, astal_cava_input, + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_FIFO, "fifo"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_PORTAUDIO, "portaudio"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_PIPEWIRE, "pipewire"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_ALSA, "alsa"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_PULSE, "pulse"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_SNDIO, "sndio"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_SHMEM, "shmem"), + G_DEFINE_ENUM_VALUE(ASTAL_CAVA_INPUT_WINSCAP, "winscap")); + G_DEFINE_TYPE_WITH_PRIVATE(AstalCavaCava, astal_cava_cava, G_TYPE_OBJECT) typedef enum { @@ -47,6 +59,8 @@ typedef enum { ASTAL_CAVA_CAVA_PROP_MONSTERCAT, ASTAL_CAVA_CAVA_PROP_NOISE, ASTAL_CAVA_CAVA_PROP_FRAMERATE, + ASTAL_CAVA_CAVA_PROP_INPUT, + ASTAL_CAVA_CAVA_PROP_SOURCE, ASTAL_CAVA_CAVA_N_PROPERTIES } AstalCavaProperties; @@ -99,6 +113,13 @@ static void astal_cava_cava_set_property(GObject* object, guint property_id, con case ASTAL_CAVA_CAVA_PROP_FRAMERATE: self->framerate = g_value_get_int(value); break; + case ASTAL_CAVA_CAVA_PROP_INPUT: + self->input = g_value_get_enum(value); + break; + case ASTAL_CAVA_CAVA_PROP_SOURCE: + g_free(self->audio_source); + self->audio_source = g_value_dup_string(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -134,6 +155,12 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa case ASTAL_CAVA_CAVA_PROP_FRAMERATE: g_value_set_int(value, self->framerate); break; + case ASTAL_CAVA_CAVA_PROP_INPUT: + g_value_set_enum(value, self->input); + break; + case ASTAL_CAVA_CAVA_PROP_SOURCE: + g_value_set_string(value, self->audio_source); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -171,16 +198,13 @@ static void astal_cava_cava_constructed(GObject* object) { .autosens = self->autosens, .sens = self->sens, .stereo = self->stereo, - .channels = self->stereo + 1, .monstercat = self->monstercat, .noise_reduction = self->noise_reduction, .framerate = self->framerate, - - //TODO: make these configurable - .audio_source = strdup("auto"), - .input = INPUT_PIPEWIRE, + .input = (enum input_method) self->input, //maybe make some of them configurable + .channels = 2, .lower_cut_off = 50, .upper_cut_off = 10000, .mono_opt = AVERAGE, @@ -230,6 +254,43 @@ static void astal_cava_cava_constructed(GObject* object) { .frame_delim = '\n', }; + if(strcmp(self->audio_source, "auto") == 0) { + switch (priv->cfg.input) { + case INPUT_ALSA: + priv->cfg.audio_source = strdup("hw:Loopback,1"); + break; + case INPUT_FIFO: + priv->cfg.audio_source = strdup("/tmp/mpd.fifo"); + break; + case INPUT_PULSE: + priv->cfg.audio_source = strdup("auto"); + break; + case INPUT_PIPEWIRE: + priv->cfg.audio_source = strdup("auto"); + break; + case INPUT_SNDIO: + priv->cfg.audio_source = strdup("default"); + break; + case INPUT_OSS: + priv->cfg.audio_source = strdup("/dev/dsp"); + break; + case INPUT_JACK: + priv->cfg.audio_source = strdup("default"); + break; + case INPUT_SHMEM: + priv->cfg.audio_source = strdup("/squeezelite-00:00:00:00:00:00"); + break; + case INPUT_PORTAUDIO: + priv->cfg.audio_source = strdup("auto"); + break; + default: + g_critical("unsupported audio source"); + } + } + else { + priv->cfg.audio_source = strdup(self->audio_source); + } + priv->audio_data = (struct audio_data) { .cava_in = calloc(BUFFER_SIZE * priv->cfg.channels * 8, sizeof(gdouble)), .input_buffer_size = BUFFER_SIZE * priv->cfg.channels, @@ -327,6 +388,12 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_FRAMERATE] = g_param_spec_int("framerate", "framerate", "framerate", 1, G_MAXINT, 60, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_INPUT] = + g_param_spec_enum("input", "input", "input", ASTAL_CAVA_TYPE_INPUT, ASTAL_CAVA_INPUT_PIPEWIRE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SOURCE] = + g_param_spec_string("source", "source", "source", "auto", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, astal_cava_cava_properties); } -- cgit v1.2.3 From 6ffd3a09cad53f76b7e6159dce68fce900dde766 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Thu, 10 Oct 2024 10:21:22 +0200 Subject: cava: make properties changeable during runtime --- lib/cava/cava.c | 492 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 289 insertions(+), 203 deletions(-) (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c index 30d7bc7..4a70c90 100644 --- a/lib/cava/cava.c +++ b/lib/cava/cava.c @@ -1,27 +1,22 @@ +#include +#include + #include "astal-cava.h" -#include "cava/common.h" #include "cava/config.h" #include "glib-object.h" #include "glib.h" -#include "glibconfig.h" - -#include -#include -#include -#include struct _AstalCavaCava { GObject parent_instance; gint bars; gboolean autosens; - gdouble sens; gboolean stereo; - gboolean monstercat; gdouble noise_reduction; gint framerate; AstalCavaInput input; gchar* audio_source; + gboolean active; GArray* values; }; @@ -33,6 +28,7 @@ typedef struct { struct audio_raw audio_raw; ptr input_src; + gboolean constructed; GThread* input_thread; guint timer_id; @@ -52,11 +48,10 @@ G_DEFINE_TYPE_WITH_PRIVATE(AstalCavaCava, astal_cava_cava, G_TYPE_OBJECT) typedef enum { ASTAL_CAVA_CAVA_PROP_VALUES = 1, + ASTAL_CAVA_CAVA_PROP_ACTIVE, ASTAL_CAVA_CAVA_PROP_BARS, ASTAL_CAVA_CAVA_PROP_AUTOSENS, - ASTAL_CAVA_CAVA_PROP_SENS, ASTAL_CAVA_CAVA_PROP_STEREO, - ASTAL_CAVA_CAVA_PROP_MONSTERCAT, ASTAL_CAVA_CAVA_PROP_NOISE, ASTAL_CAVA_CAVA_PROP_FRAMERATE, ASTAL_CAVA_CAVA_PROP_INPUT, @@ -68,7 +63,190 @@ static GParamSpec* astal_cava_cava_properties[ASTAL_CAVA_CAVA_N_PROPERTIES] = { NULL, }; +static gboolean exec_cava(AstalCavaCava* self) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + pthread_mutex_lock(&priv->audio_data.lock); + cava_execute(priv->audio_data.cava_in, priv->audio_data.samples_counter, + priv->audio_raw.cava_out, &priv->plan); + if (priv->audio_data.samples_counter > 0) priv->audio_data.samples_counter = 0; + pthread_mutex_unlock(&priv->audio_data.lock); + + g_array_remove_range(self->values, 0, priv->audio_raw.number_of_bars); + g_array_insert_vals(self->values, 0, priv->audio_raw.cava_out, priv->audio_raw.number_of_bars); + + g_object_notify(G_OBJECT(self), "values"); + + return G_SOURCE_CONTINUE; +} + +static void astal_cava_cava_cleanup(AstalCavaCava* self) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + g_source_remove(priv->timer_id); + pthread_mutex_lock(&priv->audio_data.lock); + priv->audio_data.terminate = 1; + pthread_mutex_unlock(&priv->audio_data.lock); + g_thread_join(priv->input_thread); + + cava_destroy(&priv->plan); + g_free(priv->audio_data.cava_in); + g_free(priv->audio_data.source); + + g_free(priv->cfg.audio_source); + g_free(priv->cfg.raw_target); + g_free(priv->cfg.data_format); +} + +static void astal_cava_cava_start(AstalCavaCava* self) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + priv->cfg = (struct config_params){ + .inAtty = 0, + .output = OUTPUT_RAW, + .raw_target = strdup("/dev/stdout"), + .data_format = strdup("binary"), + + .fixedbars = self->bars, + .autosens = self->autosens, + .stereo = self->stereo, + .noise_reduction = self->noise_reduction, + .framerate = self->framerate, + .input = (enum input_method)self->input, + + // maybe make some of them configurable + .channels = 2, + .lower_cut_off = 50, + .upper_cut_off = 10000, + + // not needed in this lib + .mono_opt = AVERAGE, + .waves = 0, + .userEQ = NULL, + .userEQ_keys = 0, + .userEQ_enabled = 0, + .samplerate = 44100, + .samplebits = 16, + .waveform = 0, + .monstercat = 0, + .sens = 1, + .autoconnect = 2, + .reverse = 0, + .sleep_timer = 0, + .show_idle_bar_heads = 1, + .continuous_rendering = 0, + .sdl_width = 1000, + .sdl_height = 500, + .sdl_x = -1, + .sdl_y = -1, + .sdl_full_screen = 0, + .draw_and_quit = 0, + .zero_test = 0, + .non_zero_test = 0, + .sync_updates = 0, + .disable_blanking = 1, + .bar_height = 32, + .col = 0, + .bgcol = 0, + .autobars = 0, + .raw_format = FORMAT_BINARY, + .ascii_range = 1000, + .bit_format = 16, + .gradient = 0, + .gradient_count = 0, + .bar_width = 2, + .bar_spacing = 1, + .xaxis = NONE, + .orientation = ORIENT_BOTTOM, + .color = NULL, + .bcolor = NULL, + .gradient_colors = NULL, + .vertex_shader = NULL, + .fragment_shader = NULL, + .bar_delim = ';', + .frame_delim = '\n', + }; + + if (g_strcmp0(self->audio_source, "auto") == 0) { + switch (priv->cfg.input) { + case INPUT_ALSA: + priv->cfg.audio_source = g_strdup("hw:Loopback,1"); + break; + case INPUT_FIFO: + priv->cfg.audio_source = g_strdup("/tmp/mpd.fifo"); + break; + case INPUT_PULSE: + priv->cfg.audio_source = g_strdup("auto"); + break; + case INPUT_PIPEWIRE: + priv->cfg.audio_source = g_strdup("auto"); + break; + case INPUT_SNDIO: + priv->cfg.audio_source = g_strdup("default"); + break; + case INPUT_OSS: + priv->cfg.audio_source = g_strdup("/dev/dsp"); + break; + case INPUT_JACK: + priv->cfg.audio_source = g_strdup("default"); + break; + case INPUT_SHMEM: + priv->cfg.audio_source = g_strdup("/squeezelite-00:00:00:00:00:00"); + break; + case INPUT_PORTAUDIO: + priv->cfg.audio_source = g_strdup("auto"); + break; + default: + g_critical("unsupported audio source"); + } + } else { + priv->cfg.audio_source = g_strdup(self->audio_source); + } + + priv->audio_data = (struct audio_data){ + .cava_in = calloc(BUFFER_SIZE * priv->cfg.channels * 8, sizeof(gdouble)), + .input_buffer_size = BUFFER_SIZE * priv->cfg.channels, + .cava_buffer_size = BUFFER_SIZE * priv->cfg.channels * 8, + .format = -1, + .rate = 0, + .channels = priv->cfg.channels, + .source = g_strdup(priv->cfg.audio_source), + .terminate = 0, + .samples_counter = 0, + .IEEE_FLOAT = 0, + .suspendFlag = false, + }; + + priv->input_src = get_input(&priv->audio_data, &priv->cfg); + + audio_raw_init(&priv->audio_data, &priv->audio_raw, &priv->cfg, &priv->plan); + + priv->input_thread = g_thread_new("cava_input", priv->input_src, &priv->audio_data); + + priv->timer_id = g_timeout_add(1000 / priv->cfg.framerate, G_SOURCE_FUNC(exec_cava), self); +} + +static void astal_cava_cava_restart(AstalCavaCava* self) { + if (!self->active) return; + astal_cava_cava_cleanup(self); + astal_cava_cava_start(self); +} + +gboolean astal_cava_cava_get_active(AstalCavaCava* self) { return self->active; } + +void astal_cava_cava_set_active(AstalCavaCava* self, gboolean active) { + if (self->active == active) return; + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + + self->active = active; + + if (!priv->constructed) return; + if (!active) + astal_cava_cava_cleanup(self); + else + astal_cava_cava_start(self); +} /** * astal_cava_cava_get_values @@ -80,45 +258,94 @@ static GParamSpec* astal_cava_cava_properties[ASTAL_CAVA_CAVA_N_PROPERTIES] = { GArray* astal_cava_cava_get_values(AstalCavaCava* self) { return self->values; } gint astal_cava_cava_get_bars(AstalCavaCava* self) { return self->bars; } + +void astal_cava_cava_set_bars(AstalCavaCava* self, gint bars) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->bars = bars; + if (priv->constructed) { + g_array_set_size(self->values, self->bars); + astal_cava_cava_restart(self); + } +} + gboolean astal_cava_cava_get_autosens(AstalCavaCava* self) { return self->autosens; } + +void astal_cava_cava_set_autosens(AstalCavaCava* self, gboolean autosens) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->autosens = autosens; + if (priv->constructed) astal_cava_cava_restart(self); +} + gboolean astal_cava_cava_get_stereo(AstalCavaCava* self) { return self->stereo; } -gboolean astal_cava_cava_get_monstercat(AstalCavaCava* self) { return self->monstercat; } -gdouble astal_cava_cava_get_sensitivity(AstalCavaCava* self) { return self->sens; } + +void astal_cava_cava_set_stereo(AstalCavaCava* self, gboolean stereo) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->stereo = stereo; + if (priv->constructed) astal_cava_cava_restart(self); +} + gdouble astal_cava_cava_get_noise_reduction(AstalCavaCava* self) { return self->noise_reduction; } + +void astal_cava_cava_set_noise_reduction(AstalCavaCava* self, gdouble noise) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->noise_reduction = noise; + if (priv->constructed) astal_cava_cava_restart(self); +} + gint astal_cava_cava_get_framerate(AstalCavaCava* self) { return self->framerate; } +void astal_cava_cava_set_framerate(AstalCavaCava* self, gint framerate) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->framerate = framerate; + if (priv->constructed) astal_cava_cava_restart(self); +} + +AstalCavaInput astal_cava_cava_get_input(AstalCavaCava* self) { return self->input; } + +void astal_cava_cava_set_input(AstalCavaCava* self, AstalCavaInput input) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->input = input; + if (priv->constructed) astal_cava_cava_restart(self); +} + +gchar* astal_cava_cava_get_source(AstalCavaCava* self) { return self->audio_source; } + +void astal_cava_cava_set_source(AstalCavaCava* self, const gchar* source) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + g_free(self->audio_source); + self->audio_source = g_strdup(source); + if (priv->constructed) astal_cava_cava_restart(self); +} + static void astal_cava_cava_set_property(GObject* object, guint property_id, const GValue* value, - GParamSpec* pspec) { + GParamSpec* pspec) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); switch (property_id) { case ASTAL_CAVA_CAVA_PROP_BARS: - self->bars = g_value_get_int(value); + astal_cava_cava_set_bars(self, g_value_get_int(value)); break; - case ASTAL_CAVA_CAVA_PROP_AUTOSENS: - self->autosens = g_value_get_boolean(value); + case ASTAL_CAVA_CAVA_PROP_ACTIVE: + astal_cava_cava_set_active(self, g_value_get_boolean(value)); break; - case ASTAL_CAVA_CAVA_PROP_SENS: - self->sens = g_value_get_double(value); + case ASTAL_CAVA_CAVA_PROP_AUTOSENS: + astal_cava_cava_set_autosens(self, g_value_get_boolean(value)); break; case ASTAL_CAVA_CAVA_PROP_NOISE: - self->noise_reduction = g_value_get_double(value); + astal_cava_cava_set_noise_reduction(self, g_value_get_double(value)); break; case ASTAL_CAVA_CAVA_PROP_STEREO: - self->stereo = g_value_get_boolean(value); - break; - case ASTAL_CAVA_CAVA_PROP_MONSTERCAT: - self->monstercat = g_value_get_boolean(value); + astal_cava_cava_set_stereo(self, g_value_get_boolean(value)); break; case ASTAL_CAVA_CAVA_PROP_FRAMERATE: - self->framerate = g_value_get_int(value); + astal_cava_cava_set_framerate(self, g_value_get_int(value)); break; case ASTAL_CAVA_CAVA_PROP_INPUT: - self->input = g_value_get_enum(value); + astal_cava_cava_set_input(self, g_value_get_enum(value)); break; case ASTAL_CAVA_CAVA_PROP_SOURCE: g_free(self->audio_source); - self->audio_source = g_value_dup_string(value); + astal_cava_cava_set_source(self, g_value_get_string(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); @@ -127,10 +354,13 @@ static void astal_cava_cava_set_property(GObject* object, guint property_id, con } static void astal_cava_cava_get_property(GObject* object, guint property_id, GValue* value, - GParamSpec* pspec) { + GParamSpec* pspec) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); switch (property_id) { + case ASTAL_CAVA_CAVA_PROP_ACTIVE: + g_value_set_boolean(value, self->active); + break; case ASTAL_CAVA_CAVA_PROP_BARS: g_value_set_int(value, self->bars); break; @@ -140,18 +370,12 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa case ASTAL_CAVA_CAVA_PROP_AUTOSENS: g_value_set_boolean(value, self->autosens); break; - case ASTAL_CAVA_CAVA_PROP_SENS: - g_value_set_double(value, self->sens); - break; case ASTAL_CAVA_CAVA_PROP_NOISE: g_value_set_double(value, self->noise_reduction); break; case ASTAL_CAVA_CAVA_PROP_STEREO: g_value_set_boolean(value, self->stereo); break; - case ASTAL_CAVA_CAVA_PROP_MONSTERCAT: - g_value_set_boolean(value, self->monstercat); - break; case ASTAL_CAVA_CAVA_PROP_FRAMERATE: g_value_set_int(value, self->framerate); break; @@ -167,157 +391,30 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa } } -static gboolean exec_cava(AstalCavaCava* self) { - AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); - - pthread_mutex_lock(&priv->audio_data.lock); - cava_execute(priv->audio_data.cava_in, priv->audio_data.samples_counter, - priv->audio_raw.cava_out, &priv->plan); - if (priv->audio_data.samples_counter > 0) priv->audio_data.samples_counter = 0; - pthread_mutex_unlock(&priv->audio_data.lock); - - g_array_remove_range(self->values, 0, priv->audio_raw.number_of_bars); - g_array_insert_vals(self->values, 0, priv->audio_raw.cava_out, priv->audio_raw.number_of_bars); - - g_object_notify(G_OBJECT(self), "values"); - - return G_SOURCE_CONTINUE; -} - static void astal_cava_cava_constructed(GObject* object) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); - priv->cfg = (struct config_params) { - .inAtty = 0, - .output = OUTPUT_RAW, - .raw_target = strdup("/dev/stdout"), - .data_format = strdup("binary"), - - .fixedbars = self->bars, - .autosens = self->autosens, - .sens = self->sens, - .stereo = self->stereo, - .monstercat = self->monstercat, - .noise_reduction = self->noise_reduction, - .framerate = self->framerate, - .input = (enum input_method) self->input, - - //maybe make some of them configurable - .channels = 2, - .lower_cut_off = 50, - .upper_cut_off = 10000, - .mono_opt = AVERAGE, - .waves = 0, - .userEQ = NULL, - .userEQ_keys = 0, - .userEQ_enabled = 0, - .samplerate = 44100, - .samplebits = 16, - .waveform = 0, - - //not needed in this lib - .autoconnect = 2, - .reverse = 0, - .sleep_timer = 0, - .show_idle_bar_heads = 1, - .continuous_rendering = 0, - .sdl_width = 1000, - .sdl_height = 500, - .sdl_x = -1, - .sdl_y = -1, - .sdl_full_screen = 0, - .draw_and_quit = 0, - .zero_test = 0, - .non_zero_test = 0, - .sync_updates = 0, - .disable_blanking = 0, - .bar_height = 32, - .col = 0, - .bgcol = 0, - .autobars = 0, - .raw_format = FORMAT_BINARY, - .ascii_range = 1000, - .bit_format = 16, - .gradient = 0, - .gradient_count = 0, - .bar_width = 2, - .bar_spacing = 1, - .xaxis = NONE, - .orientation = ORIENT_BOTTOM, - .color = NULL, - .bcolor = NULL, - .gradient_colors = NULL, - .vertex_shader = NULL, - .fragment_shader = NULL, - .bar_delim = ';', - .frame_delim = '\n', - }; - - if(strcmp(self->audio_source, "auto") == 0) { - switch (priv->cfg.input) { - case INPUT_ALSA: - priv->cfg.audio_source = strdup("hw:Loopback,1"); - break; - case INPUT_FIFO: - priv->cfg.audio_source = strdup("/tmp/mpd.fifo"); - break; - case INPUT_PULSE: - priv->cfg.audio_source = strdup("auto"); - break; - case INPUT_PIPEWIRE: - priv->cfg.audio_source = strdup("auto"); - break; - case INPUT_SNDIO: - priv->cfg.audio_source = strdup("default"); - break; - case INPUT_OSS: - priv->cfg.audio_source = strdup("/dev/dsp"); - break; - case INPUT_JACK: - priv->cfg.audio_source = strdup("default"); - break; - case INPUT_SHMEM: - priv->cfg.audio_source = strdup("/squeezelite-00:00:00:00:00:00"); - break; - case INPUT_PORTAUDIO: - priv->cfg.audio_source = strdup("auto"); - break; - default: - g_critical("unsupported audio source"); - } - } - else { - priv->cfg.audio_source = strdup(self->audio_source); - } - - priv->audio_data = (struct audio_data) { - .cava_in = calloc(BUFFER_SIZE * priv->cfg.channels * 8, sizeof(gdouble)), - .input_buffer_size = BUFFER_SIZE * priv->cfg.channels, - .cava_buffer_size = BUFFER_SIZE * priv->cfg.channels * 8, - .format = -1, - .rate = 0, - .channels = priv->cfg.channels, - .source = g_strdup(priv->cfg.audio_source), - .terminate = 0, - .samples_counter = 0, - .IEEE_FLOAT = 0, - .suspendFlag = false, - }; - - priv->input_src = get_input(&priv->audio_data, &priv->cfg); + gdouble* data = calloc(self->bars, sizeof(gdouble)); + memset(data, 0, self->bars * sizeof(gdouble)); + self->values = g_array_new_take(data, self->bars, TRUE, sizeof(gdouble)); - audio_raw_init(&priv->audio_data, &priv->audio_raw, &priv->cfg, &priv->plan); + priv->constructed = true; - self->values = g_array_sized_new(TRUE, TRUE, sizeof(gdouble), priv->audio_raw.number_of_bars); - g_array_set_size(self->values, priv->audio_raw.number_of_bars); - - priv->input_thread = g_thread_new("cava_input", priv->input_src, &priv->audio_data); + if (self->active) astal_cava_cava_start(self); +} - priv->timer_id = g_timeout_add(1000 / priv->cfg.framerate, G_SOURCE_FUNC(exec_cava), self); +static void astal_cava_cava_init(AstalCavaCava* self) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + priv->constructed = false; } -static void astal_cava_cava_init(AstalCavaCava* self) { } +/** + * astal_cava_get_default + * + * Returns: (nullable) (transfer none): gets the default Cava object. + */ +AstalCavaCava* astal_cava_get_default() { return astal_cava_cava_get_default(); } /** * astal_cava_cava_get_default @@ -334,20 +431,14 @@ AstalCavaCava* astal_cava_cava_get_default() { static void astal_cava_cava_dispose(GObject* object) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); - AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); - g_source_remove(priv->timer_id); - pthread_mutex_lock(&priv->audio_data.lock); - priv->audio_data.terminate = 1; - pthread_mutex_unlock(&priv->audio_data.lock); - g_thread_join(priv->input_thread); + if (self->active) astal_cava_cava_cleanup(self); + G_OBJECT_CLASS(astal_cava_cava_parent_class)->dispose(object); } static void astal_cava_cava_finalize(GObject* object) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); - AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); - cava_destroy(&priv->plan); g_array_free(self->values, TRUE); G_OBJECT_CLASS(astal_cava_cava_parent_class)->finalize(object); @@ -368,32 +459,27 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_VALUES] = g_param_spec_pointer("values", "values", "a list of values", G_PARAM_READABLE); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_ACTIVE] = g_param_spec_boolean( + "active", "active", "active", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_BARS] = g_param_spec_int("bars", "bars", "number of bars per channel", 1, G_MAXINT, 20, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_AUTOSENS] = - g_param_spec_boolean("autosens", "autosens", "dynamically adjust sensitivity", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SENS] = - g_param_spec_double("sensitivity", "sensitivity", "sensitivity", 0, G_MAXDOUBLE, 1, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_STEREO] = - g_param_spec_boolean("stereo", "stereo", "stereo", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_MONSTERCAT] = - g_param_spec_boolean("monstercat", "monstercat", "monstercat smoothing", FALSE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_param_spec_boolean("autosens", "autosens", "dynamically adjust sensitivity", TRUE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_STEREO] = g_param_spec_boolean( + "stereo", "stereo", "stereo", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_NOISE] = - g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, G_MAXDOUBLE, 0.77, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, G_MAXDOUBLE, + 0.77, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_FRAMERATE] = g_param_spec_int("framerate", "framerate", "framerate", 1, G_MAXINT, 60, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_INPUT] = - g_param_spec_enum("input", "input", "input", ASTAL_CAVA_TYPE_INPUT, ASTAL_CAVA_INPUT_PIPEWIRE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); - astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SOURCE] = - g_param_spec_string("source", "source", "source", "auto", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY); + g_param_spec_enum("input", "input", "input", ASTAL_CAVA_TYPE_INPUT, + ASTAL_CAVA_INPUT_PIPEWIRE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SOURCE] = g_param_spec_string( + "source", "source", "source", "auto", G_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, astal_cava_cava_properties); } -- cgit v1.2.3 From 10447f5abcb28f3df1544f1732f82d538130b3c9 Mon Sep 17 00:00:00 2001 From: kotontrion Date: Thu, 10 Oct 2024 11:26:17 +0200 Subject: cava: add doce --- lib/cava/cava.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c index 4a70c90..27d201b 100644 --- a/lib/cava/cava.c +++ b/lib/cava/cava.c @@ -412,14 +412,18 @@ static void astal_cava_cava_init(AstalCavaCava* self) { /** * astal_cava_get_default * - * Returns: (nullable) (transfer none): gets the default Cava object. + * gets the default Cava object. + * + * Returns: (nullable) (transfer none): */ AstalCavaCava* astal_cava_get_default() { return astal_cava_cava_get_default(); } /** * astal_cava_cava_get_default * - * Returns: (nullable) (transfer none): gets the default Cava object. + * gets the default Cava object. + * + * Returns: (nullable) (transfer none): */ AstalCavaCava* astal_cava_cava_get_default() { static AstalCavaCava* self = NULL; @@ -453,31 +457,61 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { object_class->finalize = astal_cava_cava_finalize; /** - * AstalCava:values: (type GArray(gdouble)) + * AstalCavaCava:values: (type GArray(gdouble)) * - * A list of values + * A list of values, each represent the height of one bar. The values are generally between 0 and 1 but can overshoot occasionally, in which case the sensitivity will be decreased automatically if [property@AstalCava.Cava:autosens] is set. The array will have [property@AstalCava.Cava:bars] entries. If [property@AstalCava.Cava:stereo] is set, the first half of the array will represent the left channel and the second half the right channel, so there will be only bars/2 bars per channel. If the number of bars is odd, the last value will be 0. */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_VALUES] = g_param_spec_pointer("values", "values", "a list of values", G_PARAM_READABLE); + /** + * AstalCavaCava:active: + * + * whether or not the audio capture and visualization is running. if false the values array will not be updated. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_ACTIVE] = g_param_spec_boolean( "active", "active", "active", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:bars: + * + * the number of bars the visualizer should create. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_BARS] = g_param_spec_int("bars", "bars", "number of bars per channel", 1, G_MAXINT, 20, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:autosens: + * + * When set, the sensitivity will automatically be adjusted. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_AUTOSENS] = g_param_spec_boolean("autosens", "autosens", "dynamically adjust sensitivity", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:cava: + * + * When set the output will contain visualization data for both channels. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_STEREO] = g_param_spec_boolean( "stereo", "stereo", "stereo", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_NOISE] = - g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, G_MAXDOUBLE, + g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, 1, 0.77, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_FRAMERATE] = g_param_spec_int("framerate", "framerate", "framerate", 1, G_MAXINT, 60, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:input: (type AstalCavaInput) + * + * specifies which audio server should be used. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_INPUT] = g_param_spec_enum("input", "input", "input", ASTAL_CAVA_TYPE_INPUT, ASTAL_CAVA_INPUT_PIPEWIRE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:source: + * + * specifies which audio source should be used. Refer to the cava docs on how to use this property. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SOURCE] = g_param_spec_string( "source", "source", "source", "auto", G_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, -- cgit v1.2.3 From 9da171f0dd5ce2d2472ce42dae62286dacb7595d Mon Sep 17 00:00:00 2001 From: kotontrion Date: Fri, 11 Oct 2024 13:13:23 +0200 Subject: cava: added remaining properties --- lib/cava/cava.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 170 insertions(+), 30 deletions(-) (limited to 'lib/cava/cava.c') diff --git a/lib/cava/cava.c b/lib/cava/cava.c index 27d201b..1c5ef66 100644 --- a/lib/cava/cava.c +++ b/lib/cava/cava.c @@ -5,6 +5,7 @@ #include "cava/config.h" #include "glib-object.h" #include "glib.h" +#include "glibconfig.h" struct _AstalCavaCava { GObject parent_instance; @@ -17,6 +18,10 @@ struct _AstalCavaCava { AstalCavaInput input; gchar* audio_source; gboolean active; + gint channels; + gint low_cutoff; + gint high_cutoff; + gint samplerate; GArray* values; }; @@ -56,6 +61,10 @@ typedef enum { ASTAL_CAVA_CAVA_PROP_FRAMERATE, ASTAL_CAVA_CAVA_PROP_INPUT, ASTAL_CAVA_CAVA_PROP_SOURCE, + ASTAL_CAVA_CAVA_PROP_CHANNELS, + ASTAL_CAVA_CAVA_PROP_LOW_CUTOFF, + ASTAL_CAVA_CAVA_PROP_HIGH_CUTOFF, + ASTAL_CAVA_CAVA_PROP_SAMPLERATE, ASTAL_CAVA_CAVA_N_PROPERTIES } AstalCavaProperties; @@ -102,6 +111,30 @@ static void astal_cava_cava_cleanup(AstalCavaCava* self) { static void astal_cava_cava_start(AstalCavaCava* self) { AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + if (self->framerate < 1) { + self->framerate = 1; + } + + if (self->low_cutoff < 1) { + self->low_cutoff = 1; + } + + if (self->high_cutoff < self->low_cutoff) { + self->high_cutoff = self->low_cutoff + 1; + } + + if (self->samplerate / 2 <= self->high_cutoff) { + self->samplerate = self->high_cutoff * 2 + 1; + } + + if (self->bars < 1) { + self->bars = 1; + } + + if (self->channels < 1 || self->channels > 2) { + self->channels = 2; + } + priv->cfg = (struct config_params){ .inAtty = 0, .output = OUTPUT_RAW, @@ -114,11 +147,10 @@ static void astal_cava_cava_start(AstalCavaCava* self) { .noise_reduction = self->noise_reduction, .framerate = self->framerate, .input = (enum input_method)self->input, - - // maybe make some of them configurable - .channels = 2, - .lower_cut_off = 50, - .upper_cut_off = 10000, + .channels = self->channels, + .lower_cut_off = self->low_cutoff, + .upper_cut_off = self->high_cutoff, + .samplerate = self->samplerate, // not needed in this lib .mono_opt = AVERAGE, @@ -126,7 +158,6 @@ static void astal_cava_cava_start(AstalCavaCava* self) { .userEQ = NULL, .userEQ_keys = 0, .userEQ_enabled = 0, - .samplerate = 44100, .samplebits = 16, .waveform = 0, .monstercat = 0, @@ -317,6 +348,38 @@ void astal_cava_cava_set_source(AstalCavaCava* self, const gchar* source) { if (priv->constructed) astal_cava_cava_restart(self); } +gint astal_cava_cava_get_channels(AstalCavaCava* self) { return self->channels; } + +void astal_cava_cava_set_channels(AstalCavaCava* self, gint channels) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->channels = channels; + if (priv->constructed) astal_cava_cava_restart(self); +} + +gint astal_cava_cava_get_low_cutoff(AstalCavaCava* self) { return self->low_cutoff; } + +void astal_cava_cava_set_low_cutoff(AstalCavaCava* self, gint low_cutoff) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->low_cutoff = low_cutoff; + if (priv->constructed) astal_cava_cava_restart(self); +} + +gint astal_cava_cava_get_high_cutoff(AstalCavaCava* self) { return self->high_cutoff; } + +void astal_cava_cava_set_high_cutoff(AstalCavaCava* self, gint high_cutoff) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->high_cutoff = high_cutoff; + if (priv->constructed) astal_cava_cava_restart(self); +} + +gint astal_cava_cava_get_samplerate(AstalCavaCava* self) { return self->samplerate; } + +void astal_cava_cava_set_samplerate(AstalCavaCava* self, gint samplerate) { + AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); + self->samplerate = samplerate; + if (priv->constructed) astal_cava_cava_restart(self); +} + static void astal_cava_cava_set_property(GObject* object, guint property_id, const GValue* value, GParamSpec* pspec) { AstalCavaCava* self = ASTAL_CAVA_CAVA(object); @@ -347,6 +410,18 @@ static void astal_cava_cava_set_property(GObject* object, guint property_id, con g_free(self->audio_source); astal_cava_cava_set_source(self, g_value_get_string(value)); break; + case ASTAL_CAVA_CAVA_PROP_CHANNELS: + astal_cava_cava_set_channels(self, g_value_get_int(value)); + break; + case ASTAL_CAVA_CAVA_PROP_LOW_CUTOFF: + astal_cava_cava_set_low_cutoff(self, g_value_get_int(value)); + break; + case ASTAL_CAVA_CAVA_PROP_HIGH_CUTOFF: + astal_cava_cava_set_high_cutoff(self, g_value_get_int(value)); + break; + case ASTAL_CAVA_CAVA_PROP_SAMPLERATE: + astal_cava_cava_set_samplerate(self, g_value_get_int(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -385,6 +460,18 @@ static void astal_cava_cava_get_property(GObject* object, guint property_id, GVa case ASTAL_CAVA_CAVA_PROP_SOURCE: g_value_set_string(value, self->audio_source); break; + case ASTAL_CAVA_CAVA_PROP_CHANNELS: + g_value_set_int(value, self->channels); + break; + case ASTAL_CAVA_CAVA_PROP_LOW_CUTOFF: + g_value_set_int(value, self->low_cutoff); + break; + case ASTAL_CAVA_CAVA_PROP_HIGH_CUTOFF: + g_value_set_int(value, self->high_cutoff); + break; + case ASTAL_CAVA_CAVA_PROP_SAMPLERATE: + g_value_set_int(value, self->samplerate); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -407,6 +494,9 @@ static void astal_cava_cava_constructed(GObject* object) { static void astal_cava_cava_init(AstalCavaCava* self) { AstalCavaCavaPrivate* priv = astal_cava_cava_get_instance_private(self); priv->constructed = false; + self->low_cutoff = 50; + self->high_cutoff = 10000; + self->samplerate = 44100; } /** @@ -459,22 +549,29 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { /** * AstalCavaCava:values: (type GArray(gdouble)) * - * A list of values, each represent the height of one bar. The values are generally between 0 and 1 but can overshoot occasionally, in which case the sensitivity will be decreased automatically if [property@AstalCava.Cava:autosens] is set. The array will have [property@AstalCava.Cava:bars] entries. If [property@AstalCava.Cava:stereo] is set, the first half of the array will represent the left channel and the second half the right channel, so there will be only bars/2 bars per channel. If the number of bars is odd, the last value will be 0. + * A list of values, each represent the height of one bar. The values are generally between 0 + * and 1 but can overshoot occasionally, in which case the sensitivity will be decreased + * automatically if [property@AstalCava.Cava:autosens] is set. The array will have + * [property@AstalCava.Cava:bars] entries. If [property@AstalCava.Cava:stereo] is set, the first + * half of the array will represent the left channel and the second half the right channel, so + * there will be only bars/2 bars per channel. If the number of bars is odd, the last value will + * be 0. */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_VALUES] = g_param_spec_pointer("values", "values", "a list of values", G_PARAM_READABLE); /** - * AstalCavaCava:active: - * - * whether or not the audio capture and visualization is running. if false the values array will not be updated. - */ + * AstalCavaCava:active: + * + * whether or not the audio capture and visualization is running. if false the values array will + * not be updated. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_ACTIVE] = g_param_spec_boolean( "active", "active", "active", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); /** - * AstalCavaCava:bars: - * - * the number of bars the visualizer should create. - */ + * AstalCavaCava:bars: + * + * the number of bars the visualizer should create. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_BARS] = g_param_spec_int("bars", "bars", "number of bars per channel", 1, G_MAXINT, 20, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); @@ -482,36 +579,79 @@ static void astal_cava_cava_class_init(AstalCavaCavaClass* class) { * AstalCavaCava:autosens: * * When set, the sensitivity will automatically be adjusted. - */ + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_AUTOSENS] = g_param_spec_boolean("autosens", "autosens", "dynamically adjust sensitivity", TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); /** - * AstalCavaCava:cava: - * - * When set the output will contain visualization data for both channels. - */ + * AstalCavaCava:cava: + * + * When set the output will contain visualization data for both channels. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_STEREO] = g_param_spec_boolean( "stereo", "stereo", "stereo", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:noise-reduction: + * + * adjusts the noise-reduction filter. low values are fast and noisy, large values are slow and + * smooth. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_NOISE] = - g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, 1, - 0.77, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + g_param_spec_double("noise_reduction", "noise_reduction", "noise reduction", 0, 1, 0.77, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:framerate: + * + * how often the values should be updated + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_FRAMERATE] = g_param_spec_int("framerate", "framerate", "framerate", 1, G_MAXINT, 60, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); /** - * AstalCavaCava:input: (type AstalCavaInput) - * - * specifies which audio server should be used. - */ + * AstalCavaCava:channels: + * + * how many input channels to consider + */ + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_CHANNELS] = g_param_spec_int( + "channels", "channels", "channels", 1, 2, 2, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:low-cutoff: + * + * cut off frequencies below this value + */ + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_LOW_CUTOFF] = + g_param_spec_int("low-cutoff", "low-cutoff", "lower frequency cutoff", 1, G_MAXINT, 50, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:high-cutoff: + * + * cut off frequencies above this value + */ + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_HIGH_CUTOFF] = + g_param_spec_int("high-cutoff", "high-cutoff", "higher frequency cutoff", 1, G_MAXINT, + 10000, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:samplerate: + * + * the samplerate of the input + */ + astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SAMPLERATE] = + g_param_spec_int("samplerate", "samplerate", "samplerate", 1, G_MAXINT, 44100, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT); + /** + * AstalCavaCava:input: (type AstalCavaInput) + * + * specifies which audio server should be used. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_INPUT] = g_param_spec_enum("input", "input", "input", ASTAL_CAVA_TYPE_INPUT, ASTAL_CAVA_INPUT_PIPEWIRE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT); /** - * AstalCavaCava:source: - * - * specifies which audio source should be used. Refer to the cava docs on how to use this property. - */ + * AstalCavaCava:source: + * + * specifies which audio source should be used. Refer to the cava docs on how to use this + * property. + */ astal_cava_cava_properties[ASTAL_CAVA_CAVA_PROP_SOURCE] = g_param_spec_string( "source", "source", "source", "auto", G_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_properties(object_class, ASTAL_CAVA_CAVA_N_PROPERTIES, -- cgit v1.2.3