Improved the look of the Options dialog
[rox-volume.git] / volumecontrol.py
blob9884808163f11bec4745ecc51ad6f16eb8361919
1 """
2 volumecontrol.py (a volume control widget)
4 Copyright 2004 Kenneth Hayber <khayber@socal.rr.com>
5 All rights reserved.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License.
11 This program is distributed in the hope that it will be useful
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 """
21 import rox, gtk, gobject, sys
23 CHANNEL_LEFT = 0
24 CHANNEL_RIGHT = 1
25 CHANNEL_MONO = 2
27 #bitmask values
28 _STEREO = 1
29 _LOCK = 2
30 _REC = 4
31 _MUTE = 8
33 class VolumeControl(gtk.Frame):
34 """
35 A Class that implements a volume control (stereo or mono) for a sound card
36 mixer. Each instance represents one mixer channel on the sound card.
37 """
38 def __init__(self, channel, option_mask, option_value, show_value, label=None, vertical=True):
39 """
40 Create a volume control widget
41 'channel' specifies the ossaudio device mixer channel (e.g. ossaudiodev.SOUND_VOLUME_MASTER).
42 'option_mask' configures the widget while 'option_value' sets the actual
43 value of the corresponding mask (e.g. 'option_mask |= _MUTE' shows the mute
44 checkbox while 'option_value |= _MUTE' causes it to be checked by default)
45 'show_value' controls whether the volume text is displayed or not.
46 'label' is the name of the channel (e.g. 'PCM).
47 'vertical' sets the widget's orientation (used for vertical panels)
49 The widget supports two signals 'volume_changed' and 'volume_setting_toggled'.
50 'volume_changed' always sends left and right volume settings regardless of
51 whether the control is locked or mono.
53 'volume_setting_toggled' notifies the parent of changes in the optional checkboxes.
54 """
55 gtk.Frame.__init__(self, label)
57 self.rec = self.lock = self.stereo = self.mute = False
58 if option_mask & _LOCK:
59 self.lock = True
60 self.channel_locked = option_value & _LOCK
62 if option_mask & _REC:
63 self.rec = True
64 self.channel_rec = option_value & _REC
66 if option_mask & _MUTE:
67 self.mute = True
68 self.channel_muted = option_value & _MUTE
70 if option_mask & _STEREO:
71 self.stereo = True
73 self.channel = channel
74 self.vol_left = self.vol_right = 0
75 self.set_size_request(60, 200)
77 vbox = gtk.VBox()
78 self.add(vbox)
79 hbox = gtk.HBox()
80 vbox.pack_start(hbox)
82 self.volume1 = gtk.Adjustment(0.0, 0.0, 100.0, 1.0, 10.0, 0.0)
83 if self.stereo:
84 self.volume1.connect('value_changed', self.value_changed,
85 channel, CHANNEL_LEFT)
86 else:
87 self.volume1.connect('value_changed', self.value_changed,
88 channel, CHANNEL_MONO)
90 if vertical:
91 volume1_control = gtk.VScale(self.volume1)
92 volume1_control.set_inverted(True)
93 else:
94 volume1_control = gtk.HScale(self.volume1)
95 volume1_control.set_value_pos(gtk.POS_RIGHT)
96 volume1_control.set_draw_value(show_value)
97 volume1_control.set_digits(0)
98 hbox.pack_start(volume1_control)
100 if self.stereo:
101 self.volume2 = gtk.Adjustment(0.0, 0.0, 100.0, 1.0, 10.0, 0.0)
102 self.volume2.connect('value_changed', self.value_changed,
103 channel, CHANNEL_RIGHT)
105 if vertical:
106 volume2_control = gtk.VScale(self.volume2)
107 volume2_control.set_inverted(True)
108 else:
109 volume2_control = gtk.HScale(self.volume2)
110 volume2_control.set_value_pos(gtk.POS_RIGHT)
111 volume2_control.set_draw_value(show_value)
112 volume2_control.set_digits(0)
113 hbox.pack_start(volume2_control)
115 if self.rec:
116 rec_check = gtk.CheckButton(label=_('Rec.'))
117 rec_check.set_active(self.channel_rec)
118 rec_check.connect('toggled', self.check, channel, _REC)
119 vbox.pack_end(rec_check, False, False)
120 self.rec_check = rec_check
122 if self.mute:
123 mute_check = gtk.CheckButton(label=_('Mute'))
124 mute_check.set_active(self.channel_muted)
125 mute_check.connect('toggled', self.check, channel, _MUTE)
126 vbox.pack_end(mute_check, False, False)
128 if self.stereo and self.lock:
129 lock_check = gtk.CheckButton(label=_('Lock'))
130 lock_check.set_active(self.channel_locked)
131 lock_check.connect('toggled', self.check, channel, _LOCK)
132 vbox.pack_end(lock_check, False, False)
134 self.show_all()
136 self.control1 = volume1_control
137 if self.stereo:
138 self.control2 = volume2_control
141 def set_level(self, level):
143 Allow the volume settings to be passed in from the parent.
144 'level' is a tuple of integers from 0-100 as (left, right).
146 self.volume1.set_value(level[0])
147 if self.stereo:
148 self.volume2.set_value(level[1])
150 def set_recsrc(self, val):
151 try:
152 self.rec_check.set_active(val)
153 except:
154 pass
156 def get_level(self):
158 Return the current widget's volume settings as a tuple of
159 integers from 0-100 as (left, right)
161 return (self.vol_left, self.vol_right)
163 def value_changed(self, vol, channel, channel_lr):
165 Track changes in the volume controls and pass them back to the parent
166 via the 'volume_changed' signal.
168 if channel_lr == CHANNEL_LEFT:
169 self.vol_left = int(vol.get_value())
170 if self.lock and self.channel_locked:
171 self.volume2.set_value(vol.get_value())
173 elif channel_lr == CHANNEL_RIGHT:
174 self.vol_right = int(vol.get_value())
175 if self.lock and self.channel_locked:
176 self.volume1.set_value(vol.get_value())
178 else:
179 self.vol_left = self.vol_right = int(vol.get_value())
180 self.emit("volume_changed", channel, self.vol_left, self.vol_right)
183 def show_values(self, show_value):
184 self.control1.set_draw_value(show_value)
185 if self.stereo:
186 self.control2.set_draw_value(show_value)
189 def check(self, button, channel, id):
191 Process the various checkboxes and signal the parent when they change
192 via the 'volume_setting_changed' signal.
194 if id == _LOCK:
195 self.channel_locked = not self.channel_locked
196 if self.channel_locked:
197 avg_vol = (self.vol_left+self.vol_right)/2
198 self.volume1.set_value(avg_vol)
199 self.volume2.set_value(avg_vol)
200 elif id == _MUTE:
201 self.channel_muted = not self.channel_muted
202 elif id == _REC:
203 self.channel_rec = not self.channel_rec
204 self.emit('volume_setting_toggled', channel, id, button.get_active())
207 #I need these to be called only once, not each time an instance is created.
208 gobject.signal_new('volume_changed', VolumeControl,
209 gobject.SIGNAL_RUN_LAST, gobject.TYPE_BOOLEAN,
210 (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT))
212 gobject.signal_new('volume_setting_toggled', VolumeControl,
213 gobject.SIGNAL_RUN_LAST, gobject.TYPE_BOOLEAN,
214 (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_INT))