~oem-solutions-group/unity-2d/indicator-sound

« back to all changes in this revision

Viewing changes to src/volume-widget.c

  • Committer: Ken VanDine
  • Date: 2010-09-14 19:13:49 UTC
  • mfrom: (28.2.108 indicator-sound)
  • mto: This revision was merged to the branch mainline in revision 71.
  • Revision ID: ken.vandine@canonical.com-20100914191349-pp888e13xbemy0kc
Tags: upstream-0.4.5
ImportĀ upstreamĀ versionĀ 0.4.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
Copyright 2010 Canonical Ltd.
4
 
 
5
 
Authors:
6
 
    Conor Curran <conor.curran@canonical.com>
7
 
 
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.
11
 
 
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.
16
 
 
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/>.
19
 
*/
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include "config.h"
23
 
#endif
24
 
 
25
 
#include <glib/gi18n.h>
26
 
#include <math.h>
27
 
#include <glib.h>
28
 
#include "volume-widget.h"
29
 
#include "common-defs.h"
30
 
#include <libido/idoscalemenuitem.h>
31
 
 
32
 
typedef struct _VolumeWidgetPrivate VolumeWidgetPrivate;
33
 
 
34
 
struct _VolumeWidgetPrivate
35
 
{
36
 
        DbusmenuMenuitem* twin_item;    
37
 
        GtkWidget* ido_volume_slider;
38
 
        gboolean grabbed;
39
 
};
40
 
 
41
 
#define VOLUME_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VOLUME_WIDGET_TYPE, VolumeWidgetPrivate))
42
 
 
43
 
/* Prototypes */
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);
52
 
 
53
 
static gboolean volume_widget_change_value_cb (GtkRange     *range,
54
 
                                                                                        GtkScrollType scroll,
55
 
                                                                                        gdouble       value,
56
 
                                                                                        gpointer      user_data);
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);
61
 
 
62
 
G_DEFINE_TYPE (VolumeWidget, volume_widget, G_TYPE_OBJECT);
63
 
 
64
 
static void
65
 
volume_widget_class_init (VolumeWidgetClass *klass)
66
 
{
67
 
        GObjectClass                    *gobject_class = G_OBJECT_CLASS (klass);
68
 
        
69
 
        g_type_class_add_private (klass, sizeof (VolumeWidgetPrivate));
70
 
 
71
 
        gobject_class->dispose = volume_widget_dispose;
72
 
        gobject_class->finalize = volume_widget_finalize;
73
 
}
74
 
 
75
 
static void
76
 
volume_widget_init (VolumeWidget *self)
77
 
{
78
 
        g_debug("VolumeWidget::volume_widget_init");
79
 
        VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
80
 
 
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);
85
 
 
86
 
  g_signal_connect (priv->ido_volume_slider,
87
 
                    "notify::parent", G_CALLBACK (volume_widget_parent_changed),
88
 
                    NULL);
89
 
        
90
 
  GtkWidget* volume_widget = ido_scale_menu_item_get_scale((IdoScaleMenuItem*)priv->ido_volume_slider); 
91
 
        
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);
96
 
 
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);
101
 
 
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);
106
 
 
107
 
  GtkAdjustment *adj = gtk_range_get_adjustment (GTK_RANGE (volume_widget));
108
 
  gtk_adjustment_set_step_increment(adj, 4);
109
 
}
110
 
 
111
 
static void
112
 
volume_widget_dispose (GObject *object)
113
 
{
114
 
        G_OBJECT_CLASS (volume_widget_parent_class)->dispose (object);
115
 
}
116
 
 
117
 
static void
118
 
volume_widget_finalize (GObject *object)
119
 
{
120
 
        G_OBJECT_CLASS (volume_widget_parent_class)->finalize (object);
121
 
}
122
 
 
123
 
static void 
124
 
volume_widget_property_update(DbusmenuMenuitem* item, gchar* property, 
125
 
                             GValue* value, gpointer userdata)
126
 
{       
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);                    
139
 
                }
140
 
        }
141
 
}
142
 
 
143
 
static void
144
 
volume_widget_set_twin_item(VolumeWidget* self,
145
 
                           DbusmenuMenuitem* twin_item)
146
 
{
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);   
159
 
}
160
 
 
161
 
static gboolean
162
 
volume_widget_change_value_cb (GtkRange     *range,
163
 
                                                                        GtkScrollType scroll,
164
 
                                                                        gdouble       new_value,
165
 
                                                                        gpointer      user_data)
166
 
{
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);
171
 
        return FALSE;
172
 
}
173
 
 
174
 
/*
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.
177
 
*/ 
178
 
static gboolean
179
 
volume_widget_value_changed_cb(GtkRange *range, gpointer user_data)
180
 
{
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);
186
 
        
187
 
        if(current_value == 0 || current_value == 100){
188
 
                volume_widget_update(mitem, current_value);
189
 
        }
190
 
  return FALSE;
191
 
}
192
 
 
193
 
void 
194
 
volume_widget_update(VolumeWidget* self, gdouble update)
195
 
{
196
 
        VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
197
 
        GValue value = {0};
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);
202
 
}
203
 
 
204
 
 
205
 
 
206
 
GtkWidget*
207
 
volume_widget_get_ido_slider(VolumeWidget* self)
208
 
{
209
 
        VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(self);
210
 
        return priv->ido_volume_slider; 
211
 
}
212
 
 
213
 
static void
214
 
volume_widget_parent_changed (GtkWidget *widget,
215
 
                                                gpointer   user_data)
216
 
{
217
 
  gtk_widget_set_size_request (widget, 200, -1);
218
 
  g_debug("volume_widget_parent_changed");
219
 
}
220
 
 
221
 
static void
222
 
volume_widget_slider_grabbed(GtkWidget *widget, gpointer user_data)
223
 
{
224
 
        VolumeWidget* mitem = VOLUME_WIDGET(user_data);
225
 
        VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
226
 
        priv->grabbed = TRUE;   
227
 
}
228
 
 
229
 
static void
230
 
volume_widget_slider_released(GtkWidget *widget, gpointer user_data)
231
 
{
232
 
        VolumeWidget* mitem = VOLUME_WIDGET(user_data);
233
 
        VolumeWidgetPrivate * priv = VOLUME_WIDGET_GET_PRIVATE(mitem);
234
 
        priv->grabbed = FALSE;
235
 
}
236
 
 
237
 
/**
238
 
 * volume_widget_new:
239
 
 * @returns: a new #VolumeWidget.
240
 
 **/
241
 
GtkWidget* 
242
 
volume_widget_new(DbusmenuMenuitem *item)
243
 
{
244
 
        GtkWidget* widget = g_object_new(VOLUME_WIDGET_TYPE, NULL);
245
 
        volume_widget_set_twin_item((VolumeWidget*)widget, item);
246
 
        return widget;
247
 
}
248
 
 
249