GTK+2 panel 

GTK+2 panel Git Source Tree

Root/libgpwidgets/gpw-volume.c

1/* Gtk2Panel - A bleeding edge Gtk+2 panel
2 * Copyright (C) 2009 Nicola Fontana <ntd at entidi.it>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20
21/**
22 * SECTION:gpw-volume
23 * @title: GpwVolume
24 * @short_description: A #GtkVolumeButton active widget
25 *
26 * This widget is a yet working volume changer: just set the mixer device
27 * in the GpwVolume:device property and GpwVolume will set the levels
28 * accessing it throught the ioctl() interface.
29 *
30 * It does not need any #GtkAdjustment object as it provides a suitable
31 * default one during the instance initialization.
32 **/
33
34/**
35 * GpwVolume:
36 *
37 * All fields are private and should not be used directly.
38 * Use its public methods instead.
39 **/
40
41
42#include <config.h>
43
44#ifdef HAVE_UNISTD_H
45#include <unistd.h>
46#endif
47
48#include <sys/ioctl.h>
49#include <fcntl.h>
50#include <linux/soundcard.h>
51
52#include "gpw-volume.h"
53#include "gpw-volume-private.h"
54#include "gpw-intl.h"
55
56
57enum {
58 PROP_0,
59 PROP_DEVICE
60};
61
62
63static void get_property (GObject *object,
64 guint prop_id,
65 GValue *value,
66 GParamSpec *pspec);
67static void set_property (GObject *object,
68 guint prop_id,
69 const GValue *value,
70 GParamSpec *pspec);
71static void finalize (GObject *object);
72static void set_device (GpwVolume *volume,
73 const gchar *device);
74static gboolean read_value (GpwVolume *volume);
75static void value_changed (GtkScaleButton *button,
76 gdouble value);
77
78
79G_DEFINE_TYPE(GpwVolume, gpw_volume, GTK_TYPE_VOLUME_BUTTON);
80
81
82static void
83gpw_volume_class_init(GpwVolumeClass *klass)
84{
85 GObjectClass *gobject_class;
86 GtkScaleButtonClass *scale_button_class;
87 GParamSpec *param;
88
89 gobject_class = (GObjectClass *) klass;
90 scale_button_class = (GtkScaleButtonClass *) klass;
91
92 g_type_class_add_private(klass, sizeof(GpwVolumePrivate));
93
94 gobject_class->get_property = get_property;
95 gobject_class->set_property = set_property;
96 gobject_class->finalize = finalize;
97
98 scale_button_class->value_changed = value_changed;
99
100 param = g_param_spec_string("device",
101 P_("Device"),
102 P_("The device to use to set and get the volume"),
103 NULL,
104 G_PARAM_READWRITE);
105 g_object_class_install_property(gobject_class, PROP_DEVICE, param);
106}
107
108static void
109gpw_volume_init(GpwVolume *volume)
110{
111 GpwVolumePrivate *data;
112 GtkAdjustment *adjustment;
113
114 data = G_TYPE_INSTANCE_GET_PRIVATE(volume, GPW_TYPE_VOLUME,
115 GpwVolumePrivate);
116
117 data->handle = -1;
118 data->device = NULL;
119
120 volume->data = data;
121
122 adjustment = (GtkAdjustment *) gtk_adjustment_new(0, 0, 100, 1, 10, 0);
123 gtk_scale_button_set_adjustment((GtkScaleButton *) volume, adjustment);
124}
125
126static void
127get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
128{
129 GpwVolumePrivate *data = GPW_VOLUME_GET_DATA(object);
130
131 switch (prop_id) {
132 case PROP_DEVICE:
133 g_value_set_string(value, data->device);
134 break;
135 default:
136 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
137 break;
138 }
139}
140
141static void
142set_property(GObject *object,
143 guint prop_id, const GValue *value, GParamSpec *pspec)
144{
145 GpwVolume *volume = (GpwVolume *) object;
146
147 switch (prop_id) {
148 case PROP_DEVICE:
149 set_device(volume, g_value_get_string(value));
150 read_value(volume);
151 break;
152 default:
153 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
154 break;
155 }
156}
157
158static void
159finalize(GObject *object)
160{
161 GpwVolume *volume = (GpwVolume *) object;
162
163 set_device(volume, NULL);
164
165 ((GObjectClass *) gpw_volume_parent_class)->finalize(object);
166}
167
168static void
169set_device(GpwVolume *volume, const gchar *device)
170{
171 GpwVolumePrivate *data = GPW_VOLUME_GET_DATA(volume);
172
173 /* Check if something changed */
174 if (device == data->device ||
175 (device != NULL && data->device != NULL &&
176 strcmp(device, data->device) == 0))
177 return;
178
179 /* Disconnect from the old device, if any */
180 if (data->device != NULL) {
181 g_free(data->device);
182 data->device = NULL;
183 }
184 if (data->handle > -1) {
185 close(data->handle);
186 data->handle = -1;
187 }
188
189 /* Connect to the new device, if any */
190 if (device != NULL) {
191 data->device = g_strdup(device);
192 data->handle = open(device, O_RDWR);
193 }
194}
195
196static gboolean
197read_value(GpwVolume *volume)
198{
199 GpwVolumePrivate *data;
200 GpwStereoLevel level;
201
202 data = GPW_VOLUME_GET_DATA(volume);
203
204 if (data->handle == -1 ||
205 ioctl(data->handle, SOUND_MIXER_READ_VOLUME, &level) == -1) {
206 gtk_widget_set_sensitive((GtkWidget *) volume, FALSE);
207 return FALSE;
208 }
209
210 gtk_widget_set_sensitive((GtkWidget *) volume, TRUE);
211 gtk_scale_button_set_value((GtkScaleButton *) volume, level.side.l);
212
213 return TRUE;
214}
215
216static void
217value_changed(GtkScaleButton *button, gdouble value)
218{
219 GpwVolumePrivate *data = GPW_VOLUME_GET_DATA(button);
220
221 if (data->handle > -1) {
222 GpwStereoLevel level;
223
224 /* By default, manages both the sides together */
225 level.side.l = value;
226 level.side.r = level.side.l;
227
228 ioctl(data->handle, SOUND_MIXER_WRITE_VOLUME, &level);
229 }
230}

Archive Download this file

Branches

Tags