1 |
from PyQt4.QtCore import SIGNAL, SLOT, QObject, Qt |
---|
2 |
from PyQt4.QtGui import QWidget, QMessageBox, QHBoxLayout, QVBoxLayout, QTabWidget, QGroupBox, QLabel, QDial, QSlider, QToolButton, QSizePolicy |
---|
3 |
from math import log10 |
---|
4 |
from ffado.config import * |
---|
5 |
|
---|
6 |
import logging |
---|
7 |
log = logging.getLogger('MAudioBeBoB') |
---|
8 |
|
---|
9 |
class MAudio_BeBoB_Input_Widget(QWidget): |
---|
10 |
def __init__(self,parent = None): |
---|
11 |
QWidget.__init__(self,parent) |
---|
12 |
uicLoad("ffado/mixer/maudio_bebob_input", self) |
---|
13 |
|
---|
14 |
class MAudio_BeBoB_Output_Widget(QWidget): |
---|
15 |
def __init__(self,parent = None): |
---|
16 |
QWidget.__init__(self,parent) |
---|
17 |
uicLoad("ffado/mixer/maudio_bebob_output", self) |
---|
18 |
|
---|
19 |
|
---|
20 |
class MAudio_BeBoB(QWidget): |
---|
21 |
def __init__(self,parent = None): |
---|
22 |
QWidget.__init__(self,parent) |
---|
23 |
|
---|
24 |
info = { |
---|
25 |
0x0000000a: [0, "Ozonic"], |
---|
26 |
0x00010062: [1, "Firewire Solo"], |
---|
27 |
0x00010060: [2, "Firewire Audiophile"], |
---|
28 |
0x00010046: [3, "Firewire 410"], |
---|
29 |
0x00010071: [4, "Firewire 1814"], |
---|
30 |
0x00010091: [4, "ProjectMix I/O"], |
---|
31 |
} |
---|
32 |
|
---|
33 |
labels = [ |
---|
34 |
{ |
---|
35 |
"inputs": ["Analog 1/2", "Analog 3/4", |
---|
36 |
"Stream 1/2", "Stream 3/4"], |
---|
37 |
"mixers": ["Mixer 1/2", "Mixer 3/4"], |
---|
38 |
"outputs": ["Analog 1/2", "Analog 3/4"] |
---|
39 |
}, |
---|
40 |
{ |
---|
41 |
"inputs": ["Analog 1/2", "Digital 1/2", |
---|
42 |
"Stream 1/2", "Stream 3/4"], |
---|
43 |
"mixers": ["Mixer 1/2", "Mixer 3/4"], |
---|
44 |
"outputs": ["Analog 1/2", "Digital 1/2"] |
---|
45 |
}, |
---|
46 |
{ |
---|
47 |
"inputs": ["Analog 1/2", "Digital 1/2", |
---|
48 |
"Stream 1/2", "Stream 3/4", "Stream 5/6"], |
---|
49 |
"mixers": ["Mixer 1/2", "Mixer 3/4", "Mixer 5/6", "Aux 1/2"], |
---|
50 |
"outputs": ["Analog 1/2", "Analog 3/4", "Digital 1/2", |
---|
51 |
"Headphone 1/2"] |
---|
52 |
}, |
---|
53 |
{ |
---|
54 |
"inputs": ["Analog 1/2", "Digital 1/2", |
---|
55 |
"Stream 1/2", "Stream 3/4", "Stream 5/6", |
---|
56 |
"Stream 7/8", "Stream 9/10"], |
---|
57 |
"mixers": ["Mixer 1/2", "Mixer 3/4", "Mixer 5/6", "Mixer 7/8", |
---|
58 |
"Mixer 9/10", "Aux 1/2"], |
---|
59 |
"outputs": ["Analog 1/2", "Analog 3/4", "Analog 5/6", "Analog 7/8", |
---|
60 |
"Digital 1/2", "Headphone 1/2"] |
---|
61 |
}, |
---|
62 |
{ |
---|
63 |
"inputs": ["Analog 1/2", "Analog 3/4", "Analog 5/6", "Analog 7/8", |
---|
64 |
"Stream 1/2", "Stream 3/4", "S/PDIF 1/2", |
---|
65 |
"ADAT 1/2", "ADAT 3/4", "ADAT 5/6", "ADAT 7/8"], |
---|
66 |
"mixers": ["Mixer 1/2", "Mixer 3/4", "Aux 1/2"], |
---|
67 |
"outputs": ["Analog 1/2", "Analog 3/4", |
---|
68 |
"Headphone 1/2", "Headphone 3/4"] |
---|
69 |
} |
---|
70 |
] |
---|
71 |
|
---|
72 |
# hardware inputs and stream playbacks |
---|
73 |
# format: function_id/channel_idx/panning-able |
---|
74 |
# NOTE: function_id = channel_idx = panning-able = labels["inputs"] |
---|
75 |
inputs = [ |
---|
76 |
[ |
---|
77 |
[0x03, 0x04, 0x01, 0x02], |
---|
78 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]], |
---|
79 |
[True, True, False, False] |
---|
80 |
], |
---|
81 |
[ |
---|
82 |
[0x01, 0x02, 0x04, 0x03], |
---|
83 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]], |
---|
84 |
[True, True, False, False] |
---|
85 |
], |
---|
86 |
[ |
---|
87 |
[0x04, 0x05, 0x01, 0x02, 0x03], |
---|
88 |
[[0x01, 0x02], [0x01, 0x02], |
---|
89 |
[0x01, 0x02], [0x01, 0x02], [0x01, 0x02]], |
---|
90 |
[True, True, False, False, False] |
---|
91 |
], |
---|
92 |
[ |
---|
93 |
[0x03, 0x04, 0x02, 0x01, 0x01, 0x01, 0x01], |
---|
94 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
95 |
[0x01, 0x02], [0x03, 0x04], [0x05, 0x06], [0x07, 0x08]], |
---|
96 |
[True, True, False, False, False, False, False] |
---|
97 |
], |
---|
98 |
[ |
---|
99 |
[0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x05, 0x06, 0x07, 0x08, 0x09], |
---|
100 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
101 |
[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
102 |
[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]], |
---|
103 |
[True, True, True, True, False, False, True, |
---|
104 |
True, True, True, True] |
---|
105 |
] |
---|
106 |
] |
---|
107 |
|
---|
108 |
# jack sources except for headphone |
---|
109 |
# format: function_id/source id |
---|
110 |
# NOTE: "function_id" = labels["output"] - "Headphone 1/2/3/4" |
---|
111 |
# NOTE: "source_id" = labels["mixer"] |
---|
112 |
jack_src = [ |
---|
113 |
None, |
---|
114 |
None, |
---|
115 |
[[0x01, 0x02, 0x03], |
---|
116 |
[0x00, 0x00, 0x00, 0x01]], |
---|
117 |
[[0x02, 0x03, 0x04, 0x05, 0x06], |
---|
118 |
[0x00, 0x00, 0x00, 0x00, 0x00, 0x01]], |
---|
119 |
[[0x03, 0x04], |
---|
120 |
[0x00, 0x01, 0x02]] |
---|
121 |
] |
---|
122 |
|
---|
123 |
# headphone sources |
---|
124 |
# format: sink id/source id |
---|
125 |
# NOTE: "source_id" = labels["mixer"] |
---|
126 |
hp_src = [ |
---|
127 |
None, |
---|
128 |
None, |
---|
129 |
[[0x04], |
---|
130 |
[0x00, 0x01, 0x02, 0x03]], |
---|
131 |
[[0x07], |
---|
132 |
[0x02, 0x03, 0x04, 0x05, 0x06, 0x07]], |
---|
133 |
[[0x01, 0x02], |
---|
134 |
[0x01, 0x02, 0x04]] |
---|
135 |
] |
---|
136 |
|
---|
137 |
# hardware outputs |
---|
138 |
# format: function id |
---|
139 |
# NOTE: "function_id" = labels["output"] |
---|
140 |
outputs = [ |
---|
141 |
[0x05, 0x06], |
---|
142 |
[0x02, 0x03], |
---|
143 |
[0x0c, 0x0d, 0x0e, 0x0f], |
---|
144 |
[0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f], |
---|
145 |
[0x0c, 0x0d, 0x0f, 0x10] |
---|
146 |
] |
---|
147 |
|
---|
148 |
# Mixer inputs/outputs |
---|
149 |
# format: function_id/out_stereo_channel_id/in_id/in_stereo_channel_id |
---|
150 |
# NOTE: function_id = out_stereo_channel_id = labels["mixers"] |
---|
151 |
# NOTE: in_id = in_stereo_channel_id = labels["inputs"] |
---|
152 |
mixers = [ |
---|
153 |
[ |
---|
154 |
[0x01, 0x02], |
---|
155 |
[[0x01, 0x02], [0x01, 0x02]], |
---|
156 |
[0x02, 0x03, 0x00, 0x01], |
---|
157 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]] |
---|
158 |
], |
---|
159 |
[ |
---|
160 |
[0x01, 0x01], |
---|
161 |
[[0x01, 0x02], [0x03, 0x04]], |
---|
162 |
[0x00, 0x01, 0x03, 0x02], |
---|
163 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]] |
---|
164 |
], |
---|
165 |
[ |
---|
166 |
[0x01, 0x02, 0x03, 0x04], |
---|
167 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]], |
---|
168 |
[0x03, 0x04, 0x00, 0x01, 0x02], |
---|
169 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
170 |
[0x01, 0x02], [0x01, 0x02]] |
---|
171 |
], |
---|
172 |
[ |
---|
173 |
[0x01, 0x01, 0x01, 0x01, 0x01, 0x07], |
---|
174 |
[[0x01, 0x02], [0x03, 0x04], |
---|
175 |
[0x05, 0x06], [0x07, 0x08], [0x09, 0x0a], [0x01, 0x02]], |
---|
176 |
[0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00], |
---|
177 |
[[0x01, 0x02], [0x01, 0x02], |
---|
178 |
[0x01, 0x02], [0x01, 0x02], [0x03, 0x04], |
---|
179 |
[0x05, 0x06], [0x07, 0x08]] |
---|
180 |
], |
---|
181 |
[ |
---|
182 |
[0x01, 0x02, 0x03], |
---|
183 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02]], |
---|
184 |
[0x01, 0x01, 0x01, 0x01, |
---|
185 |
0x02, 0x02, 0x03, |
---|
186 |
0x04, 0x04, 0x04, 0x04], |
---|
187 |
[[0x01, 0x02], [0x03, 0x04], [0x05, 0x06], [0x07, 0x08], |
---|
188 |
[0x01, 0x02], [0x03, 0x04], [0x01, 0x02], |
---|
189 |
[0x01, 0x02], [0x03, 0x04], [0x05, 0x06], [0x07, 0x08]] |
---|
190 |
] |
---|
191 |
] |
---|
192 |
|
---|
193 |
# Aux mixer inputs/outputs |
---|
194 |
# format: function_id/input_id/input_stereo_channel_id |
---|
195 |
# NOTE: input_id = labels["inputs"] |
---|
196 |
aux = [ |
---|
197 |
None, |
---|
198 |
None, |
---|
199 |
[ |
---|
200 |
0x0b, |
---|
201 |
[0x09, 0x0a, 0x06, 0x07, 0x08], |
---|
202 |
[[0x01, 0x02], [0x01, 0x02], |
---|
203 |
[0x01, 0x02], [0x01, 0x02], [0x01, 0x02]] |
---|
204 |
], |
---|
205 |
[ |
---|
206 |
0x09, |
---|
207 |
[0x07, 0x08, 0x06, 0x05, 0x05, 0x05, 0x05], |
---|
208 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
209 |
[0x01, 0x02], [0x03, 0x04], [0x05, 0x06], [0x07, 0x08]] |
---|
210 |
], |
---|
211 |
[ |
---|
212 |
0x0e, |
---|
213 |
[0x13, 0x14, 0x15, 0x16, 0x11, 0x12, 0x17, 0x18, 0x19, 0x1a, 0x1b], |
---|
214 |
[[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
215 |
[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], |
---|
216 |
[0x01, 0x02], [0x01, 0x02], [0x01, 0x02], [0x01, 0x02]] |
---|
217 |
] |
---|
218 |
] |
---|
219 |
|
---|
220 |
def getDisplayTitle(self): |
---|
221 |
model = self.configrom.getModelId() |
---|
222 |
return self.info[model][1] |
---|
223 |
|
---|
224 |
def buildMixer(self): |
---|
225 |
self.Selectors = {} |
---|
226 |
self.Pannings = {} |
---|
227 |
self.Volumes = {} |
---|
228 |
self.Mutes = {} |
---|
229 |
self.Mixers = {} |
---|
230 |
self.FW410HP = 0 |
---|
231 |
|
---|
232 |
model = self.configrom.getModelId() |
---|
233 |
if model not in self.info: |
---|
234 |
return; |
---|
235 |
|
---|
236 |
self.id = self.info[model][0] |
---|
237 |
name = self.info[model][1] |
---|
238 |
|
---|
239 |
tabs_layout = QHBoxLayout(self) |
---|
240 |
tabs = QTabWidget(self) |
---|
241 |
|
---|
242 |
self.addInputTab(tabs) |
---|
243 |
self.addMixTab(tabs) |
---|
244 |
if self.aux[self.id] is not None: |
---|
245 |
self.addAuxTab(tabs) |
---|
246 |
self.addOutputTab(tabs) |
---|
247 |
|
---|
248 |
tabs_layout.addWidget(tabs) |
---|
249 |
|
---|
250 |
|
---|
251 |
def addInputTab(self, tabs): |
---|
252 |
tab_input = QWidget(self) |
---|
253 |
tabs.addTab(tab_input, "In") |
---|
254 |
|
---|
255 |
tab_input_layout = QHBoxLayout() |
---|
256 |
tab_input.setLayout(tab_input_layout) |
---|
257 |
|
---|
258 |
in_labels = self.labels[self.id]["inputs"] |
---|
259 |
in_ids = self.inputs[self.id][0] |
---|
260 |
in_ch_ids = self.inputs[self.id][1] |
---|
261 |
in_pan = self.inputs[self.id][2] |
---|
262 |
|
---|
263 |
for i in range(len(in_ids)): |
---|
264 |
l_idx = self.inputs[self.id][1][i][0] |
---|
265 |
r_idx = self.inputs[self.id][1][i][1] |
---|
266 |
|
---|
267 |
widget = MAudio_BeBoB_Input_Widget(tab_input) |
---|
268 |
tab_input_layout.addWidget(widget) |
---|
269 |
|
---|
270 |
widget.name.setText(in_labels[i]) |
---|
271 |
|
---|
272 |
self.Volumes[widget.l_sld] = [ |
---|
273 |
"/Mixer/Feature_Volume_%d" % in_ids[i], l_idx, |
---|
274 |
widget.r_sld, r_idx, |
---|
275 |
widget.link |
---|
276 |
] |
---|
277 |
self.Volumes[widget.r_sld] = [ |
---|
278 |
"/Mixer/Feature_Volume_%d" % in_ids[i], r_idx, |
---|
279 |
widget.l_sld, l_idx, |
---|
280 |
widget.link |
---|
281 |
] |
---|
282 |
self.Mutes[widget.mute] = [widget.l_sld, widget.r_sld] |
---|
283 |
|
---|
284 |
if not in_pan[i]: |
---|
285 |
widget.l_pan.setDisabled(True) |
---|
286 |
widget.r_pan.setDisabled(True) |
---|
287 |
else: |
---|
288 |
self.Pannings[widget.l_pan] = [ |
---|
289 |
"/Mixer/Feature_LRBalance_%d" % in_ids[i], |
---|
290 |
l_idx |
---|
291 |
] |
---|
292 |
self.Pannings[widget.r_pan] = [ |
---|
293 |
"/Mixer/Feature_LRBalance_%d" % in_ids[i], |
---|
294 |
r_idx |
---|
295 |
] |
---|
296 |
|
---|
297 |
tab_input_layout.addStretch() |
---|
298 |
|
---|
299 |
|
---|
300 |
def addMixTab(self, tabs): |
---|
301 |
tab_mix = QWidget(self) |
---|
302 |
tabs.addTab(tab_mix, "Mix") |
---|
303 |
|
---|
304 |
tab_layout = QHBoxLayout() |
---|
305 |
tab_mix.setLayout(tab_layout) |
---|
306 |
|
---|
307 |
in_labels = self.labels[self.id]["inputs"] |
---|
308 |
in_idxs = self.inputs[self.id][0] |
---|
309 |
|
---|
310 |
mix_labels = self.labels[self.id]["mixers"] |
---|
311 |
mix_idxs = self.mixers[self.id][0] |
---|
312 |
|
---|
313 |
for i in range(len(mix_idxs)): |
---|
314 |
if mix_labels[i] == 'Aux 1/2': |
---|
315 |
continue |
---|
316 |
|
---|
317 |
grp = QGroupBox(tab_mix) |
---|
318 |
grp_layout = QVBoxLayout() |
---|
319 |
grp.setLayout(grp_layout) |
---|
320 |
tab_layout.addWidget(grp) |
---|
321 |
|
---|
322 |
label = QLabel(grp) |
---|
323 |
grp_layout.addWidget(label) |
---|
324 |
|
---|
325 |
label.setText(mix_labels[i]) |
---|
326 |
label.setAlignment(Qt.AlignCenter) |
---|
327 |
label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) |
---|
328 |
|
---|
329 |
for j in range(len(in_idxs)): |
---|
330 |
mix_in_id = self.mixers[self.id][2][j] |
---|
331 |
|
---|
332 |
button = QToolButton(grp) |
---|
333 |
grp_layout.addWidget(button) |
---|
334 |
|
---|
335 |
button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) |
---|
336 |
button.setText('%s In' % in_labels[j]) |
---|
337 |
button.setCheckable(True) |
---|
338 |
|
---|
339 |
self.Mixers[button] = [ |
---|
340 |
"/Mixer/EnhancedMixer_%d" % mix_idxs[i], |
---|
341 |
mix_in_id, j, i |
---|
342 |
] |
---|
343 |
|
---|
344 |
grp_layout.addStretch() |
---|
345 |
tab_layout.addStretch() |
---|
346 |
|
---|
347 |
def addAuxTab(self, tabs): |
---|
348 |
#local functions |
---|
349 |
def addLinkButton(parent, layout): |
---|
350 |
button = QToolButton(grp) |
---|
351 |
grp_layout.addWidget(button) |
---|
352 |
button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) |
---|
353 |
button.setText('Link') |
---|
354 |
button.setCheckable(True) |
---|
355 |
return button |
---|
356 |
def addMuteButton(parent, layout): |
---|
357 |
button = QToolButton(parent) |
---|
358 |
layout.addWidget(button) |
---|
359 |
button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum) |
---|
360 |
button.setText('Mute') |
---|
361 |
button.setCheckable(True) |
---|
362 |
return button |
---|
363 |
|
---|
364 |
# local processing |
---|
365 |
tab_aux = QWidget(self) |
---|
366 |
tabs.addTab(tab_aux, "Aux") |
---|
367 |
|
---|
368 |
layout = QHBoxLayout() |
---|
369 |
tab_aux.setLayout(layout) |
---|
370 |
|
---|
371 |
aux_label = self.labels[self.id]["mixers"][-1] |
---|
372 |
aux_id = self.aux[self.id][0] |
---|
373 |
|
---|
374 |
aux_in_labels = self.labels[self.id]["inputs"] |
---|
375 |
aux_in_ids = self.aux[self.id][1] |
---|
376 |
|
---|
377 |
for i in range(len(aux_in_ids)): |
---|
378 |
in_ch_l = self.aux[self.id][2][i][0] |
---|
379 |
in_ch_r = self.aux[self.id][2][i][1] |
---|
380 |
|
---|
381 |
grp = QGroupBox(tab_aux) |
---|
382 |
grp_layout = QVBoxLayout() |
---|
383 |
grp.setLayout(grp_layout) |
---|
384 |
layout.addWidget(grp) |
---|
385 |
|
---|
386 |
label = QLabel(grp) |
---|
387 |
grp_layout.addWidget(label) |
---|
388 |
label.setText("%s\nIn" % aux_in_labels[i]) |
---|
389 |
label.setAlignment(Qt.AlignCenter) |
---|
390 |
|
---|
391 |
grp_sld = QGroupBox(grp) |
---|
392 |
grp_sld_layout = QHBoxLayout() |
---|
393 |
grp_sld.setLayout(grp_sld_layout) |
---|
394 |
grp_layout.addWidget(grp_sld) |
---|
395 |
|
---|
396 |
l_sld = QSlider(grp_sld) |
---|
397 |
grp_sld_layout.addWidget(l_sld) |
---|
398 |
r_sld = QSlider(grp_sld) |
---|
399 |
grp_sld_layout.addWidget(r_sld) |
---|
400 |
|
---|
401 |
button = addLinkButton(grp, grp_layout) |
---|
402 |
self.Volumes[l_sld] = [ |
---|
403 |
"/Mixer/Feature_Volume_%d" % aux_in_ids[i], in_ch_l, |
---|
404 |
r_sld, in_ch_r, |
---|
405 |
button |
---|
406 |
] |
---|
407 |
self.Volumes[r_sld] = [ |
---|
408 |
"/Mixer/Feature_Volume_%d" % aux_in_ids[i], in_ch_r, |
---|
409 |
l_sld, in_ch_l, |
---|
410 |
button |
---|
411 |
] |
---|
412 |
|
---|
413 |
button = addMuteButton(grp, grp_layout) |
---|
414 |
self.Mutes[button] = [l_sld, r_sld] |
---|
415 |
|
---|
416 |
grp = QGroupBox(tab_aux) |
---|
417 |
grp_layout = QVBoxLayout() |
---|
418 |
grp.setLayout(grp_layout) |
---|
419 |
layout.addWidget(grp) |
---|
420 |
|
---|
421 |
label = QLabel(grp) |
---|
422 |
grp_layout.addWidget(label) |
---|
423 |
label.setText("%s\nOut" % aux_label) |
---|
424 |
label.setAlignment(Qt.AlignCenter) |
---|
425 |
|
---|
426 |
grp_sld = QGroupBox(grp) |
---|
427 |
grp_sld_layout = QHBoxLayout() |
---|
428 |
grp_sld.setLayout(grp_sld_layout) |
---|
429 |
grp_layout.addWidget(grp_sld) |
---|
430 |
|
---|
431 |
l_sld = QSlider(grp_sld) |
---|
432 |
grp_sld_layout.addWidget(l_sld) |
---|
433 |
r_sld = QSlider(grp_sld) |
---|
434 |
grp_sld_layout.addWidget(r_sld) |
---|
435 |
|
---|
436 |
button = addLinkButton(grp, grp_layout) |
---|
437 |
self.Volumes[l_sld] = [ |
---|
438 |
"/Mixer/Feature_Volume_%d" % aux_id, 1, |
---|
439 |
r_sld, 2, |
---|
440 |
button |
---|
441 |
] |
---|
442 |
self.Volumes[r_sld] = [ |
---|
443 |
"/Mixer/Feature_Volume_%d" % aux_id, 2, |
---|
444 |
l_sld, 1, |
---|
445 |
button |
---|
446 |
] |
---|
447 |
|
---|
448 |
button = addMuteButton(grp, grp_layout) |
---|
449 |
self.Mutes[button] = [l_sld, r_sld] |
---|
450 |
|
---|
451 |
layout.addStretch() |
---|
452 |
|
---|
453 |
def addOutputTab(self, tabs): |
---|
454 |
tab_out = QWidget(self) |
---|
455 |
tabs.addTab(tab_out, "Out") |
---|
456 |
|
---|
457 |
layout = QHBoxLayout() |
---|
458 |
tab_out.setLayout(layout) |
---|
459 |
|
---|
460 |
out_labels = self.labels[self.id]["outputs"] |
---|
461 |
out_ids = self.outputs[self.id] |
---|
462 |
|
---|
463 |
mixer_labels = self.labels[self.id]["mixers"] |
---|
464 |
|
---|
465 |
if self.jack_src[self.id] is None: |
---|
466 |
for i in range(len(out_ids)): |
---|
467 |
label = QLabel(tab_out) |
---|
468 |
layout.addWidget(label) |
---|
469 |
label.setText("%s Out is fixed to %s Out" % (mixer_labels[i], out_labels[i])) |
---|
470 |
return |
---|
471 |
|
---|
472 |
mixer_ids = self.jack_src[self.id][1] |
---|
473 |
|
---|
474 |
|
---|
475 |
for i in range(len(out_ids)): |
---|
476 |
out_label = out_labels[i] |
---|
477 |
if out_label.find('Headphone') >= 0: |
---|
478 |
continue |
---|
479 |
|
---|
480 |
out_id = self.jack_src[self.id][0][i] |
---|
481 |
|
---|
482 |
widget = MAudio_BeBoB_Output_Widget(tab_out) |
---|
483 |
layout.addWidget(widget) |
---|
484 |
|
---|
485 |
widget.name.setText(out_label) |
---|
486 |
|
---|
487 |
self.Volumes[widget.l_sld] = [ |
---|
488 |
"/Mixer/Feature_Volume_%d" % out_ids[i], 1, |
---|
489 |
widget.r_sld, 2, |
---|
490 |
widget.link |
---|
491 |
] |
---|
492 |
self.Volumes[widget.r_sld] = [ |
---|
493 |
"/Mixer/Feature_Volume_%d" % out_ids[i], 2, |
---|
494 |
widget.l_sld, 1, |
---|
495 |
widget.link |
---|
496 |
] |
---|
497 |
self.Mutes[widget.mute] = [widget.l_sld, widget.r_sld] |
---|
498 |
|
---|
499 |
self.Selectors[widget.cmb_src] = ["/Mixer/Selector_%d" % out_id] |
---|
500 |
|
---|
501 |
for j in range(len(mixer_ids)): |
---|
502 |
if (i != j and j != len(mixer_ids) - 1): |
---|
503 |
continue; |
---|
504 |
widget.cmb_src.addItem("%s Out" % mixer_labels[j], mixer_ids[j]) |
---|
505 |
|
---|
506 |
# add headphone |
---|
507 |
hp_idx = 0 |
---|
508 |
for i in range(len(out_ids)): |
---|
509 |
out_label = out_labels[i] |
---|
510 |
if out_label.find('Headphone') < 0: |
---|
511 |
continue |
---|
512 |
|
---|
513 |
hp_label = self.labels[self.id]["outputs"][i] |
---|
514 |
hp_id = self.hp_src[self.id][0][hp_idx] |
---|
515 |
hp_idx += 1 |
---|
516 |
|
---|
517 |
mixer_labels = self.labels[self.id]["mixers"] |
---|
518 |
|
---|
519 |
widget = MAudio_BeBoB_Output_Widget(tab_out) |
---|
520 |
layout.addWidget(widget) |
---|
521 |
|
---|
522 |
widget.name.setText(hp_label) |
---|
523 |
|
---|
524 |
mixer_labels = self.labels[self.id]["mixers"] |
---|
525 |
mixer_ids = self.mixers[self.id][0] |
---|
526 |
|
---|
527 |
self.Volumes[widget.l_sld] = [ |
---|
528 |
"/Mixer/Feature_Volume_%d" % out_ids[i], 1, |
---|
529 |
widget.r_sld, 2, |
---|
530 |
widget.link |
---|
531 |
] |
---|
532 |
self.Volumes[widget.r_sld] = [ |
---|
533 |
"/Mixer/Feature_Volume_%d" % out_ids[i], 2, |
---|
534 |
widget.l_sld, 1, |
---|
535 |
widget.link |
---|
536 |
] |
---|
537 |
self.Mutes[widget.mute] = [widget.l_sld, widget.r_sld] |
---|
538 |
|
---|
539 |
for i in range(len(mixer_ids)): |
---|
540 |
widget.cmb_src.addItem("%s Out" % mixer_labels[i], mixer_ids[i]) |
---|
541 |
|
---|
542 |
if self.id != 3: |
---|
543 |
self.Selectors[widget.cmb_src] = ["/Mixer/Selector_%d" % hp_id] |
---|
544 |
else: |
---|
545 |
QObject.connect(widget.cmb_src, SIGNAL('activated(int)'), self.update410HP) |
---|
546 |
self.FW410HP = widget.cmb_src |
---|
547 |
|
---|
548 |
layout.addStretch() |
---|
549 |
|
---|
550 |
def initValues(self): |
---|
551 |
for ctl, params in self.Selectors.items(): |
---|
552 |
path = params[0] |
---|
553 |
state = self.hw.getDiscrete(path) |
---|
554 |
ctl.setCurrentIndex(state) |
---|
555 |
QObject.connect(ctl, SIGNAL('activated(int)'), self.updateSelector) |
---|
556 |
|
---|
557 |
# Right - Center - Left |
---|
558 |
# 0x8000 - 0x0000 - 0x0001 - 0x7FFE |
---|
559 |
# ..., -1, 0, +1, ... |
---|
560 |
for ctl, params in self.Pannings.items(): |
---|
561 |
path = params[0] |
---|
562 |
idx = params[1] |
---|
563 |
curr = self.hw.getContignuous(path, idx) |
---|
564 |
state = -(curr / 0x7FFE) * 50 + 50 |
---|
565 |
ctl.setValue(state) |
---|
566 |
QObject.connect(ctl, SIGNAL('valueChanged(int)'), self.updatePanning) |
---|
567 |
|
---|
568 |
for ctl, params in self.Volumes.items(): |
---|
569 |
path = params[0] |
---|
570 |
idx = params[1] |
---|
571 |
pair = params[2] |
---|
572 |
p_idx = params[3] |
---|
573 |
link = params[4] |
---|
574 |
|
---|
575 |
db = self.hw.getContignuous(path, idx) |
---|
576 |
vol = self.db2vol(db) |
---|
577 |
ctl.setValue(vol) |
---|
578 |
QObject.connect(ctl, SIGNAL('valueChanged(int)'), self.updateVolume) |
---|
579 |
|
---|
580 |
# to activate link button, a pair is checked twice, sign... |
---|
581 |
pair_db = self.hw.getContignuous(path, p_idx) |
---|
582 |
if pair_db== db: |
---|
583 |
link.setChecked(True) |
---|
584 |
|
---|
585 |
for ctl, params in self.Mutes.items(): |
---|
586 |
QObject.connect(ctl, SIGNAL('clicked(bool)'), self.updateMute) |
---|
587 |
|
---|
588 |
for ctl, params in self.Mixers.items(): |
---|
589 |
path = params[0] |
---|
590 |
in_id = params[1] |
---|
591 |
mix_in_idx = params[2] |
---|
592 |
mix_out_idx = params[3] |
---|
593 |
in_ch_l = self.mixers[self.id][3][mix_in_idx][0] |
---|
594 |
out_ch_l = self.mixers[self.id][1][mix_out_idx][0] |
---|
595 |
# see /libffado/src/bebob/bebob_mixer.cpp |
---|
596 |
mux_id = self.getMultiplexedId(in_id, in_ch_l, out_ch_l) |
---|
597 |
curr = self.hw.getContignuous(path, mux_id); |
---|
598 |
if (curr == 0): |
---|
599 |
state = True |
---|
600 |
else: |
---|
601 |
state = False |
---|
602 |
ctl.setChecked(state) |
---|
603 |
QObject.connect(ctl, SIGNAL('clicked(bool)'), self.updateMixer) |
---|
604 |
|
---|
605 |
if self.id == 3: |
---|
606 |
self.read410HP() |
---|
607 |
|
---|
608 |
# helper functions |
---|
609 |
def vol2db(self, vol): |
---|
610 |
return (log10(vol + 1) - 2) * 16384 |
---|
611 |
|
---|
612 |
def db2vol(self, db): |
---|
613 |
return pow(10, db / 16384 + 2) - 1 |
---|
614 |
|
---|
615 |
def getMultiplexedId(self, in_id, in_ch_l, out_ch_l): |
---|
616 |
# see /libffado/src/bebob/bebob_mixer.cpp |
---|
617 |
return (in_id << 8) | (in_ch_l << 4) | (out_ch_l << 0) |
---|
618 |
|
---|
619 |
def updateSelector(self, state): |
---|
620 |
sender = self.sender() |
---|
621 |
path = self.Selectors[sender][0] |
---|
622 |
log.debug("set %s to %d" % (path, state)) |
---|
623 |
self.hw.setDiscrete(path, state) |
---|
624 |
|
---|
625 |
def updatePanning(self, state): |
---|
626 |
sender = self.sender() |
---|
627 |
path = self.Pannings[sender][0] |
---|
628 |
idx = self.Pannings[sender][1] |
---|
629 |
value = (state - 50) * 0x7FFE / -50 |
---|
630 |
log.debug("set %s for %d to %d(%d)" % (path, idx, value, state)) |
---|
631 |
self.hw.setContignuous(path, value, idx) |
---|
632 |
|
---|
633 |
def updateVolume(self, vol): |
---|
634 |
sender = self.sender() |
---|
635 |
path = self.Volumes[sender][0] |
---|
636 |
idx = self.Volumes[sender][1] |
---|
637 |
pair = self.Volumes[sender][2] |
---|
638 |
p_idx = self.Volumes[sender][3] |
---|
639 |
link = self.Volumes[sender][4] |
---|
640 |
|
---|
641 |
db = self.vol2db(vol) |
---|
642 |
log.debug("set %s for %d to %d(%d)" % (path, idx, db, vol)) |
---|
643 |
self.hw.setContignuous(path, db, idx) |
---|
644 |
|
---|
645 |
if link.isChecked(): |
---|
646 |
pair.setValue(vol) |
---|
647 |
|
---|
648 |
# device remeber gain even if muted |
---|
649 |
def updateMute(self, state): |
---|
650 |
sender = self.sender() |
---|
651 |
l_sld = self.Mutes[sender][0] |
---|
652 |
r_sld = self.Mutes[sender][1] |
---|
653 |
|
---|
654 |
if state: |
---|
655 |
db = 0x8000 |
---|
656 |
else: |
---|
657 |
db = 0x0000 |
---|
658 |
for w in [l_sld, r_sld]: |
---|
659 |
path = self.Volumes[w][0] |
---|
660 |
self.hw.setContignuous(self.Volumes[w][0], db) |
---|
661 |
w.setDisabled(state) |
---|
662 |
|
---|
663 |
def updateMixer(self, checked): |
---|
664 |
if checked: |
---|
665 |
state = 0x0000 |
---|
666 |
else: |
---|
667 |
state = 0x8000 |
---|
668 |
|
---|
669 |
sender = self.sender() |
---|
670 |
path = self.Mixers[sender][0] |
---|
671 |
in_id = self.Mixers[sender][1] |
---|
672 |
mix_in_idx = self.Mixers[sender][2] |
---|
673 |
mix_out_idx = self.Mixers[sender][3] |
---|
674 |
in_ch_l = self.mixers[self.id][3][mix_in_idx][0] |
---|
675 |
out_ch_l = self.mixers[self.id][1][mix_out_idx][0] |
---|
676 |
|
---|
677 |
mux_id = self.getMultiplexedId(in_id, in_ch_l, out_ch_l) |
---|
678 |
|
---|
679 |
log.debug("set %s for 0x%04X(%d/%d/%d) to %d" % (path, mux_id, in_id, in_ch_l, out_ch_l, state)) |
---|
680 |
self.hw.setContignuous(path, state, mux_id) |
---|
681 |
|
---|
682 |
def read410HP(self): |
---|
683 |
path = "/Mixer/Selector_7" |
---|
684 |
sel = self.hw.getDiscrete(path) |
---|
685 |
if sel > 0: |
---|
686 |
enbl = 5 |
---|
687 |
else: |
---|
688 |
enbl = -1 |
---|
689 |
|
---|
690 |
path = "/Mixer/EnhancedMixer_7" |
---|
691 |
for i in range(5): |
---|
692 |
in_id = 0 |
---|
693 |
in_ch_l = i * 2 + 1 |
---|
694 |
out_ch_l = 1 |
---|
695 |
mux_id = self.getMultiplexedId(in_id, in_ch_l, out_ch_l) |
---|
696 |
state = self.hw.getContignuous(path, mux_id) |
---|
697 |
if enbl < 0 and state == 0: |
---|
698 |
enbl = i |
---|
699 |
else: |
---|
700 |
self.hw.setContignuous(path, 0x8000, mux_id) |
---|
701 |
# if inconsistency between Selector and Mixer, set AUX as default |
---|
702 |
if enbl == -1: |
---|
703 |
self.hw.setDiscrete('/Mixer/Selector_7', 1); |
---|
704 |
enbl = 5 |
---|
705 |
|
---|
706 |
self.FW410HP.setCurrentIndex(enbl) |
---|
707 |
|
---|
708 |
def update410HP(self, state): |
---|
709 |
hp_id = self.hp_src[self.id][0][0] |
---|
710 |
|
---|
711 |
# each output from mixer can be multiplexed in headphone |
---|
712 |
# but here they are exclusive because of GUI simpleness, sigh... |
---|
713 |
path = "/Mixer/EnhancedMixer_7" |
---|
714 |
for i in range(5): |
---|
715 |
in_id = 0 |
---|
716 |
in_ch_l = i * 2 + 1 |
---|
717 |
out_ch_l = 1 |
---|
718 |
mux_id = self.getMultiplexedId(in_id, in_ch_l, out_ch_l) |
---|
719 |
if i == state: |
---|
720 |
value = 0x0000 |
---|
721 |
else: |
---|
722 |
value = 0x8000 |
---|
723 |
self.hw.setContignuous(path, value, mux_id) |
---|
724 |
|
---|
725 |
# Mixer/Aux is selectable exclusively |
---|
726 |
path = "/Mixer/Selector_7" |
---|
727 |
sel = (state == 5) |
---|
728 |
self.hw.setDiscrete(path, sel) |
---|
729 |
|
---|