2008-05-20 Alejandro G. Castro <alex@igalia.com>
[hildon] / src / hildon-volumebar.c
1 /*
2  * This file is a part of hildon
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation, all rights reserved.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 /**
26  * SECTION:hildon-volumebar
27  * @short_description: Base class for widgets that display a volume bar.
28  * @see_also: #HildonHVolumebar, #HildonVVolumebar
29  *
30  * #HildonVolumebar is a base class for widgets that display a volume bar that
31  * allows increasing or decreasing volume within a predefined range, and muting
32  * the volume when users click the mute icon.
33  */
34
35 #ifdef                                          HAVE_CONFIG_H
36 #include                                        <config.h>
37 #endif
38
39 #include                                        "hildon-volumebar.h"
40 #include                                        <gtk/gtk.h>
41 #include                                        <gdk/gdkkeysyms.h>
42 #include                                        "hildon-volumebar-range.h"
43 #include                                        "hildon-volumebar-private.h"
44
45 static GtkContainerClass*                       parent_class;
46
47 static void
48 hildon_volumebar_class_init                     (HildonVolumebarClass* volumebar_class);       
49
50 static void 
51 hildon_volumebar_init                           (HildonVolumebar* volumebar);
52
53 static void 
54 hildon_child_forall                             (GtkContainer * container,
55                                                  gboolean include_internals,
56                                                  GtkCallback callback,
57                                                  gpointer callback_data);
58
59 static void 
60 hildon_volumebar_destroy                        (GtkObject *self);
61
62 static void 
63 hildon_volumebar_set_property                   (GObject* object,
64                                                  guint prop_id,
65                                                  const GValue* value,
66                                                  GParamSpec* pspec);
67
68 static void 
69 hildon_volumebar_get_property                   (GObject * object,
70                                                  guint prop_id,
71                                                  GValue* value, 
72                                                  GParamSpec* pspec);
73
74 static void 
75 mute_toggled                                    (HildonVolumebar *self);
76
77 static gboolean
78 hildon_volumebar_key_press                      (GtkWidget* widget,
79                                                  GdkEventKey* event);
80
81 static void 
82 hildon_volumebar_size_allocate                  (GtkWidget *widget,
83                                                  GtkAllocation *allocation);
84
85 static void 
86 hildon_volumebar_realize                        (GtkWidget *widget);
87
88 static void 
89 hildon_volumebar_unrealize                      (GtkWidget *widget);
90
91 static void 
92 hildon_volumebar_map                            (GtkWidget *widget);
93
94 static void 
95 hildon_volumebar_unmap                          (GtkWidget *widget);
96
97 static void
98 hildon_volumebar_grab_focus                     (GtkWidget *widget);
99
100 static gboolean
101 hildon_volumebar_focus                          (GtkWidget *widget,
102                                                  GtkDirectionType direction);
103
104 static void 
105 hildon_volumebar_notify                         (GObject *self, GParamSpec *param);
106
107 enum 
108 {
109     MUTE_TOGGLED_SIGNAL,
110     LEVEL_CHANGED_SIGNAL,
111     LAST_SIGNAL
112 };
113
114 enum {
115     PROP_0,
116     PROP_HILDON_HAS_MUTE,
117     PROP_HILDON_LEVEL,
118     PROP_HILDON_MUTE
119 };
120
121 static guint                                    signals [LAST_SIGNAL] = { 0 };
122
123 /**
124  * hildon_volumebar_get_type:
125  *
126  * Initializes and returns the type of a hildon volumebar.
127  *
128  * @Returns: GType of #HildonVolumebar
129  */
130 GType G_GNUC_CONST 
131 hildon_volumebar_get_type                       (void)
132 {
133     static GType volumebar_type = 0;
134
135     if (!volumebar_type) {
136         static const GTypeInfo volumebar_info = {
137             sizeof(HildonVolumebarClass),
138             NULL,       /* base_init */
139             NULL,       /* base_finalize */
140             (GClassInitFunc) hildon_volumebar_class_init,
141             NULL,       /* class_finalize */
142             NULL,       /* class_data */
143             sizeof(HildonVolumebar),
144             0,  /* n_preallocs */
145             (GInstanceInitFunc) hildon_volumebar_init,
146         };
147         volumebar_type = g_type_register_static(GTK_TYPE_CONTAINER,
148                 "HildonVolumebar",
149                 &volumebar_info, 0);
150     }
151     return volumebar_type;
152 }
153
154 static void 
155 hildon_volumebar_class_init                     (HildonVolumebarClass *volumebar_class)
156 {
157     GObjectClass      *gobject_class    = G_OBJECT_CLASS  (volumebar_class);
158     GtkObjectClass    *object_class     = GTK_OBJECT_CLASS (volumebar_class);
159     GtkWidgetClass    *widget_class     = GTK_WIDGET_CLASS (volumebar_class);
160     GtkContainerClass *container_class  = GTK_CONTAINER_CLASS (volumebar_class);
161
162     parent_class = g_type_class_peek_parent (volumebar_class);
163
164     g_type_class_add_private (volumebar_class,
165             sizeof (HildonVolumebarPrivate));
166
167    /* Because we derived our widget from GtkContainer, we should also
168     * override forall method 
169     */
170    volumebar_class->mute_toggled        = mute_toggled;
171    container_class->forall              = hildon_child_forall;
172    widget_class->size_allocate          = hildon_volumebar_size_allocate;
173    widget_class->realize                = hildon_volumebar_realize;
174    widget_class->unrealize              = hildon_volumebar_unrealize;
175    widget_class->map                    = hildon_volumebar_map;
176    widget_class->unmap                  = hildon_volumebar_unmap;
177    widget_class->grab_focus             = hildon_volumebar_grab_focus;
178    widget_class->focus                  = hildon_volumebar_focus;
179    widget_class->key_press_event        = hildon_volumebar_key_press;
180    object_class->destroy                = hildon_volumebar_destroy;
181
182    signals[MUTE_TOGGLED_SIGNAL] = g_signal_new ("mute_toggled",
183            G_OBJECT_CLASS_TYPE
184            (object_class),
185            G_SIGNAL_RUN_LAST |
186            G_SIGNAL_ACTION,
187            G_STRUCT_OFFSET
188            (HildonVolumebarClass,
189             mute_toggled), NULL, NULL,
190            gtk_marshal_VOID__VOID,
191            G_TYPE_NONE, 0);
192
193    signals[LEVEL_CHANGED_SIGNAL] = g_signal_new ("level_changed",
194            G_OBJECT_CLASS_TYPE
195            (object_class),
196            G_SIGNAL_RUN_LAST |
197            G_SIGNAL_ACTION,
198            G_STRUCT_OFFSET
199            (HildonVolumebarClass,
200             level_changed), NULL,
201            NULL,
202            gtk_marshal_VOID__VOID,
203            G_TYPE_NONE, 0);
204
205    gobject_class->notify                = hildon_volumebar_notify;
206    gobject_class->set_property          = hildon_volumebar_set_property;
207    gobject_class->get_property          = hildon_volumebar_get_property; 
208
209    /**
210     * HildonVolumebar:has-mute:
211     *
212     * Whether the mute button is visibile.
213     */
214    g_object_class_install_property (gobject_class,
215            PROP_HILDON_HAS_MUTE, 
216            g_param_spec_boolean ("has_mute",
217                "Show/Hide the mute button",
218                "Whether the mute button is visible. Default value: TRUE",
219                TRUE,
220                G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
221
222    /**
223     * HildonVolumebar:level:
224     *
225     * Current volume level.
226     */
227    g_object_class_install_property (gobject_class,
228            PROP_HILDON_LEVEL,
229            g_param_spec_double ("level",
230                "Level",
231                "Current volume level",
232                0.0,
233                100.0,
234                50.0,
235                G_PARAM_READWRITE));
236
237    /**
238     * HildonVolumebar:mute:
239     *
240     * Whether volume is muted.
241     */
242    g_object_class_install_property (gobject_class,
243            PROP_HILDON_MUTE,
244            g_param_spec_boolean ("mute",
245                "Mute",
246                "Whether volume is muted",
247                FALSE,
248                G_PARAM_READWRITE));
249 }
250
251 static void 
252 hildon_volumebar_init                           (HildonVolumebar *volumebar)
253 {
254     HildonVolumebarPrivate *priv;
255
256     priv = HILDON_VOLUMEBAR_GET_PRIVATE(volumebar);
257     g_assert (priv);
258
259     /* Should set GTK_NO_WINDOW flag, because widget is derived from
260        GtkContainer */
261     GTK_WIDGET_SET_FLAGS (GTK_WIDGET (volumebar), GTK_NO_WINDOW);
262     GTK_WIDGET_SET_FLAGS (GTK_WIDGET (volumebar), GTK_CAN_FOCUS);
263
264     /* Initialize mute button */
265     priv->tbutton = GTK_TOGGLE_BUTTON (gtk_toggle_button_new ());
266     g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL);
267 }
268
269 static void
270 hildon_volumebar_size_allocate                  (GtkWidget *widget, 
271                                                  GtkAllocation *allocation)
272 {
273     HildonVolumebarPrivate *priv;
274
275     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
276     g_assert (priv);
277
278     if (GTK_WIDGET_CLASS (parent_class)->size_allocate)
279         GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
280
281     if (GTK_WIDGET_REALIZED (widget))
282         gdk_window_move_resize (priv->event_window,
283                 allocation->x, allocation->y,
284                 allocation->width, allocation->height);
285 }
286
287 static void
288 hildon_volumebar_realize                        (GtkWidget *widget)
289 {
290     HildonVolumebarPrivate *priv;
291     GdkWindowAttr attributes;
292     gint attributes_mask;
293
294     priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget);
295     g_assert (priv);
296
297     GTK_WIDGET_CLASS (parent_class)->realize (widget);
298
299     attributes.window_type = GDK_WINDOW_CHILD;
300     attributes.x = widget->allocation.x;
301     attributes.y = widget->allocation.y;
302     attributes.width = widget->allocation.width;
303     attributes.height = widget->allocation.height;
304     attributes.wclass = GDK_INPUT_ONLY;
305     attributes.event_mask = GDK_BUTTON_PRESS_MASK;
306
307     attributes_mask = GDK_WA_X | GDK_WA_Y;
308
309     priv->event_window = gdk_window_new (widget->window,
310             &attributes, attributes_mask);
311
312     gdk_window_set_user_data (priv->event_window, widget);
313 }
314
315 static void
316 hildon_volumebar_unrealize                      (GtkWidget *widget)
317 {
318     HildonVolumebarPrivate *priv;
319
320     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
321     g_assert (priv);
322
323     if (priv->event_window) {
324         gdk_window_set_user_data (priv->event_window, NULL);
325         gdk_window_destroy (priv->event_window);
326         priv->event_window = NULL;
327     }
328
329     GTK_WIDGET_CLASS (parent_class)->unrealize(widget);
330 }
331
332 static void
333 hildon_volumebar_map                            (GtkWidget *widget)
334 {
335     HildonVolumebarPrivate *priv;
336
337     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
338     g_assert (priv);
339
340     GTK_WIDGET_CLASS (parent_class)->map (widget);
341
342     /* the event window must be on top of all other widget windows, so show it
343      * last */
344     if (! GTK_WIDGET_SENSITIVE (widget))
345         gdk_window_show (priv->event_window);
346 }
347
348 static void 
349 hildon_volumebar_unmap                          (GtkWidget *widget)
350 {
351     HildonVolumebarPrivate *priv;
352
353     priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget);
354     g_assert (priv);
355
356     gdk_window_hide (priv->event_window);
357
358     GTK_WIDGET_CLASS (parent_class)->unmap(widget);
359 }
360
361 static void 
362 hildon_volumebar_grab_focus                     (GtkWidget *widget)
363 {
364     HildonVolumebarPrivate *priv;
365
366     priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget);
367     g_assert (priv);
368
369     if (GTK_WIDGET_CAN_FOCUS (widget)) {
370         if (gtk_toggle_button_get_active (priv->tbutton))
371             gtk_widget_grab_focus (GTK_WIDGET (priv->tbutton));
372         else
373            gtk_widget_grab_focus (GTK_WIDGET (priv->volumebar));
374     }
375 }
376
377 static gboolean
378 hildon_volumebar_focus                          (GtkWidget *widget,
379                                                  GtkDirectionType direction)
380 {
381     HildonVolumebarPrivate *priv;
382     GtkOrientation orientation;
383     gboolean has_focus;
384
385     priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget);
386     g_assert (priv);
387
388     orientation = GTK_RANGE (priv->volumebar)->orientation;
389
390     has_focus = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->volumebar)) ||
391                  GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->tbutton)));
392
393     switch (direction) {
394         case GTK_DIR_UP:
395         case GTK_DIR_DOWN:
396         case GTK_DIR_TAB_FORWARD:
397         case GTK_DIR_TAB_BACKWARD:
398             if (has_focus && orientation == GTK_ORIENTATION_HORIZONTAL)
399                 return FALSE;
400             break;
401
402         case GTK_DIR_LEFT:
403         case GTK_DIR_RIGHT:
404             if (has_focus && orientation == GTK_ORIENTATION_VERTICAL)
405                 return FALSE;
406             break;
407
408         default:
409             break;
410     }
411
412     return GTK_WIDGET_CLASS (parent_class)->focus (widget, direction);
413 }
414
415 static void
416 hildon_child_forall                             (GtkContainer *container,
417                                                  gboolean include_internals,
418                                                  GtkCallback callback, 
419                                                  gpointer callback_data)
420 {
421     HildonVolumebarPrivate *priv;
422
423     priv = HILDON_VOLUMEBAR_GET_PRIVATE (container);
424     g_assert (callback != NULL);
425     g_assert (priv);
426
427     /* No external children */
428     if (! include_internals)
429         return;
430
431     /* Execute callback for both internals */
432     (*callback) (GTK_WIDGET (priv->tbutton), callback_data);
433     (*callback) (GTK_WIDGET (priv->volumebar), callback_data);
434 }
435
436 static void
437 hildon_volumebar_notify                         (GObject *self, 
438                                                  GParamSpec *param)
439 {
440     HildonVolumebarPrivate *priv;
441
442     priv = HILDON_VOLUMEBAR_GET_PRIVATE(self);
443     g_assert (priv);
444
445     if (g_str_equal (param->name, "can-focus")) {
446         /* call set_mute() because that updates the widget's UI state */
447         hildon_volumebar_set_mute (HILDON_VOLUMEBAR (self),
448                                    hildon_volumebar_get_mute (HILDON_VOLUMEBAR (self)));
449     }
450
451     if (GTK_WIDGET_MAPPED (self)) {
452         /* show/hide the event window on sensitivity change */
453         if (g_str_equal (param->name, "sensitive")) {
454             if (GTK_WIDGET_SENSITIVE (self))
455                 gdk_window_hide (priv->event_window);
456             else
457                 gdk_window_show (priv->event_window);
458         }
459     }
460
461     if (G_OBJECT_CLASS(parent_class)->notify)
462         G_OBJECT_CLASS(parent_class)->notify (self, param);
463 }
464
465 static void 
466 hildon_volumebar_destroy                        (GtkObject *self)
467 {
468     HildonVolumebarPrivate *priv;
469
470     priv = HILDON_VOLUMEBAR_GET_PRIVATE(self);
471     g_assert (priv);
472
473     if (priv->tbutton) {
474         gtk_widget_unparent (GTK_WIDGET (priv->tbutton));
475         priv->tbutton = NULL;
476     }
477     if (priv->volumebar) {
478         gtk_widget_unparent (GTK_WIDGET (priv->volumebar));
479         priv->volumebar = NULL;
480     }
481
482     if (GTK_OBJECT_CLASS (parent_class)->destroy)
483         GTK_OBJECT_CLASS (parent_class)->destroy (self);
484 }
485
486 static void
487 hildon_volumebar_set_property                   (GObject *object,
488                                                  guint prop_id,
489                                                  const GValue *value, 
490                                                  GParamSpec *pspec)
491 {  
492     HildonVolumebarPrivate *priv;
493
494     priv = HILDON_VOLUMEBAR_GET_PRIVATE(object);
495     g_assert (priv);
496
497     switch (prop_id) {
498
499         case PROP_HILDON_HAS_MUTE:
500             /* Mute button always exists but might be hidden */
501             if (g_value_get_boolean (value))
502                 gtk_widget_show (GTK_WIDGET (priv->tbutton));
503             else
504                 gtk_widget_hide (GTK_WIDGET (priv->tbutton));
505             break;
506
507         case PROP_HILDON_LEVEL:
508             hildon_volumebar_set_level (HILDON_VOLUMEBAR (object),
509                     g_value_get_double (value));
510             break;
511
512         case PROP_HILDON_MUTE:
513             hildon_volumebar_set_mute (HILDON_VOLUMEBAR (object),
514                     g_value_get_boolean (value));
515             break;
516
517         default:
518             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
519
520             break;
521     }
522 }
523
524 static void
525 hildon_volumebar_get_property                   (GObject *object,
526                                                  guint prop_id, 
527                                                  GValue *value, 
528                                                  GParamSpec *pspec)
529 {
530     HildonVolumebarPrivate *priv;
531     HildonVolumebar *vb;
532         
533     priv = HILDON_VOLUMEBAR_GET_PRIVATE(object);
534     g_assert (priv);
535
536     vb = HILDON_VOLUMEBAR (object);
537
538     switch (prop_id) {
539
540         case PROP_HILDON_HAS_MUTE:
541             g_value_set_boolean (value, GTK_WIDGET_VISIBLE (priv->tbutton));
542             break;
543
544         case PROP_HILDON_LEVEL:
545             g_value_set_double (value, hildon_volumebar_get_level (vb));
546             break;
547
548         case PROP_HILDON_MUTE:
549             g_value_set_boolean (value, hildon_volumebar_get_mute (vb));
550             break;
551
552         default:
553             G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
554             break;
555
556     }
557 }
558
559 /**
560  * hildon_volumebar_set_level:
561  * @self: volume bar to change level on
562  * @level: new level
563  *
564  * Sets new volume level for this #HildonVolumebar.
565  */
566 void 
567 hildon_volumebar_set_level                      (HildonVolumebar *self, 
568                                                  gdouble level)
569 {
570     HildonVolumebarPrivate *priv;
571
572     g_return_if_fail(HILDON_IS_VOLUMEBAR (self));
573
574     priv = HILDON_VOLUMEBAR_GET_PRIVATE (self);
575     g_assert (priv);
576
577     hildon_volumebar_range_set_level (priv->volumebar, level);
578 }
579
580 /**
581  * hildon_volumebar_get_level:
582  * @self: volume bar to query level on
583  *
584  * Gets the volume level of this #HildonVolumebar.
585  *
586  * Returns: volume level or -1 on error
587  */
588 gdouble 
589 hildon_volumebar_get_level                      (HildonVolumebar *self)
590 {
591     HildonVolumebarPrivate *priv;
592
593     g_return_val_if_fail(HILDON_IS_VOLUMEBAR (self), -1);
594
595     priv = HILDON_VOLUMEBAR_GET_PRIVATE(self);
596     g_assert (priv);
597
598     return hildon_volumebar_range_get_level (priv->volumebar);
599 }
600
601 /**
602  * hildon_volumebar_set_mute:
603  * @self: volume bar to work on
604  * @mute: mute ON/OFF
605  *
606  * Sets mute status for this #HildonVolumebar.
607  */
608 void 
609 hildon_volumebar_set_mute                       (HildonVolumebar *self, 
610                                                  gboolean mute)
611 {
612     HildonVolumebarPrivate *priv;
613     gboolean has_focus;
614
615     g_return_if_fail (HILDON_IS_VOLUMEBAR (self));
616
617     priv = HILDON_VOLUMEBAR_GET_PRIVATE (self);
618     g_assert (priv);
619
620     has_focus = (GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->volumebar)) ||
621                  GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (priv->tbutton)));
622
623     /* Slider should be insensitive when mute is on */
624     gtk_widget_set_sensitive (GTK_WIDGET (priv->volumebar), !mute);
625
626     if (mute) {
627         /* Make mute button focusable since the slider isn't anymore */
628         g_object_set (G_OBJECT (priv->tbutton), "can-focus", TRUE, NULL);
629
630         if (has_focus)
631             gtk_widget_grab_focus (GTK_WIDGET (priv->tbutton));
632     }
633     else
634     {
635         g_object_set (G_OBJECT (priv->tbutton), "can-focus", FALSE, NULL);
636
637         if (has_focus)
638             gtk_widget_grab_focus (GTK_WIDGET (priv->volumebar));
639     }
640
641     /* Update mute button state and redraw */
642     gtk_toggle_button_set_active (priv->tbutton, mute);
643 }
644
645 /**
646  * hildon_volumebar_get_mute:
647  * @self: volume bar to query mute status
648  *
649  * Gets mute status of this #HildonVolumebar (ON/OFF).
650  *
651  * Returns: Mute status as #gboolean value.
652  */
653 gboolean 
654 hildon_volumebar_get_mute                       (HildonVolumebar *self)
655 {
656     HildonVolumebarPrivate *priv;
657
658     g_return_val_if_fail (HILDON_IS_VOLUMEBAR (self), TRUE);
659
660     priv = HILDON_VOLUMEBAR_GET_PRIVATE(self);
661     g_assert (priv);
662
663     return gtk_toggle_button_get_active (priv->tbutton);
664 }
665
666 /**
667  * hildon_volumebar_get_adjustment
668  * @self : a #HildonVolumebar
669  * 
670  * Gets the GtkAdjustment used in volume bar. This can be handy
671  * to pass to hildon_appview_set_connected_adjustment which
672  * will allow changing the volume with 'increase' / 'decrease'
673  * hardware buttons.
674  *
675  * Returns: a #GtkAdjustment used by volume bar.
676  */
677 GtkAdjustment* 
678 hildon_volumebar_get_adjustment                 (HildonVolumebar *self)
679 {
680     HildonVolumebarPrivate *priv;
681
682     g_return_val_if_fail(HILDON_IS_VOLUMEBAR(self), NULL);
683
684     priv = HILDON_VOLUMEBAR_GET_PRIVATE(self);
685     g_assert (priv);
686
687     return gtk_range_get_adjustment (GTK_RANGE (priv->volumebar));
688 }
689
690 static void
691 mute_toggled                                    (HildonVolumebar *self)
692 {
693     /* This looks like no-op, but it still does something meaningfull!
694        set_mute also updates the ui to match new state that
695        is already reported by get_mute */
696
697     hildon_volumebar_set_mute (self, hildon_volumebar_get_mute (self));
698 }
699
700 static gboolean
701 hildon_volumebar_key_press                      (GtkWidget *widget,
702                                                  GdkEventKey *event)
703 {
704     HildonVolumebarPrivate *priv;
705
706     priv = HILDON_VOLUMEBAR_GET_PRIVATE(widget);
707     g_assert (priv != NULL);
708
709     /* Enter key toggles mute button (unless it is hidden) */
710     if (event->keyval == GDK_Return && GTK_WIDGET_VISIBLE (priv->tbutton)) {
711         gtk_toggle_button_set_active (priv->tbutton, 
712                 ! hildon_volumebar_get_mute(HILDON_VOLUMEBAR(widget)));
713
714         return TRUE;
715     }
716
717     return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
718 }
719
720 /* 
721  * Sends mute-toggled signal to widget, used as a callback in derived classes.
722  */
723 void G_GNUC_INTERNAL
724 hildon_volumebar_mute_toggled                   (HildonVolumebar * self)
725 {
726     g_return_if_fail (HILDON_IS_VOLUMEBAR (self));
727     /* FIXME Emit by id */
728     g_signal_emit_by_name (self, "mute_toggled");
729 }
730
731 void G_GNUC_INTERNAL 
732 hildon_volumebar_level_change                   (HildonVolumebar *self)
733 {
734     g_return_if_fail (HILDON_IS_VOLUMEBAR (self));
735
736     /* FIXME Use numerical val, id */
737     g_signal_emit_by_name (GTK_WIDGET (self), "level_changed");
738 }
739
740 /**
741  * hildon_volumebar_set_range_insensitive_message:
742  * @widget: A @GtkWidget to assign the banner to 
743  * @message: A message to display to the user
744  *
745  * Used to asign an insensitive message to the slider of the given volumebar.
746  * It simply calls hildon_helper_set_insensitive_message on the slider/range of 
747  * the volumebar. 
748  */
749 void
750 hildon_volumebar_set_range_insensitive_message  (HildonVolumebar *widget,
751                                                  const gchar *message)
752 {
753     g_return_if_fail (HILDON_IS_VOLUMEBAR (widget));
754
755     HildonVolumebarPrivate *priv;
756     priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget);
757
758     hildon_helper_set_insensitive_message ((GtkWidget *) priv->volumebar, message);
759 }
760
761 /**
762  * hildon_volumebar_set_range_insensitive_messagef:
763  * @widget: A @GtkWidget to assign the banner to 
764  * @format : a printf-like format string
765  * @varargs : arguments for the format string
766  *
767  * A helper printf-like variant of hildon_helper_set_insensitive_message.
768  */
769 void
770 hildon_volumebar_set_range_insensitive_messagef (HildonVolumebar *widget,
771                                                  const gchar *format,
772                                                  ...)
773 {
774     g_return_if_fail (HILDON_IS_VOLUMEBAR (widget));
775
776     HildonVolumebarPrivate *priv;
777     priv = HILDON_VOLUMEBAR_GET_PRIVATE (widget);
778
779     gchar *message;
780     va_list args;
781
782     va_start (args, format);
783     message = g_strdup_vprintf (format, args);
784     va_end (args);
785
786     hildon_helper_set_insensitive_message ((GtkWidget *) priv->volumebar, message);
787
788     g_free (message);
789 }
790
791