root/trunk/libffado/support/mixer-qt4/ffado/widgets/matrixmixer.py

Revision 1666, 9.6 kB (checked in by arnonym, 12 years ago)

Simplify (de-)coupling of channels a bit.

And start with getting the mixer values on startup and on coupling. Currently only the maximum is used, no balance/pan is computed...

  • Property svn:mergeinfo set to
Line 
1 #
2 # Copyright (C) 2009 by Arnold Krille
3 #
4 # This file is part of FFADO
5 # FFADO = Free Firewire (pro-)audio drivers for linux
6 #
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, or
10 # (at your option) version 3 of the License.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 #
20
21 from PyQt4 import QtGui, QtCore, Qt
22 import dbus
23
24 class MixerNode(QtGui.QFrame):
25     def __init__(self, inputs, outputs, parent):
26         """inputs  = list of input-channel numbers
27            outputs = list of output-channel numbers
28            """
29         QtGui.QFrame.__init__(self, parent)
30         self.setLineWidth(2)
31         self.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Raised)
32
33         self.inputs = []
34         self.outputs = []
35
36         self.inputbalance = QtGui.QSlider(Qt.Qt.Horizontal, self)
37         self.inputbalance.setRange(-100, 100)
38         self.connect(self.inputbalance, QtCore.SIGNAL("valueChanged(int)"), self.valuesChanged)
39
40         self.outputbalance = QtGui.QSlider(Qt.Qt.Horizontal, self)
41         self.outputbalance.setRange(-100, 100)
42         self.connect(self.outputbalance, QtCore.SIGNAL("valueChanged(int)"), self.valuesChanged)
43
44         self.fader = QtGui.QDial(self)
45         self.fader.setRange(0,pow(2,16)-1)
46         self.connect(self.fader, QtCore.SIGNAL("valueChanged(int)"), self.valuesChanged)
47
48         self.layout = QtGui.QGridLayout(self)
49         self.setLayout(self.layout)
50
51         self.layout.addWidget(self.inputbalance, 0, 0)
52         self.layout.addWidget(self.fader, 1, 0)
53         self.layout.addWidget(self.outputbalance, 2, 0)
54
55         self.addInputs(inputs)
56         self.addOutputs(outputs)
57
58     def valuesChanged(self):
59         fader = self.fader.value()
60         values = []
61         while len(values) < len(self.inputs):
62             tmp = []
63             while len(tmp) < len(self.outputs):
64                 tmp.append(fader)
65             values.append(tmp)
66         if len(self.inputs) == len(self.outputs):
67             for i in range(len(self.inputs)):
68                 for j in range(len(self.outputs)):
69                     values[i][j] *= (i==j)
70         if len(self.outputs) == 2:
71             v = self.outputbalance.value() / 100.0
72             left = 1.0
73             right = 1.0
74             if v > 0:
75                 left = 1.0 - v
76             if v < 0:
77                 right = 1.0 + v
78             for row in values:
79                 row[0] *= left
80                 row[1] *= right
81         if len(self.inputs) == 2:
82             v = self.inputbalance.value() / 100.0
83             left = 1.0
84             right = 1.0
85             if v > 0:
86                 left = 1.0 - v
87             if v < 0:
88                 right = 1.0 + v
89             for i in range(len(self.outputs)):
90                 values[0][i] *= left
91                 values[1][i] *= right
92         ret = []
93         for i in range(len(self.inputs)):
94             for j in range(len(self.outputs)):
95                 ret.append( (self.inputs[i], self.outputs[j], values[i][j]) )
96         #print ret
97         self.emit(QtCore.SIGNAL("valueChanged"), ret)
98
99     def addInputs(self, inputs, add=True):
100         if not isinstance(inputs, list):
101             inputs = [inputs]
102         if add:
103             self.inputs += inputs
104         else:
105             for item in inputs:
106                 self.inputs.remove(item)
107         self.checkWidgets()
108     def removeInputs(self, inputs):
109         self.addInputs(inputs, False)
110
111     def addOutputs(self, outputs, add=True):
112         if not isinstance(outputs, list):
113             outputs = [outputs]
114         if add:
115             self.outputs += outputs
116         else:
117             for item in outputs:
118                 self.outputs.remove(item)
119         self.checkWidgets()
120     def removeOutputs(self, outputs):
121         self.addOutputs(outputs, False)
122
123     def checkWidgets(self):
124         if len(self.inputs)>1:
125             self.inputbalance.show()
126         else:
127             self.inputbalance.hide()
128         if len(self.outputs)>1:
129             self.outputbalance.show()
130         else:
131             self.outputbalance.hide()
132         if len(self.inputs) and len(self.outputs):
133             valuematrix = []
134             for row in self.outputs:
135                 valuematrix.append( [] )
136                 for col in self.inputs:
137                     valuematrix[self.outputs.index(row)] = self.parent().interface.getValue(row, col)
138             self.fader.setValue(max(valuematrix))
139
140
141 class MixerChannel(QtGui.QWidget):
142     def __init__(self, number, parent=None):
143         QtGui.QWidget.__init__(self, parent)
144         layout = QtGui.QGridLayout(self)
145         self.number = number
146         self.lbl = QtGui.QLabel("Ch. %i" % self.number, self)
147         layout.addWidget(self.lbl, 0, 0, 1, 2)
148
149         self.btnHide = QtGui.QToolButton(self)
150         self.btnHide.setText("Hide")
151         self.btnHide.setCheckable(True)
152         self.connect(self.btnHide, QtCore.SIGNAL("clicked(bool)"), self.hideChannel)
153         layout.addWidget(self.btnHide, 1, 0)
154
155         self.btnCouple = QtGui.QToolButton(self)
156         self.btnCouple.setText("Stereo")
157         self.btnCouple.setCheckable(True)
158         self.connect(self.btnCouple, QtCore.SIGNAL("toggled(bool)"), self.coupleWithNext)
159         layout.addWidget(self.btnCouple, 1, 1)
160
161     def hideChannel(self, hide):
162         self.btnCouple.setHidden(hide)
163         self.emit(QtCore.SIGNAL("hide"), self.number, hide)
164
165     def coupleWithNext(self, couple):
166         self.emit(QtCore.SIGNAL("couple"), self.number, couple)
167
168     def canCouple(self, cancouple):
169         #self.btnCouple.setEnabled(cancouple)
170         self.btnCouple.setHidden(not cancouple)
171
172 class MatrixMixer(QtGui.QWidget):
173     def __init__(self, servername, basepath, parent=None):
174         QtGui.QWidget.__init__(self, parent)
175         self.bus = dbus.SessionBus()
176         self.dev = self.bus.get_object(servername, basepath)
177         self.interface = dbus.Interface(self.dev, dbus_interface="org.ffado.Control.Element.MatrixMixer")
178
179         palette = self.palette()
180         palette.setColor(QtGui.QPalette.Window, palette.color(QtGui.QPalette.Window).darker());
181         self.setPalette(palette)
182
183         rows = self.interface.getRowCount()
184         cols = self.interface.getColCount()
185
186         layout = QtGui.QGridLayout(self)
187         self.setLayout(layout)
188
189         self.rowHeaders = []
190         self.columnHeaders = []
191         self.items = []
192
193         # Add row/column headers
194         for i in range(cols):
195             ch = MixerChannel(i, self)
196             self.connect(ch, QtCore.SIGNAL("couple"), self.coupleColumn)
197             self.connect(ch, QtCore.SIGNAL("hide"), self.hideColumn)
198             ch.canCouple(i+1!=cols)
199             layout.addWidget(ch, 0, i+1)
200             self.columnHeaders.append( ch )
201         for i in range(rows):
202             ch = MixerChannel(i, self)
203             self.connect(ch, QtCore.SIGNAL("couple"), self.coupleRow)
204             self.connect(ch, QtCore.SIGNAL("hide"), self.hideRow)
205             ch.canCouple(i+1!=rows)
206             layout.addWidget(ch, i+1, 0)
207             self.rowHeaders.append( ch )
208
209         # Add node-widgets
210         for i in range(rows):
211             self.items.append([])
212             for j in range(cols):
213                 node = MixerNode(j, i, self)
214                 self.connect(node, QtCore.SIGNAL("valueChanged"), self.valueChanged)
215                 layout.addWidget(node, i+1, j+1)
216                 self.items[i].append(node)
217
218         self.hiddenRows = []
219         self.hiddenCols = []
220         self.coupledRows = []
221         self.coupledCols = []
222
223
224     def checkVisibilities(self):
225         for x in range(len(self.items)):
226             for y in range(len(self.items[x])):
227                 self.items[x][y].setHidden( (x in self.hiddenRows) | (x in self.coupledRows) | (y in self.hiddenCols) | (y in self.coupledCols) )
228
229     def coupleColumn(self, column, couple):
230         if column+1 < len(self.columnHeaders):
231             self.columnHeaders[column+1].setHidden(couple)
232         if column > 0:
233             self.columnHeaders[column-1].canCouple(not couple)
234         if couple:
235             self.coupledCols.append(column+1)
236         else:
237             self.coupledCols.remove(column+1)
238         for row in self.items:
239             row[column].addInputs(column+1,couple)
240             row[column+1].addInputs(column+1,not couple)
241         self.checkVisibilities()
242
243     def coupleRow(self, row, couple):
244         if row+1 < len(self.rowHeaders):
245             self.rowHeaders[row+1].setHidden(couple)
246         if row > 0:
247             self.rowHeaders[row-1].canCouple(not couple)
248         if couple:
249             self.coupledRows.append(row+1)
250         else:
251             self.coupledRows.remove(row+1)
252         for col in self.items[row]:
253             col.addOutputs(row+1,couple)
254         for col in self.items[row+1]:
255             col.addOutputs(row+1,not couple)
256         self.checkVisibilities()
257
258     def hideColumn(self, column, hide):
259         if hide:
260             self.hiddenCols.append(column)
261         else:
262             self.hiddenCols.remove(column)
263         self.checkVisibilities()
264     def hideRow(self, row, hide):
265         if hide:
266             self.hiddenRows.append(row)
267         else:
268             self.hiddenRows.remove(row)
269         self.checkVisibilities()
270
271     def valueChanged(self, n):
272         #print "MatrixNode.valueChanged( %s )" % str(n)
273         for tmp in n:
274             self.interface.setValue(tmp[1], tmp[0], tmp[2])
275
276
277 #
278 # vim: et ts=4 sw=4
Note: See TracBrowser for help on using the browser.