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 |
---|
| 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)) |
---|
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)) |
---|
| 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 | |
---|
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() |
---|
| 188 | self.items[x][y].setHidden( |
---|
| 189 | (x in self.hiddenRows) |
---|
| 190 | | (y in self.hiddenCols) |
---|
| 191 | ) |
---|
| 192 | |
---|