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

Revision 1695, 9.2 kB (checked in by arnonym, 14 years ago)

stupid error(s)...

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