root/trunk/libffado/support/mixer-qt4/ffado/mixer/saffire_dice.py

Revision 1794, 11.2 kB (checked in by arnonym, 11 years ago)

This might (or might not) fix #256 by actually implementing EAP-support for the Pro40.

Please someone test this and report back.

Everything should work except:

  • The volume knob doesn't seem to have an effect on the Pro24, don't know about the Pro40. It writes to the right registers but somehow the hardware doesn't recognise it.
  • The "Use ADAT-Out as S/PDIF" and "Pad Output" are not implemented yet.
  • I don't know whether changing to nickname works with the Pro40. It doesn't with the Pro24 altough the correct registers are written to. Probably sending an OP-code is missing...
  • 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 from ffado.widgets.matrixmixer import MatrixMixer
25 from ffado.widgets.crossbarrouter import *
26
27 from ffado.config import *
28
29 class BooleanControl:
30     def __init__(self, hw, path):
31         self.iface = dbus.Interface(
32                 hw.bus.get_object(hw.servername, path),
33                 dbus_interface="org.ffado.Control.Element.Boolean")
34         self.value = self.iface.selected()
35
36     def selected(self):
37         return self.value
38
39     def select(self, n):
40         if self.iface.select(n):
41             self.value = n
42             return True
43         return False
44
45 class DiscreteControl:
46     def __init__(self, hw, path):
47         self.iface = dbus.Interface(
48                 hw.bus.get_object(hw.servername, path),
49                 dbus_interface="org.ffado.Control.Element.Discrete")
50         self.value = self.iface.getValue()
51
52     def getvalue(self):
53         return self.value
54
55     def setvalue(self, v):
56         if v != self.value:
57             self.iface.setValue(v)
58             self.value = v
59
60 class MonitoringModel(QtCore.QAbstractTableModel):
61     def __init__(self, hw, parent):
62         QtCore.QAbstractTableModel.__init__(self, parent)
63
64         self.hw = hw
65
66         self.mutestates = ("Global", "True", "False")
67
68         self.globaldims = []
69         self.globalmutes = []
70         self.perchannelmutes = []
71         self.globalvolumes = []
72         self.perchannelvolumes = []
73         for i in range(10):
74             self.globaldims.append(BooleanControl(self.hw, self.hw.basepath + ("/EAP/Monitoring/GlobalDim/AffectsCh%i" % i)))
75             self.globalmutes.append(BooleanControl(self.hw, self.hw.basepath + ("/EAP/Monitoring/GlobalMute/AffectsCh%i" % i)))
76             self.perchannelmutes.append(BooleanControl(self.hw, self.hw.basepath + ("/EAP/Monitoring/PerChannel/Mute%i" % i)))
77             self.globalvolumes.append(BooleanControl(self.hw, self.hw.basepath + ("/EAP/Monitoring/GlobalVolume/AffectsCh%i" % i)))
78             self.perchannelvolumes.append(DiscreteControl(self.hw, self.hw.basepath + ("/EAP/Monitoring/PerChannel/Volume%i" % i)))
79
80     def rowCount(self, parent):
81         return 3
82
83     def columnCount(self, parent):
84         return 10
85
86     def headerData(self, section, orientation, role=Qt.Qt.DisplayRole):
87         if role != Qt.Qt.DisplayRole:
88             #print "headerData will return nothing"
89             return None
90         #print "headerData() Will return a label"
91         if orientation == Qt.Qt.Horizontal:
92             return "Ch. %i" % section
93         if orientation == Qt.Qt.Vertical:
94             return ("Mute", "Dim", "Volume")[section]
95         return None
96
97     def data(self, index, role):
98         if not role in (Qt.Qt.DisplayRole, Qt.Qt.EditRole):
99             return None
100         row = index.row()
101         col = index.column()
102         if role == Qt.Qt.DisplayRole:
103             if row is 0:
104                 if self.perchannelmutes[col].selected():
105                     return self.mutestates[1]
106                 else:
107                     if self.globalmutes[col].selected():
108                         return self.mutestates[0]
109                 return self.mutestates[2]
110             if row is 1:
111                 if self.globaldims[col].selected():
112                     return "Enabled"
113                 else:
114                     return "Disabled"
115             if row is 2:
116                 if self.globalvolumes[col].selected():
117                     return "Global"
118                 else:
119                     return self.perchannelvolumes[col].getvalue()
120         if role == Qt.Qt.EditRole:
121             if row is 0:
122                 return QtCore.QStringList(self.mutestates)
123             if row is 1:
124                 return QtCore.QStringList(("Enabled","Disabled"))
125             if row is 2:
126                 if self.globalvolumes[col].selected():
127                     return 1
128                 return self.perchannelvolumes[col].getvalue()
129         return "%i,%i" % (row,col)
130
131     def setData(self, index, value, role=Qt.Qt.EditRole):
132         col = index.column()
133         row = index.row()
134         if row == 0:
135             if value == "Global":
136                 self.globalmutes[col].select(True)
137                 self.perchannelmutes[col].select(False)
138             else:
139                 self.globalmutes[col].select(False)
140                 if value == "True": value = True
141                 if value == "False": value = False
142                 self.perchannelmutes[col].select(value)
143             return True
144         if row == 1:
145             if value == "Enabled": value = True
146             if value == "Disabled": value = False
147             return self.globaldims[col].select(value)
148         if row == 2:
149             #print "setData() value=%s" % value.toString()
150             v = int(value.toString())
151             #print " integer is %i" % v
152             if v > 0:
153                 return self.globalvolumes[col].select(True)
154             else:
155                 self.globalvolumes[col].select(False)
156                 self.perchannelvolumes[col].setvalue(v)
157         return False
158
159     def flags(self, index):
160         ret = QtCore.QAbstractTableModel.flags(self, index)
161         if index.row() in (0,1,2):
162             ret |= Qt.Qt.ItemIsEditable
163         return ret
164
165
166
167 class MonitoringDelegate(QtGui.QStyledItemDelegate):
168     def __init__(self, parent):
169         QtGui.QStyledItemDelegate.__init__(self, parent)
170
171     def createEditor(self, parent, option, index):
172         if index.data(Qt.Qt.EditRole).type() == QtCore.QVariant.StringList:
173             combo = QtGui.QComboBox(parent)
174             self.connect(combo, QtCore.SIGNAL("activated(int)"), self.currentChanged)
175             return combo
176         else:
177             return QtGui.QStyledItemDelegate.createEditor(self, parent, option, index)
178
179     def setEditorData(self, editor, index):
180         if isinstance(editor, QtGui.QComboBox):
181             list = index.data(Qt.Qt.EditRole).toStringList()
182             editor.addItems(list)
183             editor.setCurrentIndex(list.indexOf(index.data(Qt.Qt.DisplayRole).toString()))
184         else:
185             QtGui.QStyledItemDelegate.setEditorData(self, editor, index)
186
187     def setModelData(self, editor, model, index):
188         if isinstance(editor, QtGui.QComboBox):
189             model.setData(index, editor.currentText(), Qt.Qt.EditRole)
190         else:
191             QtGui.QStyledItemDelegate.setModelData(self, editor, model, index)
192
193     def currentChanged(self):
194         #print "currentChanged() sender=%s" % (str(self.sender()))
195         editor = self.sender()
196         self.emit(QtCore.SIGNAL("commitData(QWidget*)"), editor)
197         self.emit(QtCore.SIGNAL("closeEditor(QWidget*)"), editor)
198
199 class Saffire_Dice(QtGui.QWidget):
200     def __init__(self, parent=None):
201         QtGui.QWidget.__init__(self, parent)
202         self.layout = QtGui.QGridLayout(self)
203         self.setLayout(self.layout)
204         self.tabs = QtGui.QTabWidget(self)
205         self.layout.addWidget(self.tabs)
206
207     def buildMixer(self):
208         #print self.hw
209         #print self.hw.getText("/Generic/Nickname")
210         self.matrix = MatrixMixer(self.hw.servername, self.hw.basepath+"/EAP/MatrixMixer", self)
211         scrollarea = QtGui.QScrollArea(self.tabs)
212         scrollarea.setWidgetResizable(True)
213         scrollarea.setWidget(self.matrix)
214         self.tabs.addTab(scrollarea, "Matrix")
215
216         self.router = CrossbarRouter(self.hw.servername, self.hw.basepath+"/EAP/Router", self)
217         scrollarea = QtGui.QScrollArea(self.tabs)
218         scrollarea.setWidgetResizable(True)
219         scrollarea.setWidget(self.router)
220         self.tabs.addTab(scrollarea, "Routing")
221
222         model = MonitoringModel(self.hw, self)
223
224         widget = QtGui.QWidget()
225         uicLoad("ffado/mixer/saffire_dice_monitoring.ui", widget)
226         widget.monitoringView.setModel(model)
227         widget.monitoringView.setItemDelegate(MonitoringDelegate(self))
228         self.tabs.addTab(widget, "Monitoring")
229
230         self.muteInterface = BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalMute/State")
231         widget.btnMute.setChecked(self.muteInterface.selected())
232         self.connect(widget.btnMute, QtCore.SIGNAL("toggled(bool)"), self.muteToggle)
233         self.dimInterface = BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalDim/State")
234         widget.btnDim.setChecked(self.dimInterface.selected())
235         self.connect(widget.btnDim, QtCore.SIGNAL("toggled(bool)"), self.dimToggle)
236
237         self.dimLevelInterface = DiscreteControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalDim/Level")
238         widget.dimLevel.setValue(self.dimLevelInterface.getvalue())
239         self.connect(widget.dimLevel, QtCore.SIGNAL("valueChanged(int)"), self.dimLevelChanged)
240         self.volumeInterface = DiscreteControl(self.hw, self.hw.basepath+"/EAP/Monitoring/GlobalVolume/Level")
241         widget.volumeKnob.setValue(self.volumeInterface.getvalue())
242         self.connect(widget.volumeKnob, QtCore.SIGNAL("valueChanged(int)"), self.volumeChanged)
243
244         if self.configrom.getModelName() == "SAFFIRE_PRO_24":
245             self.ch1inst = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch1LineInst")
246             widget.chkInst1.setChecked(self.ch1inst.selected())
247             self.connect(widget.chkInst1, QtCore.SIGNAL("toggled(bool)"), self.ch1inst.select)
248             self.ch2inst = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch2LineInst")
249             widget.chkInst2.setChecked(self.ch2inst.selected())
250             self.connect(widget.chkInst2, QtCore.SIGNAL("toggled(bool)"), self.ch2inst.select)
251             self.ch3level = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch3Level")
252             widget.chkLevel3.setChecked(self.ch3level.selected())
253             self.connect(widget.chkLevel3, QtCore.SIGNAL("toggled(bool)"), self.ch3level.select)
254             self.ch4level = BooleanControl(self.hw, self.hw.basepath + "/EAP/Ch4Level")
255             widget.chkLevel4.setChecked(self.ch4level.selected())
256             self.connect(widget.chkLevel4, QtCore.SIGNAL("toggled(bool)"), self.ch4level.select)
257             widget.chkSpdif.deleteLater()
258             widget.btnPad.deleteLater()
259         else:
260             widget.chkInst1.deleteLater()
261             widget.chkInst2.deleteLater()
262             widget.chkLevel3.deleteLater()
263             widget.chkLevel4.deleteLater()
264
265
266     def muteToggle(self, mute):
267         self.muteInterface.select(mute)
268     def dimToggle(self, mute):
269         self.dimInterface.select(mute)
270
271     def dimLevelChanged(self, value):
272         self.dimLevelInterface.setvalue(value)
273     def volumeChanged(self, value):
274         self.volumeInterface.setvalue(value)
275
276     def getDisplayTitle(self):
277         return "Saffire PRO40/PRO24 Mixer"
278
279 #
280 # vim: et ts=4 sw=4
Note: See TracBrowser for help on using the browser.