]> code.delx.au - pulseaudio/blob - src/tests/volume-ui.py
channelmap: Add 2.1 surround
[pulseaudio] / src / tests / volume-ui.py
1 #!/usr/bin/python
2
3 import pygtk, gtk, sys
4 from ctypes import *
5
6 try:
7 libpulse = cdll.LoadLibrary("../.libs/libpulse.so")
8 except OSError:
9 try:
10 libpulse = cdll.LoadLibrary(".libs/libpulse.so")
11 except OSError:
12 libpulse = cdll.LoadLibrary("libpulse.so")
13
14 class ChannelMap(Structure):
15 _fields_ = [("channels", c_ubyte),
16 ("map", c_uint * 32)]
17
18 _to_name = libpulse.pa_channel_map_to_name
19 _to_name.restype = c_char_p
20 _to_name.argtypes = [c_void_p]
21
22 _to_pretty_name = libpulse.pa_channel_map_to_pretty_name
23 _to_pretty_name.restype = c_char_p
24 _to_pretty_name.argtypes = [c_void_p]
25
26 _snprint = libpulse.pa_channel_map_snprint
27 _snprint.restype = c_char_p
28 _snprint.argtypes = [c_char_p, c_ulong, c_void_p]
29
30 _position_to_string = libpulse.pa_channel_position_to_string
31 _position_to_string.restype = c_char_p
32 _position_to_string.argtypes = [c_uint]
33
34 _position_to_pretty_string = libpulse.pa_channel_position_to_pretty_string
35 _position_to_pretty_string.restype = c_char_p
36 _position_to_pretty_string.argtypes = [c_uint]
37
38 _can_balance = libpulse.pa_channel_map_can_balance
39 _can_balance.restype = c_int
40 _can_balance.argtypes = [c_void_p]
41
42 _can_fade = libpulse.pa_channel_map_can_fade
43 _can_fade.restype = c_int
44 _can_fade.argtypes = [c_void_p]
45
46 _parse = libpulse.pa_channel_map_parse
47 _parse.restype = c_void_p
48 _parse.argtypes = [c_void_p, c_char_p]
49
50 def to_name(this):
51 return this._to_name(byref(this))
52
53 def to_pretty_name(this):
54 return this._to_pretty_name(byref(this))
55
56 def snprint(this):
57 s = create_string_buffer(336)
58 r = this._snprint(s, len(s), byref(this))
59
60 if r is None:
61 return None
62 else:
63 return s.value
64
65 def position_to_string(this, pos):
66 return this._position_to_string(pos)
67
68 def position_to_pretty_string(this, pos):
69 return this._position_to_pretty_string(pos)
70
71 def can_balance(this):
72 return bool(this._can_balance(byref(this)))
73
74 def can_fade(this):
75 return bool(this._can_fade(byref(this)))
76
77 def parse(this, s):
78 if this._parse(byref(this), s) is None:
79 raise Exception("Parse failure")
80
81
82 class CVolume(Structure):
83 _fields_ = [("channels", c_ubyte),
84 ("values", c_uint32 * 32)]
85
86 _snprint = libpulse.pa_cvolume_snprint
87 _snprint.restype = c_char_p
88 _snprint.argtypes = [c_char_p, c_ulong, c_void_p]
89
90 _max = libpulse.pa_cvolume_max
91 _max.restype = c_uint32
92 _max.argtypes = [c_void_p]
93
94 _scale = libpulse.pa_cvolume_scale
95 _scale.restype = c_void_p
96 _scale.argtypes = [c_void_p, c_uint32]
97
98 _get_balance = libpulse.pa_cvolume_get_balance
99 _get_balance.restype = c_float
100 _get_balance.argtypes = [c_void_p, c_void_p]
101
102 _get_fade = libpulse.pa_cvolume_get_fade
103 _get_fade.restype = c_float
104 _get_fade.argtypes = [c_void_p, c_void_p]
105
106 _set_balance = libpulse.pa_cvolume_set_balance
107 _set_balance.restype = c_void_p
108 _set_balance.argtypes = [c_void_p, c_void_p, c_float]
109
110 _set_fade = libpulse.pa_cvolume_set_fade
111 _set_fade.restype = c_void_p
112 _set_fade.argtypes = [c_void_p, c_void_p, c_float]
113
114 _to_dB = libpulse.pa_sw_volume_to_dB
115 _to_dB.restype = c_double
116 _to_dB.argytpes = [c_uint32]
117
118 def snprint(this):
119 s = create_string_buffer(320)
120 r = this._snprint(s, len(s), byref(this))
121
122 if r is None:
123 return None
124 else:
125 return s.raw
126
127 def max(this):
128 return this._max(byref(this))
129
130 def scale(this, v):
131 return this._scale(byref(this), v)
132
133 def get_balance(this, cm):
134 return this._get_balance(byref(this), byref(cm))
135
136 def get_fade(this, cm):
137 return this._get_fade(byref(this), byref(cm))
138
139 def set_balance(this, cm, f):
140 return this._set_balance(byref(this), byref(cm), f)
141
142 def set_fade(this, cm, f):
143 return this._set_fade(byref(this), byref(cm), f)
144
145 def to_dB(this, channel = None):
146 if channel is None:
147 return this._to_dB(this.max())
148
149 return this._to_dB(this.values[channel])
150
151 cm = ChannelMap()
152
153 if len(sys.argv) > 1:
154 cm.parse(sys.argv[1])
155 else:
156 cm.parse("surround-51")
157
158 v = CVolume()
159 v.channels = cm.channels
160
161 for i in range(cm.channels):
162 v.values[i] = 65536
163
164 title = cm.to_pretty_name()
165 if title is None:
166 title = cm.snprint()
167
168 window = gtk.Window(gtk.WINDOW_TOPLEVEL)
169 window.set_title(unicode(title))
170 window.set_border_width(12)
171
172 vbox = gtk.VBox(spacing=6)
173
174 channel_labels = {}
175 channel_scales = {}
176 channel_dB_labels = {}
177
178 def update_volume(update_channels = True, update_fade = True, update_balance = True, update_scale = True):
179 if update_channels:
180 for i in range(cm.channels):
181 channel_scales[i].set_value(v.values[i])
182
183 if update_scale:
184 value_scale.set_value(v.max())
185
186 if update_balance:
187 balance_scale.set_value(v.get_balance(cm))
188
189 if update_fade:
190 fade_scale.set_value(v.get_fade(cm))
191
192 for i in range(cm.channels):
193 channel_dB_labels[i].set_label("%0.2f dB" % v.to_dB(i))
194
195 value_dB_label.set_label("%0.2f dB" % v.to_dB())
196
197 def fade_value_changed(fs):
198 v.set_fade(cm, fade_scale.get_value())
199 update_volume(update_fade = False)
200
201 def balance_value_changed(fs):
202 v.set_balance(cm, balance_scale.get_value())
203 update_volume(update_balance = False)
204
205 def value_value_changed(fs):
206 v.scale(int(value_scale.get_value()))
207 update_volume(update_scale = False)
208
209 def channel_value_changed(fs, i):
210 v.values[i] = int(channel_scales[i].get_value())
211 update_volume(update_channels = False)
212
213 for i in range(cm.channels):
214 channel_labels[i] = gtk.Label(cm.position_to_pretty_string(cm.map[i]))
215 channel_labels[i].set_alignment(0, 1)
216 vbox.pack_start(channel_labels[i], expand=False, fill=True)
217
218 channel_scales[i] = gtk.HScale()
219 channel_scales[i].set_range(0, 65536*3/2)
220 channel_scales[i].set_digits(0)
221 channel_scales[i].set_value_pos(gtk.POS_RIGHT)
222 vbox.pack_start(channel_scales[i], expand=False, fill=True)
223
224 channel_dB_labels[i] = gtk.Label("-xxx dB")
225 channel_dB_labels[i].set_alignment(1, 1)
226 vbox.pack_start(channel_dB_labels[i], expand=False, fill=True)
227
228 value_label = gtk.Label("Value")
229 value_label.set_alignment(0, .5)
230 vbox.pack_start(value_label, expand=False, fill=True)
231 value_scale = gtk.HScale()
232 value_scale.set_range(0, 65536*3/2)
233 value_scale.set_value_pos(gtk.POS_RIGHT)
234 value_scale.set_digits(0)
235 vbox.pack_start(value_scale, expand=False, fill=True)
236 value_dB_label = gtk.Label("-xxx dB")
237 value_dB_label.set_alignment(1, 1)
238 vbox.pack_start(value_dB_label, expand=False, fill=True)
239
240 balance_label = gtk.Label("Balance")
241 balance_label.set_alignment(0, .5)
242 vbox.pack_start(balance_label, expand=False, fill=True)
243 balance_scale = gtk.HScale()
244 balance_scale.set_range(-1.0, +1.0)
245 balance_scale.set_value_pos(gtk.POS_RIGHT)
246 balance_scale.set_digits(2)
247 vbox.pack_start(balance_scale, expand=False, fill=True)
248
249 fade_label = gtk.Label("Fade")
250 fade_label.set_alignment(0, .5)
251 vbox.pack_start(fade_label, expand=False, fill=True)
252 fade_scale = gtk.HScale()
253 fade_scale.set_range(-1.0, +1.0)
254 fade_scale.set_value_pos(gtk.POS_RIGHT)
255 fade_scale.set_digits(2)
256 vbox.pack_start(fade_scale, expand=False, fill=True)
257
258 window.add(vbox)
259 window.set_default_size(600, 50)
260
261 update_volume()
262
263 for i in range(cm.channels):
264 channel_scales[i].connect("value_changed", channel_value_changed, i)
265 fade_scale.connect("value_changed", fade_value_changed)
266 balance_scale.connect("value_changed", balance_value_changed)
267 value_scale.connect("value_changed", value_value_changed)
268
269 vbox.show_all()
270
271 if not cm.can_balance():
272 balance_label.hide()
273 balance_scale.hide()
274
275 if not cm.can_fade():
276 fade_label.hide()
277 fade_scale.hide()
278
279
280 window.show()
281
282 gtk.main()