2
Copyright 2010 Canonical Ltd.
5
Conor Curran <conor.curran@canonical.com>
7
This program is free software: you can redistribute it and/or modify it
8
under the terms of the GNU General Public License version 3, as published
9
by the Free Software Foundation.
11
This program is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranties of
13
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
14
PURPOSE. See the GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License along
17
with this program. If not, see <http://www.gnu.org/licenses/>.
23
#include <glib/gi18n.h>
24
#include "slider-menu-item.h"
25
#include "common-defs.h"
26
#include "pulseaudio-mgr.h"
28
typedef struct _SliderMenuItemPrivate SliderMenuItemPrivate;
30
struct _SliderMenuItemPrivate {
36
pa_channel_map channel_map;
37
pa_volume_t base_volume;
40
#define SLIDER_MENU_ITEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SLIDER_MENU_ITEM_TYPE, SliderMenuItemPrivate))
43
static void slider_menu_item_class_init (SliderMenuItemClass *klass);
44
static void slider_menu_item_init (SliderMenuItem *self);
45
static void slider_menu_item_dispose (GObject *object);
46
static void slider_menu_item_finalize (GObject *object);
47
static void handle_event (DbusmenuMenuitem * mi, const gchar * name,
48
GVariant * value, guint timestamp);
49
static pa_cvolume slider_menu_item_construct_mono_volume (const pa_cvolume* vol);
50
static void slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent);
52
G_DEFINE_TYPE (SliderMenuItem, slider_menu_item, DBUSMENU_TYPE_MENUITEM);
55
slider_menu_item_class_init (SliderMenuItemClass *klass)
57
GObjectClass *object_class = G_OBJECT_CLASS (klass);
59
g_type_class_add_private (klass, sizeof (SliderMenuItemPrivate));
61
object_class->dispose = slider_menu_item_dispose;
62
object_class->finalize = slider_menu_item_finalize;
64
DbusmenuMenuitemClass * mclass = DBUSMENU_MENUITEM_CLASS(klass);
65
mclass->handle_event = handle_event;
70
slider_menu_item_init (SliderMenuItem *self)
72
dbusmenu_menuitem_property_set( DBUSMENU_MENUITEM(self),
73
DBUSMENU_MENUITEM_PROP_TYPE,
74
DBUSMENU_VOLUME_MENUITEM_TYPE );
76
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
78
priv->index = NOT_ACTIVE;
85
slider_menu_item_dispose (GObject *object)
87
G_OBJECT_CLASS (slider_menu_item_parent_class)->dispose (object);
92
slider_menu_item_finalize (GObject *object)
94
G_OBJECT_CLASS (slider_menu_item_parent_class)->finalize (object);
98
handle_event (DbusmenuMenuitem * mi,
103
g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_DOUBLE));
104
g_return_if_fail (IS_SLIDER_MENU_ITEM (mi));
106
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (SLIDER_MENU_ITEM (mi));
107
gdouble volume_input = g_variant_get_double (value);
110
g_debug ("slider menu item handle event with value %f on name %s",
115
slider_menu_item_update_volume (SLIDER_MENU_ITEM (mi), volume_input);
116
if (volume_input > 0)
117
device_ensure_sink_is_unmuted (priv->a_sink);
122
slider_menu_item_populate (SliderMenuItem* self, const pa_sink_info* update)
124
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
125
priv->name = g_strdup (update->name);
126
priv->index = update->index;
127
priv->volume = slider_menu_item_construct_mono_volume (&update->volume);
128
priv->base_volume = update->base_volume;
129
priv->channel_map = update->channel_map;
130
priv->mute = update->mute;
132
pa_volume_t vol = pa_cvolume_max (&update->volume);
133
gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
134
GVariant* new_volume = g_variant_new_double (volume_percent);
135
dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
136
DBUSMENU_VOLUME_MENUITEM_LEVEL,
138
GVariant* new_mute_update = g_variant_new_boolean (update->mute == 1);
139
dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
140
DBUSMENU_VOLUME_MENUITEM_MUTE,
143
slider_menu_item_enable (self, TRUE);
148
slider_menu_item_update_volume (SliderMenuItem* self, gdouble percent)
150
g_return_if_fail (IS_SLIDER_MENU_ITEM (self));
152
pa_cvolume mono_new_volume;
153
pa_cvolume_init(&mono_new_volume);
154
mono_new_volume.channels = 1;
155
pa_volume_t new_volume_value = (pa_volume_t) ((percent * PA_VOLUME_NORM) / 100);
157
if (new_volume_value == PA_VOLUME_INVALID || new_volume_value >= PA_VOLUME_MAX){
158
g_warning ("slider_menu_item_update_volume - volume is out of range !");
162
pa_cvolume_set(&mono_new_volume, 1, new_volume_value);
164
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
165
if (!pa_cvolume_valid (&mono_new_volume)){
166
g_warning ("Invalid volume - ignore it!");
169
if (!pa_channel_map_valid(&priv->channel_map)){
170
g_warning ("Invalid channel map - ignore update volume!");
173
pa_cvolume_set(&priv->volume, priv->channel_map.channels, new_volume_value);
174
pm_update_volume (priv->index, mono_new_volume);
179
slider_menu_item_update (SliderMenuItem* self, const pa_sink_info* update)
181
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
183
priv->volume = slider_menu_item_construct_mono_volume (&update->volume);
184
priv->base_volume = update->base_volume;
185
priv->channel_map = update->channel_map;
187
pa_volume_t vol = pa_cvolume_max (&update->volume);
188
gdouble volume_percent = ((gdouble) vol * 100) / PA_VOLUME_NORM;
190
GVariant* new_volume = g_variant_new_double (volume_percent);
193
g_debug ("slider menu item update - volume update to ui to %f", volume_percent);
196
dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
197
DBUSMENU_VOLUME_MENUITEM_LEVEL,
200
if (priv->mute != update->mute){
201
priv->mute = update->mute;
203
g_debug ("volume menu item - update - mute on ui = %i", update->mute);
205
GVariant* new_mute_update = g_variant_new_boolean (update->mute == 1);
206
dbusmenu_menuitem_property_set_variant (DBUSMENU_MENUITEM(self),
207
DBUSMENU_VOLUME_MENUITEM_MUTE,
213
* Enable/Disabled can be considered the equivalent of whether we have an active
214
* sink or not, let the widget have inherent state.
217
slider_menu_item_enable (SliderMenuItem* self, gboolean active)
219
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
221
dbusmenu_menuitem_property_set_bool (DBUSMENU_MENUITEM(self),
222
DBUSMENU_MENUITEM_PROP_ENABLED,
225
priv->index = NOT_ACTIVE;
226
if(priv->name != NULL){
234
slider_menu_item_get_sink_index (SliderMenuItem* self)
236
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);
241
slider_menu_item_construct_mono_volume (const pa_cvolume* vol)
243
pa_cvolume new_volume;
244
pa_cvolume_init(&new_volume);
245
new_volume.channels = 1;
246
pa_volume_t max_vol = pa_cvolume_max(vol);
247
pa_cvolume_set(&new_volume, 1, max_vol);
252
slider_menu_item_new (Device* sink)
254
SliderMenuItem *self = g_object_new(SLIDER_MENU_ITEM_TYPE, NULL);
255
SliderMenuItemPrivate* priv = SLIDER_MENU_ITEM_GET_PRIVATE (self);