/* * Copyright (C) 2014 Michal Ratajsky * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the licence, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include #include #include #include "matemixer-device.h" #include "matemixer-device-switch.h" #include "matemixer-stream.h" #include "matemixer-switch.h" /** * SECTION:matemixer-device * @short_description: Hardware or software device in the sound system * @include: libmatemixer/matemixer.h * * A #MateMixerDevice represents a sound device, most typically a sound card. * * Each device may contain an arbitrary number of streams. */ struct _MateMixerDevicePrivate { gchar *name; gchar *label; gchar *icon; }; enum { PROP_0, PROP_NAME, PROP_LABEL, PROP_ICON, N_PROPERTIES }; static GParamSpec *properties[N_PROPERTIES] = { NULL, }; enum { STREAM_ADDED, STREAM_REMOVED, SWITCH_ADDED, SWITCH_REMOVED, N_SIGNALS }; static guint signals[N_SIGNALS] = { 0, }; static void mate_mixer_device_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec); static void mate_mixer_device_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec); static void mate_mixer_device_finalize (GObject *object); G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MateMixerDevice, mate_mixer_device, G_TYPE_OBJECT) static MateMixerStream * mate_mixer_device_real_get_stream (MateMixerDevice *device, const gchar *name); static MateMixerDeviceSwitch *mate_mixer_device_real_get_switch (MateMixerDevice *device, const gchar *name); static void mate_mixer_device_class_init (MateMixerDeviceClass *klass) { GObjectClass *object_class; klass->get_stream = mate_mixer_device_real_get_stream; klass->get_switch = mate_mixer_device_real_get_switch; object_class = G_OBJECT_CLASS (klass); object_class->finalize = mate_mixer_device_finalize; object_class->get_property = mate_mixer_device_get_property; object_class->set_property = mate_mixer_device_set_property; /** * MateMixerDevice:name: * * The name of the device. The name serves as a unique identifier and * in most cases it is not in a user-readable form. */ properties[PROP_NAME] = g_param_spec_string ("name", "Name", "Name of the device", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * MateMixerDevice:label: * * The label of the device. This is a potentially translated string * that should be presented to users in the user interface. */ properties[PROP_LABEL] = g_param_spec_string ("label", "Label", "Label of the device", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); /** * MateMixerDevice:icon: * * The XDG icon name of the device. */ properties[PROP_ICON] = g_param_spec_string ("icon", "Icon", "XDG icon name of the device", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPERTIES, properties); /** * MateMixerDevice::stream-added: * @device: a #MateMixerDevice * @name: name of the added stream * * The signal is emitted each time a device stream is added. * * Note that at the time this signal is emitted, the controls and switches * of the stream may not yet be known. */ signals[STREAM_ADDED] = g_signal_new ("stream-added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (MateMixerDeviceClass, stream_added), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); /** * MateMixerDevice::stream-removed: * @device: a #MateMixerDevice * @name: name of the removed stream * * The signal is emitted each time a device stream is removed. * * When this signal is emitted, the stream is no longer known to the library, * it will not be included in the stream list provided by the * mate_mixer_device_list_streams() function and it is not possible to get * the stream with mate_mixer_device_get_stream(). */ signals[STREAM_REMOVED] = g_signal_new ("stream-removed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (MateMixerDeviceClass, stream_removed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); /** * MateMixerDevice::switch-added: * @device: a #MateMixerDevice * @name: name of the added switch * * The signal is emitted each time a device switch is added. */ signals[SWITCH_ADDED] = g_signal_new ("switch-added", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (MateMixerDeviceClass, switch_added), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); /** * MateMixerDevice::switch-removed: * @device: a #MateMixerDevice * @name: name of the removed switch * * The signal is emitted each time a device switch is removed. * * When this signal is emitted, the switch is no longer known to the library, * it will not be included in the switch list provided by the * mate_mixer_device_list_switches() function and it is not possible to get * the switch with mate_mixer_device_get_switch(). */ signals[SWITCH_REMOVED] = g_signal_new ("switch-removed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (MateMixerDeviceClass, switch_removed), NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); } static void mate_mixer_device_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { MateMixerDevice *device; device = MATE_MIXER_DEVICE (object); switch (param_id) { case PROP_NAME: g_value_set_string (value, device->priv->name); break; case PROP_LABEL: g_value_set_string (value, device->priv->label); break; case PROP_ICON: g_value_set_string (value, device->priv->icon); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void mate_mixer_device_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { MateMixerDevice *device; device = MATE_MIXER_DEVICE (object); switch (param_id) { case PROP_NAME: /* Construct-only string */ device->priv->name = g_value_dup_string (value); break; case PROP_LABEL: /* Construct-only string */ device->priv->label = g_value_dup_string (value); break; case PROP_ICON: /* Construct-only string */ device->priv->icon = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void mate_mixer_device_init (MateMixerDevice *device) { device->priv = mate_mixer_device_get_instance_private (device); } static void mate_mixer_device_finalize (GObject *object) { MateMixerDevice *device; device = MATE_MIXER_DEVICE (object); g_free (device->priv->name); g_free (device->priv->label); g_free (device->priv->icon); G_OBJECT_CLASS (mate_mixer_device_parent_class)->finalize (object); } /** * mate_mixer_device_get_name: * @device: a #MateMixerDevice * * Gets the name of the device. * * The name serves as a unique identifier and in most cases it is not in a * user-readable form. * * The returned name is guaranteed to be unique across all the known devices * and may be used to get the #MateMixerDevice using * mate_mixer_context_get_device(). * * Returns: the name of the device. */ const gchar * mate_mixer_device_get_name (MateMixerDevice *device) { g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); return device->priv->name; } /** * mate_mixer_device_get_label: * @device: a #MateMixerDevice * * Gets the label of the device. * * This is a potentially translated string that should be presented to users * in the user interface. * * Returns: the label of the device. */ const gchar * mate_mixer_device_get_label (MateMixerDevice *device) { g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); return device->priv->label; } /** * mate_mixer_device_get_icon: * @device: a #MateMixerDevice * * Gets the XDG icon name of the device. * * Returns: the icon name or %NULL. */ const gchar * mate_mixer_device_get_icon (MateMixerDevice *device) { g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); return device->priv->icon; } /** * mate_mixer_device_get_stream: * @device: a #MateMixerDevice * @name: a stream name * * Gets the device stream with the given name. * * Returns: a #MateMixerStream or %NULL if there is no such stream. */ MateMixerStream * mate_mixer_device_get_stream (MateMixerDevice *device, const gchar *name) { g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); g_return_val_if_fail (name != NULL, NULL); return MATE_MIXER_DEVICE_GET_CLASS (device)->get_stream (device, name); } /** * mate_mixer_device_get_switch: * @device: a #MateMixerDevice * @name: a switch name * * Gets the device switch with the given name. * * Note that this function will only return a switch that belongs to the device * and not to a stream of the device. See mate_mixer_device_list_switches() for * information about the difference between device and stream switches. * * To get a stream switch, rather than a device switch, use * mate_mixer_stream_get_switch(). * * Returns: a #MateMixerDeviceSwitch or %NULL if there is no such device switch. */ MateMixerDeviceSwitch * mate_mixer_device_get_switch (MateMixerDevice *device, const gchar *name) { g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); g_return_val_if_fail (name != NULL, NULL); return MATE_MIXER_DEVICE_GET_CLASS (device)->get_switch (device, name); } /** * mate_mixer_device_list_streams: * @device: a #MateMixerDevice * * Gets the list of streams that belong to the device. * * The returned #GList is owned by the #MateMixerDevice and may be invalidated * at any time. * * Returns: a #GList of the device streams or %NULL if the device does not have * any streams. */ const GList * mate_mixer_device_list_streams (MateMixerDevice *device) { MateMixerDeviceClass *klass; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); klass = MATE_MIXER_DEVICE_GET_CLASS (device); if (G_LIKELY (klass->list_streams != NULL)) return klass->list_streams (device); return NULL; } /** * mate_mixer_device_list_switches: * @device: a #MateMixerDevice * * Gets the list of switches the belong to the device. * * Note that a switch may belong either to a device, or to a stream. Unlike * stream switches, device switches returned by this function are not classified * as input or output (as streams are), but they operate on the whole device. * * Use mate_mixer_stream_list_switches() to get a list of switches that belong * to a stream. * * The returned #GList is owned by the #MateMixerDevice and may be invalidated * at any time. * * Returns: a #GList of the device switches or %NULL if the device does not have * any switches. */ const GList * mate_mixer_device_list_switches (MateMixerDevice *device) { MateMixerDeviceClass *klass; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); klass = MATE_MIXER_DEVICE_GET_CLASS (device); if (G_LIKELY (klass->list_switches != NULL)) return klass->list_switches (device); return NULL; } static MateMixerStream * mate_mixer_device_real_get_stream (MateMixerDevice *device, const gchar *name) { const GList *list; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); g_return_val_if_fail (name != NULL, NULL); list = mate_mixer_device_list_streams (device); while (list != NULL) { MateMixerStream *stream = MATE_MIXER_STREAM (list->data); if (strcmp (name, mate_mixer_stream_get_name (stream)) == 0) return stream; list = list->next; } return NULL; } static MateMixerDeviceSwitch * mate_mixer_device_real_get_switch (MateMixerDevice *device, const gchar *name) { const GList *list; g_return_val_if_fail (MATE_MIXER_IS_DEVICE (device), NULL); g_return_val_if_fail (name != NULL, NULL); list = mate_mixer_device_list_switches (device); while (list != NULL) { MateMixerSwitch *swtch = MATE_MIXER_SWITCH (list->data); if (strcmp (name, mate_mixer_switch_get_name (swtch)) == 0) return MATE_MIXER_DEVICE_SWITCH (swtch); list = list->next; } return NULL; }