GTK+2 panel 

GTK+2 panel Git Source Tree

Root/volume.c

1#include "customwidgets.h"
2
3#include <sys/ioctl.h>
4#include <fcntl.h>
5#include <linux/soundcard.h>
6
7
8typedef struct
9{
10 GtkWidget *widget;
11 gint handle;
12
13 GdkPixmap *offscreen;
14 gint width;
15 gint height;
16
17 gint level;
18} GpVolume;
19
20
21static gbooleangp_volume_read(GpVolume*volume);
22static gbooleangp_volume_write(GpVolume*volume);
23static gbooleangp_volume_button_release(GpVolume*volume,
24 GdkEventButton*event);
25static gbooleangp_volume_scroll(GpVolume*volume,
26 GdkEventScroll*event);
27static gbooleangp_volume_configure(GpVolume*volume,
28 GdkEventConfigure*event);
29static gbooleangp_volume_update(GpVolume*volume);
30static gbooleangp_volume_expose(GpVolume*volume,
31 GdkEventExpose*event);
32static voidgp_volume_destroy(GpVolume*volume);
33
34
35GtkWidget *
36gp_volume_new (gchar *widget_name,
37 gchar *device,
38 gchar *string2,
39 gint int1,
40 gint int2)
41{
42 gchar *real_device;
43 GpVolume *volume;
44
45 if (device == NULL || device[0] == '\0')
46 real_device = g_strdup ("/dev/mixer");
47 else
48 real_device = g_strdup (device);
49
50 volume = g_new0 (GpVolume, 1);
51
52 volume->widget = gtk_drawing_area_new ();
53 gtk_widget_set_name (volume->widget, widget_name);
54 gtk_widget_set_size_request (volume->widget, 35, -1);
55
56 volume->handle = open (real_device, O_RDWR);
57 g_free (real_device);
58
59 if (gp_volume_read (volume))
60 {
61 gtk_widget_add_events (volume->widget, GDK_BUTTON_RELEASE_MASK|GDK_SCROLL_MASK);
62 g_signal_connect_swapped (volume->widget,"button-release-event",
63G_CALLBACK (gp_volume_button_release), volume);
64 g_signal_connect_swapped (volume->widget,"scroll-event",
65G_CALLBACK (gp_volume_scroll), volume);
66 g_signal_connect_swapped (volume->widget,"configure-event",
67G_CALLBACK (gp_volume_configure), volume);
68 g_signal_connect_swapped (volume->widget, "expose-event",
69G_CALLBACK (gp_volume_expose), volume);
70 g_signal_connect_swapped (volume->widget, "destroy",
71G_CALLBACK (gp_volume_destroy), volume);
72 }
73
74 return volume->widget;
75}
76
77
78typedef union
79{
80 guint16 all;
81 struct
82 {
83 guint8 l;
84 guint8 r;
85 } side;
86 int safe_guard;
87} GpVolumeStereo;
88
89static gboolean
90gp_volume_read (GpVolume *volume)
91{
92 GpVolumeStereo level;
93
94 if (ioctl (volume->handle, SOUND_MIXER_READ_VOLUME, &level.all) < 0)
95 return FALSE;
96
97 volume->level = level.side.l;
98 return TRUE;
99}
100
101static gboolean
102gp_volume_write (GpVolume *volume)
103{
104 GpVolumeStereo level;
105
106 level.side.l = volume->level;
107 level.side.r = volume->level;
108
109 return ioctl (volume->handle, SOUND_MIXER_WRITE_VOLUME, &level) >= 0;
110}
111
112static gboolean
113gp_volume_button_release (GpVolume *volume,
114 GdkEventButton *event)
115{
116 return FALSE;
117}
118
119static gboolean
120gp_volume_scroll (GpVolume *volume,
121 GdkEventScroll *event)
122{
123 switch (event->direction)
124 {
125 case GDK_SCROLL_UP:
126 volume->level += 5;
127 if (volume->level > 100)
128volume->level = 100;
129 break;
130
131 case GDK_SCROLL_DOWN:
132 volume->level -= 5;
133 if (volume->level < 0)
134volume->level = 0;
135 break;
136
137 default:
138 return FALSE;
139 }
140
141 gp_volume_write (volume);
142 gp_volume_update (volume);
143 return FALSE;
144}
145
146static gboolean
147gp_volume_configure (GpVolume *volume,
148 GdkEventConfigure *event)
149{
150 GtkWidget *widget;
151 GdkPixbuf *icon;
152
153 if (volume->offscreen)
154 {
155 if (volume->width == event->width && volume->height == event->height)
156return TRUE;
157
158 g_object_unref (volume->offscreen);
159 }
160
161 widget = volume->widget;
162
163 volume->offscreen = gdk_pixmap_new (widget->window, event->width, event->height, -1);
164 volume->width = event->width;
165 volume->height = event->height;
166 gdk_draw_rectangle (volume->offscreen,
167 widget->style->bg_gc[GTK_STATE_NORMAL],
168 TRUE,
169 0, 0,
170 event->width, event->height);
171
172 /* Add the icon (if found) */
173 icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
174 "volume", event->height, 0, NULL);
175 if (icon != NULL)
176 {
177 gdk_draw_pixbuf (volume->offscreen,
178 widget->style->bg_gc[GTK_STATE_NORMAL],
179 icon,
180 0, 0,
181 event->width - event->height, 0,
182 -1, -1,
183 GDK_RGB_DITHER_NORMAL,
184 0, 0);
185 g_object_unref (icon);
186 }
187
188 gp_volume_update (volume);
189 return TRUE;
190}
191
192static gboolean
193gp_volume_update (GpVolume *volume)
194{
195 GtkWidget *widget;
196 gint xthickness, ythickness;
197 gint real_height, y;
198
199 widget = volume->widget;
200 xthickness = widget->style->xthickness;
201 ythickness = widget->style->ythickness;
202 real_height = volume->height-(ythickness*2) - 2;
203 y = volume->level * real_height / 100;
204
205 gdk_draw_rectangle (volume->offscreen,
206 widget->style->bg_gc[GTK_STATE_SELECTED],
207 TRUE,
208 xthickness, ythickness,
209 5, real_height+2);
210 gdk_draw_rectangle (volume->offscreen,
211 widget->style->fg_gc[GTK_STATE_SELECTED],
212 TRUE,
213 xthickness+1, real_height+ythickness+1-y,
214 3, y);
215
216 gtk_widget_queue_draw (widget);
217 return TRUE;
218}
219
220static gboolean
221gp_volume_expose (GpVolume *volume,
222 GdkEventExpose *event)
223{
224 gdk_draw_drawable (volume->widget->window,
225 volume->widget->style->bg_gc[GTK_STATE_NORMAL],
226 volume->offscreen,
227 event->area.x, event->area.y,
228 event->area.x, event->area.y,
229 event->area.width, event->area.height);
230
231 return FALSE;
232}
233
234static void
235gp_volume_destroy (GpVolume *volume)
236{
237 if (volume->handle > 0)
238 close (volume->handle);
239
240 if (volume->offscreen != NULL)
241 g_object_unref (volume->offscreen);
242
243 g_free (volume);
244}

Archive Download this file

Branches

Tags