summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/oss/Makefile.am12
-rw-r--r--backends/oss/oss-backend.c498
-rw-r--r--backends/oss/oss-backend.h8
-rw-r--r--backends/oss/oss-common.h38
-rw-r--r--backends/oss/oss-device.c525
-rw-r--r--backends/oss/oss-device.h73
-rw-r--r--backends/oss/oss-stream-control.c529
-rw-r--r--backends/oss/oss-stream-control.h74
-rw-r--r--backends/oss/oss-stream.c315
-rw-r--r--backends/oss/oss-stream.h75
-rw-r--r--configure.ac3
-rw-r--r--examples/monitor.c56
-rw-r--r--libmatemixer/Makefile.am4
-rw-r--r--libmatemixer/matemixer-backend.c33
-rw-r--r--libmatemixer/matemixer-enum-types.c31
-rw-r--r--libmatemixer/matemixer-enum-types.h3
-rw-r--r--libmatemixer/matemixer-enums.h55
-rw-r--r--libmatemixer/matemixer-stream-control.c445
-rw-r--r--libmatemixer/matemixer-stream-control.h148
-rw-r--r--libmatemixer/matemixer-stream.c475
-rw-r--r--libmatemixer/matemixer-stream.h156
21 files changed, 2974 insertions, 582 deletions
diff --git a/backends/oss/Makefile.am b/backends/oss/Makefile.am
index 3f0b8ea..44caeb8 100644
--- a/backends/oss/Makefile.am
+++ b/backends/oss/Makefile.am
@@ -11,11 +11,19 @@ libmatemixer_oss_la_CFLAGS = \
$(OSS_CFLAGS)
libmatemixer_oss_la_SOURCES = \
+ oss-common.h \
oss-backend.c \
- oss-backend.h
+ oss-backend.h \
+ oss-device.c \
+ oss-device.h \
+ oss-stream.c \
+ oss-stream.h \
+ oss-stream-control.c \
+ oss-stream-control.h
libmatemixer_oss_la_LIBADD = \
- $(GLIB_LIBS)
+ $(GLIB_LIBS) \
+ $(OSS_LIBS)
libmatemixer_oss_la_LDFLAGS = \
-avoid-version \
diff --git a/backends/oss/oss-backend.c b/backends/oss/oss-backend.c
index 22d3547..6e058f8 100644
--- a/backends/oss/oss-backend.c
+++ b/backends/oss/oss-backend.c
@@ -15,43 +15,95 @@
* 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 "oss-backend.h"
+#include "oss-common.h"
+#include "oss-device.h"
#define BACKEND_NAME "OSS"
-#define BACKEND_PRIORITY 90
+#define BACKEND_PRIORITY 9
+
+#define PATH_SNDSTAT "/dev/sndstat"
+
+struct _OssBackendPrivate
+{
+ GFile *sndstat;
+ GFile *dev;
+ GFileMonitor *dev_monitor;
+ GHashTable *devices;
+ GHashTable *streams;
+ MateMixerStream *default_input;
+ MateMixerStream *default_output;
+ MateMixerState state;
+};
enum {
PROP_0,
PROP_STATE,
PROP_DEFAULT_INPUT,
- PROP_DEFAULT_OUTPUT,
- N_PROPERTIES
+ PROP_DEFAULT_OUTPUT
};
static void mate_mixer_backend_interface_init (MateMixerBackendInterface *iface);
static void oss_backend_class_init (OssBackendClass *klass);
static void oss_backend_class_finalize (OssBackendClass *klass);
+
static void oss_backend_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec);
+
static void oss_backend_init (OssBackend *oss);
+static void oss_backend_dispose (GObject *object);
+static void oss_backend_finalize (GObject *object);
G_DEFINE_DYNAMIC_TYPE_EXTENDED (OssBackend, oss_backend,
G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE_DYNAMIC (MATE_MIXER_TYPE_BACKEND,
mate_mixer_backend_interface_init))
-static gboolean backend_open (MateMixerBackend *backend);
-static MateMixerState backend_get_state (MateMixerBackend *backend);
+static gboolean oss_backend_open (MateMixerBackend *backend);
+static void oss_backend_close (MateMixerBackend *backend);
+static GList * oss_backend_list_devices (MateMixerBackend *backend);
+static GList * oss_backend_list_streams (MateMixerBackend *backend);
+
+static void change_state (OssBackend *oss,
+ MateMixerState state);
+
+static void on_dev_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ OssBackend *oss);
+
+static gboolean read_device (OssBackend *oss,
+ const gchar *path);
+
+static gchar * read_device_description (OssBackend *oss,
+ const gchar *path,
+ gint fd);
+static gchar * read_device_sndstat_description (const gchar *path,
+ GFileInputStream *input);
+
+static void add_device (OssBackend *oss,
+ OssDevice *device);
+static void remove_device (OssBackend *oss,
+ OssDevice *device);
static MateMixerBackendInfo info;
@@ -66,8 +118,7 @@ backend_module_init (GTypeModule *module)
info.backend_type = MATE_MIXER_BACKEND_OSS;
}
-const MateMixerBackendInfo *
-backend_module_get_info (void)
+const MateMixerBackendInfo *backend_module_get_info (void)
{
return &info;
}
@@ -75,8 +126,10 @@ backend_module_get_info (void)
static void
mate_mixer_backend_interface_init (MateMixerBackendInterface *iface)
{
- iface->open = backend_open;
- iface->get_state = backend_get_state;
+ iface->open = oss_backend_open;
+ iface->close = oss_backend_close;
+ iface->list_devices = oss_backend_list_devices;
+ iface->list_streams = oss_backend_list_streams;
}
static void
@@ -85,11 +138,15 @@ oss_backend_class_init (OssBackendClass *klass)
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = oss_backend_dispose;
+ object_class->finalize = oss_backend_finalize;
object_class->get_property = oss_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 (OssBackendPrivate));
}
/* Called in the code generated by G_DEFINE_DYNAMIC_TYPE_EXTENDED() */
@@ -104,13 +161,20 @@ oss_backend_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
+ OssBackend *oss;
+
+ oss = OSS_BACKEND (object);
+
switch (param_id) {
case PROP_STATE:
- g_value_set_enum (value, MATE_MIXER_STATE_READY);
+ 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, NULL);
+ g_value_set_object (value, oss->priv->default_output);
+ break;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -121,16 +185,420 @@ oss_backend_get_property (GObject *object,
static void
oss_backend_init (OssBackend *oss)
{
+ oss->priv = G_TYPE_INSTANCE_GET_PRIVATE (oss,
+ OSS_TYPE_BACKEND,
+ OssBackendPrivate);
+
+ oss->priv->devices = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ oss->priv->streams = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+}
+
+static void
+oss_backend_dispose (GObject *object)
+{
+ oss_backend_close (MATE_MIXER_BACKEND (object));
+}
+
+static void
+oss_backend_finalize (GObject *object)
+{
+ OssBackend *oss;
+
+ oss = OSS_BACKEND (object);
+
+ g_hash_table_destroy (oss->priv->devices);
+ g_hash_table_destroy (oss->priv->streams);
}
static gboolean
-backend_open (MateMixerBackend *backend)
+oss_backend_open (MateMixerBackend *backend)
{
+ OssBackend *oss;
+ GError *error = NULL;
+ gint i;
+
+ g_return_val_if_fail (OSS_IS_BACKEND (backend), FALSE);
+
+ oss = OSS_BACKEND (backend);
+
+ /* Monitor changes on /dev to catch hot-(un)plugged devices */
+ // XXX works on linux, doesn't on freebsd, what to do on netbsd/openbsd?
+ oss->priv->dev = g_file_new_for_path ("/dev");
+ oss->priv->dev_monitor = g_file_monitor_directory (oss->priv->dev,
+ G_FILE_MONITOR_NONE,
+ NULL,
+ &error);
+ if (oss->priv->dev_monitor != NULL) {
+ g_signal_connect (G_OBJECT (oss->priv->dev_monitor),
+ "changed",
+ G_CALLBACK (on_dev_monitor_changed),
+ oss);
+ } else {
+ g_debug ("Failed to monitor /dev: %s", error->message);
+ g_error_free (error);
+ }
+
+#if !defined(__linux__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
+ /* 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 = g_file_new_for_path (PATH_SNDSTAT);
+#endif
+
+ for (i = 0; i < 5; i++) {
+ /* According to the OSS documentation the mixer devices are
+ * /dev/mixer0 - /dev/mixer4, of course some systems create them
+ * dynamically but this approach should be good enough */
+ gchar *path = g_strdup_printf ("/dev/mixer%i", i);
+
+ if (read_device (oss, path) == FALSE && i == 0) {
+ /* For the first mixer device check also /dev/mixer, but it
+ * might be a symlink to a real mixer device */
+ if (g_file_test ("/dev/mixer", G_FILE_TEST_IS_SYMLINK) == FALSE)
+ read_device (oss, "/dev/mixer");
+ }
+
+ g_free (path);
+ }
+
+ change_state (oss, MATE_MIXER_STATE_READY);
return TRUE;
}
-static MateMixerState
-backend_get_state (MateMixerBackend *backend)
+void
+oss_backend_close (MateMixerBackend *backend)
+{
+ OssBackend *oss;
+
+ g_return_if_fail (OSS_IS_BACKEND (backend));
+
+ oss = OSS_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);
+
+ g_clear_object (&oss->priv->dev_monitor);
+ g_clear_object (&oss->priv->dev);
+ g_clear_object (&oss->priv->sndstat);
+}
+
+static GList *
+oss_backend_list_devices (MateMixerBackend *backend)
+{
+ GList *list;
+
+ g_return_val_if_fail (OSS_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 (OSS_BACKEND (backend)->priv->devices);
+ if (list != NULL) {
+ g_list_foreach (list, (GFunc) g_object_ref, NULL);
+
+ return list;
+ }
+ return NULL;
+}
+
+static GList *
+oss_backend_list_streams (MateMixerBackend *backend)
+{
+ GList *list;
+
+ g_return_val_if_fail (OSS_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 (OSS_BACKEND (backend)->priv->streams);
+ if (list != NULL) {
+ g_list_foreach (list, (GFunc) g_object_ref, NULL);
+
+ return list;
+ }
+ return NULL;
+}
+
+static void
+change_state (OssBackend *oss, MateMixerState state)
+{
+ if (oss->priv->state == state)
+ return;
+
+ oss->priv->state = state;
+
+ g_object_notify (G_OBJECT (oss), "state");
+}
+
+static void
+on_dev_monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event_type,
+ OssBackend *oss)
+{
+ gchar *path;
+
+ if (event_type != G_FILE_MONITOR_EVENT_CREATED &&
+ event_type != G_FILE_MONITOR_EVENT_DELETED)
+ return;
+
+ path = g_file_get_path (file);
+
+ /* Only handle creation and deletion of mixer devices */
+ if (g_str_has_prefix (path, "/dev/mixer") == FALSE) {
+ g_free (path);
+ return;
+ }
+ if (strcmp (path, "/dev/mixer") == 0 &&
+ g_file_test (path, G_FILE_TEST_IS_SYMLINK) == TRUE) {
+ g_free (path);
+ return;
+ }
+
+ if (event_type == G_FILE_MONITOR_EVENT_DELETED) {
+ OssDevice *device;
+
+ device = g_hash_table_lookup (oss->priv->devices, path);
+ if (device != NULL)
+ remove_device (oss, device);
+ } else
+ read_device (oss, path);
+
+ g_free (path);
+}
+
+static gboolean
+read_device (OssBackend *oss, const gchar *path)
+{
+ OssDevice *device;
+ gint fd;
+ gboolean ret;
+ const gchar *description;
+
+ /* We assume that the name and capabilities of a device do not change */
+ device = g_hash_table_lookup (oss->priv->devices, path);
+ if (G_UNLIKELY (device != NULL)) {
+ g_debug ("Attempt to re-read already know device %s", path);
+ return TRUE;
+ }
+
+ fd = g_open (path, O_RDWR, 0);
+ if (fd == -1) {
+ if (errno != ENOENT && errno != ENXIO)
+ g_debug ("%s: %s", path, g_strerror (errno));
+ return FALSE;
+ }
+
+ device = oss_device_new (path, fd);
+
+ description = read_device_description (oss, path, fd);
+ if (description != NULL)
+ oss_device_set_description (device, description);
+ else
+ oss_device_set_description (device, _("Unknown device"));
+
+ /* Close the descriptor as the device should dup it if it intends
+ * to keep it */
+ g_close (fd, NULL);
+
+ ret = oss_device_read (device);
+ if (ret == TRUE)
+ add_device (oss, device);
+
+ g_object_unref (device);
+ return ret;
+}
+
+static gchar *
+read_device_description (OssBackend *oss, const gchar *path, gint fd)
+{
+ struct mixer_info info;
+
+ if (ioctl (fd, SOUND_MIXER_INFO, &info) == 0) {
+ /* Prefer device name supplied by the system, but this fails on FreeBSD */
+ return g_strdup (info.name);
+ }
+
+ /* Reading the sndstat file is a bit desperate, but seem to be the only
+ * way to determine the name of the sound card on FreeBSD, it also has an
+ * advantage in being able to find out the default one */
+ if (oss->priv->sndstat != NULL) {
+ GError *error = NULL;
+ GFileInputStream *input = g_file_read (oss->priv->sndstat, NULL, &error);
+
+ if (input == NULL) {
+ /* The file can only be open by one application, otherwise the call
+ * fails with EBUSY */
+ if (error->code == G_IO_ERROR_BUSY) {
+ g_debug ("Delayed reading %s as it is busy", PATH_SNDSTAT);
+ // XXX use timeout and try again
+ } else {
+ if (error->code == G_IO_ERROR_NOT_FOUND)
+ g_debug ("Device description is unknown as %s does not exist",
+ PATH_SNDSTAT);
+ else
+ g_debug ("%s: %s", PATH_SNDSTAT, error->message);
+
+ g_clear_object (&oss->priv->sndstat);
+ }
+ g_error_free (error);
+ } else
+ return read_device_sndstat_description (path, input);
+ }
+
+ return NULL;
+}
+
+static gchar *
+read_device_sndstat_description (const gchar *path, GFileInputStream *input)
{
- return MATE_MIXER_STATE_READY;
+ gchar *line;
+ gchar *prefix;
+ gchar *description = NULL;
+ GDataInputStream *stream;
+
+ if (G_UNLIKELY (g_str_has_prefix (path, "/dev/mixer")) == FALSE) {
+ g_warn_if_reached ();
+ return NULL;
+ }
+
+ /* We assume that the mixer device number matches the pcm number in the
+ * sndstat file, this is a bit desperate, but it seems to do the
+ * right thing in practice */
+ prefix = g_strdup_printf ("pcm%u: ",
+ (guint) g_ascii_strtoull (path + sizeof ("/dev/mixer") - 1,
+ NULL,
+ 10));
+
+ stream = g_data_input_stream_new (G_INPUT_STREAM (input));
+
+ while (TRUE) {
+ GError *error = NULL;
+ gchar *p;
+
+ line = g_data_input_stream_read_line (stream, NULL, NULL, &error);
+ if (line == NULL) {
+ if (error != NULL) {
+ g_warning ("%s: %s", path, error->message);
+ g_error_free (error);
+ }
+ break;
+ }
+
+ 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;
+ }
+
+ g_object_unref (stream);
+ g_free (prefix);
+
+ return description;
+}
+
+static void
+add_device (OssBackend *oss, OssDevice *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,
+ g_strdup (oss_device_get_path (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 = oss_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 = oss_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 (OssBackend *oss, OssDevice *device)
+{
+ MateMixerStream *stream;
+ const gchar *path;
+
+ /* Remove the device streams first as they are a part of the device */
+ stream = oss_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 = oss_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);
+ }
+
+ path = oss_device_get_path (device);
+
+ /* Remove the device */
+ g_object_ref (device);
+
+ g_hash_table_remove (oss->priv->devices, path);
+ g_signal_emit_by_name (G_OBJECT (oss),
+ "device-removed",
+ mate_mixer_device_get_name (MATE_MIXER_DEVICE (device)));
+
+ g_object_unref (device);
}
diff --git a/backends/oss/oss-backend.h b/backends/oss/oss-backend.h
index 02567ed..b766799 100644
--- a/backends/oss/oss-backend.h
+++ b/backends/oss/oss-backend.h
@@ -36,12 +36,16 @@
#define OSS_BACKEND_GET_CLASS(o) \
(G_TYPE_INSTANCE_GET_CLASS ((o), OSS_TYPE_BACKEND, OssBackendClass))
-typedef struct _OssBackend OssBackend;
-typedef struct _OssBackendClass OssBackendClass;
+typedef struct _OssBackend OssBackend;
+typedef struct _OssBackendClass OssBackendClass;
+typedef struct _OssBackendPrivate OssBackendPrivate;
struct _OssBackend
{
GObject parent;
+
+ /*< private >*/
+ OssBackendPrivate *priv;
};
struct _OssBackendClass
diff --git a/backends/oss/oss-common.h b/backends/oss/oss-common.h
new file mode 100644
index 0000000..7251b86
--- /dev/null
+++ b/backends/oss/oss-common.h
@@ -0,0 +1,38 @@
+/*
+ * 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/>.
+ */
+
+#ifndef OSS_COMMON_H
+#define OSS_COMMON_H
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#ifdef HAVE_SYS_SOUNDCARD_H
+# include <sys/soundcard.h>
+#elif HAVE_SOUNDCARD_H
+# include <soundcard.h>
+#elif HAVE_MACHINE_SOUNDCARD_H
+# include <machine/soundcard.h>
+#else
+# error "No OSS header file present"
+#endif
+
+#endif /* OSS_COMMON_H */
diff --git a/backends/oss/oss-device.c b/backends/oss/oss-device.c
new file mode 100644
index 0000000..f33ff57
--- /dev/null
+++ b/backends/oss/oss-device.c
@@ -0,0 +1,525 @@
+/*
+ * 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 <errno.h>
+#include <unistd.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+
+#include <libmatemixer/matemixer-device.h>
+#include <libmatemixer/matemixer-enums.h>
+#include <libmatemixer/matemixer-port.h>
+#include <libmatemixer/matemixer-port-private.h>
+#include <libmatemixer/matemixer-stream.h>
+#include <libmatemixer/matemixer-stream-control.h>
+
+#include "oss-common.h"
+#include "oss-device.h"
+#include "oss-stream.h"
+#include "oss-stream-control.h"
+
+#define OSS_DEVICE_ICON "audio-card"
+
+typedef struct
+{
+ gchar *name;
+ gchar *description;
+ MateMixerStreamControlRole role;
+ MateMixerStreamFlags flags;
+} OssDeviceName;
+
+static const OssDeviceName const oss_devices[] = {
+ { "vol", N_("Volume"), MATE_MIXER_STREAM_CONTROL_ROLE_MASTER, MATE_MIXER_STREAM_OUTPUT },
+ { "bass", N_("Bass"), MATE_MIXER_STREAM_CONTROL_ROLE_BASS, MATE_MIXER_STREAM_OUTPUT },
+ { "treble", N_("Treble"), MATE_MIXER_STREAM_CONTROL_ROLE_TREBLE, MATE_MIXER_STREAM_OUTPUT },
+ { "synth", N_("Synth"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_INPUT },
+ { "pcm", N_("PCM"), MATE_MIXER_STREAM_CONTROL_ROLE_PCM, MATE_MIXER_STREAM_OUTPUT },
+ { "speaker", N_("Speaker"), MATE_MIXER_STREAM_CONTROL_ROLE_SPEAKER, MATE_MIXER_STREAM_OUTPUT },
+ { "line", N_("Line-in"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "mic", N_("Microphone"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "cd", N_("CD"), MATE_MIXER_STREAM_CONTROL_ROLE_CD, MATE_MIXER_STREAM_INPUT },
+ /* Recording monitor */
+ { "mix", N_("Mixer"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_OUTPUT },
+ { "pcm2", N_("PCM-2"), MATE_MIXER_STREAM_CONTROL_ROLE_PCM, MATE_MIXER_STREAM_OUTPUT },
+ /* Recording level (master input) */
+ { "rec", N_("Record"), MATE_MIXER_STREAM_CONTROL_ROLE_MASTER, MATE_MIXER_STREAM_INPUT },
+ { "igain", N_("In-gain"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_INPUT },
+ { "ogain", N_("Out-gain"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_OUTPUT },
+ { "line1", N_("Line-1"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "line2", N_("Line-2"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "line3", N_("Line-3"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "dig1", N_("Digital-1"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_NO_FLAGS },
+ { "dig2", N_("Digital-2"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_NO_FLAGS },
+ { "dig3", N_("Digital-3"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_NO_FLAGS },
+ { "phin", N_("Phone-in"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "phout", N_("Phone-out"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_OUTPUT },
+ { "video", N_("Video"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "radio", N_("Radio"), MATE_MIXER_STREAM_CONTROL_ROLE_PORT, MATE_MIXER_STREAM_INPUT },
+ { "monitor", N_("Monitor"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_OUTPUT },
+ { "depth", N_("3D-depth"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_OUTPUT },
+ { "center", N_("3D-center"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_OUTPUT },
+ { "midi", N_("MIDI"), MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN, MATE_MIXER_STREAM_INPUT }
+};
+
+struct _OssDevicePrivate
+{
+ gint fd;
+ gchar *path;
+ gchar *name;
+ gchar *description;
+ MateMixerStream *input;
+ MateMixerStream *output;
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_DESCRIPTION,
+ PROP_ICON,
+ PROP_ACTIVE_PROFILE,
+ PROP_PATH,
+ PROP_FD
+};
+
+static void mate_mixer_device_interface_init (MateMixerDeviceInterface *iface);
+
+static void oss_device_class_init (OssDeviceClass *klass);
+
+static void oss_device_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void oss_device_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void oss_device_init (OssDevice *device);
+static void oss_device_finalize (GObject *object);
+
+G_DEFINE_TYPE_WITH_CODE (OssDevice, oss_device, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (MATE_MIXER_TYPE_DEVICE,
+ mate_mixer_device_interface_init))
+
+static const gchar *oss_device_get_name (MateMixerDevice *device);
+static const gchar *oss_device_get_description (MateMixerDevice *device);
+static const gchar *oss_device_get_icon (MateMixerDevice *device);
+
+static gboolean read_mixer_devices (OssDevice *device);
+
+static void
+mate_mixer_device_interface_init (MateMixerDeviceInterface *iface)
+{
+ iface->get_name = oss_device_get_name;
+ iface->get_description = oss_device_get_description;
+ iface->get_icon = oss_device_get_icon;
+}
+
+static void
+oss_device_class_init (OssDeviceClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = oss_device_finalize;
+ object_class->get_property = oss_device_get_property;
+ object_class->set_property = oss_device_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_PATH,
+ g_param_spec_string ("path",
+ "Path",
+ "Path to the device",
+ NULL,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class,
+ PROP_FD,
+ g_param_spec_int ("fd",
+ "File descriptor",
+ "File descriptor of the device",
+ G_MININT,
+ G_MAXINT,
+ -1,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_override_property (object_class, PROP_NAME, "name");
+ g_object_class_override_property (object_class, PROP_DESCRIPTION, "description");
+ g_object_class_override_property (object_class, PROP_ICON, "icon");
+ g_object_class_override_property (object_class, PROP_ACTIVE_PROFILE, "active-profile");
+
+ g_type_class_add_private (object_class, sizeof (OssDevicePrivate));
+}
+
+static void
+oss_device_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ OssDevice *device;
+
+ device = OSS_DEVICE (object);
+
+ switch (param_id) {
+ case PROP_NAME:
+ g_value_set_string (value, device->priv->name);
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, device->priv->description);
+ break;
+ case PROP_ICON:
+ g_value_set_string (value, OSS_DEVICE_ICON);
+ break;
+ case PROP_ACTIVE_PROFILE:
+ /* Not supported */
+ g_value_set_object (value, NULL);
+ break;
+ case PROP_PATH:
+ g_value_set_string (value, device->priv->path);
+ break;
+ case PROP_FD:
+ g_value_set_int (value, device->priv->fd);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+oss_device_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ OssDevice *device;
+
+ device = OSS_DEVICE (object);
+
+ switch (param_id) {
+ case PROP_PATH:
+ /* Construct-only string */
+ device->priv->path = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_FD:
+ device->priv->fd = dup (g_value_get_int (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+oss_device_init (OssDevice *device)
+{
+ device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device,
+ OSS_TYPE_DEVICE,
+ OssDevicePrivate);
+}
+
+static void
+oss_device_finalize (GObject *object)
+{
+ OssDevice *device;
+
+ device = OSS_DEVICE (object);
+
+ g_free (device->priv->name);
+ g_free (device->priv->description);
+
+ if (device->priv->fd != -1)
+ g_close (device->priv->fd, NULL);
+
+ G_OBJECT_CLASS (oss_device_parent_class)->finalize (object);
+}
+
+OssDevice *
+oss_device_new (const gchar *path, gint fd)
+{
+ OssDevice *device;
+ gchar *basename;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ device = g_object_new (OSS_TYPE_DEVICE,
+ "path", path,
+ "fd", fd,
+ NULL);
+
+ basename = g_path_get_basename (path);
+
+ device->priv->name = g_strdup_printf ("oss-%s", basename);
+ g_free (basename);
+
+ return device;
+}
+
+gboolean
+oss_device_read (OssDevice *device)
+{
+ gchar *name;
+ gchar *basename;
+ MateMixerStreamControl *ctl;
+
+ g_return_val_if_fail (OSS_IS_DEVICE (device), FALSE);
+
+ // XXX avoid calling this function repeatedly
+
+ g_debug ("Querying device %s (%s)",
+ device->priv->path,
+ device->priv->description);
+
+ basename = g_path_get_basename (device->priv->path);
+
+ name = g_strdup_printf ("oss-input-%s", basename);
+ device->priv->input = MATE_MIXER_STREAM (oss_stream_new (name,
+ device->priv->description,
+ MATE_MIXER_STREAM_INPUT));
+ g_free (name);
+
+ name = g_strdup_printf ("oss-output-%s", basename);
+ device->priv->output = MATE_MIXER_STREAM (oss_stream_new (name,
+ device->priv->description,
+ MATE_MIXER_STREAM_OUTPUT |
+ MATE_MIXER_STREAM_PORTS_FIXED));
+ g_free (name);
+
+ if (read_mixer_devices (device) == FALSE)
+ return FALSE;
+
+ // XXX prefer active ports as default if there is no default
+
+ ctl = mate_mixer_stream_get_default_control (device->priv->input);
+ if (ctl == NULL) {
+ const GList *list = mate_mixer_stream_list_controls (device->priv->input);
+
+ if (list != NULL) {
+ ctl = MATE_MIXER_STREAM_CONTROL (list->data);
+ oss_stream_set_default_control (OSS_STREAM (device->priv->input),
+ OSS_STREAM_CONTROL (ctl));
+ } else
+ g_clear_object (&device->priv->input);
+ }
+
+ if (ctl != NULL)
+ g_debug ("Default input stream control is %s",
+ mate_mixer_stream_control_get_description (ctl));
+
+ ctl = mate_mixer_stream_get_default_control (device->priv->output);
+ if (ctl == NULL) {
+ const GList *list = mate_mixer_stream_list_controls (device->priv->output);
+
+ if (list != NULL) {
+ ctl = MATE_MIXER_STREAM_CONTROL (list->data);
+ oss_stream_set_default_control (OSS_STREAM (device->priv->output),
+ OSS_STREAM_CONTROL (ctl));
+ } else
+ g_clear_object (&device->priv->output);
+ }
+
+ if (ctl != NULL)
+ g_debug ("Default output stream control is %s",
+ mate_mixer_stream_control_get_description (ctl));
+
+ return TRUE;
+}
+
+const gchar *
+oss_device_get_path (OssDevice *odevice)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (odevice), FALSE);
+
+ return odevice->priv->path;
+}
+
+MateMixerStream *
+oss_device_get_input_stream (OssDevice *odevice)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (odevice), FALSE);
+
+ return odevice->priv->input;
+}
+
+MateMixerStream *
+oss_device_get_output_stream (OssDevice *odevice)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (odevice), FALSE);
+
+ return odevice->priv->output;
+}
+
+gboolean
+oss_device_set_description (OssDevice *odevice, const gchar *description)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (odevice), FALSE);
+
+ if (g_strcmp0 (odevice->priv->description, description) != 0) {
+ g_free (odevice->priv->description);
+
+ odevice->priv->description = g_strdup (description);
+
+ g_object_notify (G_OBJECT (odevice), "description");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+read_mixer_devices (OssDevice *device)
+{
+ gint devmask,
+ stereomask,
+ recmask;
+ gint ret;
+ gint i;
+ OssStreamControl *ctl;
+
+ ret = ioctl (device->priv->fd, MIXER_READ (SOUND_MIXER_DEVMASK), &devmask);
+ if (ret < 0)
+ goto fail;
+ ret = ioctl (device->priv->fd, MIXER_READ (SOUND_MIXER_STEREODEVS), &stereomask);
+ if (ret < 0)
+ goto fail;
+ ret = ioctl (device->priv->fd, MIXER_READ (SOUND_MIXER_RECMASK), &recmask);
+ if (ret < 0)
+ goto fail;
+
+ for (i = 0; i < MIN (G_N_ELEMENTS (oss_devices), SOUND_MIXER_NRDEVICES); i++) {
+ gboolean stereo;
+ gboolean input = FALSE;
+ MateMixerPort *port = NULL;
+
+ /* Skip unavailable controls */
+ if ((devmask & (1 << i)) == 0)
+ continue;
+
+ if ((stereomask & (1 << i)) > 0)
+ stereo = TRUE;
+ else
+ stereo = FALSE;
+
+ if (oss_devices[i].flags == MATE_MIXER_STREAM_NO_FLAGS) {
+ if ((recmask & (1 << i)) > 0)
+ input = TRUE;
+ }
+ if (oss_devices[i].flags == MATE_MIXER_STREAM_INPUT) {
+ if ((recmask & (1 << i)) == 0) {
+ g_debug ("Skipping non-input device %s", oss_devices[i].name);
+ continue;
+ }
+ input = TRUE;
+ }
+
+ ctl = oss_stream_control_new (device->priv->fd,
+ i,
+ oss_devices[i].name,
+ oss_devices[i].description,
+ stereo);
+
+ if (oss_devices[i].role == MATE_MIXER_STREAM_CONTROL_ROLE_PORT)
+ port = _mate_mixer_port_new (oss_devices[i].name,
+ oss_devices[i].description,
+ NULL,
+ 0,
+ 0);
+
+ if (input == TRUE) {
+ oss_stream_add_control (OSS_STREAM (device->priv->input), ctl);
+
+ if (i == SOUND_MIXER_RECLEV || i == SOUND_MIXER_IGAIN) {
+ if (i == SOUND_MIXER_RECLEV) {
+ oss_stream_set_default_control (OSS_STREAM (device->priv->input), ctl);
+ } else {
+ MateMixerStreamControl *defctl;
+
+ defctl = mate_mixer_stream_get_default_control (device->priv->input);
+ if (defctl == NULL)
+ oss_stream_set_default_control (OSS_STREAM (device->priv->input), ctl);
+ }
+ }
+
+ if (port != NULL)
+ oss_stream_add_port (OSS_STREAM (device->priv->input), port);
+ } else {
+ oss_stream_add_control (OSS_STREAM (device->priv->output), ctl);
+
+ if (i == SOUND_MIXER_VOLUME) {
+ oss_stream_set_default_control (OSS_STREAM (device->priv->output), ctl);
+ }
+ else if (i == SOUND_MIXER_PCM) {
+ MateMixerStreamControl *defctl;
+
+ defctl = mate_mixer_stream_get_default_control (device->priv->output);
+ if (defctl == NULL)
+ oss_stream_set_default_control (OSS_STREAM (device->priv->output), ctl);
+ }
+
+ if (port != NULL)
+ oss_stream_add_port (OSS_STREAM (device->priv->output), port);
+ }
+
+ if (port != NULL)
+ oss_stream_control_set_port (ctl, port);
+
+ oss_stream_control_set_role (ctl, oss_devices[i].role);
+
+ g_debug ("Added control %s",
+ mate_mixer_stream_control_get_description (MATE_MIXER_STREAM_CONTROL (ctl)));
+
+ oss_stream_control_update (ctl);
+ }
+ return TRUE;
+
+fail:
+ g_warning ("Failed to read device %s: %s",
+ device->priv->path,
+ g_strerror (errno));
+
+ return FALSE;
+}
+
+static const gchar *
+oss_device_get_name (MateMixerDevice *device)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (device), NULL);
+
+ return OSS_DEVICE (device)->priv->name;
+}
+
+static const gchar *
+oss_device_get_description (MateMixerDevice *device)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (device), NULL);
+
+ return OSS_DEVICE (device)->priv->description;
+}
+
+static const gchar *
+oss_device_get_icon (MateMixerDevice *device)
+{
+ g_return_val_if_fail (OSS_IS_DEVICE (device), NULL);
+
+ return OSS_DEVICE_ICON;
+}
diff --git a/backends/oss/oss-device.h b/backends/oss/oss-device.h
new file mode 100644
index 0000000..fe40eb2
--- /dev/null
+++ b/backends/oss/oss-device.h
@@ -0,0 +1,73 @@
+/*
+ * 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/>.
+ */
+
+#ifndef OSS_DEVICE_H
+#define OSS_DEVICE_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define OSS_TYPE_DEVICE \
+ (oss_device_get_type ())
+#define OSS_DEVICE(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), OSS_TYPE_DEVICE, OssDevice))
+#define OSS_IS_DEVICE(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSS_TYPE_DEVICE))
+#define OSS_DEVICE_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_CAST ((k), OSS_TYPE_DEVICE, OssDeviceClass))
+#define OSS_IS_DEVICE_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_TYPE ((k), OSS_TYPE_DEVICE))
+#define OSS_DEVICE_GET_CLASS(o) \
+ (G_TYPE_INSTANCE_GET_CLASS ((o), OSS_TYPE_DEVICE, OssDeviceClass))
+
+typedef struct _OssDevice OssDevice;
+typedef struct _OssDeviceClass OssDeviceClass;
+typedef struct _OssDevicePrivate OssDevicePrivate;
+
+struct _OssDevice
+{
+ GObject parent;
+
+ /*< private >*/
+ OssDevicePrivate *priv;
+};
+
+struct _OssDeviceClass
+{
+ GObjectClass parent;
+};
+
+GType oss_device_get_type (void) G_GNUC_CONST;
+
+OssDevice * oss_device_new (const gchar *path,
+ gint fd);
+
+gboolean oss_device_read (OssDevice *device);
+
+const gchar * oss_device_get_path (OssDevice *odevice);
+
+MateMixerStream *oss_device_get_input_stream (OssDevice *odevice);
+MateMixerStream *oss_device_get_output_stream (OssDevice *odevice);
+
+gboolean oss_device_set_description (OssDevice *odevice,
+ const gchar *description);
+
+G_END_DECLS
+
+#endif /* OSS_DEVICE_H */
diff --git a/backends/oss/oss-stream-control.c b/backends/oss/oss-stream-control.c
new file mode 100644
index 0000000..0b1db26
--- /dev/null
+++ b/backends/oss/oss-stream-control.c
@@ -0,0 +1,529 @@
+/*
+ * 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 <unistd.h>
+#include <errno.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+
+#include <libmatemixer/matemixer-port.h>
+#include <libmatemixer/matemixer-stream-control.h>
+
+#include "oss-common.h"
+#include "oss-stream-control.h"
+
+struct _OssStreamControlPrivate
+{
+ gint fd;
+ gint dev_number;
+ gchar *name;
+ gchar *description;
+ guint volume[2];
+ gfloat balance;
+ gboolean stereo;
+ MateMixerPort *port;
+ MateMixerStreamControlRole role;
+ MateMixerStreamControlFlags flags;
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_DESCRIPTION,
+ PROP_FLAGS,
+ PROP_MUTE,
+ PROP_VOLUME,
+ PROP_BALANCE,
+ PROP_FADE,
+ PROP_FD,
+ PROP_DEV_NUMBER,
+ PROP_STEREO
+};
+
+static void mate_mixer_stream_control_interface_init (MateMixerStreamControlInterface *iface);
+
+static void oss_stream_control_class_init (OssStreamControlClass *klass);
+
+static void oss_stream_control_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void oss_stream_control_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void oss_stream_control_init (OssStreamControl *octl);
+static void oss_stream_control_finalize (GObject *object);
+
+G_DEFINE_TYPE_WITH_CODE (OssStreamControl, oss_stream_control, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (MATE_MIXER_TYPE_STREAM_CONTROL,
+ mate_mixer_stream_control_interface_init))
+
+static const gchar * oss_stream_control_get_name (MateMixerStreamControl *ctl);
+static const gchar * oss_stream_control_get_description (MateMixerStreamControl *ctl);
+
+static guint oss_stream_control_get_num_channels (MateMixerStreamControl *ctl);
+
+static gboolean oss_stream_control_set_volume (MateMixerStreamControl *ctl,
+ guint volume);
+
+static guint oss_stream_control_get_channel_volume (MateMixerStreamControl *ctl,
+ guint channel);
+static gboolean oss_stream_control_set_channel_volume (MateMixerStreamControl *ctl,
+ guint channel,
+ guint volume);
+
+static MateMixerChannelPosition oss_stream_control_get_channel_position (MateMixerStreamControl *ctl,
+ guint channel);
+static gboolean oss_stream_control_has_channel_position (MateMixerStreamControl *ctl,
+ MateMixerChannelPosition position);
+
+static gboolean oss_stream_control_set_balance (MateMixerStreamControl *ctl,
+ gfloat balance);
+
+static guint oss_stream_control_get_min_volume (MateMixerStreamControl *ctl);
+static guint oss_stream_control_get_max_volume (MateMixerStreamControl *ctl);
+static guint oss_stream_control_get_normal_volume (MateMixerStreamControl *ctl);
+static guint oss_stream_control_get_base_volume (MateMixerStreamControl *ctl);
+
+static void
+mate_mixer_stream_control_interface_init (MateMixerStreamControlInterface *iface)
+{
+ iface->get_name = oss_stream_control_get_name;
+ iface->get_description = oss_stream_control_get_description;
+ iface->get_num_channels = oss_stream_control_get_num_channels;
+ iface->set_volume = oss_stream_control_set_volume;
+ iface->get_channel_volume = oss_stream_control_get_channel_volume;
+ iface->set_channel_volume = oss_stream_control_set_channel_volume;
+ iface->get_channel_position = oss_stream_control_get_channel_position;
+ iface->has_channel_position = oss_stream_control_has_channel_position;
+ iface->set_balance = oss_stream_control_set_balance;
+ iface->get_min_volume = oss_stream_control_get_min_volume;
+ iface->get_max_volume = oss_stream_control_get_max_volume;
+ iface->get_normal_volume = oss_stream_control_get_normal_volume;
+ iface->get_base_volume = oss_stream_control_get_base_volume;
+}
+
+static void
+oss_stream_control_class_init (OssStreamControlClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = oss_stream_control_finalize;
+ object_class->get_property = oss_stream_control_get_property;
+ object_class->set_property = oss_stream_control_set_property;
+
+ g_object_class_install_property (object_class,
+ PROP_FD,
+ g_param_spec_int ("fd",
+ "File descriptor",
+ "File descriptor of the device",
+ G_MININT,
+ G_MAXINT,
+ -1,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class,
+ PROP_DEV_NUMBER,
+ g_param_spec_int ("dev-number",
+ "Dev number",
+ "OSS device number",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class,
+ PROP_STEREO,
+ g_param_spec_boolean ("stereo",
+ "Stereo",
+ "Stereo",
+ FALSE,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_class_override_property (object_class, PROP_NAME, "name");
+ g_object_class_override_property (object_class, PROP_DESCRIPTION, "description");
+ g_object_class_override_property (object_class, PROP_FLAGS, "flags");
+ g_object_class_override_property (object_class, PROP_MUTE, "mute");
+ g_object_class_override_property (object_class, PROP_VOLUME, "volume");
+ g_object_class_override_property (object_class, PROP_BALANCE, "balance");
+ g_object_class_override_property (object_class, PROP_FADE, "fade");
+
+ g_type_class_add_private (object_class, sizeof (OssStreamControlPrivate));
+}
+
+static void
+oss_stream_control_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ OssStreamControl *octl;
+
+ octl = OSS_STREAM_CONTROL (object);
+
+ switch (param_id) {
+ case PROP_NAME:
+ g_value_set_string (value, octl->priv->name);
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, octl->priv->description);
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, octl->priv->flags);
+ break;
+ case PROP_MUTE:
+ /* Not supported */
+ g_value_set_boolean (value, FALSE);
+ break;
+ case PROP_VOLUME:
+ g_value_set_uint (value, MAX (octl->priv->volume[0], octl->priv->volume[1]));
+ break;
+ case PROP_BALANCE:
+ g_value_set_float (value, octl->priv->balance);
+ break;
+ case PROP_FADE:
+ /* Not supported */
+ g_value_set_float (value, 0.0f);
+ break;
+ case PROP_FD:
+ g_value_set_int (value, octl->priv->fd);
+ break;
+ case PROP_DEV_NUMBER:
+ g_value_set_int (value, octl->priv->dev_number);
+ break;
+ case PROP_STEREO:
+ g_value_set_boolean (value, octl->priv->stereo);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+oss_stream_control_set_property (GObject *object,
+ guint param_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ OssStreamControl *octl;
+
+ octl = OSS_STREAM_CONTROL (object);
+
+ switch (param_id) {
+ case PROP_FD:
+ octl->priv->fd = dup (g_value_get_int (value));
+ break;
+ case PROP_DEV_NUMBER:
+ octl->priv->dev_number = g_value_get_int (value);
+ break;
+ case PROP_STEREO:
+ octl->priv->stereo = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+oss_stream_control_init (OssStreamControl *octl)
+{
+ octl->priv = G_TYPE_INSTANCE_GET_PRIVATE (octl,
+ OSS_TYPE_STREAM_CONTROL,
+ OssStreamControlPrivate);
+}
+
+static void
+oss_stream_control_finalize (GObject *object)
+{
+ OssStreamControl *octl;
+
+ octl = OSS_STREAM_CONTROL (object);
+
+ g_free (octl->priv->name);
+ g_free (octl->priv->description);
+
+ if (octl->priv->fd != -1)
+ g_close (octl->priv->fd, NULL);
+
+ G_OBJECT_CLASS (oss_stream_control_parent_class)->finalize (object);
+}
+
+OssStreamControl *
+oss_stream_control_new (gint fd,
+ gint dev_number,
+ const gchar *name,
+ const gchar *description,
+ gboolean stereo)
+{
+ OssStreamControl *ctl;
+
+ ctl = g_object_new (OSS_TYPE_STREAM_CONTROL,
+ "fd", fd,
+ "dev-number", dev_number,
+ "stereo", stereo,
+ NULL);
+
+ ctl->priv->name = g_strdup (name);
+ ctl->priv->description = g_strdup (description);
+
+ return ctl;
+}
+
+gboolean
+oss_stream_control_update (OssStreamControl *octl)
+{
+ gint v;
+ gint ret;
+
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE);
+
+ ret = ioctl (octl->priv->fd, MIXER_READ (octl->priv->dev_number), &v);
+ if (ret < 0) {
+ g_warning ("Failed to read volume: %s", g_strerror (errno));
+ return FALSE;
+ }
+
+ octl->priv->volume[0] = v & 0xFF;
+
+ if (octl->priv->stereo == TRUE)
+ octl->priv->volume[1] = (v >> 8) & 0xFF;
+
+ return TRUE;
+}
+
+gboolean
+oss_stream_control_set_port (OssStreamControl *octl, MateMixerPort *port)
+{
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE);
+
+ // XXX provide property
+
+ if (octl->priv->port != NULL)
+ g_object_unref (octl->priv->port);
+
+ octl->priv->port = g_object_ref (port);
+ return TRUE;
+}
+
+gboolean
+oss_stream_control_set_role (OssStreamControl *octl, MateMixerStreamControlRole role)
+{
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE);
+
+ octl->priv->role = role;
+ return TRUE;
+}
+
+static const gchar *
+oss_stream_control_get_name (MateMixerStreamControl *ctl)
+{
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), NULL);
+
+ return OSS_STREAM_CONTROL (ctl)->priv->name;
+}
+
+static const gchar *
+oss_stream_control_get_description (MateMixerStreamControl *ctl)
+{
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), NULL);
+
+ return OSS_STREAM_CONTROL (ctl)->priv->description;
+}
+
+static guint
+oss_stream_control_get_num_channels (MateMixerStreamControl *ctl)
+{
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), 0);
+
+ if (OSS_STREAM_CONTROL (ctl)->priv->stereo == TRUE)
+ return 2;
+ else
+ return 1;
+}
+
+static gboolean
+oss_stream_control_set_volume (MateMixerStreamControl *ctl, guint volume)
+{
+ OssStreamControl *octl;
+ int v;
+ int ret;
+
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE);
+
+ octl = OSS_STREAM_CONTROL (ctl);
+
+ /* Some backends may allow setting higher value than maximum, but not here */
+ if (volume > 100)
+ volume = 100;
+
+ v = volume;
+ if (octl->priv->stereo == TRUE)
+ v |= (volume & 0xFF) << 8;
+
+ ret = ioctl (octl->priv->fd, MIXER_WRITE (octl->priv->dev_number), &v);
+ if (ret < 0) {
+ g_warning ("Failed to set volume: %s", g_strerror (errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static guint
+oss_stream_control_get_channel_volume (MateMixerStreamControl *ctl, guint channel)
+{
+ OssStreamControl *octl;
+
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), 0);
+
+ octl = OSS_STREAM_CONTROL (ctl);
+
+ if (channel > 1)
+ return 0;
+
+ /* Right channel on mono stream will always have zero volume */
+ return octl->priv->volume[channel];
+}
+
+static gboolean
+oss_stream_control_set_channel_volume (MateMixerStreamControl *ctl,
+ guint channel,
+ guint volume)
+{
+ OssStreamControl *octl;
+ int ret;
+ int v;
+
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE);
+
+ if (channel > 1)
+ return FALSE;
+
+ octl = OSS_STREAM_CONTROL (ctl);
+
+ /* Some backends may allow setting higher value than maximum, but not here */
+ if (volume > 100)
+ volume = 100;
+
+ if (channel == 0)
+ v = volume;
+ else
+ v = octl->priv->volume[0];
+
+ if (channel == 1) {
+ if (octl->priv->stereo == FALSE)
+ return FALSE;
+
+ v |= volume << 8;
+ } else
+ v |= octl->priv->volume[1] << 8;
+
+ ret = ioctl (octl->priv->fd, MIXER_WRITE (octl->priv->dev_number), &v);
+ if (ret < 0) {
+ g_warning ("Failed to set channel volume: %s", g_strerror (errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static MateMixerChannelPosition
+oss_stream_control_get_channel_position (MateMixerStreamControl *ctl, guint channel)
+{
+ OssStreamControl *octl;
+
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), MATE_MIXER_CHANNEL_UNKNOWN);
+
+ octl = OSS_STREAM_CONTROL (ctl);
+
+ if (octl->priv->stereo == TRUE) {
+ if (channel == 0)
+ return MATE_MIXER_CHANNEL_FRONT_LEFT;
+ else if (channel == 1)
+ return MATE_MIXER_CHANNEL_FRONT_RIGHT;
+ } else {
+ if (channel == 0)
+ return MATE_MIXER_CHANNEL_MONO;
+ }
+ return MATE_MIXER_CHANNEL_UNKNOWN;
+}
+
+static gboolean
+oss_stream_control_has_channel_position (MateMixerStreamControl *ctl,
+ MateMixerChannelPosition position)
+{
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE);
+
+ if (position == MATE_MIXER_CHANNEL_MONO)
+ return OSS_STREAM_CONTROL (ctl)->priv->stereo == FALSE;
+
+ if (position == MATE_MIXER_CHANNEL_FRONT_LEFT ||
+ position == MATE_MIXER_CHANNEL_FRONT_RIGHT)
+ return OSS_STREAM_CONTROL (ctl)->priv->stereo == TRUE;
+
+ return FALSE;
+}
+
+static gboolean
+oss_stream_control_set_balance (MateMixerStreamControl *ctl, gfloat balance)
+{
+ OssStreamControl *octl;
+
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (ctl), FALSE);
+
+ octl = OSS_STREAM_CONTROL (ctl);
+
+ if (octl->priv->stereo == FALSE)
+ return FALSE;
+
+ // XXX
+ return TRUE;
+}
+
+static guint
+oss_stream_control_get_min_volume (MateMixerStreamControl *ctl)
+{
+ return 0;
+}
+
+static guint
+oss_stream_control_get_max_volume (MateMixerStreamControl *ctl)
+{
+ return 100;
+}
+
+static guint
+oss_stream_control_get_normal_volume (MateMixerStreamControl *ctl)
+{
+ return 100;
+}
+
+static guint
+oss_stream_control_get_base_volume (MateMixerStreamControl *ctl)
+{
+ return 100;
+}
diff --git a/backends/oss/oss-stream-control.h b/backends/oss/oss-stream-control.h
new file mode 100644
index 0000000..420af48
--- /dev/null
+++ b/backends/oss/oss-stream-control.h
@@ -0,0 +1,74 @@
+/*
+ * 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/>.
+ */
+
+#ifndef OSS_STREAM_CONTROL_H
+#define OSS_STREAM_CONTROL_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define OSS_TYPE_STREAM_CONTROL \
+ (oss_stream_control_get_type ())
+#define OSS_STREAM_CONTROL(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), OSS_TYPE_STREAM_CONTROL, OssStreamControl))
+#define OSS_IS_STREAM_CONTROL(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSS_TYPE_STREAM_CONTROL))
+#define OSS_STREAM_CONTROL_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_CAST ((k), OSS_TYPE_STREAM_CONTROL, OssStreamControlClass))
+#define OSS_IS_STREAM_CONTROL_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_TYPE ((k), OSS_TYPE_STREAM_CONTROL))
+#define OSS_STREAM_CONTROL_GET_CLASS(o) \
+ (G_TYPE_INSTANCE_GET_CLASS ((o), OSS_TYPE_STREAM_CONTROL, OssStreamControlClass))
+
+typedef struct _OssStreamControl OssStreamControl;
+typedef struct _OssStreamControlClass OssStreamControlClass;
+typedef struct _OssStreamControlPrivate OssStreamControlPrivate;
+
+struct _OssStreamControl
+{
+ GObject parent;
+
+ /*< private >*/
+ OssStreamControlPrivate *priv;
+};
+
+struct _OssStreamControlClass
+{
+ GObjectClass parent;
+};
+
+GType oss_stream_control_get_type (void) G_GNUC_CONST;
+
+OssStreamControl *oss_stream_control_new (gint fd,
+ gint dev_number,
+ const gchar *name,
+ const gchar *description,
+ gboolean stereo);
+
+gboolean oss_stream_control_update (OssStreamControl *octl);
+
+gboolean oss_stream_control_set_port (OssStreamControl *octl,
+ MateMixerPort *port);
+
+gboolean oss_stream_control_set_role (OssStreamControl *octl,
+ MateMixerStreamControlRole role);
+
+G_END_DECLS
+
+#endif /* OSS_STREAM_CONTROL_H */
diff --git a/backends/oss/oss-stream.c b/backends/oss/oss-stream.c
new file mode 100644
index 0000000..69bfd06
--- /dev/null
+++ b/backends/oss/oss-stream.c
@@ -0,0 +1,315 @@
+/*
+ * 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 <string.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include <libmatemixer/matemixer-device.h>
+#include <libmatemixer/matemixer-enums.h>
+#include <libmatemixer/matemixer-stream.h>
+
+#include "oss-stream.h"
+#include "oss-stream-control.h"
+
+struct _OssStreamPrivate
+{
+ gchar *name;
+ gchar *description;
+ MateMixerDevice *device;
+ MateMixerStreamFlags flags;
+ MateMixerStreamState state;
+ GHashTable *ports;
+ GList *ports_list;
+ GHashTable *controls;
+ GList *controls_list;
+ OssStreamControl *control;
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_DESCRIPTION,
+ PROP_DEVICE,
+ PROP_FLAGS,
+ PROP_STATE,
+ PROP_ACTIVE_PORT,
+};
+
+static void mate_mixer_stream_interface_init (MateMixerStreamInterface *iface);
+
+static void oss_stream_class_init (OssStreamClass *klass);
+
+static void oss_stream_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void oss_stream_init (OssStream *ostream);
+static void oss_stream_dispose (GObject *object);
+static void oss_stream_finalize (GObject *object);
+
+G_DEFINE_TYPE_WITH_CODE (OssStream, oss_stream, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (MATE_MIXER_TYPE_STREAM,
+ mate_mixer_stream_interface_init))
+
+static const gchar * oss_stream_get_name (MateMixerStream *stream);
+static const gchar * oss_stream_get_description (MateMixerStream *stream);
+
+static MateMixerStreamControl *oss_stream_get_control (MateMixerStream *stream,
+ const gchar *name);
+static MateMixerStreamControl *oss_stream_get_default_control (MateMixerStream *stream);
+
+static const GList * oss_stream_list_controls (MateMixerStream *stream);
+static const GList * oss_stream_list_ports (MateMixerStream *stream);
+
+static void
+mate_mixer_stream_interface_init (MateMixerStreamInterface *iface)
+{
+ iface->get_name = oss_stream_get_name;
+ iface->get_description = oss_stream_get_description;
+ iface->get_control = oss_stream_get_control;
+ iface->get_default_control = oss_stream_get_default_control;
+ iface->list_controls = oss_stream_list_controls;
+ iface->list_ports = oss_stream_list_ports;
+}
+
+static void
+oss_stream_class_init (OssStreamClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = oss_stream_dispose;
+ object_class->finalize = oss_stream_finalize;
+ object_class->get_property = oss_stream_get_property;
+
+ g_object_class_override_property (object_class, PROP_NAME, "name");
+ g_object_class_override_property (object_class, PROP_DESCRIPTION, "description");
+ g_object_class_override_property (object_class, PROP_DEVICE, "device");
+ g_object_class_override_property (object_class, PROP_FLAGS, "flags");
+ g_object_class_override_property (object_class, PROP_STATE, "state");
+ g_object_class_override_property (object_class, PROP_ACTIVE_PORT, "active-port");
+
+ g_type_class_add_private (object_class, sizeof (OssStreamPrivate));
+}
+
+static void
+oss_stream_get_property (GObject *object,
+ guint param_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ OssStream *ostream;
+
+ ostream = OSS_STREAM (object);
+
+ switch (param_id) {
+ case PROP_NAME:
+ g_value_set_string (value, ostream->priv->name);
+ break;
+ case PROP_DESCRIPTION:
+ g_value_set_string (value, ostream->priv->description);
+ break;
+ case PROP_DEVICE:
+ g_value_set_object (value, ostream->priv->device);
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, ostream->priv->flags);
+ break;
+ case PROP_STATE:
+ /* Not supported */
+ g_value_set_enum (value, MATE_MIXER_STREAM_STATE_UNKNOWN);
+ break;
+ case PROP_ACTIVE_PORT:
+ // XXX
+ g_value_set_object (value, NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+oss_stream_init (OssStream *ostream)
+{
+ ostream->priv = G_TYPE_INSTANCE_GET_PRIVATE (ostream,
+ OSS_TYPE_STREAM,
+ OssStreamPrivate);
+
+ ostream->priv->controls = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+
+ ostream->priv->ports = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ g_object_unref);
+}
+
+static void
+oss_stream_dispose (GObject *object)
+{
+ OssStream *ostream;
+
+ ostream = OSS_STREAM (object);
+
+ g_hash_table_remove_all (ostream->priv->controls);
+ g_hash_table_remove_all (ostream->priv->ports);
+
+ G_OBJECT_CLASS (oss_stream_parent_class)->finalize (object);
+}
+
+static void
+oss_stream_finalize (GObject *object)
+{
+ OssStream *ostream;
+
+ ostream = OSS_STREAM (object);
+
+ g_free (ostream->priv->name);
+ g_free (ostream->priv->description);
+
+ g_hash_table_destroy (ostream->priv->controls);
+ g_hash_table_destroy (ostream->priv->ports);
+
+ G_OBJECT_CLASS (oss_stream_parent_class)->finalize (object);
+}
+
+OssStream *
+oss_stream_new (const gchar *name,
+ const gchar *description,
+ MateMixerStreamFlags flags)
+{
+ OssStream *stream;
+
+ stream = g_object_new (OSS_TYPE_STREAM, NULL);
+
+ stream->priv->name = g_strdup (name);
+ stream->priv->description = g_strdup (description);
+ stream->priv->flags = flags;
+
+ return stream;
+}
+
+gboolean
+oss_stream_add_control (OssStream *ostream, OssStreamControl *octl)
+{
+ const gchar *name;
+
+ g_return_val_if_fail (OSS_IS_STREAM (ostream), FALSE);
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE);
+
+ name = mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (octl));
+
+ g_hash_table_insert (ostream->priv->controls,
+ g_strdup (name),
+ octl);
+ return TRUE;
+}
+
+gboolean
+oss_stream_set_default_control (OssStream *ostream, OssStreamControl *octl)
+{
+ g_return_val_if_fail (OSS_IS_STREAM (ostream), FALSE);
+ g_return_val_if_fail (OSS_IS_STREAM_CONTROL (octl), FALSE);
+
+ /* This function is only used internally so avoid validating that the control
+ * belongs to this stream */
+ if (ostream->priv->control != NULL)
+ g_object_unref (ostream->priv->control);
+
+ ostream->priv->control = g_object_ref (octl);
+ return TRUE;
+}
+
+gboolean
+oss_stream_add_port (OssStream *ostream, MateMixerPort *port)
+{
+ g_return_val_if_fail (OSS_IS_STREAM (ostream), FALSE);
+ g_return_val_if_fail (MATE_MIXER_IS_PORT (port), FALSE);
+
+ g_hash_table_insert (ostream->priv->ports,
+ g_strdup (mate_mixer_port_get_name (port)),
+ port);
+ return TRUE;
+}
+
+static const gchar *
+oss_stream_get_name (MateMixerStream *stream)
+{
+ g_return_val_if_fail (OSS_IS_STREAM (stream), NULL);
+
+ return OSS_STREAM (stream)->priv->name;
+}
+
+static const gchar *
+oss_stream_get_description (MateMixerStream *stream)
+{
+ g_return_val_if_fail (OSS_IS_STREAM (stream), NULL);
+
+ return OSS_STREAM (stream)->priv->description;
+}
+
+static MateMixerStreamControl *
+oss_stream_get_control (MateMixerStream *stream, const gchar *name)
+{
+ g_return_val_if_fail (OSS_IS_STREAM (stream), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ return g_hash_table_lookup (OSS_STREAM (stream)->priv->controls, name);
+}
+
+static MateMixerStreamControl *
+oss_stream_get_default_control (MateMixerStream *stream)
+{
+ g_return_val_if_fail (OSS_IS_STREAM (stream), NULL);
+
+ return MATE_MIXER_STREAM_CONTROL (OSS_STREAM (stream)->priv->control);
+}
+
+static const GList *
+oss_stream_list_controls (MateMixerStream *stream)
+{
+ OssStream *ostream;
+
+ g_return_val_if_fail (OSS_IS_STREAM (stream), NULL);
+
+ ostream = OSS_STREAM (stream);
+
+ if (ostream->priv->controls_list == NULL)
+ ostream->priv->controls_list = g_hash_table_get_values (ostream->priv->controls);
+
+ return ostream->priv->controls_list;
+}
+
+static const GList *
+oss_stream_list_ports (MateMixerStream *stream)
+{
+ OssStream *ostream;
+
+ g_return_val_if_fail (OSS_IS_STREAM (stream), NULL);
+
+ ostream = OSS_STREAM (stream);
+
+ if (ostream->priv->ports_list == NULL)
+ ostream->priv->ports_list = g_hash_table_get_values (ostream->priv->ports);
+
+ return ostream->priv->ports_list;
+}
diff --git a/backends/oss/oss-stream.h b/backends/oss/oss-stream.h
new file mode 100644
index 0000000..d6c2fb2
--- /dev/null
+++ b/backends/oss/oss-stream.h
@@ -0,0 +1,75 @@
+/*
+ * 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/>.
+ */
+
+#ifndef OSS_STREAM_H
+#define OSS_STREAM_H
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "oss-stream-control.h"
+
+G_BEGIN_DECLS
+
+#define OSS_TYPE_STREAM \
+ (oss_stream_get_type ())
+#define OSS_STREAM(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), OSS_TYPE_STREAM, OssStream))
+#define OSS_IS_STREAM(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSS_TYPE_STREAM))
+#define OSS_STREAM_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_CAST ((k), OSS_TYPE_STREAM, OssStreamClass))
+#define OSS_IS_STREAM_CLASS(k) \
+ (G_TYPE_CHECK_CLASS_TYPE ((k), OSS_TYPE_STREAM))
+#define OSS_STREAM_GET_CLASS(o) \
+ (G_TYPE_INSTANCE_GET_CLASS ((o), OSS_TYPE_STREAM, OssStreamClass))
+
+typedef struct _OssStream OssStream;
+typedef struct _OssStreamClass OssStreamClass;
+typedef struct _OssStreamPrivate OssStreamPrivate;
+
+struct _OssStream
+{
+ GObject parent;
+
+ /*< private >*/
+ OssStreamPrivate *priv;
+};
+
+struct _OssStreamClass
+{
+ GObjectClass parent;
+};
+
+GType oss_stream_get_type (void) G_GNUC_CONST;
+
+OssStream * oss_stream_new (const gchar *name,
+ const gchar *description,
+ MateMixerStreamFlags flags);
+
+gboolean oss_stream_add_control (OssStream *stream,
+ OssStreamControl *ctl);
+
+gboolean oss_stream_set_default_control (OssStream *stream,
+ OssStreamControl *ctl);
+
+gboolean oss_stream_add_port (OssStream *ostream,
+ MateMixerPort *port);
+
+G_END_DECLS
+
+#endif /* OSS_STREAM_H */
diff --git a/configure.ac b/configure.ac
index d9bffc6..65e06e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -67,6 +67,7 @@ PKG_CHECK_MODULES(GLIB, [
glib-2.0 >= $GLIB_REQUIRED_VERSION
gobject-2.0 >= $GLIB_REQUIRED_VERSION
gmodule-2.0 >= $GLIB_REQUIRED_VERSION
+ gio-2.0 >= $GLIB_REQUIRED_VERSION
])
GTK_DOC_CHECK([1.10], [--flavour no-tmpl])
@@ -131,6 +132,7 @@ if test "x$enable_oss" != "xno"; then
if test "x$ac_cv_header_soundcard_h" = "xyes" -o \
"x$ac_cv_header_sys_soundcard_h" = "xyes" -o \
"x$ac_cv_header_machine_soundcard_h" = "xyes"; then
+ AC_CHECK_LIB([ossaudio], [_oss_ioctl], [OSS_LIBS="-lossaudio"])
have_oss=yes
else
have_oss=no
@@ -151,6 +153,7 @@ AM_CONDITIONAL(HAVE_OSS, test "x$have_oss" = "xyes")
AC_SUBST(HAVE_OSS)
AC_SUBST(OSS_CFLAGS)
+AC_SUBST(OSS_LIBS)
# =======================================================================
# Compiler warnings
diff --git a/examples/monitor.c b/examples/monitor.c
index 3267b36..dca5105 100644
--- a/examples/monitor.c
+++ b/examples/monitor.c
@@ -89,7 +89,7 @@ create_role_string (MateMixerClientStreamRole role)
}
static gchar *
-create_volume_bar (MateMixerStream *stream, double *percent)
+create_volume_bar (MateMixerStreamControl *ctl, double *percent)
{
GString *string;
gint64 volume;
@@ -100,9 +100,9 @@ create_volume_bar (MateMixerStream *stream, double *percent)
int length = 30;
int stars;
- volume = mate_mixer_stream_get_volume (stream);
- volume_min = mate_mixer_stream_get_min_volume (stream);
- volume_max = mate_mixer_stream_get_normal_volume (stream);
+ volume = mate_mixer_stream_control_get_volume (ctl);
+ volume_min = mate_mixer_stream_control_get_min_volume (ctl);
+ volume_max = mate_mixer_stream_control_get_normal_volume (ctl);
string = g_string_new ("[");
@@ -192,24 +192,21 @@ print_streams (void)
streams = mate_mixer_control_list_streams (control);
while (streams) {
- MateMixerStream *stream = MATE_MIXER_STREAM (streams->data);
- MateMixerClientStream *client = NULL;
- gchar *volume_bar;
- gdouble volume;
+ MateMixerStream *stream = MATE_MIXER_STREAM (streams->data);
+ MateMixerStreamControl *ctl;
+ MateMixerClientStream *client = NULL;
+ gchar *volume_bar;
+ gdouble volume;
if (mate_mixer_stream_get_flags (stream) & MATE_MIXER_STREAM_CLIENT) {
/* The application-specific details are accessible through the client
* interface, which all client streams implement */
client = MATE_MIXER_CLIENT_STREAM (stream);
-
- /* Ignore event streams */
- if (mate_mixer_client_stream_get_role (client) == MATE_MIXER_CLIENT_STREAM_ROLE_EVENT) {
- streams = streams->next;
- continue;
- }
}
- volume_bar = create_volume_bar (stream, &volume);
+ ctl = mate_mixer_stream_get_default_control (stream);
+
+ volume_bar = create_volume_bar (ctl, &volume);
g_print ("Stream %s\n"
" |-| Description : %s\n"
@@ -222,10 +219,10 @@ print_streams (void)
mate_mixer_stream_get_description (stream),
volume_bar,
volume,
- mate_mixer_stream_get_mute (stream) ? "Yes" : "No",
- mate_mixer_stream_get_num_channels (stream),
- mate_mixer_stream_get_balance (stream),
- mate_mixer_stream_get_fade (stream));
+ mate_mixer_stream_control_get_mute (ctl) ? "Yes" : "No",
+ mate_mixer_stream_control_get_num_channels (ctl),
+ mate_mixer_stream_control_get_balance (ctl),
+ mate_mixer_stream_control_get_fade (ctl));
if (client != NULL) {
MateMixerClientStreamFlags client_flags;
@@ -275,17 +272,20 @@ print_cached_streams (void)
while (streams) {
MateMixerStream *stream = MATE_MIXER_STREAM (streams->data);
+ MateMixerStreamControl *ctl;
MateMixerClientStream *client;
MateMixerClientStreamFlags client_flags;
MateMixerClientStreamRole client_role;
gchar *volume_bar;
gdouble volume;
- client = MATE_MIXER_CLIENT_STREAM (stream);
+ ctl = mate_mixer_stream_get_default_control (stream);
+
+ client = MATE_MIXER_CLIENT_STREAM (stream);
client_flags = mate_mixer_client_stream_get_flags (client);
client_role = mate_mixer_client_stream_get_role (client);
- volume_bar = create_volume_bar (stream, &volume);
+ volume_bar = create_volume_bar (ctl, &volume);
g_print ("Cached stream %s\n"
" |-| Role : %s\n"
@@ -298,10 +298,10 @@ print_cached_streams (void)
create_role_string (client_role),
volume_bar,
volume,
- mate_mixer_stream_get_mute (stream) ? "Yes" : "No",
- mate_mixer_stream_get_num_channels (stream),
- mate_mixer_stream_get_balance (stream),
- mate_mixer_stream_get_fade (stream));
+ mate_mixer_stream_control_get_mute (ctl) ? "Yes" : "No",
+ mate_mixer_stream_control_get_num_channels (ctl),
+ mate_mixer_stream_control_get_balance (ctl),
+ mate_mixer_stream_control_get_fade (ctl));
if (client_flags & MATE_MIXER_CLIENT_STREAM_APPLICATION) {
gchar *app = create_app_string (mate_mixer_client_stream_get_app_name (client),
@@ -394,7 +394,7 @@ int main (int argc, char *argv[])
GError *error = NULL;
GOptionEntry entries[] = {
- { "backend", 'b', 0, G_OPTION_ARG_STRING, &backend, "Sound system to use (pulseaudio, null)", NULL },
+ { "backend", 'b', 0, G_OPTION_ARG_STRING, &backend, "Sound system to use (pulseaudio, oss, oss4, null)", NULL },
{ "server", 's', 0, G_OPTION_ARG_STRING, &server, "Sound server address", NULL },
{ NULL }
};
@@ -427,6 +427,10 @@ int main (int argc, char *argv[])
if (backend) {
if (!strcmp (backend, "pulseaudio"))
mate_mixer_control_set_backend_type (control, MATE_MIXER_BACKEND_PULSEAUDIO);
+ else if (!strcmp (backend, "oss"))
+ mate_mixer_control_set_backend_type (control, MATE_MIXER_BACKEND_OSS);
+ else if (!strcmp (backend, "oss4"))
+ mate_mixer_control_set_backend_type (control, MATE_MIXER_BACKEND_OSS4);
else if (!strcmp (backend, "null"))
mate_mixer_control_set_backend_type (control, MATE_MIXER_BACKEND_NULL);
else
diff --git a/libmatemixer/Makefile.am b/libmatemixer/Makefile.am
index 8c219d4..9666684 100644
--- a/libmatemixer/Makefile.am
+++ b/libmatemixer/Makefile.am
@@ -17,6 +17,7 @@ libmatemixer_include_HEADERS = \
matemixer-enums.h \
matemixer-port.h \
matemixer-stream.h \
+ matemixer-stream-control.h \
matemixer-version.h
libmatemixer_la_CFLAGS = $(GLIB_CFLAGS)
@@ -37,7 +38,8 @@ libmatemixer_la_SOURCES = \
matemixer-enum-types.h \
matemixer-port.c \
matemixer-port-private.h \
- matemixer-stream.c
+ matemixer-stream.c \
+ matemixer-stream-control.c
libmatemixer_la_LIBADD = $(GLIB_LIBS)
diff --git a/libmatemixer/matemixer-backend.c b/libmatemixer/matemixer-backend.c
index be5c704..e070090 100644
--- a/libmatemixer/matemixer-backend.c
+++ b/libmatemixer/matemixer-backend.c
@@ -176,10 +176,15 @@ mate_mixer_backend_close (MateMixerBackend *backend)
MateMixerState
mate_mixer_backend_get_state (MateMixerBackend *backend)
{
+ MateMixerState state = MATE_MIXER_STATE_UNKNOWN;
+
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), MATE_MIXER_STATE_UNKNOWN);
- /* Implementation required */
- return MATE_MIXER_BACKEND_GET_INTERFACE (backend)->get_state (backend);
+ g_object_get (G_OBJECT (backend),
+ "state", &state,
+ NULL);
+
+ return state;
}
GList *
@@ -230,16 +235,18 @@ mate_mixer_backend_list_cached_streams (MateMixerBackend *backend)
MateMixerStream *
mate_mixer_backend_get_default_input_stream (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
+ MateMixerStream *stream = NULL;
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ g_object_get (G_OBJECT (stream),
+ "default-input", &stream,
+ NULL);
- if (iface->get_default_input_stream)
- return iface->get_default_input_stream (backend);
+ if (stream != NULL)
+ g_object_unref (stream);
- return NULL;
+ return stream;
}
gboolean
@@ -261,16 +268,18 @@ mate_mixer_backend_set_default_input_stream (MateMixerBackend *backend,
MateMixerStream *
mate_mixer_backend_get_default_output_stream (MateMixerBackend *backend)
{
- MateMixerBackendInterface *iface;
+ MateMixerStream *stream = NULL;
g_return_val_if_fail (MATE_MIXER_IS_BACKEND (backend), NULL);
- iface = MATE_MIXER_BACKEND_GET_INTERFACE (backend);
+ g_object_get (G_OBJECT (stream),
+ "default-output", &stream,
+ NULL);
- if (iface->get_default_output_stream)
- return iface->get_default_output_stream (backend);
+ if (stream != NULL)
+ g_object_unref (stream);
- return NULL;
+ return stream;
}
gboolean
diff --git a/libmatemixer/matemixer-enum-types.c b/libmatemixer/matemixer-enum-types.c
index 339b673..50e3bf4 100644
--- a/libmatemixer/matemixer-enum-types.c
+++ b/libmatemixer/matemixer-enum-types.c
@@ -94,14 +94,7 @@ mate_mixer_stream_flags_get_type (void)
{ MATE_MIXER_STREAM_INPUT, "MATE_MIXER_STREAM_INPUT", "input" },
{ MATE_MIXER_STREAM_OUTPUT, "MATE_MIXER_STREAM_OUTPUT", "output" },
{ MATE_MIXER_STREAM_CLIENT, "MATE_MIXER_STREAM_CLIENT", "client" },
- { MATE_MIXER_STREAM_HAS_MUTE, "MATE_MIXER_STREAM_HAS_MUTE", "has-mute" },
- { MATE_MIXER_STREAM_HAS_VOLUME, "MATE_MIXER_STREAM_HAS_VOLUME", "has-volume" },
- { MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME, "MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME", "has-decibel-volume" },
- { MATE_MIXER_STREAM_HAS_FLAT_VOLUME, "MATE_MIXER_STREAM_HAS_FLAT_VOLUME", "has-flat-volume" },
{ MATE_MIXER_STREAM_HAS_MONITOR, "MATE_MIXER_STREAM_HAS_MONITOR", "has-monitor" },
- { MATE_MIXER_STREAM_CAN_SET_VOLUME, "MATE_MIXER_STREAM_CAN_SET_VOLUME", "can-set-volume" },
- { MATE_MIXER_STREAM_CAN_BALANCE, "MATE_MIXER_STREAM_CAN_BALANCE", "can-balance" },
- { MATE_MIXER_STREAM_CAN_FADE, "MATE_MIXER_STREAM_CAN_FADE", "can-fade" },
{ MATE_MIXER_STREAM_CAN_SUSPEND, "MATE_MIXER_STREAM_CAN_SUSPEND", "can-suspend" },
{ 0, NULL, NULL }
};
@@ -133,6 +126,30 @@ mate_mixer_stream_state_get_type (void)
}
GType
+mate_mixer_stream_control_flags_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GFlagsValue values[] = {
+ { MATE_MIXER_STREAM_CONTROL_NO_FLAGS, "MATE_MIXER_STREAM_CONTROL_NO_FLAGS", "no-flags" },
+ { MATE_MIXER_STREAM_CONTROL_HAS_MUTE, "MATE_MIXER_STREAM_CONTROL_HAS_MUTE", "has-mute" },
+ { MATE_MIXER_STREAM_CONTROL_HAS_VOLUME, "MATE_MIXER_STREAM_CONTROL_HAS_VOLUME", "has-volume" },
+ { MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL_VOLUME, "MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL_VOLUME", "has-decibel-volume" },
+ { MATE_MIXER_STREAM_CONTROL_HAS_FLAT_VOLUME, "MATE_MIXER_STREAM_CONTROL_HAS_FLAT_VOLUME", "has-flat-volume" },
+ { MATE_MIXER_STREAM_CONTROL_CAN_SET_VOLUME, "MATE_MIXER_STREAM_CONTROL_CAN_SET_VOLUME", "can-set-volume" },
+ { MATE_MIXER_STREAM_CONTROL_CAN_BALANCE, "MATE_MIXER_STREAM_CONTROL_CAN_BALANCE", "can-balance" },
+ { MATE_MIXER_STREAM_CONTROL_CAN_FADE, "MATE_MIXER_STREAM_CONTROL_CAN_FADE", "can-fade" },
+ { 0, NULL, NULL }
+ };
+ etype = g_flags_register_static (
+ g_intern_static_string ("MateMixerStreamControlFlags"),
+ values);
+ }
+ return etype;
+}
+
+GType
mate_mixer_client_stream_flags_get_type (void)
{
static GType etype = 0;
diff --git a/libmatemixer/matemixer-enum-types.h b/libmatemixer/matemixer-enum-types.h
index 03c1297..1dc13cc 100644
--- a/libmatemixer/matemixer-enum-types.h
+++ b/libmatemixer/matemixer-enum-types.h
@@ -43,6 +43,9 @@ GType mate_mixer_stream_flags_get_type (void) G_GNUC_CONST;
#define MATE_MIXER_TYPE_STREAM_STATE (mate_mixer_stream_state_get_type ())
GType mate_mixer_stream_state_get_type (void) G_GNUC_CONST;
+#define MATE_MIXER_TYPE_STREAM_CONTROL_FLAGS (mate_mixer_stream_control_flags_get_type ())
+GType mate_mixer_stream_control_flags_get_type (void) G_GNUC_CONST;
+
#define MATE_MIXER_TYPE_CLIENT_STREAM_FLAGS (mate_mixer_client_stream_flags_get_type ())
GType mate_mixer_client_stream_flags_get_type (void) G_GNUC_CONST;
diff --git a/libmatemixer/matemixer-enums.h b/libmatemixer/matemixer-enums.h
index 7e523bb..b99f4c5 100644
--- a/libmatemixer/matemixer-enums.h
+++ b/libmatemixer/matemixer-enums.h
@@ -48,6 +48,7 @@ typedef enum {
* will be the first one to try unless you select a specific backend
* to connect to.
* @MATE_MIXER_BACKEND_OSS:
+ * @MATE_MIXER_BACKEND_OSS4:
* @MATE_MIXER_BACKEND_NULL:
* Fallback backend which never fails to initialize, but provides no
* functionality. This backend has the lowest priority and will be used
@@ -58,6 +59,7 @@ typedef enum {
MATE_MIXER_BACKEND_UNKNOWN,
MATE_MIXER_BACKEND_PULSEAUDIO,
MATE_MIXER_BACKEND_OSS,
+ MATE_MIXER_BACKEND_OSS4,
MATE_MIXER_BACKEND_NULL
} MateMixerBackendType;
@@ -81,14 +83,7 @@ typedef enum { /*< flags >*/
* @MATE_MIXER_STREAM_INPUT:
* @MATE_MIXER_STREAM_OUTPUT:
* @MATE_MIXER_STREAM_CLIENT:
- * @MATE_MIXER_STREAM_HAS_MUTE:
- * @MATE_MIXER_STREAM_HAS_VOLUME:
- * @MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME:
- * @MATE_MIXER_STREAM_HAS_FLAT_VOLUME:
* @MATE_MIXER_STREAM_HAS_MONITOR:
- * @MATE_MIXER_STREAM_CAN_SET_VOLUME:
- * @MATE_MIXER_STREAM_CAN_BALANCE:
- * @MATE_MIXER_STREAM_CAN_FADE:
* @MATE_MIXER_STREAM_CAN_SUSPEND:
*/
typedef enum { /*< flags >*/
@@ -96,15 +91,10 @@ typedef enum { /*< flags >*/
MATE_MIXER_STREAM_INPUT = 1 << 0,
MATE_MIXER_STREAM_OUTPUT = 1 << 1,
MATE_MIXER_STREAM_CLIENT = 1 << 2,
- MATE_MIXER_STREAM_HAS_MUTE = 1 << 3,
- MATE_MIXER_STREAM_HAS_VOLUME = 1 << 4,
- MATE_MIXER_STREAM_HAS_DECIBEL_VOLUME = 1 << 5,
- MATE_MIXER_STREAM_HAS_FLAT_VOLUME = 1 << 6,
- MATE_MIXER_STREAM_HAS_MONITOR = 1 << 7,
- MATE_MIXER_STREAM_CAN_SET_VOLUME = 1 << 8,
- MATE_MIXER_STREAM_CAN_BALANCE = 1 << 9,
- MATE_MIXER_STREAM_CAN_FADE = 1 << 10,
- MATE_MIXER_STREAM_CAN_SUSPEND = 1 << 11
+ MATE_MIXER_STREAM_HAS_MONITOR = 1 << 3,
+ MATE_MIXER_STREAM_CAN_SUSPEND = 1 << 4,
+ MATE_MIXER_STREAM_PORTS_FIXED = 1 << 5,
+ MATE_MIXER_STREAM_PORTS_EXCLUSIVE = 1 << 6,
} MateMixerStreamFlags;
/**
@@ -122,6 +112,39 @@ typedef enum {
} MateMixerStreamState;
/**
+ * MateMixerStreamControlFlags:
+ * @MATE_MIXER_STREAM_CONTROL_NO_FLAGS:
+ * @MATE_MIXER_STREAM_CONTROL_HAS_MUTE:
+ * @MATE_MIXER_STREAM_CONTROL_HAS_VOLUME:
+ * @MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL_VOLUME:
+ * @MATE_MIXER_STREAM_CONTROL_HAS_FLAT_VOLUME:
+ * @MATE_MIXER_STREAM_CONTROL_CAN_SET_VOLUME:
+ * @MATE_MIXER_STREAM_CONTROL_CAN_BALANCE:
+ * @MATE_MIXER_STREAM_CONTROL_CAN_FADE:
+ */
+typedef enum {
+ MATE_MIXER_STREAM_CONTROL_NO_FLAGS = 0,
+ MATE_MIXER_STREAM_CONTROL_HAS_MUTE = 1 << 0,
+ MATE_MIXER_STREAM_CONTROL_HAS_VOLUME = 1 << 1,
+ MATE_MIXER_STREAM_CONTROL_HAS_DECIBEL_VOLUME = 1 << 2,
+ MATE_MIXER_STREAM_CONTROL_HAS_FLAT_VOLUME = 1 << 3,
+ MATE_MIXER_STREAM_CONTROL_CAN_SET_VOLUME = 1 << 4,
+ MATE_MIXER_STREAM_CONTROL_CAN_BALANCE = 1 << 5,
+ MATE_MIXER_STREAM_CONTROL_CAN_FADE = 1 << 6
+} MateMixerStreamControlFlags;
+
+typedef enum {
+ MATE_MIXER_STREAM_CONTROL_ROLE_UNKNOWN,
+ MATE_MIXER_STREAM_CONTROL_ROLE_MASTER,
+ MATE_MIXER_STREAM_CONTROL_ROLE_PCM,
+ MATE_MIXER_STREAM_CONTROL_ROLE_BASS,
+ MATE_MIXER_STREAM_CONTROL_ROLE_TREBLE,
+ MATE_MIXER_STREAM_CONTROL_ROLE_CD,
+ MATE_MIXER_STREAM_CONTROL_ROLE_SPEAKER,
+ MATE_MIXER_STREAM_CONTROL_ROLE_PORT
+} MateMixerStreamControlRole;
+
+/**
* MateMixerClientStreamFlags:
* @MATE_MIXER_CLIENT_STREAM_NO_FLAGS:
* @MATE_MIXER_CLIENT_STREAM_APPLICATION:
diff --git a/libmatemixer/matemixer-stream-control.c b/libmatemixer/matemixer-stream-control.c
new file mode 100644
index 0000000..19d35a1
--- /dev/null
+++ b/libmatemixer/matemixer-stream-control.c
@@ -0,0 +1,445 @@
+/*
+ * 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 <glib.h>
+#include <glib-object.h>
+
+#include "matemixer-enums.h"
+#include "matemixer-enum-types.h"
+#include "matemixer-stream-control.h"
+
+/**
+ * SECTION:matemixer-stream-control
+ * @include: libmatemixer/matemixer.h
+ */
+
+G_DEFINE_INTERFACE (MateMixerStreamControl, mate_mixer_stream_control, G_TYPE_OBJECT)
+
+static void
+mate_mixer_stream_control_default_init (MateMixerStreamControlInterface *iface)
+{
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("name",
+ "Name",
+ "Name of the stream control",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_string ("description",
+ "Description",
+ "Description of the stream control",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_flags ("flags",
+ "Flags",
+ "Capability flags of the stream control",
+ MATE_MIXER_TYPE_STREAM_CONTROL_FLAGS,
+ MATE_MIXER_STREAM_CONTROL_NO_FLAGS,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_boolean ("mute",
+ "Mute",
+ "Mute state of the stream control",
+ FALSE,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_uint ("volume",
+ "Volume",
+ "Volume of the stream control",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_float ("balance",
+ "Balance",
+ "Balance value of the stream control",
+ -1.0f,
+ 1.0f,
+ 0.0f,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ g_object_interface_install_property (iface,
+ g_param_spec_float ("fade",
+ "Fade",
+ "Fade value of the stream control",
+ -1.0f,
+ 1.0f,
+ 0.0f,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+}
+
+const gchar *
+mate_mixer_stream_control_get_name (MateMixerStreamControl *ctl)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), NULL);
+
+ /* Implementation required */
+ return MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl)->get_name (ctl);
+}
+
+const gchar *
+mate_mixer_stream_control_get_description (MateMixerStreamControl *ctl)
+{
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), NULL);
+
+ /* Implementation required */
+ return MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl)->get_description (ctl);
+}
+
+MateMixerStreamControlFlags
+mate_mixer_stream_control_get_flags (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlFlags flags = MATE_MIXER_STREAM_CONTROL_NO_FLAGS;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), MATE_MIXER_STREAM_CONTROL_NO_FLAGS);
+
+ g_object_get (G_OBJECT (ctl),
+ "flags", &flags,
+ NULL);
+
+ return flags;
+}
+
+gboolean
+mate_mixer_stream_control_get_mute (MateMixerStreamControl *ctl)
+{
+ gboolean mute = FALSE;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ g_object_get (G_OBJECT (ctl),
+ "mute", &mute,
+ NULL);
+
+ return mute;
+}
+
+gboolean
+mate_mixer_stream_control_set_mute (MateMixerStreamControl *ctl, gboolean mute)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_mute != NULL)
+ return iface->set_mute (ctl, mute);
+
+ return FALSE;
+}
+
+guint
+mate_mixer_stream_control_get_volume (MateMixerStreamControl *ctl)
+{
+ guint volume = 0;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ g_object_get (G_OBJECT (ctl),
+ "volume", &volume,
+ NULL);
+
+ return volume;
+}
+
+gboolean
+mate_mixer_stream_control_set_volume (MateMixerStreamControl *ctl, guint volume)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_volume != NULL)
+ return iface->set_volume (ctl, volume);
+
+ return FALSE;
+}
+
+gdouble
+mate_mixer_stream_control_get_decibel (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), -MATE_MIXER_INFINITY);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_decibel != NULL)
+ return iface->get_decibel (ctl);
+
+ return -MATE_MIXER_INFINITY;
+}
+
+gboolean
+mate_mixer_stream_control_set_decibel (MateMixerStreamControl *ctl, gdouble decibel)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_decibel != NULL)
+ return iface->set_decibel (ctl, decibel);
+
+ return FALSE;
+}
+
+guint
+mate_mixer_stream_control_get_num_channels (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_num_channels != NULL)
+ return iface->get_num_channels (ctl);
+
+ return 0;
+}
+
+MateMixerChannelPosition
+mate_mixer_stream_control_get_channel_position (MateMixerStreamControl *ctl, guint channel)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), MATE_MIXER_CHANNEL_UNKNOWN);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_channel_position != NULL)
+ return iface->get_channel_position (ctl, channel);
+
+ return MATE_MIXER_CHANNEL_UNKNOWN;
+}
+
+guint
+mate_mixer_stream_control_get_channel_volume (MateMixerStreamControl *ctl, guint channel)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_channel_volume != NULL)
+ return iface->get_channel_volume (ctl, channel);
+
+ return 0;
+}
+
+gboolean
+mate_mixer_stream_control_set_channel_volume (MateMixerStreamControl *ctl,
+ guint channel,
+ guint volume)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_channel_volume != NULL)
+ return iface->set_channel_volume (ctl, channel, volume);
+
+ return FALSE;
+}
+
+gdouble
+mate_mixer_stream_control_get_channel_decibel (MateMixerStreamControl *ctl, guint channel)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), -MATE_MIXER_INFINITY);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_channel_decibel != NULL)
+ return iface->get_channel_decibel (ctl, channel);
+
+ return -MATE_MIXER_INFINITY;
+}
+
+gboolean
+mate_mixer_stream_control_set_channel_decibel (MateMixerStreamControl *ctl,
+ guint channel,
+ gdouble decibel)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_channel_decibel != NULL)
+ return iface->set_channel_decibel (ctl, channel, decibel);
+
+ return FALSE;
+}
+
+gboolean
+mate_mixer_stream_control_has_channel_position (MateMixerStreamControl *ctl,
+ MateMixerChannelPosition position)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->has_channel_position != NULL)
+ return iface->has_channel_position (ctl, position);
+
+ return FALSE;
+}
+
+gfloat
+mate_mixer_stream_control_get_balance (MateMixerStreamControl *ctl)
+{
+ gfloat balance = 0.0f;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0.0f);
+
+ g_object_get (G_OBJECT (ctl),
+ "balance", &balance,
+ NULL);
+
+ return 0.0f;
+}
+
+gboolean
+mate_mixer_stream_control_set_balance (MateMixerStreamControl *ctl, gfloat balance)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_balance != NULL)
+ return iface->set_balance (ctl, balance);
+
+ return FALSE;
+}
+
+gfloat
+mate_mixer_stream_control_get_fade (MateMixerStreamControl *ctl)
+{
+ gfloat fade = 0.0f;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0.0f);
+
+ g_object_get (G_OBJECT (ctl),
+ "fade", &fade,
+ NULL);
+
+ return fade;
+}
+
+gboolean
+mate_mixer_stream_control_set_fade (MateMixerStreamControl *ctl, gfloat fade)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), FALSE);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->set_fade != NULL)
+ return iface->set_fade (ctl, fade);
+
+ return FALSE;
+}
+
+guint
+mate_mixer_stream_control_get_min_volume (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_min_volume != NULL)
+ return iface->get_min_volume (ctl);
+
+ return 0;
+}
+
+guint
+mate_mixer_stream_control_get_max_volume (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_max_volume != NULL)
+ return iface->get_max_volume (ctl);
+
+ return 0;
+}
+
+guint
+mate_mixer_stream_control_get_normal_volume (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_normal_volume != NULL)
+ return iface->get_normal_volume (ctl);
+
+ return 0;
+}
+
+guint
+mate_mixer_stream_control_get_base_volume (MateMixerStreamControl *ctl)
+{
+ MateMixerStreamControlInterface *iface;
+
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM_CONTROL (ctl), 0);
+
+ iface = MATE_MIXER_STREAM_CONTROL_GET_INTERFACE (ctl);
+
+ if (iface->get_base_volume != NULL)
+ return iface->get_base_volume (ctl);
+
+ return 0;
+}
diff --git a/libmatemixer/matemixer-stream-control.h b/libmatemixer/matemixer-stream-control.h
new file mode 100644
index 0000000..727ed54
--- /dev/null
+++ b/libmatemixer/matemixer-stream-control.h
@@ -0,0 +1,148 @@
+/*
+ * 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/>.
+ */
+
+#ifndef MATEMIXER_STREAM_CONTROL_H
+#define MATEMIXER_STREAM_CONTROL_H
+
+#include <math.h>
+#include <glib.h>
+#include <glib-object.h>
+
+#include <libmatemixer/matemixer-enums.h>
+
+G_BEGIN_DECLS
+
+#ifdef INFINITY
+# define MATE_MIXER_INFINITY INFINITY
+#else
+# define MATE_MIXER_INFINITY G_MAXDOUBLE
+#endif
+
+#define MATE_MIXER_TYPE_STREAM_CONTROL \
+ (mate_mixer_stream_control_get_type ())
+#define MATE_MIXER_STREAM_CONTROL(o) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((o), MATE_MIXER_TYPE_STREAM_CONTROL, MateMixerStreamControl))
+#define MATE_MIXER_IS_STREAM_CONTROL(o) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((o), MATE_MIXER_TYPE_STREAM_CONTROL))
+#define MATE_MIXER_STREAM_CONTROL_GET_INTERFACE(o) \
+ (G_TYPE_INSTANCE_GET_INTERFACE ((o), MATE_MIXER_TYPE_STREAM_CONTROL, MateMixerStreamControlInterface))
+
+typedef struct _MateMixerStreamControl MateMixerStreamControl; /* dummy object */
+typedef struct _MateMixerStreamControlInterface MateMixerStreamControlInterface;
+
+struct _MateMixerStreamControlInterface
+{
+ GTypeInterface parent_iface;
+
+ /*< private >*/
+ const gchar * (*get_name) (MateMixerStreamControl *ctl);
+ const gchar * (*get_description) (MateMixerStreamControl *ctl);
+
+ gboolean (*set_mute) (MateMixerStreamControl *ctl,
+ gboolean mute);
+
+ guint (*get_num_channels) (MateMixerStreamControl *ctl);
+
+ gboolean (*set_volume) (MateMixerStreamControl *ctl,
+ guint volume);
+
+ gdouble (*get_decibel) (MateMixerStreamControl *ctl);
+ gboolean (*set_decibel) (MateMixerStreamControl *ctl,
+ gdouble decibel);
+
+ gboolean (*has_channel_position) (MateMixerStreamControl *ctl,
+ MateMixerChannelPosition position);
+ MateMixerChannelPosition (*get_channel_position) (MateMixerStreamControl *ctl,
+ guint channel);
+
+ guint (*get_channel_volume) (MateMixerStreamControl *ctl,
+ guint channel);
+ gboolean (*set_channel_volume) (MateMixerStreamControl *ctl,
+ guint channel,
+ guint volume);
+
+ gdouble (*get_channel_decibel) (MateMixerStreamControl *ctl,
+ guint channel);
+ gboolean (*set_channel_decibel) (MateMixerStreamControl *ctl,
+ guint channel,
+ gdouble decibel);
+
+ gboolean (*set_balance) (MateMixerStreamControl *ctl,
+ gfloat balance);
+
+ gboolean (*set_fade) (MateMixerStreamControl *ctl,
+ gfloat fade);
+
+ guint (*get_min_volume) (MateMixerStreamControl *ctl);
+ guint (*get_max_volume) (MateMixerStreamControl *ctl);
+ guint (*get_normal_volume) (MateMixerStreamControl *ctl);
+ guint (*get_base_volume) (MateMixerStreamControl *ctl);
+};
+
+GType mate_mixer_stream_control_get_type (void) G_GNUC_CONST;
+
+const gchar * mate_mixer_stream_control_get_name (MateMixerStreamControl *ctl);
+const gchar * mate_mixer_stream_control_get_description (MateMixerStreamControl *ctl);
+MateMixerStreamControlFlags mate_mixer_stream_control_get_flags (MateMixerStreamControl *ctl);
+
+gboolean mate_mixer_stream_control_get_mute (MateMixerStreamControl *ctl);
+gboolean mate_mixer_stream_control_set_mute (MateMixerStreamControl *ctl,
+ gboolean mute);
+
+guint mate_mixer_stream_control_get_num_channels (MateMixerStreamControl *ctl);
+
+guint mate_mixer_stream_control_get_volume (MateMixerStreamControl *ctl);
+gboolean mate_mixer_stream_control_set_volume (MateMixerStreamControl *ctl,
+ guint volume);
+
+gdouble mate_mixer_stream_control_get_decibel (MateMixerStreamControl *ctl);
+gboolean mate_mixer_stream_control_set_decibel (MateMixerStreamControl *ctl,
+ gdouble decibel);
+
+gboolean mate_mixer_stream_control_has_channel_position (MateMixerStreamControl *ctl,
+ MateMixerChannelPosition position);
+MateMixerChannelPosition mate_mixer_stream_control_get_channel_position (MateMixerStreamControl *ctl,
+ guint channel);
+
+guint mate_mixer_stream_control_get_channel_volume (MateMixerStreamControl *ctl,
+ guint channel);
+gboolean mate_mixer_stream_control_set_channel_volume (MateMixerStreamControl *ctl,
+ guint channel,
+ guint volume);
+
+gdouble mate_mixer_stream_control_get_channel_decibel (MateMixerStreamControl *ctl,
+ guint channel);
+gboolean mate_mixer_stream_control_set_channel_decibel (MateMixerStreamControl *ctl,
+ guint channel,
+ gdouble decibel);
+
+gfloat mate_mixer_stream_control_get_balance (MateMixerStreamControl *ctl);
+gboolean mate_mixer_stream_control_set_balance (MateMixerStreamControl *ctl,
+ gfloat balance);
+
+gfloat mate_mixer_stream_control_get_fade (MateMixerStreamControl *ctl);
+gboolean mate_mixer_stream_control_set_fade (MateMixerStreamControl *ctl,
+ gfloat fade);
+
+guint mate_mixer_stream_control_get_min_volume (MateMixerStreamControl *ctl);
+guint mate_mixer_stream_control_get_max_volume (MateMixerStreamControl *ctl);
+guint mate_mixer_stream_control_get_normal_volume (MateMixerStreamControl *ctl);
+guint mate_mixer_stream_control_get_base_volume (MateMixerStreamControl *ctl);
+
+G_END_DECLS
+
+#endif /* MATEMIXER_STREAM_CONTROL_H */
diff --git a/libmatemixer/matemixer-stream.c b/libmatemixer/matemixer-stream.c
index 6bec2be..888fddb 100644
--- a/libmatemixer/matemixer-stream.c
+++ b/libmatemixer/matemixer-stream.c
@@ -84,44 +84,6 @@ mate_mixer_stream_default_init (MateMixerStreamInterface *iface)
G_PARAM_STATIC_STRINGS));
g_object_interface_install_property (iface,
- g_param_spec_boolean ("mute",
- "Mute",
- "Mute state of the stream",
- FALSE,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_interface_install_property (iface,
- g_param_spec_uint ("volume",
- "Volume",
- "Volume of the stream",
- 0,
- G_MAXUINT,
- 0,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_interface_install_property (iface,
- g_param_spec_float ("balance",
- "Balance",
- "Balance value of the stream",
- -1.0f,
- 1.0f,
- 0.0f,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_interface_install_property (iface,
- g_param_spec_float ("fade",
- "Fade",
- "Fade value of the stream",
- -1.0f,
- 1.0f,
- 0.0f,
- G_PARAM_READABLE |
- G_PARAM_STATIC_STRINGS));
-
- g_object_interface_install_property (iface,
g_param_spec_object ("active-port",
"Active port",
"The currently active port of the stream",
@@ -145,327 +107,161 @@ mate_mixer_stream_default_init (MateMixerStreamInterface *iface)
const gchar *
mate_mixer_stream_get_name (MateMixerStream *stream)
{
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
+
+ /* Implementation required */
return MATE_MIXER_STREAM_GET_INTERFACE (stream)->get_name (stream);
}
const gchar *
mate_mixer_stream_get_description (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
-
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_description)
- return iface->get_description (stream);
-
- return NULL;
+ /* Implementation required */
+ return MATE_MIXER_STREAM_GET_INTERFACE (stream)->get_description (stream);
}
MateMixerDevice *
mate_mixer_stream_get_device (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
+ MateMixerDevice *device = NULL;
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
+ g_object_get (G_OBJECT (stream),
+ "device", &device,
+ NULL);
- if (iface->get_device)
- return iface->get_device (stream);
+ if (device != NULL)
+ g_object_unref (device);
+
+ return device;
- return NULL;
}
MateMixerStreamFlags
mate_mixer_stream_get_flags (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
+ MateMixerStreamFlags flags = MATE_MIXER_STREAM_NO_FLAGS;
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), MATE_MIXER_STREAM_NO_FLAGS);
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_flags)
- return iface->get_flags (stream);
+ g_object_get (G_OBJECT (stream),
+ "flags", &flags,
+ NULL);
- return MATE_MIXER_STREAM_NO_FLAGS;
+ return flags;
}
MateMixerStreamState
mate_mixer_stream_get_state (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
+ MateMixerStreamState state = MATE_MIXER_STREAM_STATE_UNKNOWN;
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), MATE_MIXER_STREAM_STATE_UNKNOWN);
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_state)
- return iface->get_state (stream);
+ g_object_get (G_OBJECT (stream),
+ "state", &state,
+ NULL);
- return MATE_MIXER_STREAM_STATE_UNKNOWN;
+ return state;
}
-gboolean
-mate_mixer_stream_get_mute (MateMixerStream *stream)
+MateMixerStreamControl *
+mate_mixer_stream_get_control (MateMixerStream *stream, const gchar *name)
{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_mute)
- return iface->get_mute (stream);
-
- return FALSE;
-}
-
-gboolean
-mate_mixer_stream_set_mute (MateMixerStream *stream, gboolean mute)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->set_mute)
- return iface->set_mute (stream, mute);
-
- return FALSE;
-}
-
-guint
-mate_mixer_stream_get_volume (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_volume)
- return iface->get_volume (stream);
-
- return 0;
-}
-
-gboolean
-mate_mixer_stream_set_volume (MateMixerStream *stream, guint volume)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->set_volume)
- return iface->set_volume (stream, volume);
-
- return FALSE;
-}
-
-gdouble
-mate_mixer_stream_get_decibel (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), -MATE_MIXER_INFINITY);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_decibel)
- return iface->get_decibel (stream);
-
- return -MATE_MIXER_INFINITY;
-}
-
-gboolean
-mate_mixer_stream_set_decibel (MateMixerStream *stream, gdouble decibel)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->set_decibel)
- return iface->set_decibel (stream, decibel);
-
- return FALSE;
-}
-
-guint
-mate_mixer_stream_get_num_channels (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_num_channels)
- return iface->get_num_channels (stream);
-
- return 0;
-}
-
-MateMixerChannelPosition
-mate_mixer_stream_get_channel_position (MateMixerStream *stream, guint channel)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), MATE_MIXER_CHANNEL_UNKNOWN);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_channel_position)
- return iface->get_channel_position (stream, channel);
-
- return MATE_MIXER_CHANNEL_UNKNOWN;
-}
-
-guint
-mate_mixer_stream_get_channel_volume (MateMixerStream *stream, guint channel)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_channel_volume)
- return iface->get_channel_volume (stream, channel);
-
- return 0;
-}
-
-gboolean
-mate_mixer_stream_set_channel_volume (MateMixerStream *stream,
- guint channel,
- guint volume)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->set_channel_volume)
- return iface->set_channel_volume (stream, channel, volume);
-
- return FALSE;
-}
-
-gdouble
-mate_mixer_stream_get_channel_decibel (MateMixerStream *stream, guint channel)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), -MATE_MIXER_INFINITY);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_channel_decibel)
- return iface->get_channel_decibel (stream, channel);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
- return -MATE_MIXER_INFINITY;
+ /* Implementation required */
+ return MATE_MIXER_STREAM_GET_INTERFACE (stream)->get_control (stream, name);
}
-gboolean
-mate_mixer_stream_set_channel_decibel (MateMixerStream *stream,
- guint channel,
- gdouble decibel)
+MateMixerStreamControl *
+mate_mixer_stream_get_default_control (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->set_channel_decibel)
- return iface->set_channel_decibel (stream, channel, decibel);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
- return FALSE;
+ /* Implementation required */
+ return MATE_MIXER_STREAM_GET_INTERFACE (stream)->get_default_control (stream);
}
-gboolean
-mate_mixer_stream_has_channel_position (MateMixerStream *stream,
- MateMixerChannelPosition position)
+MateMixerPort *
+mate_mixer_stream_get_port (MateMixerStream *stream, const gchar *name)
{
MateMixerStreamInterface *iface;
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->has_channel_position)
- return iface->has_channel_position (stream, position);
+ if (iface->get_port != NULL)
+ return iface->get_port (stream, name);
return FALSE;
}
-gfloat
-mate_mixer_stream_get_balance (MateMixerStream *stream)
+MateMixerPort *
+mate_mixer_stream_get_active_port (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
+ MateMixerPort *port = NULL;
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0.0f);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
+ g_object_get (G_OBJECT (stream),
+ "active-port", &port,
+ NULL);
- if (iface->get_balance)
- return iface->get_balance (stream);
+ if (port != NULL)
+ g_object_unref (port);
- return 0.0f;
+ return port;
}
gboolean
-mate_mixer_stream_set_balance (MateMixerStream *stream, gfloat balance)
+mate_mixer_stream_set_active_port (MateMixerStream *stream, MateMixerPort *port)
{
MateMixerStreamInterface *iface;
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
+ g_return_val_if_fail (MATE_MIXER_IS_PORT (port), FALSE);
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->set_balance)
- return iface->set_balance (stream, balance);
+ if (iface->set_active_port != NULL)
+ return iface->set_active_port (stream, port);
return FALSE;
}
-gfloat
-mate_mixer_stream_get_fade (MateMixerStream *stream)
+const GList *
+mate_mixer_stream_list_controls (MateMixerStream *stream)
{
MateMixerStreamInterface *iface;
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0.0f);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->get_fade)
- return iface->get_fade (stream);
+ if (iface->list_controls != NULL)
+ return iface->list_controls (stream);
- return 0.0f;
+ return NULL;
}
-gboolean
-mate_mixer_stream_set_fade (MateMixerStream *stream, gfloat fade)
+const GList *
+mate_mixer_stream_list_ports (MateMixerStream *stream)
{
MateMixerStreamInterface *iface;
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
+ g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->set_fade)
- return iface->set_fade (stream, fade);
+ if (iface->list_ports != NULL)
+ return iface->list_ports (stream);
- return FALSE;
+ return NULL;
}
gboolean
@@ -477,7 +273,7 @@ mate_mixer_stream_suspend (MateMixerStream *stream)
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->suspend)
+ if (iface->suspend != NULL)
return iface->suspend (stream);
return FALSE;
@@ -492,57 +288,28 @@ mate_mixer_stream_resume (MateMixerStream *stream)
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->resume)
+ if (iface->resume != NULL)
return iface->resume (stream);
return FALSE;
}
gboolean
-mate_mixer_stream_monitor_start (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->monitor_start)
- return iface->monitor_start (stream);
-
- return FALSE;
-}
-
-void
-mate_mixer_stream_monitor_stop (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_if_fail (MATE_MIXER_IS_STREAM (stream));
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->monitor_stop)
- iface->monitor_stop (stream);
-}
-
-gboolean
-mate_mixer_stream_monitor_is_running (MateMixerStream *stream)
+mate_mixer_stream_monitor_get_enabled (MateMixerStream *stream)
{
- MateMixerStreamInterface *iface;
+ gboolean enabled = FALSE;
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->monitor_is_running)
- return iface->monitor_is_running (stream);
+ g_object_get (G_OBJECT (stream),
+ "monitor-enabled", &enabled,
+ NULL);
- return FALSE;
+ return enabled;
}
gboolean
-mate_mixer_stream_monitor_set_name (MateMixerStream *stream, const gchar *name)
+mate_mixer_stream_monitor_set_enabled (MateMixerStream *stream, gboolean enabled)
{
MateMixerStreamInterface *iface;
@@ -550,29 +317,14 @@ mate_mixer_stream_monitor_set_name (MateMixerStream *stream, const gchar *name)
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->monitor_set_name)
- return iface->monitor_set_name (stream, name);
+ if (iface->monitor_set_enabled != NULL)
+ return iface->monitor_set_enabled (stream, enabled);
return FALSE;
}
-const GList *
-mate_mixer_stream_list_ports (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), NULL);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->list_ports)
- return iface->list_ports (stream);
-
- return NULL;
-}
-
-MateMixerPort *
-mate_mixer_stream_get_active_port (MateMixerStream *stream)
+const gchar *
+mate_mixer_stream_monitor_get_name (MateMixerStream *stream)
{
MateMixerStreamInterface *iface;
@@ -580,84 +332,23 @@ mate_mixer_stream_get_active_port (MateMixerStream *stream)
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->get_active_port)
- return iface->get_active_port (stream);
+ if (iface->monitor_get_name != NULL)
+ return iface->monitor_get_name (stream);
- return NULL;
+ return FALSE;
}
gboolean
-mate_mixer_stream_set_active_port (MateMixerStream *stream, MateMixerPort *port)
+mate_mixer_stream_monitor_set_name (MateMixerStream *stream, const gchar *name)
{
MateMixerStreamInterface *iface;
g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), FALSE);
- g_return_val_if_fail (MATE_MIXER_IS_PORT (port), FALSE);
iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
- if (iface->set_active_port)
- return iface->set_active_port (stream, port);
+ if (iface->monitor_set_name != NULL)
+ return iface->monitor_set_name (stream, name);
return FALSE;
}
-
-guint
-mate_mixer_stream_get_min_volume (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_min_volume)
- return iface->get_min_volume (stream);
-
- return 0;
-}
-
-guint
-mate_mixer_stream_get_max_volume (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_max_volume)
- return iface->get_max_volume (stream);
-
- return 0;
-}
-
-guint
-mate_mixer_stream_get_normal_volume (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_normal_volume)
- return iface->get_normal_volume (stream);
-
- return 0;
-}
-
-guint
-mate_mixer_stream_get_base_volume (MateMixerStream *stream)
-{
- MateMixerStreamInterface *iface;
-
- g_return_val_if_fail (MATE_MIXER_IS_STREAM (stream), 0);
-
- iface = MATE_MIXER_STREAM_GET_INTERFACE (stream);
-
- if (iface->get_base_volume)
- return iface->get_base_volume (stream);
-
- return 0;
-}
diff --git a/libmatemixer/matemixer-stream.h b/libmatemixer/matemixer-stream.h
index e91a2a5..aecf40e 100644
--- a/libmatemixer/matemixer-stream.h
+++ b/libmatemixer/matemixer-stream.h
@@ -18,13 +18,13 @@
#ifndef MATEMIXER_STREAM_H
#define MATEMIXER_STREAM_H
-#include <math.h>
#include <glib.h>
#include <glib-object.h>
#include <libmatemixer/matemixer-device.h>
#include <libmatemixer/matemixer-enums.h>
#include <libmatemixer/matemixer-port.h>
+#include <libmatemixer/matemixer-stream-control.h>
G_BEGIN_DECLS
@@ -51,131 +51,69 @@ struct _MateMixerStreamInterface
GTypeInterface parent_iface;
/*< private >*/
- /* Virtual table */
- const gchar * (*get_name) (MateMixerStream *stream);
- const gchar * (*get_description) (MateMixerStream *stream);
- MateMixerDevice * (*get_device) (MateMixerStream *stream);
- MateMixerStreamFlags (*get_flags) (MateMixerStream *stream);
- MateMixerStreamState (*get_state) (MateMixerStream *stream);
- gboolean (*get_mute) (MateMixerStream *stream);
- gboolean (*set_mute) (MateMixerStream *stream,
- gboolean mute);
- guint (*get_num_channels) (MateMixerStream *stream);
- guint (*get_volume) (MateMixerStream *stream);
- gboolean (*set_volume) (MateMixerStream *stream,
- guint volume);
- gdouble (*get_decibel) (MateMixerStream *stream);
- gboolean (*set_decibel) (MateMixerStream *stream,
- gdouble decibel);
- MateMixerChannelPosition (*get_channel_position) (MateMixerStream *stream,
- guint channel);
- guint (*get_channel_volume) (MateMixerStream *stream,
- guint channel);
- gboolean (*set_channel_volume) (MateMixerStream *stream,
- guint channel,
- guint volume);
- gdouble (*get_channel_decibel) (MateMixerStream *stream,
- guint channel);
- gboolean (*set_channel_decibel) (MateMixerStream *stream,
- guint channel,
- gdouble decibel);
- gboolean (*has_channel_position) (MateMixerStream *stream,
- MateMixerChannelPosition position);
- gfloat (*get_balance) (MateMixerStream *stream);
- gboolean (*set_balance) (MateMixerStream *stream,
- gfloat balance);
- gfloat (*get_fade) (MateMixerStream *stream);
- gboolean (*set_fade) (MateMixerStream *stream,
- gfloat fade);
- gboolean (*suspend) (MateMixerStream *stream);
- gboolean (*resume) (MateMixerStream *stream);
- gboolean (*monitor_start) (MateMixerStream *stream);
- void (*monitor_stop) (MateMixerStream *stream);
- gboolean (*monitor_is_running) (MateMixerStream *stream);
- gboolean (*monitor_set_name) (MateMixerStream *stream,
- const gchar *name);
- const GList * (*list_ports) (MateMixerStream *stream);
- MateMixerPort * (*get_active_port) (MateMixerStream *stream);
- gboolean (*set_active_port) (MateMixerStream *stream,
- MateMixerPort *port);
- guint (*get_min_volume) (MateMixerStream *stream);
- guint (*get_max_volume) (MateMixerStream *stream);
- guint (*get_normal_volume) (MateMixerStream *stream);
- guint (*get_base_volume) (MateMixerStream *stream);
+ const gchar * (*get_name) (MateMixerStream *stream);
+ const gchar * (*get_description) (MateMixerStream *stream);
- /* Signals */
- void (*monitor_value) (MateMixerStream *stream,
- gdouble value);
-};
-
-GType mate_mixer_stream_get_type (void) G_GNUC_CONST;
+ MateMixerStreamControl *(*get_control) (MateMixerStream *stream,
+ const gchar *name);
+ MateMixerStreamControl *(*get_default_control) (MateMixerStream *stream);
-const gchar * mate_mixer_stream_get_name (MateMixerStream *stream);
-const gchar * mate_mixer_stream_get_description (MateMixerStream *stream);
-MateMixerDevice * mate_mixer_stream_get_device (MateMixerStream *stream);
-MateMixerStreamFlags mate_mixer_stream_get_flags (MateMixerStream *stream);
-MateMixerStreamState mate_mixer_stream_get_state (MateMixerStream *stream);
+ MateMixerPort * (*get_port) (MateMixerStream *stream,
+ const gchar *name);
-gboolean mate_mixer_stream_get_mute (MateMixerStream *stream);
-gboolean mate_mixer_stream_set_mute (MateMixerStream *stream,
- gboolean mute);
+ gboolean (*set_active_port) (MateMixerStream *stream,
+ MateMixerPort *port);
-guint mate_mixer_stream_get_num_channels (MateMixerStream *stream);
+ const GList * (*list_controls) (MateMixerStream *stream);
+ const GList * (*list_ports) (MateMixerStream *stream);
-guint mate_mixer_stream_get_volume (MateMixerStream *stream);
-gboolean mate_mixer_stream_set_volume (MateMixerStream *stream,
- guint volume);
+ gboolean (*suspend) (MateMixerStream *stream);
+ gboolean (*resume) (MateMixerStream *stream);
-gdouble mate_mixer_stream_get_decibel (MateMixerStream *stream);
-gboolean mate_mixer_stream_set_decibel (MateMixerStream *stream,
- gdouble decibel);
+ gboolean (*monitor_set_enabled) (MateMixerStream *stream,
+ gboolean enabled);
-MateMixerChannelPosition mate_mixer_stream_get_channel_position (MateMixerStream *stream,
- guint channel);
+ const gchar * (*monitor_get_name) (MateMixerStream *stream);
+ gboolean (*monitor_set_name) (MateMixerStream *stream,
+ const gchar *name);
-guint mate_mixer_stream_get_channel_volume (MateMixerStream *stream,
- guint channel);
-gboolean mate_mixer_stream_set_channel_volume (MateMixerStream *stream,
- guint channel,
- guint volume);
-
-gdouble mate_mixer_stream_get_channel_decibel (MateMixerStream *stream,
- guint channel);
-gboolean mate_mixer_stream_set_channel_decibel (MateMixerStream *stream,
- guint channel,
- gdouble decibel);
+ /* Signals */
+ void (*monitor_value) (MateMixerStream *stream,
+ gdouble value);
+};
-gboolean mate_mixer_stream_has_channel_position (MateMixerStream *stream,
- MateMixerChannelPosition position);
+GType mate_mixer_stream_get_type (void) G_GNUC_CONST;
-gfloat mate_mixer_stream_get_balance (MateMixerStream *stream);
-gboolean mate_mixer_stream_set_balance (MateMixerStream *stream,
- gfloat balance);
+const gchar * mate_mixer_stream_get_name (MateMixerStream *stream);
+const gchar * mate_mixer_stream_get_description (MateMixerStream *stream);
+MateMixerDevice * mate_mixer_stream_get_device (MateMixerStream *stream);
+MateMixerStreamFlags mate_mixer_stream_get_flags (MateMixerStream *stream);
+MateMixerStreamState mate_mixer_stream_get_state (MateMixerStream *stream);
-gfloat mate_mixer_stream_get_fade (MateMixerStream *stream);
-gboolean mate_mixer_stream_set_fade (MateMixerStream *stream,
- gfloat fade);
+MateMixerStreamControl *mate_mixer_stream_get_control (MateMixerStream *stream,
+ const gchar *name);
+MateMixerStreamControl *mate_mixer_stream_get_default_control (MateMixerStream *stream);
-gboolean mate_mixer_stream_suspend (MateMixerStream *stream);
-gboolean mate_mixer_stream_resume (MateMixerStream *stream);
+MateMixerPort * mate_mixer_stream_get_port (MateMixerStream *stream,
+ const gchar *name);
-gboolean mate_mixer_stream_monitor_start (MateMixerStream *stream);
-void mate_mixer_stream_monitor_stop (MateMixerStream *stream);
+MateMixerPort * mate_mixer_stream_get_active_port (MateMixerStream *stream);
+gboolean mate_mixer_stream_set_active_port (MateMixerStream *stream,
+ MateMixerPort *port);
-gboolean mate_mixer_stream_monitor_is_running (MateMixerStream *stream);
-gboolean mate_mixer_stream_monitor_set_name (MateMixerStream *stream,
- const gchar *name);
+const GList * mate_mixer_stream_list_controls (MateMixerStream *stream);
+const GList * mate_mixer_stream_list_ports (MateMixerStream *stream);
-const GList * mate_mixer_stream_list_ports (MateMixerStream *stream);
+gboolean mate_mixer_stream_suspend (MateMixerStream *stream);
+gboolean mate_mixer_stream_resume (MateMixerStream *stream);
-MateMixerPort * mate_mixer_stream_get_active_port (MateMixerStream *stream);
-gboolean mate_mixer_stream_set_active_port (MateMixerStream *stream,
- MateMixerPort *port);
+gboolean mate_mixer_stream_monitor_get_enabled (MateMixerStream *stream);
+gboolean mate_mixer_stream_monitor_set_enabled (MateMixerStream *stream,
+ gboolean enabled);
-guint mate_mixer_stream_get_min_volume (MateMixerStream *stream);
-guint mate_mixer_stream_get_max_volume (MateMixerStream *stream);
-guint mate_mixer_stream_get_normal_volume (MateMixerStream *stream);
-guint mate_mixer_stream_get_base_volume (MateMixerStream *stream);
+const gchar * mate_mixer_stream_monitor_get_name (MateMixerStream *stream);
+gboolean mate_mixer_stream_monitor_set_name (MateMixerStream *stream,
+ const gchar *name);
G_END_DECLS