aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/active-sink.c349
-rw-r--r--src/active-sink.h85
-rw-r--r--src/device.c290
-rw-r--r--src/device.h84
-rw-r--r--src/pulseaudio-mgr.c86
-rw-r--r--src/pulseaudio-mgr.h4
-rw-r--r--src/slider-menu-item.c119
-rw-r--r--src/slider-menu-item.h12
-rw-r--r--src/sound-service-dbus.c10
-rw-r--r--src/voip-input-menu-item.c6
-rw-r--r--src/voip-input-menu-item.h4
12 files changed, 543 insertions, 510 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7525d71..f7dc2ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -92,8 +92,8 @@ indicator_sound_service_SOURCES = \
sound-service.c \
pulseaudio-mgr.h \
pulseaudio-mgr.c \
- active-sink.c \
- active-sink.h \
+ device.c \
+ device.h \
sound-service-dbus.h \
sound-service-dbus.c \
slider-menu-item.h \
diff --git a/src/active-sink.c b/src/active-sink.c
deleted file mode 100644
index a78d33e..0000000
--- a/src/active-sink.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
-Copyright 2011 Canonical Ltd.
-
-Authors:
- Conor Curran <conor.curran@canonical.com>
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
-by the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
-PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-#include <libdbusmenu-glib/menuitem.h>
-
-#include "active-sink.h"
-#include "slider-menu-item.h"
-#include "mute-menu-item.h"
-#include "voip-input-menu-item.h"
-#include "pulseaudio-mgr.h"
-
-typedef struct _ActiveSinkPrivate ActiveSinkPrivate;
-
-struct _ActiveSinkPrivate
-{
- SliderMenuItem* volume_slider_menuitem;
- MuteMenuItem* mute_menuitem;
- VoipInputMenuItem* voip_input_menu_item;
- SoundState current_sound_state;
- SoundServiceDbus* service;
- gint index;
- gchar* name;
- pa_cvolume volume;
- pa_channel_map channel_map;
- pa_volume_t base_volume;
-};
-
-#define ACTIVE_SINK_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), ACTIVE_SINK_TYPE, ActiveSinkPrivate))
-
-/* Prototypes */
-static void active_sink_class_init (ActiveSinkClass *klass);
-static void active_sink_init (ActiveSink *self);
-static void active_sink_dispose (GObject *object);
-static void active_sink_finalize (GObject *object);
-
-static SoundState active_sink_get_state_from_volume (ActiveSink* self);
-static pa_cvolume active_sink_construct_mono_volume (const pa_cvolume* vol);
-static void active_sink_volume_update (ActiveSink* self, gdouble percent);
-static void active_sink_mute_update (ActiveSink* self, gboolean muted);
-
-G_DEFINE_TYPE (ActiveSink, active_sink, G_TYPE_OBJECT);
-
-static void
-active_sink_class_init (ActiveSinkClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (ActiveSinkPrivate));
-
- gobject_class->dispose = active_sink_dispose;
- gobject_class->finalize = active_sink_finalize;
-}
-
-static void
-active_sink_init (ActiveSink *self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- priv->mute_menuitem = NULL;
- priv->volume_slider_menuitem = NULL;
- priv->voip_input_menu_item = NULL;
- priv->current_sound_state = UNAVAILABLE;
- priv->index = -1;
- priv->name = NULL;
- priv->service = NULL;
-
- // Init our menu items.
- priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);
- priv->voip_input_menu_item = g_object_new (VOIP_INPUT_MENU_ITEM_TYPE, NULL);;
- priv->volume_slider_menuitem = slider_menu_item_new (self);
- mute_menu_item_enable (priv->mute_menuitem, FALSE);
- slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
-}
-
-static void
-active_sink_dispose (GObject *object)
-{
- G_OBJECT_CLASS (active_sink_parent_class)->dispose (object);
-}
-
-static void
-active_sink_finalize (GObject *object)
-{
- G_OBJECT_CLASS (active_sink_parent_class)->finalize (object);
-}
-
-void
-active_sink_populate (ActiveSink* sink,
- const pa_sink_info* update)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE(sink);
-
- priv->name = g_strdup (update->name);
- priv->index = update->index;
- active_sink_mute_update (sink, update->mute);
- priv->volume = active_sink_construct_mono_volume (&update->volume);
- priv->base_volume = update->base_volume;
- priv->channel_map = update->channel_map;
-
- pa_volume_t vol = pa_cvolume_max (&update->volume);
- gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
-
- active_sink_volume_update (sink, volume_percent);
- active_sink_mute_update (sink, update->mute);
- mute_menu_item_enable (priv->mute_menuitem, TRUE);
- slider_menu_item_enable (priv->volume_slider_menuitem, TRUE);
-
- g_debug ("Active sink has been populated - volume %f", volume_percent);
-}
-
-void
-active_sink_activate_voip_item (ActiveSink* self, gint sink_input_index, gint client_index)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- if (voip_input_menu_item_is_interested (priv->voip_input_menu_item,
- sink_input_index,
- client_index)){
- voip_input_menu_item_enable (priv->voip_input_menu_item, TRUE);
- }
-}
-
-void
-active_sink_deactivate_voip_source (ActiveSink* self, gboolean visible)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- visible &= voip_input_menu_item_is_active (priv->voip_input_menu_item);
- voip_input_menu_item_deactivate_source (priv->voip_input_menu_item, visible);
-}
-
-void
-active_sink_deactivate_voip_client (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- voip_input_menu_item_deactivate_voip_client (priv->voip_input_menu_item);
-}
-
-void
-active_sink_update (ActiveSink* sink,
- const pa_sink_info* update)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink);
- active_sink_mute_update (sink, update->mute);
- priv->volume = active_sink_construct_mono_volume (&update->volume);
- priv->base_volume = update->base_volume;
- priv->channel_map = update->channel_map;
-
- pa_volume_t vol = pa_cvolume_max (&update->volume);
- gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
-
- active_sink_volume_update (sink, volume_percent);
- active_sink_mute_update (sink, update->mute);
-}
-
-// To the UI
-static void
-active_sink_volume_update (ActiveSink* self, gdouble percent)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- slider_menu_item_update (priv->volume_slider_menuitem, percent);
- SoundState state = active_sink_get_state_from_volume (self);
- if (priv->current_sound_state != state){
- priv->current_sound_state = state;
- sound_service_dbus_update_sound_state (priv->service,
- priv->current_sound_state);
- }
-}
-
-// From the UI
-void
-active_sink_update_volume (ActiveSink* self, gdouble percent)
-{
- pa_cvolume new_volume;
- pa_cvolume_init(&new_volume);
- new_volume.channels = 1;
- pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
- pa_cvolume_set(&new_volume, 1, new_volume_value);
-
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
-
- pa_cvolume_set(&priv->volume, priv->channel_map.channels, new_volume_value);
- pm_update_volume (priv->index, new_volume);
-}
-
-
-gint
-active_sink_get_current_sink_input_index (ActiveSink* sink)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink);
- return voip_input_menu_item_get_sink_input_index (priv->voip_input_menu_item);
-}
-
-static void
-active_sink_mute_update (ActiveSink* self, gboolean muted)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- mute_menu_item_update (priv->mute_menuitem, muted);
- SoundState state = active_sink_get_state_from_volume (self);
-
- if (muted == TRUE){
- state = MUTED;
- }
- if (priv->current_sound_state != state){
- priv->current_sound_state = state;
- sound_service_dbus_update_sound_state (priv->service, state);
- }
-}
-
-void
-active_sink_ensure_sink_is_unmuted (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- if (mute_menu_item_is_muted (priv->mute_menuitem)){
- pm_update_mute (FALSE);
- }
-}
-
-
-static SoundState
-active_sink_get_state_from_volume (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- GVariant* v = dbusmenu_menuitem_property_get_variant (DBUSMENU_MENUITEM(priv->volume_slider_menuitem),
- DBUSMENU_VOLUME_MENUITEM_LEVEL);
- gdouble volume_percent = g_variant_get_double (v);
-
- SoundState state = LOW_LEVEL;
-
- if (volume_percent < 30.0 && volume_percent > 0) {
- state = LOW_LEVEL;
- }
- else if (volume_percent < 70.0 && volume_percent >= 30.0) {
- state = MEDIUM_LEVEL;
- }
- else if (volume_percent >= 70.0) {
- state = HIGH_LEVEL;
- }
- else if (volume_percent == 0.0) {
- state = ZERO_LEVEL;
- }
- return state;
-}
-
-pa_cvolume
-active_sink_construct_mono_volume (const pa_cvolume* vol)
-{
- pa_cvolume new_volume;
- pa_cvolume_init(&new_volume);
- new_volume.channels = 1;
- pa_volume_t max_vol = pa_cvolume_max(vol);
- pa_cvolume_set(&new_volume, 1, max_vol);
- return new_volume;
-}
-
-void
-active_sink_determine_blocking_state (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- if (mute_menu_item_is_muted (priv->mute_menuitem)){
- /**
- We don't want to set the current state to blocking
- as this is a fire and forget event.
- */
- sound_service_dbus_update_sound_state (priv->service,
- BLOCKED);
- }
-}
-
-gint
-active_sink_get_index (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- return priv->index;
-}
-
-gboolean
-active_sink_is_populated (ActiveSink* sink)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink);
- return (priv->index != -1);
-}
-
-void
-active_sink_deactivate (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- priv->current_sound_state = UNAVAILABLE;
- sound_service_dbus_update_sound_state (priv->service,
- priv->current_sound_state);
- mute_menu_item_enable (priv->mute_menuitem, FALSE);
- slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
- priv->index = -1;
- g_free(priv->name);
- priv->name = NULL;
-}
-
-SoundState
-active_sink_get_state (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- return priv->current_sound_state;
-}
-
-void
-active_sink_update_voip_input_source (ActiveSink* self, const pa_source_info* update)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- voip_input_menu_item_update (priv->voip_input_menu_item, update);
-}
-
-gboolean
-active_sink_is_voip_source_populated (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- return voip_input_menu_item_is_populated (priv->voip_input_menu_item);
-}
-
-gint active_sink_get_source_index (ActiveSink* self)
-{
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (self);
- return voip_input_menu_item_get_index (priv->voip_input_menu_item);
-}
-
-ActiveSink*
-active_sink_new (SoundServiceDbus* service)
-{
- ActiveSink* sink = g_object_new (ACTIVE_SINK_TYPE, NULL);
- ActiveSinkPrivate* priv = ACTIVE_SINK_GET_PRIVATE (sink);
- priv->service = service;
- sound_service_dbus_build_sound_menu (service,
- mute_menu_item_get_button (priv->mute_menuitem),
- DBUSMENU_MENUITEM (priv->volume_slider_menuitem),
- DBUSMENU_MENUITEM (priv->voip_input_menu_item));
- pm_establish_pulse_connection (sink);
- return sink;
-}
diff --git a/src/active-sink.h b/src/active-sink.h
deleted file mode 100644
index 57b3079..0000000
--- a/src/active-sink.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2010 Canonical Ltd.
- *
- * Authors:
- * Conor Curran <conor.curran@canonical.com>
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3, as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranties of
- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __ACTIVE_SINK_H__
-#define __ACTIVE_SINK_H__
-
-#include <glib.h>
-#include <glib-object.h>
-
-#include "common-defs.h"
-#include "sound-service-dbus.h"
-
-#include <pulse/pulseaudio.h>
-
-G_BEGIN_DECLS
-
-#define ACTIVE_SINK_TYPE (active_sink_get_type ())
-#define ACTIVE_SINK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), ACTIVE_SINK_TYPE, ActiveSink))
-#define ACTIVE_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), ACTIVE_SINK_TYPE, ActiveSinkClass))
-#define IS_ACTIVE_SINK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), ACTIVE_SINK_TYPE))
-#define IS_ACTIVE_SINK_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), ACTIVE_SINK_TYPE))
-#define ACTIVE_SINK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), ACTIVE_SINK_TYPE, ActiveSinkClass))
-
-typedef struct _ActiveSink ActiveSink;
-typedef struct _ActiveSinkClass ActiveSinkClass;
-
-struct _ActiveSink {
- GObject parent;
-};
-
-struct _ActiveSinkClass {
- GObjectClass parent_class;
-};
-
-GType active_sink_get_type (void) G_GNUC_CONST;
-
-/**
- * TODO
- * Refactor this to become a device manager obj basically acting as wrapper for
- * the communication between pulseaudio-mgr and the individual items.
- * First steps collapse slider/volume related stuff into slider-menu-item.
- */
-
-// Sink related
-void active_sink_populate (ActiveSink* sink, const pa_sink_info* update);
-void active_sink_update (ActiveSink* sink, const pa_sink_info* update);
-gboolean active_sink_is_populated (ActiveSink* sink);
-gint active_sink_get_index (ActiveSink* self);
-void active_sink_deactivate (ActiveSink* self);
-void active_sink_update_mute (ActiveSink* self, gboolean mute_update);
-void active_sink_update_volume (ActiveSink* self, gdouble percent);
-void active_sink_ensure_sink_is_unmuted (ActiveSink* self);
-
-// source and sinkinput/client related for VOIP functionality
-void active_sink_update_voip_input_source (ActiveSink* sink, const pa_source_info* update);
-void active_sink_activate_voip_item (ActiveSink* sink, gint sink_input_index, gint client_index);
-gint active_sink_get_current_sink_input_index (ActiveSink* sink);
-gboolean active_sink_is_voip_source_populated (ActiveSink* sink);
-gint active_sink_get_source_index (ActiveSink* self);
-void active_sink_determine_blocking_state (ActiveSink* self);
-void active_sink_deactivate_voip_source (ActiveSink* self, gboolean visible);
-void active_sink_deactivate_voip_client (ActiveSink* self);
-SoundState active_sink_get_state (ActiveSink* self);
-
-ActiveSink* active_sink_new (SoundServiceDbus* service);
-
-G_END_DECLS
-
-#endif
diff --git a/src/device.c b/src/device.c
new file mode 100644
index 0000000..2f38beb
--- /dev/null
+++ b/src/device.c
@@ -0,0 +1,290 @@
+/*
+Copyright 2011 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <libdbusmenu-glib/menuitem.h>
+
+#include "device.h"
+#include "slider-menu-item.h"
+#include "mute-menu-item.h"
+#include "voip-input-menu-item.h"
+#include "pulseaudio-mgr.h"
+
+typedef struct _DevicePrivate DevicePrivate;
+
+struct _DevicePrivate
+{
+ SliderMenuItem* volume_slider_menuitem;
+ MuteMenuItem* mute_menuitem;
+ VoipInputMenuItem* voip_input_menu_item;
+ SoundState current_sound_state;
+ SoundServiceDbus* service;
+};
+
+#define DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEVICE_TYPE, DevicePrivate))
+
+/* Prototypes */
+static void device_class_init (DeviceClass *klass);
+static void device_init (Device *self);
+static void device_dispose (GObject *object);
+static void device_finalize (GObject *object);
+
+static SoundState device_get_state_from_volume (Device* self);
+static void device_mute_update (Device* self, gboolean muted);
+
+G_DEFINE_TYPE (Device, device, G_TYPE_OBJECT);
+
+static void
+device_class_init (DeviceClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (DevicePrivate));
+
+ gobject_class->dispose = device_dispose;
+ gobject_class->finalize = device_finalize;
+}
+
+static void
+device_init (Device *self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ priv->mute_menuitem = NULL;
+ priv->volume_slider_menuitem = NULL;
+ priv->voip_input_menu_item = NULL;
+ priv->current_sound_state = UNAVAILABLE;
+ priv->service = NULL;
+
+ // Init our menu items.
+ priv->mute_menuitem = g_object_new (MUTE_MENU_ITEM_TYPE, NULL);
+ priv->voip_input_menu_item = g_object_new (VOIP_INPUT_MENU_ITEM_TYPE, NULL);;
+ priv->volume_slider_menuitem = slider_menu_item_new (self);
+ mute_menu_item_enable (priv->mute_menuitem, FALSE);
+ slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
+}
+
+static void
+device_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (device_parent_class)->dispose (object);
+}
+
+static void
+device_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (device_parent_class)->finalize (object);
+}
+
+void
+device_populate (Device* self,
+ const pa_sink_info* update)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE(self);
+ device_mute_update (self, update->mute);
+ mute_menu_item_enable (priv->mute_menuitem, TRUE);
+ slider_menu_item_populate (priv->volume_slider_menuitem, update);
+ SoundState state = device_get_state_from_volume (self);
+ if (priv->current_sound_state != state){
+ priv->current_sound_state = state;
+ sound_service_dbus_update_sound_state (priv->service,
+ priv->current_sound_state);
+ }
+
+}
+
+void
+device_activate_voip_item (Device* self, gint sink_input_index, gint client_index)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ if (voip_input_menu_item_is_interested (priv->voip_input_menu_item,
+ sink_input_index,
+ client_index)){
+ voip_input_menu_item_enable (priv->voip_input_menu_item, TRUE);
+ }
+}
+
+void
+device_deactivate_voip_source (Device* self, gboolean visible)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ visible &= voip_input_menu_item_is_active (priv->voip_input_menu_item);
+ voip_input_menu_item_deactivate_source (priv->voip_input_menu_item, visible);
+}
+
+void
+device_deactivate_voip_client (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ voip_input_menu_item_deactivate_voip_client (priv->voip_input_menu_item);
+}
+
+void
+device_update (Device* self,
+ const pa_sink_info* update)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ slider_menu_item_update (priv->volume_slider_menuitem, update);
+
+ SoundState state = device_get_state_from_volume (self);
+ if (priv->current_sound_state != state){
+ priv->current_sound_state = state;
+ sound_service_dbus_update_sound_state (priv->service,
+ priv->current_sound_state);
+ }
+
+ device_mute_update (self, update->mute);
+}
+
+gint
+device_get_current_sink_input_index (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ return voip_input_menu_item_get_sink_input_index (priv->voip_input_menu_item);
+}
+
+static void
+device_mute_update (Device* self, gboolean muted)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ mute_menu_item_update (priv->mute_menuitem, muted);
+ SoundState state = device_get_state_from_volume (self);
+
+ if (muted == TRUE){
+ state = MUTED;
+ }
+ // Only send signals if something has changed
+ if (priv->current_sound_state != state){
+ priv->current_sound_state = state;
+ sound_service_dbus_update_sound_state (priv->service, state);
+ }
+}
+
+void
+device_ensure_sink_is_unmuted (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ if (mute_menu_item_is_muted (priv->mute_menuitem)){
+ pm_update_mute (FALSE);
+ }
+}
+
+
+static SoundState
+device_get_state_from_volume (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ GVariant* v = dbusmenu_menuitem_property_get_variant (DBUSMENU_MENUITEM(priv->volume_slider_menuitem),
+ DBUSMENU_VOLUME_MENUITEM_LEVEL);
+ gdouble volume_percent = g_variant_get_double (v);
+
+ SoundState state = LOW_LEVEL;
+
+ if (volume_percent < 30.0 && volume_percent > 0) {
+ state = LOW_LEVEL;
+ }
+ else if (volume_percent < 70.0 && volume_percent >= 30.0) {
+ state = MEDIUM_LEVEL;
+ }
+ else if (volume_percent >= 70.0) {
+ state = HIGH_LEVEL;
+ }
+ else if (volume_percent == 0.0) {
+ state = ZERO_LEVEL;
+ }
+ return state;
+}
+
+void
+device_determine_blocking_state (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ if (mute_menu_item_is_muted (priv->mute_menuitem)){
+ /**
+ We don't want to set the current state to blocking
+ as this is a fire and forget event.
+ */
+ sound_service_dbus_update_sound_state (priv->service,
+ BLOCKED);
+ }
+}
+
+gint
+device_get_index (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ return slider_menu_item_get_sink_index (priv->volume_slider_menuitem);
+}
+
+gboolean
+device_is_populated (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ return dbusmenu_menuitem_property_get_bool (DBUSMENU_MENUITEM (priv->volume_slider_menuitem),
+ DBUSMENU_MENUITEM_PROP_ENABLED);
+}
+
+void
+device_deactivate (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ priv->current_sound_state = UNAVAILABLE;
+ sound_service_dbus_update_sound_state (priv->service,
+ priv->current_sound_state);
+ mute_menu_item_enable (priv->mute_menuitem, FALSE);
+ slider_menu_item_enable (priv->volume_slider_menuitem, FALSE);
+}
+
+SoundState
+device_get_state (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ return priv->current_sound_state;
+}
+
+void
+device_update_voip_input_source (Device* self, const pa_source_info* update)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ voip_input_menu_item_update (priv->voip_input_menu_item, update);
+}
+
+gboolean
+device_is_voip_source_populated (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ return voip_input_menu_item_is_populated (priv->voip_input_menu_item);
+}
+
+gint device_get_source_index (Device* self)
+{
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (self);
+ return voip_input_menu_item_get_index (priv->voip_input_menu_item);
+}
+
+Device*
+device_new (SoundServiceDbus* service)
+{
+ Device* sink = g_object_new (DEVICE_TYPE, NULL);
+ DevicePrivate* priv = DEVICE_GET_PRIVATE (sink);
+ priv->service = service;
+ sound_service_dbus_build_sound_menu (service,
+ mute_menu_item_get_button (priv->mute_menuitem),
+ DBUSMENU_MENUITEM (priv->volume_slider_menuitem),
+ DBUSMENU_MENUITEM (priv->voip_input_menu_item));
+ pm_establish_pulse_connection (sink);
+ return sink;
+}
diff --git a/src/device.h b/src/device.h
new file mode 100644
index 0000000..42d8189
--- /dev/null
+++ b/src/device.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010 Canonical Ltd.
+ *
+ * Authors:
+ * Conor Curran <conor.curran@canonical.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __DEVICE_H__
+#define __DEVICE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include "common-defs.h"
+#include "sound-service-dbus.h"
+
+#include <pulse/pulseaudio.h>
+
+G_BEGIN_DECLS
+
+#define DEVICE_TYPE (device_get_type ())
+#define DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DEVICE_TYPE, Device))
+#define DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), DEVICE_TYPE, DeviceClass))
+#define IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DEVICE_TYPE))
+#define IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), DEVICE_TYPE))
+#define DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), DEVICE_TYPE, DeviceClass))
+
+typedef struct _Device Device;
+typedef struct _DeviceClass DeviceClass;
+
+struct _Device {
+ GObject parent;
+};
+
+struct _DeviceClass {
+ GObjectClass parent_class;
+};
+
+GType device_get_type (void) G_GNUC_CONST;
+
+/**
+ * TODO
+ * Refactor this to become a device manager obj basically acting as wrapper for
+ * the communication between pulseaudio-mgr and the individual items.
+ * First steps collapse slider/volume related stuff into slider-menu-item.
+ */
+
+// Sink related
+void device_populate (Device* sink, const pa_sink_info* update);
+void device_update (Device* sink, const pa_sink_info* update);
+gboolean device_is_populated (Device* sink);
+gint device_get_index (Device* self);
+void device_deactivate (Device* self);
+void device_update_mute (Device* self, gboolean mute_update);
+void device_ensure_sink_is_unmuted (Device* self);
+
+// source and sinkinput/client related for VOIP functionality
+void device_update_voip_input_source (Device* sink, const pa_source_info* update);
+void device_activate_voip_item (Device* sink, gint sink_input_index, gint client_index);
+gint device_get_current_sink_input_index (Device* sink);
+gboolean device_is_voip_source_populated (Device* sink);
+gint device_get_source_index (Device* self);
+void device_determine_blocking_state (Device* self);
+void device_deactivate_voip_source (Device* self, gboolean visible);
+void device_deactivate_voip_client (Device* self);
+SoundState device_get_state (Device* self);
+
+Device* device_new (SoundServiceDbus* service);
+
+G_END_DECLS
+
+#endif
diff --git a/src/pulseaudio-mgr.c b/src/pulseaudio-mgr.c
index 6d11221..036b46b 100644
--- a/src/pulseaudio-mgr.c
+++ b/src/pulseaudio-mgr.c
@@ -68,7 +68,7 @@ static void pm_sink_input_info_callback (pa_context *c,
const pa_sink_input_info *info,
int eol,
void *userdata);
-static void pm_update_active_sink (pa_context *c,
+static void pm_update_device (pa_context *c,
const pa_sink_info *info,
int eol,
void *userdata);
@@ -89,11 +89,11 @@ static pa_glib_mainloop *pa_main_loop = NULL;
Entry Point
**/
void
-pm_establish_pulse_connection (ActiveSink* active_sink)
+pm_establish_pulse_connection (Device* device)
{
pa_main_loop = pa_glib_mainloop_new (g_main_context_default ());
g_assert (pa_main_loop);
- reconnect_to_pulse ((gpointer)active_sink);
+ reconnect_to_pulse ((gpointer)device);
}
/**
@@ -119,7 +119,7 @@ reconnect_to_pulse (gpointer user_data)
{
g_debug("Attempt a pulse connection");
// reset
- g_return_val_if_fail (IS_ACTIVE_SINK (user_data), FALSE);
+ g_return_val_if_fail (IS_DEVICE (user_data), FALSE);
connection_attempts += 1;
if (pulse_context != NULL) {
@@ -216,38 +216,38 @@ pm_subscribed_events_callback (pa_context *c,
uint32_t index,
void* userdata)
{
- if (IS_ACTIVE_SINK (userdata) == FALSE){
+ if (IS_DEVICE (userdata) == FALSE){
g_critical ("subscribed events callback - our userdata is not what we think it should be");
return;
}
- ActiveSink* sink = ACTIVE_SINK (userdata);
+ Device* sink = DEVICE (userdata);
switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
case PA_SUBSCRIPTION_EVENT_SINK:
// We don't care about any other sink other than the active one.
- if (index != active_sink_get_index (sink))
+ if (index != device_get_index (sink))
return;
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
- active_sink_deactivate (sink);
+ device_deactivate (sink);
}
else{
pa_operation_unref (pa_context_get_sink_info_by_index (c,
index,
- pm_update_active_sink,
+ pm_update_device,
userdata) );
}
break;
case PA_SUBSCRIPTION_EVENT_SOURCE:
g_debug ("Looks like source event of some description - index = %i", index);
// We don't care about any other sink other than the active one.
- if (index != active_sink_get_source_index (sink))
+ if (index != device_get_source_index (sink))
return;
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
g_debug ("Source removal event - index = %i", index);
- active_sink_deactivate_voip_source (sink, FALSE);
+ device_deactivate_voip_source (sink, FALSE);
}
else{
pa_operation_unref (pa_context_get_source_info_by_index (c,
@@ -260,12 +260,12 @@ pm_subscribed_events_callback (pa_context *c,
// We don't care about sink input removals.
g_debug ("sink input event");
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
- gint cached_index = active_sink_get_current_sink_input_index (sink);
+ gint cached_index = device_get_current_sink_input_index (sink);
g_debug ("Just saw a sink input removal event - index = %i and cached index = %i", index, cached_index);
if (index == cached_index){
- active_sink_deactivate_voip_client (sink);
+ device_deactivate_voip_client (sink);
}
}
else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
@@ -308,7 +308,7 @@ pm_context_state_callback (pa_context *c, void *userdata)
break;
case PA_CONTEXT_FAILED:
g_warning("PA_CONTEXT_FAILED - Is PulseAudio Daemon running ?");
- active_sink_deactivate (ACTIVE_SINK (userdata));
+ device_deactivate (DEVICE (userdata));
if (reconnect_idle_id == 0){
reconnect_idle_id = g_timeout_add_seconds (RECONNECT_DELAY,
reconnect_to_pulse,
@@ -362,7 +362,7 @@ pm_server_info_callback (pa_context *c,
if (info == NULL) {
g_warning("No PA server - get the hell out of here");
- active_sink_deactivate (ACTIVE_SINK (userdata));
+ device_deactivate (DEVICE (userdata));
return;
}
// Go for the default sink
@@ -373,7 +373,7 @@ pm_server_info_callback (pa_context *c,
pm_default_sink_info_callback,
userdata) )) {
g_warning("pa_context_get_sink_info_by_namet() failed");
- active_sink_deactivate (ACTIVE_SINK (userdata));
+ device_deactivate (DEVICE (userdata));
pa_operation_unref(operation);
return;
}
@@ -382,7 +382,7 @@ pm_server_info_callback (pa_context *c,
pm_sink_info_callback,
userdata))) {
g_warning("pa_context_get_sink_info_list() failed");
- active_sink_deactivate (ACTIVE_SINK (userdata));
+ device_deactivate (DEVICE (userdata));
pa_operation_unref(operation);
return;
}
@@ -421,14 +421,14 @@ pm_sink_info_callback (pa_context *c,
return;
}
else {
- if (IS_ACTIVE_SINK (userdata) == FALSE || sink == NULL){
+ if (IS_DEVICE (userdata) == FALSE || sink == NULL){
g_warning ("sink info callback - our user data is not what we think it should be or the sink parameter is null");
return;
}
- ActiveSink* a_sink = ACTIVE_SINK (userdata);
- if (active_sink_is_populated (a_sink) == FALSE &&
+ Device* a_sink = DEVICE (userdata);
+ if (device_is_populated (a_sink) == FALSE &&
g_ascii_strncasecmp("auto_null", sink->name, 9) != 0){
- active_sink_populate (a_sink, sink);
+ device_populate (a_sink, sink);
}
}
}
@@ -443,16 +443,16 @@ pm_default_sink_info_callback (pa_context *c,
return;
}
else {
- if (IS_ACTIVE_SINK (userdata) == FALSE || info == NULL){
+ if (IS_DEVICE (userdata) == FALSE || info == NULL){
g_warning ("Default sink info callback - our user data is not what we think it should be or the info parameter is null");
return;
}
// Only repopulate if there is a change with regards the index
- if (active_sink_get_index (ACTIVE_SINK (userdata)) == info->index)
+ if (device_get_index (DEVICE (userdata)) == info->index)
return;
g_debug ("Pulse Server has handed us a new default sink");
- active_sink_populate (ACTIVE_SINK (userdata), info);
+ device_populate (DEVICE (userdata), info);
}
}
@@ -466,18 +466,18 @@ pm_sink_input_info_callback (pa_context *c,
return;
}
else {
- if (info == NULL || IS_ACTIVE_SINK (userdata) == FALSE) {
+ if (info == NULL || IS_DEVICE (userdata) == FALSE) {
g_warning("Sink input info callback : SINK INPUT INFO IS NULL or our user_data is not what we think it should be");
return;
}
- if (IS_ACTIVE_SINK (userdata) == FALSE){
+ if (IS_DEVICE (userdata) == FALSE){
g_warning ("sink input info callback - our user data is not what we think it should be");
return;
}
// Check if this is Voip sink input
gint result = pa_proplist_contains (info->proplist, PA_PROP_MEDIA_ROLE);
- ActiveSink* a_sink = ACTIVE_SINK (userdata);
+ Device* a_sink = DEVICE (userdata);
if (result == 1){
g_debug ("Sink input info has media role property");
@@ -485,7 +485,7 @@ pm_sink_input_info_callback (pa_context *c,
g_debug ("prop role = %s", value);
if (g_strcmp0 (value, "phone") == 0) {
g_debug ("And yes its a VOIP app ... sink input index = %i", info->index);
- active_sink_activate_voip_item (a_sink, (gint)info->index, (gint)info->client);
+ device_activate_voip_item (a_sink, (gint)info->index, (gint)info->client);
// TODO to start with we will assume our source is the same as what this 'client'
// is pointing at. This should probably be more intelligent :
// query for the list of source output info's and going on the name of the client
@@ -494,14 +494,14 @@ pm_sink_input_info_callback (pa_context *c,
}
// And finally check for the mute blocking state
- if (active_sink_get_index (a_sink) == info->sink){
- active_sink_determine_blocking_state (a_sink);
+ if (device_get_index (a_sink) == info->sink){
+ device_determine_blocking_state (a_sink);
}
}
}
static void
-pm_update_active_sink (pa_context *c,
+pm_update_device (pa_context *c,
const pa_sink_info *info,
int eol,
void *userdata)
@@ -510,11 +510,11 @@ pm_update_active_sink (pa_context *c,
return;
}
else{
- if (IS_ACTIVE_SINK (userdata) == FALSE || info == NULL){
- g_warning ("update_active_sink - our user data is not what we think it should be or the info parameter is null");
+ if (IS_DEVICE (userdata) == FALSE || info == NULL){
+ g_warning ("update_device - our user data is not what we think it should be or the info parameter is null");
return;
}
- active_sink_update (ACTIVE_SINK(userdata), info);
+ device_update (DEVICE(userdata), info);
}
}
@@ -551,16 +551,16 @@ pm_default_source_info_callback (pa_context *c,
return;
}
else {
- if (IS_ACTIVE_SINK (userdata) == FALSE || info == NULL){
+ if (IS_DEVICE (userdata) == FALSE || info == NULL){
g_warning ("Default source info callback - our user data is not what we think it should be or the source info parameter is null");
return;
}
// If there is an index change we need to change our cached source
- if (active_sink_get_source_index (ACTIVE_SINK (userdata)) == info->index)
+ if (device_get_source_index (DEVICE (userdata)) == info->index)
return;
g_debug ("Pulse Server has handed us a new default source");
- active_sink_deactivate_voip_source (ACTIVE_SINK (userdata), TRUE);
- active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info);
+ device_deactivate_voip_source (DEVICE (userdata), TRUE);
+ device_update_voip_input_source (DEVICE (userdata), info);
}
}
@@ -574,13 +574,13 @@ pm_source_info_callback (pa_context *c,
return;
}
else {
- if (IS_ACTIVE_SINK (userdata) == FALSE || info == NULL){
+ if (IS_DEVICE (userdata) == FALSE || info == NULL){
g_warning ("source info callback - our user data is not what we think it should be or the source info parameter is null");
return;
}
// For now we will take the first available
- if (active_sink_is_voip_source_populated (ACTIVE_SINK (userdata)) == FALSE){
- active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info);
+ if (device_is_voip_source_populated (DEVICE (userdata)) == FALSE){
+ device_update_voip_input_source (DEVICE (userdata), info);
}
}
}
@@ -595,11 +595,11 @@ pm_update_source_info_callback (pa_context *c,
return;
}
else {
- if (IS_ACTIVE_SINK (userdata) == FALSE || info == NULL ){
+ if (IS_DEVICE (userdata) == FALSE || info == NULL ){
g_warning ("source info update callback - our user data is not what we think it should be or the source info paramter is null");
return;
}
g_debug ("Got a source update for %s , index %i", info->name, info->index);
- active_sink_update_voip_input_source (ACTIVE_SINK (userdata), info);
+ device_update_voip_input_source (DEVICE (userdata), info);
}
}
diff --git a/src/pulseaudio-mgr.h b/src/pulseaudio-mgr.h
index d61117d..ace47f3 100644
--- a/src/pulseaudio-mgr.h
+++ b/src/pulseaudio-mgr.h
@@ -17,9 +17,9 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "active-sink.h"
+#include "device.h"
-void pm_establish_pulse_connection (ActiveSink* active_sink);
+void pm_establish_pulse_connection (Device* device);
void close_pulse_activites();
void pm_update_volume (gint sink_index, pa_cvolume new_volume);
void pm_update_mic_gain (gint source_index, pa_cvolume new_gain);
diff --git a/src/slider-menu-item.c b/src/slider-menu-item.c
index 1c88f01..fb66563 100644
--- a/src/slider-menu-item.c
+++ b/src/slider-menu-item.c
@@ -23,11 +23,17 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
#include "slider-menu-item.h"
#include "common-defs.h"
+#include "pulseaudio-mgr.h"
typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate;
struct _SliderMenuItemPrivate {
- ActiveSink* a_sink;
+ Device* a_sink;
+ gint index;
+ gchar* name;
+ pa_cvolume volume;
+ pa_channel_map channel_map;
+ pa_volume_t base_volume;
};
#define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate))
@@ -39,6 +45,8 @@ static void slider_menu_item_dispose (GObject *object);
static void slider_menu_item_finalize (GObject *object);
static void handle_event (DbusmenuMenuitem * mi, const gchar * name,
GVariant * value, guint timestamp);
+static pa_cvolume slider_menu_item_construct_mono_volume (const pa_cvolume* vol);
+static void slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent);
G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM);
@@ -63,7 +71,13 @@ slider_menu_item_init (SliderMenuItem *self)
g_debug("Building new Slider Menu Item");
dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self),
DBUSMENU_MENUITEM_PROP_TYPE,
- DBUSMENU_VOLUME_MENUITEM_TYPE );
+ DBUSMENU_VOLUME_MENUITEM_TYPE );
+
+ SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
+
+ priv->index = -1;
+ priv->name = NULL;
+
return;
}
@@ -97,33 +111,108 @@ handle_event (DbusmenuMenuitem * mi,
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (SLIDER_MENU_ITEM (mi));
gdouble volume_input = g_variant_get_double(input);
//g_debug ("slider menu item about to update volume %f", volume_input);
- active_sink_update_volume (priv->a_sink, volume_input);
- active_sink_ensure_sink_is_unmuted (priv->a_sink);
+ slider_menu_item_update_volume (SLIDER_MENU_ITEM (mi), volume_input);
+ device_ensure_sink_is_unmuted (priv->a_sink);
}
}
}
+
+void
+slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update)
+{
+ SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
+ priv->name = g_strdup (update->name);
+ priv->index = update->index;
+ priv->volume = slider_menu_item_construct_mono_volume (&update->volume);
+ priv->base_volume = update->base_volume;
+ priv->channel_map = update->channel_map;
+
+ pa_volume_t vol = pa_cvolume_max (&update->volume);
+ gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
+ GVariant* new_volume = g_variant_new_double (volume_percent);
+ dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
+ DBUSMENU_VOLUME_MENUITEM_LEVEL,
+ new_volume);
+ slider_menu_item_enable (self, TRUE);
+}
+
+// From the UI
+static void
+slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent)
+{
+ pa_cvolume new_volume;
+ pa_cvolume_init(&new_volume);
+ new_volume.channels = 1;
+ pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
+ pa_cvolume_set(&new_volume, 1, new_volume_value);
+
+ SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
+
+ pa_cvolume_set(&priv->volume, priv->channel_map.channels, new_volume_value);
+ pm_update_volume (priv->index, new_volume);
+}
+
+// To the UI
void
-slider_menu_item_update (SliderMenuItem* item,
- gdouble update)
+slider_menu_item_update (SliderMenuItem* self, const pa_sink_info* update)
{
- GVariant* new_volume = g_variant_new_double(update);
- dbusmenu_menuitem_property_set_variant(DBUSMENU_MENUITEM(item),
- DBUSMENU_VOLUME_MENUITEM_LEVEL,
- new_volume);
+ SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
+
+ priv->volume = slider_menu_item_construct_mono_volume (&update->volume);
+ priv->base_volume = update->base_volume;
+ priv->channel_map = update->channel_map;
+
+ pa_volume_t vol = pa_cvolume_max (&update->volume);
+ gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
+
+ GVariant* new_volume = g_variant_new_double (volume_percent);
+ dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
+ DBUSMENU_VOLUME_MENUITEM_LEVEL,
+ new_volume);
}
+/*
+ * Enable/Disabled can be considered the equivalent of whether we have an active
+ * sink or not, let the widget have inherent state.
+ */
void
-slider_menu_item_enable (SliderMenuItem* item,
- gboolean active)
+slider_menu_item_enable (SliderMenuItem* self, gboolean active)
{
- dbusmenu_menuitem_property_set_bool( DBUSMENU_MENUITEM(item),
+ SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
+
+ dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM(self),
DBUSMENU_MENUITEM_PROP_ENABLED,
- active );
+ active);
+ if(active == FALSE){
+ priv->index = -1;
+ if(priv->name != NULL){
+ g_free(priv->name);
+ priv->name = NULL;
+ }
+ }
+}
+
+gint
+slider_menu_item_get_sink_index (SliderMenuItem* self)
+{
+ SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
+ return priv->index;
+}
+
+static pa_cvolume
+slider_menu_item_construct_mono_volume (const pa_cvolume* vol)
+{
+ pa_cvolume new_volume;
+ pa_cvolume_init(&new_volume);
+ new_volume.channels = 1;
+ pa_volume_t max_vol = pa_cvolume_max(vol);
+ pa_cvolume_set(&new_volume, 1, max_vol);
+ return new_volume;
}
SliderMenuItem*
-slider_menu_item_new (ActiveSink* sink)
+slider_menu_item_new (Device* sink)
{
SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL);
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
diff --git a/src/slider-menu-item.h b/src/slider-menu-item.h
index f094c71..4375971 100644
--- a/src/slider-menu-item.h
+++ b/src/slider-menu-item.h
@@ -23,7 +23,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib-object.h>
#include <libdbusmenu-glib/menuitem.h>
-#include "active-sink.h"
+#include "device.h"
G_BEGIN_DECLS
@@ -47,10 +47,16 @@ struct _SliderMenuItem {
GType slider_menu_item_get_type (void);
-void slider_menu_item_update(SliderMenuItem* item, gdouble update);
+void slider_menu_item_update(SliderMenuItem* item, const pa_sink_info* update);
void slider_menu_item_enable(SliderMenuItem* item, gboolean active);
+void slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update);
+//void
+//active_sink_update (ActiveSink* sink,
+// const pa_sink_info* update)
-SliderMenuItem* slider_menu_item_new (ActiveSink* sink);
+gint slider_menu_item_get_sink_index (SliderMenuItem* self);
+
+SliderMenuItem* slider_menu_item_new (Device* sink);
G_END_DECLS
diff --git a/src/sound-service-dbus.c b/src/sound-service-dbus.c
index 8d0cc0b..7c817af 100644
--- a/src/sound-service-dbus.c
+++ b/src/sound-service-dbus.c
@@ -29,7 +29,7 @@
#include <libdbusmenu-glib/client.h>
#include "sound-service-dbus.h"
-#include "active-sink.h"
+#include "device.h"
#include "gen-sound-service.xml.h"
#include "dbus-shared-names.h"
@@ -55,7 +55,7 @@ typedef struct _SoundServiceDbusPrivate SoundServiceDbusPrivate;
struct _SoundServiceDbusPrivate {
GDBusConnection* connection;
DbusmenuMenuitem* root_menuitem;
- ActiveSink* active_sink;
+ Device* device;
};
static GDBusNodeInfo * node_info = NULL;
@@ -155,7 +155,7 @@ sound_service_dbus_create_root_item (SoundServiceDbus* self)
paths);
dbusmenu_server_set_root (server, priv->root_menuitem);
g_object_unref (priv->root_menuitem);
- priv->active_sink = active_sink_new (self);
+ priv->device = device_new (self);
return priv->root_menuitem;
}
@@ -272,8 +272,8 @@ bus_method_call (GDBusConnection * connection,
SoundServiceDbusPrivate *priv = SOUND_SERVICE_DBUS_GET_PRIVATE (service);
if (g_strcmp0(method, "GetSoundState") == 0) {
- g_debug("Get state - %i", active_sink_get_state (priv->active_sink));
- retval = g_variant_new ( "(i)", active_sink_get_state (priv->active_sink));
+ g_debug("Get state - %i", device_get_state (priv->device));
+ retval = g_variant_new ( "(i)", device_get_state (priv->device));
}
else if (g_strcmp0(method, "BlacklistMediaPlayer") == 0) {
gboolean blacklist;
diff --git a/src/voip-input-menu-item.c b/src/voip-input-menu-item.c
index a742654..a92f91c 100644
--- a/src/voip-input-menu-item.c
+++ b/src/voip-input-menu-item.c
@@ -28,7 +28,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
typedef struct _VoipInputMenuItemPrivate VoipInputMenuItemPrivate;
struct _VoipInputMenuItemPrivate {
- ActiveSink* a_sink;
+ Device* a_sink;
pa_cvolume volume;
gint mute;
guint32 volume_steps;
@@ -129,8 +129,6 @@ handle_event (DbusmenuMenuitem * mi,
if (priv->mute == 1) {
pm_update_mic_mute (priv->source_index, 0);
}
- //active_sink_update_volume (priv->a_sink, volume_input);
- //active_sink_ensure_sink_is_unmuted (priv->a_sink);
}
}
}
@@ -268,7 +266,7 @@ voip_input_menu_item_enable (VoipInputMenuItem* item,
}
VoipInputMenuItem*
-voip_input_menu_item_new (ActiveSink* sink)
+voip_input_menu_item_new (Device* sink)
{
VoipInputMenuItem *self = g_object_new(VOIP_INPUT_MENU_ITEM_TYPE, NULL);
VoipInputMenuItemPrivate* priv = VOIP_INPUT_MENU_ITEM_GET_PRIVATE (self);
diff --git a/src/voip-input-menu-item.h b/src/voip-input-menu-item.h
index 6f4ed85..30ada5a 100644
--- a/src/voip-input-menu-item.h
+++ b/src/voip-input-menu-item.h
@@ -22,7 +22,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib.h>
#include <pulse/pulseaudio.h>
#include <libdbusmenu-glib/menuitem.h>
-#include "active-sink.h"
+#include "device.h"
G_BEGIN_DECLS
@@ -62,7 +62,7 @@ gint voip_input_menu_item_get_sink_input_index (VoipInputMenuItem* item);
void voip_input_menu_item_deactivate_source (VoipInputMenuItem* item, gboolean visible);
void voip_input_menu_item_deactivate_voip_client (VoipInputMenuItem* item);
-VoipInputMenuItem* voip_input_menu_item_new (ActiveSink* sink);
+VoipInputMenuItem* voip_input_menu_item_new (Device* sink);
G_END_DECLS