summaryrefslogtreecommitdiff
path: root/backends/oss4/oss4-backend.c
diff options
context:
space:
mode:
authorMichal Ratajsky <[email protected]>2014-08-12 04:56:55 +0200
committerMichal Ratajsky <[email protected]>2014-08-12 04:56:55 +0200
commit6c6d4239ddc807e922df3874654f99eea291aadb (patch)
tree558f48fc965476344a946d93088680db3b5bac41 /backends/oss4/oss4-backend.c
parent8436ec1641eee8868128755f6d1475230cea25e6 (diff)
downloadlibmatemixer-6c6d4239ddc807e922df3874654f99eea291aadb.tar.bz2
libmatemixer-6c6d4239ddc807e922df3874654f99eea291aadb.tar.xz
Add ALSA, improve OSS and remove OSS4
Diffstat (limited to 'backends/oss4/oss4-backend.c')
-rw-r--r--backends/oss4/oss4-backend.c487
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);
-}