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 gint width, height;
152 GdkPixbuf *icon;
153
154 widget = volume->widget;
155 width = widget->allocation.width;
156 height = widget->allocation.height;
157
158 if (volume->offscreen)
159 {
160 if (volume->width == width && volume->height == height)
161return TRUE;
162
163 g_object_unref (volume->offscreen);
164 }
165
166 volume->offscreen = gdk_pixmap_new (widget->window, width, height, -1);
167 volume->width = width;
168 volume->height = height;
169 gdk_draw_rectangle (volume->offscreen,
170 widget->style->bg_gc[GTK_STATE_NORMAL],
171 TRUE,
172 0, 0,
173 width, height);
174
175 /* Add the icon (if found) */
176 icon = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
177 "volume", height, 0, NULL);
178 if (icon != NULL)
179 {
180 gdk_draw_pixbuf (volume->offscreen,
181 volume->widget->style->bg_gc[GTK_STATE_NORMAL],
182 icon,
183 0, 0,
184 width-height, 0,
185 -1, -1,
186 GDK_RGB_DITHER_NORMAL,
187 0, 0);
188 g_object_unref (icon);
189 }
190
191 gp_volume_update (volume);
192 return TRUE;
193}
194
195static gboolean
196gp_volume_update (GpVolume *volume)
197{
198 GtkWidget *widget;
199 gint xthickness, ythickness;
200 gint real_height, y;
201
202 widget = volume->widget;
203 xthickness = widget->style->xthickness;
204 ythickness = widget->style->ythickness;
205 real_height = volume->height-(ythickness*2) - 2;
206 y = volume->level * real_height / 100;
207
208 gdk_draw_rectangle (volume->offscreen,
209 widget->style->bg_gc[GTK_STATE_SELECTED],
210 TRUE,
211 xthickness, ythickness,
212 5, real_height+2);
213 gdk_draw_rectangle (volume->offscreen,
214 widget->style->fg_gc[GTK_STATE_SELECTED],
215 TRUE,
216 xthickness+1, real_height+ythickness+1-y,
217 3, y);
218
219 gtk_widget_queue_draw (widget);
220 return TRUE;
221}
222
223static gboolean
224gp_volume_expose (GpVolume *volume,
225 GdkEventExpose *event)
226{
227 gdk_draw_drawable (volume->widget->window,
228 volume->widget->style->bg_gc[GTK_STATE_NORMAL],
229 volume->offscreen,
230 event->area.x, event->area.y,
231 event->area.x, event->area.y,
232 event->area.width, event->area.height);
233
234 return FALSE;
235}
236
237static void
238gp_volume_destroy (GpVolume *volume)
239{
240 if (volume->handle > 0)
241 close (volume->handle);
242
243 if (volume->offscreen != NULL)
244 g_object_unref (volume->offscreen);
245
246 g_free (volume);
247}

Archive Download this file

Branches

Tags