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

Revision 1706, 7.5 kB (checked in by arnonym, 11 years ago)

Panning multiple channels to multiple channels is rather complicated. Probably more complicated then what is needed for ffado-mixer. So go back to individual controls for each junction. They look like colored labels but are in fact sliders. A context-menu with predefined values and a direct input for numbers will come soon...

  • 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, math
23
24 import logging
25 log = logging.getLogger("matrixmixer")
26
27 class ColorForNumber:
28     def __init__(self):
29         self.colors = dict()
30
31     def addColor(self, n, color):
32         self.colors[n] = color
33
34     def getColor(self, n):
35         #print "ColorForNumber.getColor( %g )" % (n)
36         keys = self.colors.keys()
37         low = keys[-1]
38         high = keys[-1]
39         for i in range(len(keys)-1):
40             if keys[i] <= n and keys[i+1] > n:
41                 low = keys[i]
42                 high = keys[i+1]
43         #print "%g is between %g and %g" % (n, low, high)
44         f = 0
45         if high != low:
46             f = (n-low) / (high-low)
47         lc = self.colors[low]
48         hc = self.colors[high]
49         return QtGui.QColor(
50                 (1-f)*lc.red()   + f*hc.red(),
51                 (1-f)*lc.green() + f*hc.green(),
52                 (1-f)*lc.blue()  + f*hc.blue() )
53
54 class MixerNode(QtGui.QAbstractSlider):
55     def __init__(self, input, output, value, parent):
56         QtGui.QAbstractSlider.__init__(self, parent)
57         log.debug("MixerNode.__init__( %i, %i, %i, %s )" % (input, output, value, str(parent)) )
58
59         self.pos = QtCore.QPointF(0, 0)
60         self.input = input
61         self.output = output
62         self.setOrientation(Qt.Qt.Vertical)
63         self.setRange(0, pow(2, 16)-1)
64         self.setValue(value)
65         self.connect(self, QtCore.SIGNAL("valueChanged(int)"), self.internalValueChanged)
66
67         self.bgcolors = ColorForNumber()
68         self.bgcolors.addColor(0.0*65535, QtGui.QColor(  0,   0,   0))
69         self.bgcolors.addColor(0.1*65535, QtGui.QColor(  0,   0, 128))
70         self.bgcolors.addColor(0.8*65535, QtGui.QColor(255, 255,   0))
71         self.bgcolors.addColor(1.0*65535, QtGui.QColor(255,   0,   0))
72
73     def mousePressEvent(self, ev):
74         if ev.buttons() & Qt.Qt.LeftButton:
75             self.pos = ev.posF()
76             self.tmpvalue = self.value()
77             ev.accept()
78             #log.debug("MixerNode.mousePressEvent() %s" % str(self.pos))
79
80     def mouseMoveEvent(self, ev):
81         if hasattr(self, "tmpvalue") and self.pos is not QtCore.QPointF(0, 0):
82             newpos = ev.posF()
83             change = newpos.y() - self.pos.y()
84             #log.debug("MixerNode.mouseReleaseEvent() change %s" % (str(change)))
85             self.setValue( self.tmpvalue - math.copysign(pow(abs(change), 2), change) )
86             ev.accept()
87         pass
88
89     def mouseReleaseEvent(self, ev):
90         if hasattr(self, "tmpvalue") and self.pos is not QtCore.QPointF(0, 0):
91             newpos = ev.posF()
92             change = newpos.y() - self.pos.y()
93             #log.debug("MixerNode.mouseReleaseEvent() change %s" % (str(change)))
94             self.setValue( self.tmpvalue - math.copysign(pow(abs(change), 2), change) )
95             self.pos = QtCore.QPointF(0, 0)
96             del self.tmpvalue
97             ev.accept()
98
99     def paintEvent(self, ev):
100         p = QtGui.QPainter(self)
101         rect = self.rect()
102         v = self.value()
103         color = self.bgcolors.getColor(v)
104         p.fillRect(rect, color)
105         if color.valueF() < 0.5:
106             p.setPen(QtGui.QColor(255, 255, 255))
107         else:
108             p.setPen(QtGui.QColor(0, 0, 0))
109         p.drawText(rect, Qt.Qt.AlignCenter, str(self.value()))
110
111     def internalValueChanged(self, value):
112         #log.debug("MixerNode.internalValueChanged( %i )" % value)
113         self.emit(QtCore.SIGNAL("valueChanged"), (self.input, self.output, value) )
114
115
116
117 class MixerChannel(QtGui.QWidget):
118     def __init__(self, number, parent=None, name=""):
119         QtGui.QWidget.__init__(self, parent)
120         layout = QtGui.QGridLayout(self)
121         self.number = number
122         if name is not "":
123             name = " (%s)" % name
124         self.lbl = QtGui.QLabel("Ch. %i\n%s" % (self.number, name), self)
125         layout.addWidget(self.lbl, 0, 0, 1, 2)
126
127         self.btnHide = QtGui.QToolButton(self)
128         self.btnHide.setText("Hide")
129         self.btnHide.setCheckable(True)
130         self.connect(self.btnHide, QtCore.SIGNAL("clicked(bool)"), self.hideChannel)
131         layout.addWidget(self.btnHide, 1, 0)
132
133     def hideChannel(self, hide):
134         self.emit(QtCore.SIGNAL("hide"), self.number, hide)
135
136
137
138 class MatrixMixer(QtGui.QWidget):
139     def __init__(self, servername, basepath, parent=None):
140         QtGui.QWidget.__init__(self, parent)
141         self.bus = dbus.SessionBus()
142         self.dev = self.bus.get_object(servername, basepath)
143         self.interface = dbus.Interface(self.dev, dbus_interface="org.ffado.Control.Element.MatrixMixer")
144
145         palette = self.palette()
146         palette.setColor(QtGui.QPalette.Window, palette.color(QtGui.QPalette.Window).darker());
147         self.setPalette(palette)
148
149         rows = self.interface.getColCount()
150         cols = self.interface.getRowCount()
151         log.debug("Mixer has %i rows and %i columns" % (rows, cols))
152
153         layout = QtGui.QGridLayout(self)
154         self.setLayout(layout)
155
156         self.rowHeaders = []
157         self.columnHeaders = []
158         self.items = []
159
160         # Add row/column headers
161         for i in range(cols):
162             ch = MixerChannel(i, self, self.interface.getColName(i))
163             self.connect(ch, QtCore.SIGNAL("hide"), self.hideColumn)
164             layout.addWidget(ch, 0, i+1)
165             self.columnHeaders.append( ch )
166         for i in range(rows):
167             ch = MixerChannel(i, self, self.interface.getRowName(i))
168             self.connect(ch, QtCore.SIGNAL("hide"), self.hideRow)
169             layout.addWidget(ch, i+1, 0)
170             self.rowHeaders.append( ch )
171
172         # Add node-widgets
173         for i in range(rows):
174             self.items.append([])
175             for j in range(cols):
176                 node = MixerNode(j, i, self.interface.getValue(i,j), self)
177                 self.connect(node, QtCore.SIGNAL("valueChanged"), self.valueChanged)
178                 layout.addWidget(node, i+1, j+1)
179                 self.items[i].append(node)
180
181         self.hiddenRows = []
182         self.hiddenCols = []
183
184
185     def checkVisibilities(self):
186         for x in range(len(self.items)):
187             for y in range(len(self.items[x])):
188                 self.items[x][y].setHidden(
189                         (x in self.hiddenRows)
190                         | (y in self.hiddenCols)
191                         )
192
193
194     def hideColumn(self, column, hide):
195         if hide:
196             self.hiddenCols.append(column)
197         else:
198             self.hiddenCols.remove(column)
199         self.checkVisibilities()
200     def hideRow(self, row, hide):
201         if hide:
202             self.hiddenRows.append(row)
203         else:
204             self.hiddenRows.remove(row)
205         self.checkVisibilities()
206
207     def valueChanged(self, n):
208         log.debug("MatrixNode.valueChanged( %s )" % str(n))
209         self.interface.setValue(n[1], n[0], n[2])
210
211
212 #
213 # vim: et ts=4 sw=4
Note: See TracBrowser for help on using the browser.