[volume plugin] Feature enhancement:
authorJim Huang <jserv.tw@gmail.com>
Fri, 10 Oct 2008 06:56:53 +0000 (06:56 +0000)
committerJim Huang <jserv.tw@gmail.com>
Fri, 10 Oct 2008 06:56:53 +0000 (06:56 +0000)
  . Support mouse scrolling to adjust volume
  . Mouse middle button to switch mute
  . Visual icon update reflecting to volume

src/plugins/volume/volume-impl.c
src/plugins/volume/volume.c

index 7c218ba..6739d02 100644 (file)
@@ -1,5 +1,6 @@
 /**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+ * Copyright (c) 2006, 2008 LxDE Developers,
+ *     see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -40,6 +41,7 @@
 #include <fcntl.h>
 
 extern int mixer_fd;
+extern GtkSpinButton* vol_spin;
 
 typedef struct stereovolume
 {
@@ -177,6 +179,8 @@ create_volume_window (void)
 
        gtk_window_add_accel_group (GTK_WINDOW (volume_window), accel_group);
 
+       vol_spin = spinbutton1;
+
        return volume_window;
 }
 
index 54d0c82..f8c38b5 100644 (file)
@@ -1,5 +1,6 @@
 /**
- * Copyright (c) 2006 LxDE Developers, see the file AUTHORS for details.
+ * Copyright (c) 2006, 2008 LxDE Developers,
+ *     see the file AUTHORS for details.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 int mixer_fd;
 
+GtkSpinButton *vol_spin;
+static gdouble vol_before_mute;
+static gdouble curr_volume;
+static GtkWidget *curr_image;
+static gboolean skip_botton1_event;
+
 typedef struct {
     GtkWidget *mainw;
     GtkWidget *dlg;
@@ -59,44 +66,186 @@ volume_destructor(Plugin *p)
     RET();
 }
 
-static void on_volume_focus (GtkWidget* dlg, GdkEventFocus *event, volume_t *vol)
+static void update_icon (Plugin* p)
 {
-    /* FIXME: use smarter method */
-    gtk_widget_destroy( dlg );
-    vol->dlg = NULL;
+       volume_t *vol = (volume_t*) p->priv;
+       
+       GdkPixbuf *icon;
+       GtkWidget *image;
+       GtkIconTheme* theme;
+       GtkIconInfo* info;
+       
+       theme = gtk_icon_theme_get_default();
+       
+       if (curr_volume <= 0) {
+               info = gtk_icon_theme_lookup_icon( theme, "stock_volume-mute", 24, 0 );
+       }
+       else if (curr_volume > 0 && curr_volume <= 50) {
+               info = gtk_icon_theme_lookup_icon( theme, "stock_volume-min", 24, 0 );
+       }
+       else if (curr_volume > 50 && curr_volume <= 75) {
+               info = gtk_icon_theme_lookup_icon( theme, "stock_volume-med", 24, 0 );
+       }
+       else if (curr_volume > 75) {
+               info = gtk_icon_theme_lookup_icon( theme, "stock_volume-max", 24, 0 );
+       }
+
+       if (info ) {
+               icon = gdk_pixbuf_new_from_file_at_size(
+                               gtk_icon_info_get_filename( info ),
+                               24, 24, NULL );
+               gtk_icon_info_free( info );
+       }
+       else {
+                       icon = gdk_pixbuf_new_from_xpm_data((const char **) volume_xpm);
+       }
+       
+        
+       
+       if (icon) {
+               if (curr_image) { 
+                       gtk_container_remove(GTK_CONTAINER (vol->mainw),curr_image);
+                       curr_image = NULL;
+               }
+               image = gtk_image_new_from_pixbuf(icon);
+               gtk_container_add (GTK_CONTAINER (vol->mainw), image);
+                
+               curr_image = image;
+       }
+       gtk_widget_show_all(vol->mainw);
+       return;
 }
 
