3
Copyright 2010 Canonical Ltd.
6
Conor Curran <conor.curran@canonical.com>
8
This program is free software: you can redistribute it and/or modify it
9
under the terms of the GNU General Public License version 3, as published
10
by the Free Software Foundation.
12
This program is distributed in the hope that it will be useful, but
13
WITHOUT ANY WARRANTY; without even the implied warranties of
14
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
15
PURPOSE. See the GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License along
18
with this program. If not, see <http://www.gnu.org/licenses/>.
25
#include <glib/gi18n.h>
28
#include "volume-widget.h"
29
#include "common-defs.h"
30
#include <libido/idoscalemenuitem.h>
32
typedef struct _VolumeWidgetPrivate VolumeWidgetPrivate;
34
struct _VolumeWidgetPrivate
36
DbusmenuMenuitem* twin_item;
37
GtkWidget* ido_volume_slider;
41
#define VOLUME_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOLUME_WIDGET_TYPE, VolumeWidgetPrivate))
44
static void volume_widget_class_init (VolumeWidgetClass *klass);
45
static void volume_widget_init (VolumeWidget *self);
46
static void volume_widget_dispose (GObject *object);
47
static void volume_widget_finalize (GObject *object);
48
static void volume_widget_set_twin_item( VolumeWidget* self,
49
DbusmenuMenuitem* twin_item);
50
static void volume_widget_property_update( DbusmenuMenuitem* item, gchar* property,
51
GValue* value, gpointer userdata);
53
static gboolean volume_widget_change_value_cb (GtkRange *range,
57
static gboolean volume_widget_value_changed_cb(GtkRange *range, gpointer user_data);
58
static void volume_widget_slider_grabbed(GtkWidget *widget, gpointer user_data);
59
static void volume_widget_slider_released(GtkWidget *widget, gpointer user_data);
60
static void volume_widget_parent_changed (GtkWidget *widget, gpointer user_data);
62
G_DEFINE_TYPE (VolumeWidget, volume_widget, G_TYPE_OBJECT);
65
volume_widget_class_init (VolumeWidgetClass *klass)
67
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
69
g_type_class_add_private (klass, sizeof (VolumeWidgetPrivate));
71
gobject_class->dispose = volume_widget_dispose;
72
gobject_class->finalize = volume_widget_finalize;
76
volume_widget_init (VolumeWidget *self)
78
g_debug("VolumeWidget::volume_widget_init");
79
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
81
priv->ido_volume_slider = ido_scale_menu_item_new_with_range ("VOLUME", IDO_RANGE_STYLE_DEFAULT, 0, 0, 100, 1);
82
g_object_ref (priv->ido_volume_slider);
83
ido_scale_menu_item_set_style (IDO_SCALE_MENU_ITEM (priv->ido_volume_slider), IDO_SCALE_MENU_ITEM_STYLE_IMAGE);
84
g_object_set(priv->ido_volume_slider, "reverse-scroll-events", TRUE, NULL);
86
g_signal_connect (priv->ido_volume_slider,
87
"notify::parent", G_CALLBACK (volume_widget_parent_changed),
90
GtkWidget* volume_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
92
g_signal_connect(volume_widget, "change-value", G_CALLBACK(volume_widget_change_value_cb), self);
93
g_signal_connect(volume_widget, "value-changed", G_CALLBACK(volume_widget_value_changed_cb), self);
94
g_signal_connect(priv->ido_volume_slider, "slider-grabbed", G_CALLBACK(volume_widget_slider_grabbed), self);
95
g_signal_connect(priv->ido_volume_slider, "slider-released", G_CALLBACK(volume_widget_slider_released), self);
97
GtkWidget* primary_image = ido_scale_menu_item_get_primary_image((IdoScaleMenuItem*)priv->ido_volume_slider);
98
GIcon * primary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-low-zero-panel");
99
gtk_image_set_from_gicon(GTK_IMAGE(primary_image), primary_gicon, GTK_ICON_SIZE_MENU);
100
g_object_unref(primary_gicon);
102
GtkWidget* secondary_image = ido_scale_menu_item_get_secondary_image((IdoScaleMenuItem*)priv->ido_volume_slider);
103
GIcon * secondary_gicon = g_themed_icon_new_with_default_fallbacks("audio-volume-high-panel");
104
gtk_image_set_from_gicon(GTK_IMAGE(secondary_image), secondary_gicon, GTK_ICON_SIZE_MENU);
105
g_object_unref(secondary_gicon);
107
GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (volume_widget));
108
gtk_adjustment_set_step_increment(adj, 4);
112
volume_widget_dispose (GObject *object)
114
G_OBJECT_CLASS (volume_widget_parent_class)->dispose (object);
118
volume_widget_finalize (GObject *object)
120
G_OBJECT_CLASS (volume_widget_parent_class)->finalize (object);
124
volume_widget_property_update(DbusmenuMenuitem* item, gchar* property,
125
GValue* value, gpointer userdata)
127
g_return_if_fail (IS_VOLUME_WIDGET (userdata));
128
VolumeWidget* mitem = VOLUME_WIDGET(userdata);
129
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
130
g_debug("scrub-widget::property_update for prop %s", property);
131
if(g_ascii_strcasecmp(DBUSMENU_VOLUME_MENUITEM_LEVEL, property) == 0){
132
if(priv->grabbed == FALSE){
133
GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
134
GtkRange *range = (GtkRange*)slider;
135
gdouble update = g_value_get_double (value);
136
g_debug("volume-widget - update level with value %f", update);
137
gtk_range_set_value(range, update);
138
determine_state_from_volume(update);
144
volume_widget_set_twin_item(VolumeWidget* self,
145
DbusmenuMenuitem* twin_item)
147
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
148
priv->twin_item = twin_item;
149
g_object_ref(priv->twin_item);
150
g_signal_connect(G_OBJECT(twin_item), "property-changed",
151
G_CALLBACK(volume_widget_property_update), self);
152
gdouble initial_level = g_value_get_double (dbusmenu_menuitem_property_get_value(twin_item,
153
DBUSMENU_VOLUME_MENUITEM_LEVEL));
154
g_debug("volume_widget_set_twin_item initial level = %f", initial_level);
155
GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
156
GtkRange *range = (GtkRange*)slider;
157
gtk_range_set_value(range, initial_level);
158
determine_state_from_volume(initial_level);
162
volume_widget_change_value_cb (GtkRange *range,
163
GtkScrollType scroll,
167
g_return_val_if_fail (IS_VOLUME_WIDGET (user_data), FALSE);
168
VolumeWidget* mitem = VOLUME_WIDGET(user_data);
169
volume_widget_update(mitem, new_value);
170
determine_state_from_volume(new_value);
175
We only want this callback to catch mouse icon press events
176
which set the slider to 0 or 100. Ignore all other events.
179
volume_widget_value_changed_cb(GtkRange *range, gpointer user_data)
181
g_return_val_if_fail (IS_VOLUME_WIDGET (user_data), FALSE);
182
VolumeWidget* mitem = VOLUME_WIDGET(user_data);
183
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
184
GtkWidget *slider = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider);
185
gdouble current_value = CLAMP(gtk_range_get_value(GTK_RANGE(slider)), 0, 100);
187
if(current_value == 0 || current_value == 100){
188
volume_widget_update(mitem, current_value);
194
volume_widget_update(VolumeWidget* self, gdouble update)
196
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
198
g_value_init(&value, G_TYPE_DOUBLE);
199
gdouble clamped = CLAMP(update, 0, 100);
200
g_value_set_double(&value, clamped);
201
dbusmenu_menuitem_handle_event (priv->twin_item, "update", &value, 0);
207
volume_widget_get_ido_slider(VolumeWidget* self)
209
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
210
return priv->ido_volume_slider;
214
volume_widget_parent_changed (GtkWidget *widget,
217
gtk_widget_set_size_request (widget, 200, -1);
218
g_debug("volume_widget_parent_changed");
222
volume_widget_slider_grabbed(GtkWidget *widget, gpointer user_data)
224
VolumeWidget* mitem = VOLUME_WIDGET(user_data);
225
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
226
priv->grabbed = TRUE;
230
volume_widget_slider_released(GtkWidget *widget, gpointer user_data)
232
VolumeWidget* mitem = VOLUME_WIDGET(user_data);
233
VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
234
priv->grabbed = FALSE;
239
* @returns: a new #VolumeWidget.
242
volume_widget_new(DbusmenuMenuitem *item)
244
GtkWidget* widget = g_object_new(VOLUME_WIDGET_TYPE, NULL);
245
volume_widget_set_twin_item((VolumeWidget*)widget, item);