From 61282477e9b9530c0419335428b8ffafa6138775 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Thu, 2 Jun 2022 18:26:26 +0900 Subject: [PATCH] ctl: elem-info-enumerated: add class for element information of enumerated type The element information of enumerated type delivers an additional property for indexed string labels. This commit adds gobject class for the information. Signed-off-by: Takashi Sakamoto --- src/ctl/alsactl.h | 1 + src/ctl/alsactl.map | 3 + src/ctl/elem-info-enumerated.c | 129 +++++++++++++++++++++++++++++ src/ctl/elem-info-enumerated.h | 22 +++++ src/ctl/meson.build | 2 + tests/alsactl-elem-info-enumerated | 27 ++++++ tests/meson.build | 1 + 7 files changed, 185 insertions(+) create mode 100644 src/ctl/elem-info-enumerated.c create mode 100644 src/ctl/elem-info-enumerated.h create mode 100644 tests/alsactl-elem-info-enumerated diff --git a/src/ctl/alsactl.h b/src/ctl/alsactl.h index d77aae4..865c3b0 100644 --- a/src/ctl/alsactl.h +++ b/src/ctl/alsactl.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/src/ctl/alsactl.map b/src/ctl/alsactl.map index f93f23f..8602092 100644 --- a/src/ctl/alsactl.map +++ b/src/ctl/alsactl.map @@ -100,4 +100,7 @@ ALSA_GOBJECT_0_3_0 { "alsactl_elem_info_integer64_get_type"; "alsactl_elem_info_integer64_new"; + + "alsactl_elem_info_enumerated_get_type"; + "alsactl_elem_info_enumerated_new"; } ALSA_GOBJECT_0_2_0; diff --git a/src/ctl/elem-info-enumerated.c b/src/ctl/elem-info-enumerated.c new file mode 100644 index 0000000..6070f00 --- /dev/null +++ b/src/ctl/elem-info-enumerated.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +#include "privates.h" + +/** + * ALSACtlElemInfoEnumerated: + * An object to express information for enumerated type of element. + * + * A [class@GObject.Object] derived object class for enumerated type of element. + * + * The object wraps `struct snd_ctl_elem_info` in UAPI of Linux sound subsystem. + */ +typedef struct { + struct snd_ctl_elem_info data; + gchar **labels; +} ALSACtlElemInfoEnumeratedPrivate; + +static void elem_info_common_iface_init(ALSACtlElemInfoCommonInterface *iface); +static void elem_info_single_array_iface_init(ALSACtlElemInfoSingleArrayInterface *iface); + +G_DEFINE_TYPE_WITH_CODE(ALSACtlElemInfoEnumerated, alsactl_elem_info_enumerated, G_TYPE_OBJECT, + G_ADD_PRIVATE(ALSACtlElemInfoEnumerated) + G_IMPLEMENT_INTERFACE(ALSACTL_TYPE_ELEM_INFO_COMMON, + elem_info_common_iface_init) + G_IMPLEMENT_INTERFACE(ALSACTL_TYPE_ELEM_INFO_SINGLE_ARRAY, + elem_info_single_array_iface_init)) + +enum elem_info_enumerated_prop_type { + ELEM_INFO_ENUMERATED_PROP_LABELS = ELEM_INFO_SINGLE_ARRAY_PROP_COUNT, + ELEM_INFO_ENUMERATED_PROP_COUNT, +}; + +static void ctl_elem_info_enumerated_finalize(GObject *obj) +{ + ALSACtlElemInfoEnumerated *self = ALSACTL_ELEM_INFO_ENUMERATED(obj); + ALSACtlElemInfoEnumeratedPrivate *priv = alsactl_elem_info_enumerated_get_instance_private(self); + + g_strfreev(priv->labels); + + G_OBJECT_CLASS(alsactl_elem_info_enumerated_parent_class)->finalize(obj); +} + +static void ctl_elem_info_enumerated_set_property(GObject *obj, guint id, const GValue *val, + GParamSpec *spec) +{ + ALSACtlElemInfoEnumerated *self = ALSACTL_ELEM_INFO_ENUMERATED(obj); + ALSACtlElemInfoEnumeratedPrivate *priv = alsactl_elem_info_enumerated_get_instance_private(self); + + switch (id) { + case ELEM_INFO_ENUMERATED_PROP_LABELS: + if (priv->labels != NULL) + g_strfreev(priv->labels); + priv->labels = g_strdupv(g_value_get_boxed(val)); + break; + default: + elem_info_single_array_set_property(&priv->data, obj, id, val, spec); + break; + } +} + +static void ctl_elem_info_enumerated_get_property(GObject *obj, guint id, GValue *val, + GParamSpec *spec) +{ + ALSACtlElemInfoEnumerated *self = ALSACTL_ELEM_INFO_ENUMERATED(obj); + ALSACtlElemInfoEnumeratedPrivate *priv = alsactl_elem_info_enumerated_get_instance_private(self); + + switch (id) { + case ELEM_INFO_ENUMERATED_PROP_LABELS: + g_value_set_static_boxed(val, priv->labels); + break; + default: + elem_info_single_array_get_property(&priv->data, obj, id, val, spec); + break; + } +} + +static void alsactl_elem_info_enumerated_class_init(ALSACtlElemInfoEnumeratedClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + + gobject_class->finalize = ctl_elem_info_enumerated_finalize; + gobject_class->set_property = ctl_elem_info_enumerated_set_property; + gobject_class->get_property = ctl_elem_info_enumerated_get_property; + + elem_info_single_array_class_override_properties(gobject_class); + + /** + * ALSACtlElemInfoEnumerated:labels: + * + * The list of indexed labels for the element. There is limitation that: + * + * - The length of label including terminator should be within 64 bytes. + * - The total length of labels including terminators should be within (64 * 1024) bytes. + * + * Since: 0.3. + */ + g_object_class_install_property(gobject_class, ELEM_INFO_ENUMERATED_PROP_LABELS, + g_param_spec_boxed("labels", "labels", + "The list of indexed labels for the element", + G_TYPE_STRV, + G_PARAM_READWRITE)); +} + +static void alsactl_elem_info_enumerated_init(ALSACtlElemInfoEnumerated *self) +{ + return; +} + +static void elem_info_common_iface_init(ALSACtlElemInfoCommonInterface *iface) +{ + return; +} + +static void elem_info_single_array_iface_init(ALSACtlElemInfoSingleArrayInterface *iface) +{ + return; +} + +/** + * alsactl_elem_info_enumerated_new: + * + * Allocate and return an instance of [class@ElemInfoEnumerated]. + * + * Returns: An instance of [class@ElemInfoEnumerated]. + */ +ALSACtlElemInfoEnumerated *alsactl_elem_info_enumerated_new() +{ + return g_object_new(ALSACTL_TYPE_ELEM_INFO_ENUMERATED, + ELEM_TYPE_PROP_NAME, ALSACTL_ELEM_TYPE_ENUMERATED, NULL); +} diff --git a/src/ctl/elem-info-enumerated.h b/src/ctl/elem-info-enumerated.h new file mode 100644 index 0000000..ae7c08e --- /dev/null +++ b/src/ctl/elem-info-enumerated.h @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +#ifndef __ALSA_GOBJECT_ALSACTL_ELEM_INFO_ENUMERATED_H__ +#define __ALSA_GOBJECT_ALSACTL_ELEM_INFO_ENUMERATED_H__ + +#include + +G_BEGIN_DECLS + +#define ALSACTL_TYPE_ELEM_INFO_ENUMERATED (alsactl_elem_info_enumerated_get_type()) + +G_DECLARE_DERIVABLE_TYPE(ALSACtlElemInfoEnumerated, alsactl_elem_info_enumerated, ALSACTL, + ELEM_INFO_ENUMERATED, GObject) + +struct _ALSACtlElemInfoEnumeratedClass { + GObjectClass parent_class; +}; + +ALSACtlElemInfoEnumerated *alsactl_elem_info_enumerated_new(); + +G_END_DECLS + +#endif diff --git a/src/ctl/meson.build b/src/ctl/meson.build index d242663..c35480f 100644 --- a/src/ctl/meson.build +++ b/src/ctl/meson.build @@ -22,6 +22,7 @@ sources = files( 'elem-info-bytes.c', 'elem-info-integer.c', 'elem-info-integer64.c', + 'elem-info-enumerated.c', ) headers = files( @@ -38,6 +39,7 @@ headers = files( 'elem-info-bytes.h', 'elem-info-integer.h', 'elem-info-integer64.h', + 'elem-info-enumerated.h', ) privates = files( diff --git a/tests/alsactl-elem-info-enumerated b/tests/alsactl-elem-info-enumerated new file mode 100644 index 0000000..26716ed --- /dev/null +++ b/tests/alsactl-elem-info-enumerated @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +from sys import exit +from errno import ENXIO + +from helper import test + +import gi +gi.require_version('ALSACtl', '0.0') +from gi.repository import ALSACtl + +target = ALSACtl.ElemInfoEnumerated.new() +props = ( + 'elem-id', + 'elem-type', + 'access', + 'owner', + 'value-count', + 'labels', +) +methods = ( + 'new', +) +signals = () + +if not test(target, props, methods, signals): + exit(ENXIO) diff --git a/tests/meson.build b/tests/meson.build index cd9862d..48dc604 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -12,6 +12,7 @@ tests = { 'alsactl-elem-info-bytes', 'alsactl-elem-info-integer', 'alsactl-elem-info-integer64', + 'alsactl-elem-info-enumerated', 'alsactl-elem-value', ], 'timer': [ -- 2.47.3