-static int on_button_press (GtkWidget* widget, GdkEventButton* evt, Plugin* p)
+static void on_volume_focus (GtkWidget* dlg, GdkEventFocus *event, Plugin* p)
 {
-    volume_t *vol = (volume_t*) p->priv;
+       volume_t *vol = (volume_t*) p->priv;
+       
+       if (! vol_spin) return;
+       GtkAdjustment *vol_adjustment = gtk_spin_button_get_adjustment (vol_spin);
+       if (! vol_adjustment) return;
+       curr_volume = gtk_adjustment_get_value (vol_adjustment);
+       
+       update_icon(p);
+       
+       /* FIXME: use smarter method */
+       gtk_widget_destroy( dlg );
+       vol->dlg = NULL;
+}
 
-    if( evt->button == 1 ) { /*  Left click*/
-        if( ! vol->dlg ) {
-            vol->dlg = create_volume_window();
+static void on_mouse_scroll (GtkWidget* widget, GdkEventScroll* evt, Plugin* p)
+{
+       volume_t *vol = (volume_t*) p->priv;
 
-            /* setting background to default */
-            gtk_widget_set_style(vol->dlg, p->panel->defstyle);
+       if ( ! vol->dlg ) {
 
-            g_signal_connect( vol->dlg, "focus-out-event",
-                      G_CALLBACK(on_volume_focus), vol );
+               vol->dlg = create_volume_window();
+               g_signal_connect( vol->mainw, "delete-event",
+                               G_CALLBACK(on_volume_focus), p );
 
-            gtk_window_present( GTK_WINDOW(vol->dlg) );
-        } else {
-            gtk_widget_destroy(vol->dlg);
-            vol->dlg = NULL;
-        }
-    }
-    else if( evt->button == 3 )  /* right button */
-    {
-        GtkMenu* popup = lxpanel_get_panel_menu( p->panel, p, FALSE );
-        gtk_menu_popup( popup, NULL, NULL, NULL, NULL, evt->button, evt->time );
-        return TRUE;
-    }
-    return FALSE;
+       }
+       else {
+               if (! vol_spin) return;
+               GtkAdjustment *vol_adjustment = 
+                       gtk_spin_button_get_adjustment (vol_spin);
+               if (! vol_adjustment) return;
+
+               curr_volume = gtk_adjustment_get_value (vol_adjustment);
+
+               if (evt->direction == GDK_SCROLL_UP) {
+                       curr_volume += 2;
+               }
+               else /*if (evt->direction == GDK_SCROLL_DOWN)*/ {
+                       curr_volume -= 2;
+               }
+               update_icon(p);
+               gtk_adjustment_set_value (vol_adjustment, curr_volume);
+               gtk_spin_button_set_adjustment(vol_spin, vol_adjustment);
+               skip_botton1_event = TRUE;
+       }
+}
+
+static void on_button_press (GtkWidget* widget, GdkEventButton* evt, Plugin* p)
+{
+       volume_t *vol = (volume_t*) p->priv;
+
+       /* for scroll correction */
+       if (skip_botton1_event) {
+               gtk_widget_destroy(vol->dlg);
+               vol->dlg = NULL;
+               skip_botton1_event = FALSE;
+       }
+
+       switch ( evt->button ) { 
+       case 1: {       /*  Left click */
+               if ( ! vol->dlg ) {
+                       vol->dlg = create_volume_window();
+
+                       /* setting background to default */
+                       gtk_widget_set_style(vol->dlg, p->panel->defstyle);
+
+                       g_signal_connect( vol->dlg, "focus-out-event",
+                                       G_CALLBACK(on_volume_focus), p );
+
+                       gtk_window_present( GTK_WINDOW(vol->dlg) );
+               }
+               else {
+                       /* update icon */
+                       if (! vol_spin) return;
+                       GtkAdjustment *vol_adjustment =
+                               gtk_spin_button_get_adjustment (vol_spin);
+                       if (! vol_adjustment) return;
+                       curr_volume = gtk_adjustment_get_value (vol_adjustment);
+                       update_icon(p);
+
+                       gtk_widget_destroy(vol->dlg);
+                       vol->dlg = NULL;
+               }
+               break;
+       }
+
+       case 3: {       /* right button */
+               GtkMenu* popup = lxpanel_get_panel_menu( p->panel, p, FALSE );
+               gtk_menu_popup( popup, NULL, NULL, NULL, NULL, evt->button, evt->time );
+               return TRUE;
+       }
+
+       case 2: {       /* middle mouse button */
+               if ( ! vol->dlg ) {
+                       vol->dlg = create_volume_window();
+               }
+
+               if (! vol_spin) return;
+               GtkAdjustment *vol_adjustment =
+                       gtk_spin_button_get_adjustment (vol_spin);
+               if (! vol_adjustment) return;
+
+               curr_volume = gtk_adjustment_get_value (vol_adjustment);
+
+               if (curr_volume > 0) {
+                       /* turning to mute */
+                       vol_before_mute = curr_volume;
+                       curr_volume = 0;
+               }
+               else {
+                       curr_volume = vol_before_mute;
+               }
+
+               gtk_adjustment_set_value (vol_adjustment, curr_volume);
+               gtk_spin_button_set_adjustment(vol_spin, vol_adjustment);
+
+               update_icon(p);
+
+               gtk_widget_destroy( vol->dlg );
+               vol->dlg = NULL;
+               break;
+       }
+       default:        /* never here */
+               break;
+       }
+       return FALSE;
 }
 
