diff options
Diffstat (limited to 'backends/oss4/oss4-backend.c')
-rw-r--r-- | backends/oss4/oss4-backend.c | 487 |
1 files changed, 0 insertions, 487 deletions
diff --git a/backends/oss4/oss4-backend.c b/backends/oss4/oss4-backend.c deleted file mode 100644 index bd79fdf..0000000 --- a/backends/oss4/oss4-backend.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (C) 2014 Michal Ratajsky <[email protected]> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <glib.h> -#include <glib-object.h> -#include <glib/gstdio.h> -#include <glib/gprintf.h> -#include <glib/gi18n.h> -#include <gio/gio.h> - -#include <libmatemixer/matemixer-backend.h> -#include <libmatemixer/matemixer-backend-module.h> -#include <libmatemixer/matemixer-enums.h> -#include <libmatemixer/matemixer-stream.h> - -#include "oss4-backend.h" -#include "oss4-common.h" -#include "oss4-device.h" - -#define BACKEND_NAME "OSS4" -#define BACKEND_PRIORITY 8 - -#define PATH_SNDSTAT "/dev/sndstat" - -struct _Oss4BackendPrivate -{ - gint fd; - gchar *sndstat; - GHashTable *devices; - GHashTable *streams; - MateMixerStream *default_input; - MateMixerStream *default_output; - MateMixerState state; -}; - -enum { - PROP_0, - PROP_STATE, - PROP_DEFAULT_INPUT, - PROP_DEFAULT_OUTPUT -}; - -static void mate_mixer_backend_interface_init (MateMixerBackendInterface *iface); - -static void oss4_backend_class_init (Oss4BackendClass *klass); -static void oss4_backend_class_finalize (Oss4BackendClass *klass); - -static void oss4_backend_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); - -static void oss4_backend_init (Oss4Backend *oss); -static void oss4_backend_dispose (GObject *object); -static void oss4_backend_finalize (GObject *object); - -G_DEFINE_DYNAMIC_TYPE_EXTENDED (Oss4Backend, oss4_backend, - G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE_DYNAMIC (MATE_MIXER_TYPE_BACKEND, - mate_mixer_backend_interface_init)) - -static gboolean oss4_backend_open (MateMixerBackend *backend); -static void oss4_backend_close (MateMixerBackend *backend); -static GList * oss4_backend_list_devices (MateMixerBackend *backend); -static GList * oss4_backend_list_streams (MateMixerBackend *backend); - -static void change_state (Oss4Backend *oss, - MateMixerState state); - -static gboolean read_device (Oss4Backend *oss, gint index); - -static gchar * read_device_sndstat_description (Oss4Backend *oss, - const gchar *prefix); - -static void add_device (Oss4Backend *oss, Oss4Device *device); -static void remove_device (Oss4Backend *oss, Oss4Device *device); - -static MateMixerBackendInfo info; - -void -backend_module_init (GTypeModule *module) -{ - oss4_backend_register_type (module); - - info.name = BACKEND_NAME; - info.priority = BACKEND_PRIORITY; - info.g_type = OSS4_TYPE_BACKEND; - info.backend_type = MATE_MIXER_BACKEND_OSS4; -} - -const MateMixerBackendInfo *backend_module_get_info (void) -{ - return &info; -} - -static void -mate_mixer_backend_interface_init (MateMixerBackendInterface *iface) -{ - iface->open = oss4_backend_open; - iface->close = oss4_backend_close; - iface->list_devices = oss4_backend_list_devices; - iface->list_streams = oss4_backend_list_streams; -} - -static void -oss4_backend_class_init (Oss4BackendClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->dispose = oss4_backend_dispose; - object_class->finalize = oss4_backend_finalize; - object_class->get_property = oss4_backend_get_property; - - g_object_class_override_property (object_class, PROP_STATE, "state"); - g_object_class_override_property (object_class, PROP_DEFAULT_INPUT, "default-input"); - g_object_class_override_property (object_class, PROP_DEFAULT_OUTPUT, "default-output"); - - g_type_class_add_private (object_class, sizeof (Oss4BackendPrivate)); -} - -/* Called in the code generated by G_DEFINE_DYNAMIC_TYPE_EXTENDED() */ -static void -oss4_backend_class_finalize (Oss4BackendClass *klass) -{ -} - -static void -oss4_backend_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - Oss4Backend *oss; - - oss = OSS4_BACKEND (object); - - switch (param_id) { - case PROP_STATE: - g_value_set_enum (value, oss->priv->state); - break; - case PROP_DEFAULT_INPUT: - g_value_set_object (value, oss->priv->default_input); - break; - case PROP_DEFAULT_OUTPUT: - g_value_set_object (value, oss->priv->default_output); - break; - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -oss4_backend_init (Oss4Backend *oss) -{ - oss->priv = G_TYPE_INSTANCE_GET_PRIVATE (oss, - OSS4_TYPE_BACKEND, - Oss4BackendPrivate); - - oss->priv->devices = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - g_object_unref); - - oss->priv->streams = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); -} - -static void -oss4_backend_dispose (GObject *object) -{ - oss4_backend_close (MATE_MIXER_BACKEND (object)); -} - -static void -oss4_backend_finalize (GObject *object) -{ - Oss4Backend *oss; - - oss = OSS4_BACKEND (object); - - g_hash_table_destroy (oss->priv->devices); - g_hash_table_destroy (oss->priv->streams); -} - -static gboolean -oss4_backend_open (MateMixerBackend *backend) -{ - Oss4Backend *oss; - gint fd; - gint i; - gint ret; - struct oss_sysinfo info; - - g_return_val_if_fail (OSS4_IS_BACKEND (backend), FALSE); - - oss = OSS4_BACKEND (backend); - - fd = g_open ("/dev/mixer", O_RDONLY, 0); - if (fd == -1) - fd = g_open ("/dev/mixer0", O_RDONLY, 0); - if (fd == -1) { - change_state (oss, MATE_MIXER_STATE_FAILED); - return FALSE; - } - - /* Query the number of mixer devices */ - ret = ioctl (fd, OSS_SYSINFO, &info); - if (ret == -1) { - close (fd); - change_state (oss, MATE_MIXER_STATE_FAILED); - return FALSE; - } - - g_debug ("The sound system is %s version %s", - info.product, - info.version); - -#if !defined(__linux__) - /* At least on systems based on FreeBSD we will need to read devices names - * from the sndstat file, but avoid even trying that on systems where this - * is not needed and the file is not present */ - oss->priv->sndstat = PATH_SNDSTAT; -#endif - - oss->priv->fd = fd; - - for (i = 0; i < info.nummixers; i++) - read_device (oss, i); - - change_state (oss, MATE_MIXER_STATE_READY); - return TRUE; -} - -void -oss4_backend_close (MateMixerBackend *backend) -{ - Oss4Backend *oss; - - g_return_if_fail (OSS4_IS_BACKEND (backend)); - - oss = OSS4_BACKEND (backend); - - g_clear_object (&oss->priv->default_input); - g_clear_object (&oss->priv->default_output); - - g_hash_table_remove_all (oss->priv->streams); - g_hash_table_remove_all (oss->priv->devices); -} - -static GList * -oss4_backend_list_devices (MateMixerBackend *backend) -{ - GList *list; - - g_return_val_if_fail (OSS4_IS_BACKEND (backend), NULL); - - /* Convert the hash table to a sorted linked list, this list is expected - * to be cached in the main library */ - list = g_hash_table_get_values (OSS4_BACKEND (backend)->priv->devices); - if (list != NULL) { - g_list_foreach (list, (GFunc) g_object_ref, NULL); - - return list; - } - return NULL; -} - -static GList * -oss4_backend_list_streams (MateMixerBackend *backend) -{ - GList *list; - - g_return_val_if_fail (OSS4_IS_BACKEND (backend), NULL); - - /* Convert the hash table to a sorted linked list, this list is expected - * to be cached in the main library */ - list = g_hash_table_get_values (OSS4_BACKEND (backend)->priv->streams); - if (list != NULL) { - g_list_foreach (list, (GFunc) g_object_ref, NULL); - - return list; - } - return NULL; -} - -static void -change_state (Oss4Backend *oss, MateMixerState state) -{ - if (oss->priv->state == state) - return; - - oss->priv->state = state; - - g_object_notify (G_OBJECT (oss), "state"); -} - -static gboolean -read_device (Oss4Backend *oss, gint index) -{ - Oss4Device *device; - gboolean ret; - gchar *description = NULL; - struct oss_mixerinfo info; - - /* We assume that the name and capabilities of a device do not change */ - device = g_hash_table_lookup (oss->priv->devices, GINT_TO_POINTER (index)); - if (G_UNLIKELY (device != NULL)) { - g_debug ("Attempt to re-read already know device with index %d", index); - return TRUE; - } - - info.dev = index; - ret = ioctl (oss->priv->fd, SNDCTL_MIXERINFO, &info); - if (ret == -1) { - g_debug ("Failed to read mixer info: %s", g_strerror (errno)); - return FALSE; - } - - if (info.enabled == 0) - return TRUE; - - /* Use the id as the device name and try to figure out the name of the - * sound card from the sndstat file if it is available, otherwise use - * the name from the mixer info */ - if (oss->priv->sndstat != NULL && - g_str_has_prefix (info.name, "pcm") == TRUE) - description = read_device_sndstat_description (oss, info.name); - - if (description == NULL) - description = g_strdup (info.name); - - device = oss4_device_new (info.id, description, oss->priv->fd, index); - - ret = oss4_device_read (device); - if (ret == TRUE) - add_device (oss, device); - - g_object_unref (device); - g_free (description); - - return ret; -} - -static gchar * -read_device_sndstat_description (Oss4Backend *oss, const gchar *prefix) -{ - FILE *fp; - gchar line[256]; - gchar *description = NULL; - - g_debug ("reading prefix %s", prefix); - - fp = fopen (oss->priv->sndstat, "r"); - if (fp == NULL) { - g_warning ("Failed to read %s: %s", oss->priv->sndstat, g_strerror (errno)); - return FALSE; - } - - while (fgets (line, sizeof (line), fp) != NULL) { - gchar *p; - - if (g_str_has_prefix (line, prefix) == FALSE) - continue; - - /* Example line: - * pcm0: <ATI R6xx (HDMI)> (play) default */ - p = strchr (line, '<'); - if (p != NULL && *p && *(++p)) { - gchar *end = strchr (p, '>'); - - if (end != NULL) - description = g_strndup (p, end - p); - } - - // XXX we can also read "default" at the end of the line - // XXX http://ashish.is.lostca.se/2011/05/23/default-sound-device-in-freebsd/ - if (g_str_has_suffix (line, "default") || - g_str_has_suffix (line, "default)")) - ; - - if (description != NULL) - break; - } - - fclose (fp); - return description; -} - -static void -add_device (Oss4Backend *oss, Oss4Device *device) -{ - MateMixerStream *stream; - - /* Add device, file path is used as the key rather than the name, because - * the name is not known until an OssDevice instance is created */ - g_hash_table_insert (oss->priv->devices, - GINT_TO_POINTER (oss4_device_get_index (device)), - g_object_ref (device)); - - g_signal_emit_by_name (G_OBJECT (oss), - "device-added", - mate_mixer_device_get_name (MATE_MIXER_DEVICE (device))); - - /* Add streams if they exist */ - stream = oss4_device_get_input_stream (device); - if (stream != NULL) { - g_hash_table_insert (oss->priv->streams, - g_strdup (mate_mixer_stream_get_name (stream)), - g_object_ref (stream)); - - g_signal_emit_by_name (G_OBJECT (oss), - "stream-added", - mate_mixer_stream_get_name (stream)); - } - - stream = oss4_device_get_output_stream (device); - if (stream != NULL) { - g_hash_table_insert (oss->priv->streams, - g_strdup (mate_mixer_stream_get_name (stream)), - g_object_ref (stream)); - - g_signal_emit_by_name (G_OBJECT (oss), - "stream-added", - mate_mixer_stream_get_name (stream)); - } -} - -static void -remove_device (Oss4Backend *oss, Oss4Device *device) -{ - MateMixerStream *stream; - - /* Remove the device streams first as they are a part of the device */ - stream = oss4_device_get_input_stream (device); - if (stream != NULL) { - const gchar *name = mate_mixer_stream_get_name (stream); - - g_hash_table_remove (oss->priv->streams, name); - g_signal_emit_by_name (G_OBJECT (oss), - "stream-removed", - name); - } - - stream = oss4_device_get_output_stream (device); - if (stream != NULL) { - const gchar *name = mate_mixer_stream_get_name (stream); - - g_hash_table_remove (oss->priv->streams, stream); - g_signal_emit_by_name (G_OBJECT (oss), - "stream-removed", - name); - } - - /* Remove the device */ - g_object_ref (device); - - g_hash_table_remove (oss->priv->devices, - GINT_TO_POINTER (oss4_device_get_index (device))); - - g_signal_emit_by_name (G_OBJECT (oss), - "device-removed", - mate_mixer_device_get_name (MATE_MIXER_DEVICE (device))); - - g_object_unref (device); -} |