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

Revision 1658, 8.6 kB (checked in by arnonym, 14 years ago)

Taking everything apart and recombine it:

  • Hiding channels works.
  • Combining channels to stereo-pairs works.
  • Controlling the volume works.

Left for the next commits (to be seen on a per mixer-element basis):

  • Control input- and output-balance.
  • Allow for more than two inputs or outputs.
  • Change the mapping of inputs->outputs.
  • 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
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.QLabel("Input Balance", self)
37         self.outputbalance = QtGui.QLabel("Output Balance", self)
38
39         #self.fader = QtGui.QLabel("Fader", self)
40         self.fader = QtGui.QDial(self)
41         self.fader.setRange(0,pow(2,16)-1)
42         self.connect(self.fader, QtCore.SIGNAL("valueChanged(int)"), self.valuesChanged)
43
44         self.layout = QtGui.QGridLayout(self)
45         self.setLayout(self.layout)
46
47         self.layout.addWidget(self.inputbalance, 0, 0)
48         self.layout.addWidget(self.fader, 1, 0)
49         self.layout.addWidget(self.outputbalance, 2, 0)
50
51         self.addInputs(inputs)
52         self.addOutputs(outputs)
53
54     def valuesChanged(self):
55         fader = self.fader.value()
56         values = []
57         while len(values) < len(self.inputs):
58             tmp = []
59             while len(tmp) < len(self.outputs):
60                 tmp.append(fader)
61             values.append(tmp)
62         #print values
63         if len(self.inputs) == len(self.outputs):
64             for i in range(len(self.inputs)):
65                 for j in range(len(self.outputs)):
66                     values[i][j] *= (i==j)
67         #print values
68         ret = []
69         for i in range(len(self.inputs)):
70             for j in range(len(self.outputs)):
71                 ret.append( (self.inputs[i], self.outputs[j], values[i][j]) )
72         #print ret
73         self.emit(QtCore.SIGNAL("valueChanged"), ret)
74
75     def addInputs(self, inputs):
76         if isinstance(inputs, list):
77             self.inputs += inputs
78         else:
79             self.inputs.append(inputs)
80         self.checkWidgets()
81     def removeInputs(self, inputs):
82         if isinstance(inputs, list):
83             for item in inputs:
84                 self.inputs.remove(item)
85         else:
86             self.inputs.remove(inputs)
87         self.checkWidgets()
88
89     def addOutputs(self, outputs):
90         if isinstance(outputs, list):
91             self.outputs += outputs
92         else:
93             self.outputs.append(outputs)
94         self.checkWidgets()
95     def removeOutputs(self, outputs):
96         if isinstance(outputs, list):
97             for item in outputs:
98                 self.outputs.remove(item)
99         else:
100             self.outputs.remove(outputs)
101         self.checkWidgets()
102
103     def checkWidgets(self):
104         if len(self.inputs)>1:
105             self.inputbalance.show()
106         else:
107             self.inputbalance.hide()
108         if len(self.outputs)>1:
109             self.outputbalance.show()
110         else:
111             self.outputbalance.hide()
112
113
114 class MixerChannel(QtGui.QWidget):
115     def __init__(self, number, parent=None):
116         QtGui.QWidget.__init__(self, parent)
117         layout = QtGui.QGridLayout(self)
118         self.number = number
119         self.lbl = QtGui.QLabel("Ch. %i" % self.number, self)
120         layout.addWidget(self.lbl, 0, 0, 1, 2)
121
122         self.btnHide = QtGui.QToolButton(self)
123         self.btnHide.setText("Hide")
124         self.btnHide.setCheckable(True)
125         self.connect(self.btnHide, QtCore.SIGNAL("clicked(bool)"), self.hideChannel)
126         layout.addWidget(self.btnHide, 1, 0)
127
128         self.btnCouple = QtGui.QToolButton(self)
129         self.btnCouple.setText("Stereo")
130         self.btnCouple.setCheckable(True)
131         self.connect(self.btnCouple, QtCore.SIGNAL("toggled(bool)"), self.coupleWithNext)
132         layout.addWidget(self.btnCouple, 1, 1)
133
134     def hideChannel(self, hide):
135         self.btnCouple.setHidden(hide)
136         self.emit(QtCore.SIGNAL("hide"), self.number, hide)
137
138     def coupleWithNext(self, couple):
139         self.emit(QtCore.SIGNAL("couple"), self.number, couple)
140
141     def canCouple(self, cancouple):
142         #self.btnCouple.setEnabled(cancouple)
143         self.btnCouple.setHidden(not cancouple)
144
145 class MatrixMixer(QtGui.QWidget):
146     def __init__(self, servername, basepath, parent=None):
147         QtGui.QWidget.__init__(self, parent)
148         self.bus = dbus.SessionBus()
149         self.dev = self.bus.get_object(servername, basepath)
150         self.interface = dbus.Interface(self.dev, dbus_interface="org.ffado.Control.Element.MatrixMixer")
151
152         palette = self.palette()
153         palette.setColor(QtGui.QPalette.Window, palette.color(QtGui.QPalette.Window).darker());
154         self.setPalette(palette)
155
156         rows = self.interface.getRowCount()
157         cols = self.interface.getColCount()
158
159         layout = QtGui.QGridLayout(self)
160         self.setLayout(layout)
161
162         self.rowHeaders = []
163         self.columnHeaders = []
164         self.items = []
165
166         # Add row/column headers
167         for i in range(cols):
168             ch = MixerChannel(i, self)
169             self.connect(ch, QtCore.SIGNAL("couple"), self.coupleColumn)
170             self.connect(ch, QtCore.SIGNAL("hide"), self.hideColumn)
171             ch.canCouple(i+1!=cols)
172             layout.addWidget(ch, 0, i+1)
173             self.columnHeaders.append( ch )
174         for i in range(rows):
175             ch = MixerChannel(i, self)
176             self.connect(ch, QtCore.SIGNAL("couple"), self.coupleRow)
177             self.connect(ch, QtCore.SIGNAL("hide"), self.hideRow)
178             ch.canCouple(i+1!=rows)
179             layout.addWidget(ch, i+1, 0)
180             self.rowHeaders.append( ch )
181
182         # Add node-widgets
183         for i in range(rows):
184             self.items.append([])
185             for j in range(cols):
186                 node = MixerNode(j, i, self)
187                 self.connect(node, QtCore.SIGNAL("valueChanged"), self.valueChanged)
188                 layout.addWidget(node, i+1, j+1)
189                 self.items[i].append(node)
190
191         self.hiddenRows = []
192         self.hiddenCols = []
193         self.coupledRows = []
194         self.coupledCols = []
195
196
197     def checkVisibilities(self):
198         for x in range(len(self.items)):
199             for y in range(len(self.items[x])):
200                 self.items[x][y].setHidden( (x in self.hiddenRows) | (x in self.coupledRows) | (y in self.hiddenCols) | (y in self.coupledCols) )
201
202     def coupleColumn(self, column, couple):
203         if column+1 < len(self.columnHeaders):
204             self.columnHeaders[column+1].setHidden(couple)
205         if column > 0:
206             self.columnHeaders[column-1].canCouple(not couple)
207         if couple:
208             self.coupledCols.append(column+1)
209         else:
210             self.coupledCols.remove(column+1)
211         for row in self.items:
212             if couple:
213                 row[column].addInputs(column+1)
214             else:
215                 row[column].removeInputs(column+1)
216         self.checkVisibilities()
217
218     def coupleRow(self, row, couple):
219         if row+1 < len(self.rowHeaders):
220             self.rowHeaders[row+1].setHidden(couple)
221         if row > 0:
222             self.rowHeaders[row-1].canCouple(not couple)
223         if couple:
224             self.coupledRows.append(row+1)
225         else:
226             self.coupledRows.remove(row+1)
227         for col in self.items[row]:
228             if couple:
229                 col.addOutputs(row+1)
230             else:
231                 col.removeOutputs(row+1)
232         self.checkVisibilities()
233
234     def hideColumn(self, column, hide):
235         if hide:
236             self.hiddenCols.append(column)
237         else:
238             self.hiddenCols.remove(column)
239         self.checkVisibilities()
240     def hideRow(self, row, hide):
241         if hide:
242             self.hiddenRows.append(row)
243         else:
244             self.hiddenRows.remove(row)
245         self.checkVisibilities()
246
247     def valueChanged(self, n):
248         #print "MatrixNode.valueChanged( %s )" % str(n)
249         for tmp in n:
250             self.interface.setValue(tmp[1], tmp[0], tmp[2])
251
252
253 #
254 # vim: et ts=4 sw=4
Note: See TracBrowser for help on using the browser.