-static int
-volume_constructor(Plugin *p, char **fp)
+static int volume_constructor(Plugin *p, char **fp)
 {
     volume_t *vol;
     line s;
@@ -104,6 +253,11 @@ volume_constructor(Plugin *p, char **fp)
     GtkWidget *image;
     GtkIconTheme* theme;
     GtkIconInfo* info;
+    
+    vol_before_mute = 1;
+    curr_volume = 0;
+    curr_image = NULL;
+    skip_botton1_event = FALSE;
 
     ENTER;
     s.len = 256;
@@ -119,27 +273,25 @@ volume_constructor(Plugin *p, char **fp)
 
     vol->mainw = gtk_event_box_new();
 
-    theme = gtk_icon_theme_get_default();
-    if ( (info = gtk_icon_theme_lookup_icon( theme, "stock_volume", 24, 0 ) ) ) {
-        icon = gdk_pixbuf_new_from_file_at_size(
-                gtk_icon_info_get_filename( info ),
-                24, 24, NULL );
-        gtk_icon_info_free( info );
-    }
-    else
-            icon = gdk_pixbuf_new_from_xpm_data((const char **) volume_xpm);
-    if (icon) {
-        image = gtk_image_new_from_pixbuf(icon);
-        gtk_container_add (GTK_CONTAINER (vol->mainw), image);
-    }
-
     gtk_widget_add_events( vol->mainw, GDK_BUTTON_PRESS_MASK );
     g_signal_connect( vol->mainw, "button-press-event",
             G_CALLBACK(on_button_press), p );
+            
+    g_signal_connect( vol->mainw, "scroll-event",
+            G_CALLBACK(on_mouse_scroll), p );
     gtk_widget_set_size_request( vol->mainw, 24, 24 );
 
-    vol->dlg = NULL;
-    gtk_widget_show_all(vol->mainw);
+    /* obtain current volume */
+    vol->dlg = create_volume_window();
+    if (! vol_spin) return;
+       GtkAdjustment *vol_adjustment =
+               gtk_spin_button_get_adjustment (vol_spin);
+    if (! vol_adjustment) return;
+    curr_volume = gtk_adjustment_get_value (vol_adjustment);
+    
+    update_icon(p);
+       gtk_widget_destroy( vol->dlg );
+    vol->dlg = NULL;  
 
     vol->tooltips = gtk_tooltips_new ();
 #if GLIB_CHECK_VERSION( 2, 10, 0 )