root/branches/libffado-2.0/support/mixer-qt4/ffado_panelmanager.py

Revision 1370, 11.4 kB (checked in by ppalmers, 15 years ago)

fix up saffire mixers (closes #147)

Line 
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2005-2008 by Pieter Palmers
4 #               2007-2008 by Arnold Krille
5 #
6 # This file is part of FFADO
7 # FFADO = Free Firewire (pro-)audio drivers for linux
8 #
9 # FFADO is based upon FreeBoB.
10 #
11 # This program is free software: you can redistribute it and/or modify
12 # it under the terms of the GNU General Public License as published by
13 # the Free Software Foundation, either version 3 of the License, or
14 # (at your option) any later version.
15 #
16 # This program is distributed in the hope that it will be useful,
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 # GNU General Public License for more details.
20 #
21 # You should have received a copy of the GNU General Public License
22 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 #
24 from ffadomixer_config import FFADO_VERSION, FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH
25
26 from PyQt4.QtGui import QFrame, QWidget, QTabWidget, QVBoxLayout
27 from PyQt4.QtCore import QTimer
28
29 from ffado_panelmanagerstatusui import Ui_PanelManagerStatusUI
30
31 from ffado_dbus_util import *
32 from ffado_registration import *
33
34 from mixer_phase88 import *
35 from mixer_phase24 import *
36 from mixer_saffire import SaffireMixer
37 from mixer_saffirepro import SaffireProMixer
38 from mixer_audiofire import AudioFireMixer
39 from mixer_bcoaudio5 import *
40 from mixer_edirolfa66 import *
41 from mixer_edirolfa101 import *
42 from mixer_mackie_onyxmixer import *
43 from mixer_quatafire import *
44 from mixer_motu import *
45 from mixer_dummy import *
46 from mixer_global import GlobalMixer
47
48 import logging
49 log = logging.getLogger('panelmanager')
50
51 use_generic = False
52 try:
53     from mixer_generic import *
54     log.info("The generic mixer is found, seems to be a developer using ffadomixer...")
55 except ImportError:
56     pass
57 else:
58     use_generic = True
59
60 SupportedDevices=[
61     [(0x000aac, 0x00000003),'Phase88Control'],
62     [(0x000aac, 0x00000004),'Phase24Control'],
63     [(0x000aac, 0x00000007),'Phase24Control'],
64     [(0x00130e, 0x00000003),'SaffireProMixer'],
65     [(0x00130e, 0x00000006),'SaffireProMixer'],
66     [(0x00130e, 0x00000000),'SaffireMixer'],
67     [(0x001486, 0x00000af2),'AudioFireMixer'],
68     [(0x001486, 0x00000af4),'AudioFireMixer'],
69     [(0x001486, 0x00000af8),'AudioFireMixer'],
70     [(0x001486, 0x0000af12),'AudioFireMixer'],
71     [(0x0007f5, 0x00010049),'BCoAudio5Control'],
72     [(0x0040AB, 0x00010049),'EdirolFa66Control'],
73     [(0x0040AB, 0x00010048),'EdirolFa101Control'],
74     [(0x00000f, 0x00010067),'MackieOnyxMixer'],
75     [(0x000f1b, 0x00010064),'QuataFireMixer'],
76     [(0x0001f2, 0x00000000),'MotuMixer'],
77     ]
78
79 # pseudo-guid
80 GUID_GENERIC_MIXER = 0
81
82
83 class HLine( QFrame ):
84     def __init__( self, parent ):
85         QFrame.__init__( self, parent )
86         self.setFrameShape( QFrame.HLine )
87         self.setLineWidth( 2 )
88         self.setMinimumHeight( 10 )
89
90 class PanelManagerStatus(QWidget, Ui_PanelManagerStatusUI):
91     def __init__(self, parent):
92         QWidget.__init__(self,parent)
93         self.setupUi(self)
94
95 class PanelManager(QWidget):
96     def __init__(self, parent, devmgr):
97         QWidget.__init__(self, parent)
98         self.devmgr = devmgr
99         self.devmgr.registerPreUpdateCallback(self.devlistPreUpdate)
100         self.devmgr.registerPostUpdateCallback(self.devlistPostUpdate)
101         self.devmgr.registerUpdateCallback(self.devlistUpdate)
102         self.devmgr.registerDestroyedCallback(self.devmgrDestroyed)
103
104         # maps a device GUID to a QT panel
105         self.panels = {}
106
107         # a layout for ourselves
108         self.layout = QVBoxLayout( self )
109
110         # the tabs
111         self.tabs = QTabWidget(self)
112         self.tabs.hide()
113         self.layout.addWidget(self.tabs)
114
115         # a dialog that is shown during update
116         self.status = PanelManagerStatus(self)
117         self.status.lblMessage.setText("Initializing...")
118         self.layout.addWidget(self.status)
119         self.status.show()
120
121         # live check timer
122         self.alivetimer = QTimer()
123         QObject.connect( self.alivetimer, SIGNAL('timeout()'), self.commCheck )
124         self.alivetimer.start( 2000 )
125
126     def count(self):
127         return self.tabs.count()
128
129     def pollPanels(self):
130         # only when not modifying the tabs
131         if self.tabs.isEnabled():
132             for guid in self.panels.keys():
133                 w = self.panels[guid]
134                 for child in w.children():
135                     #log.debug("poll child %s,%s" % (guid,child))
136                     if 'polledUpdate' in dir(child):
137                         try:
138                             child.polledUpdate()
139                         except:
140                             log.error("error in polled update")
141                             raise
142
143     def devlistPreUpdate(self):
144         log.debug("devlistPreUpdate")
145         self.tabs.setEnabled(False)
146         self.tabs.hide()
147         self.status.lblMessage.setText("Bus reconfiguration in progress, please wait...")
148         self.status.show()
149
150     def devlistPostUpdate(self):
151         log.debug("devlistPostUpdate")
152         self.updatePanels()
153
154     def devlistUpdate(self):
155         log.debug("devlistUpdate")
156
157     def devmgrDestroyed(self):
158         log.debug("devmgrDestroyed")
159         self.alivetimer.stop()
160         self.tabs.setEnabled(False)
161         self.tabs.hide()
162         self.status.lblMessage.setText("DBUS server was shut down, please restart it and restart ffadomixer...")
163         self.status.show()
164
165     def commCheck(self):
166         try:
167             nbDevices = self.devmgr.getNbDevices()
168         except:
169             log.debug("comms lost")
170             self.tabs.setEnabled(False)
171             self.tabs.hide()
172             self.status.lblMessage.setText("Failed to communicate with DBUS server. Please restart it and restart ffadomixer...")
173             self.status.show()
174             self.alivetimer.stop()
175
176     def updatePanels(self):
177         nbDevices = self.devmgr.getNbDevices()
178
179         # list of panels present
180         guids_with_tabs = self.panels.keys()
181
182         # build list of guids on the bus now
183         guids_present = []
184         guid_indexes = {}
185         for idx in range(nbDevices):
186             path = self.devmgr.getDeviceName(idx)
187             cfgrom = ConfigRomInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path)
188             guid = cfgrom.getGUID()
189             guids_present.append(guid)
190             guid_indexes[guid] = idx
191
192         # figure out what to remove
193         # the special panel (generic)
194         # that has (pseudo-)GUID 0
195         # is also automatically removed
196         to_remove = []
197         for guid in guids_with_tabs:
198             if not guid in guids_present:
199                 to_remove.append(guid)
200                 log.debug("going to remove %s" % str(guid))
201             else:
202                 log.debug("going to keep %s" % str(guid))
203
204         # figure out what to add
205         to_add = []
206         for guid in guids_present:
207             if not guid in guids_with_tabs:
208                 to_add.append(guid)
209                 log.debug("going to add %s" % str(guid))
210
211         # update the widget
212         for guid in to_remove:
213             w = self.panels[guid]
214             del self.panels[guid] # remove from the list
215             idx = self.tabs.indexOf(w)
216             self.tabs.removeTab(idx)
217             del w # GC might also take care of that
218
219         for guid in to_add:
220             # retrieve the device manager index
221             idx = guid_indexes[guid]
222             path = self.devmgr.getDeviceName(idx)
223             log.debug("Adding device %d: %s" % (idx, path))
224
225             cfgrom = ConfigRomInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path)
226             vendorId = cfgrom.getVendorId()
227             modelId = cfgrom.getModelId()
228             unitVersion = cfgrom.getUnitVersion()
229             guid = cfgrom.getGUID()
230             vendorName = cfgrom.getVendorName()
231             modelName = cfgrom.getModelName()
232             log.debug(" Found (%s, %X, %X) %s %s" % (str(guid), vendorId, modelId, vendorName, modelName))
233
234             # check whether this has already been registered at ffado.org
235             reg = ffado_registration(FFADO_VERSION, int(guid, 16),
236                                      vendorId, modelId,
237                                      vendorName, modelName)
238             reg.check_for_registration()
239
240             thisdev = (vendorId, modelId);
241             # The MOTU devices use unitVersion to differentiate models.  For the
242             # moment thought we don't need to know precisely which model we're
243             # using.
244             if vendorId == 0x1f2:
245                 thisdev = (vendorId, 0x00000000)
246
247             dev = None
248             for d in SupportedDevices:
249                 if d[0] == thisdev:
250                     dev = d
251
252             w = QWidget( self.tabs )
253             l = QVBoxLayout( w )
254
255             # create a control object
256             hw = ControlInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path)
257             clockselect = ClockSelectInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path )
258             samplerateselect = SamplerateSelectInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path )
259             nickname = TextInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path+"/Generic/Nickname" )
260
261             #
262             # Generic elements for all mixers follow here:
263             #
264             tmp = GlobalMixer( w )
265             tmp.configrom = cfgrom
266             tmp.clockselect = clockselect
267             tmp.samplerateselect = samplerateselect
268             tmp.nickname = nickname
269             tmp.hw = hw
270             tmp.initValues()
271             l.addWidget( tmp, 1 )
272
273             #
274             # Line to separate
275             #
276             l.addWidget( HLine( w ) )
277
278             #
279             # Specific (or dummy) mixer widgets get loaded in the following
280             #
281             if dev != None:
282                 mixerapp = dev[1]
283                 exec( "mixerwidget = "+mixerapp+"( w )" )
284             else:
285                 mixerwidget = DummyMixer( w )
286                 mixerapp = modelName+" (Dummy)"
287
288             #
289             # The same for all mixers
290             #
291             l.addWidget( mixerwidget, 10 )
292             mixerwidget.configrom = cfgrom
293             mixerwidget.clockselect = clockselect
294             mixerwidget.samplerateselect = samplerateselect
295             mixerwidget.nickname = nickname
296             mixerwidget.hw = hw
297             if 'buildMixer' in dir(mixerwidget):
298                 mixerwidget.buildMixer()
299             if 'initValues' in dir(mixerwidget):
300                 mixerwidget.initValues()
301             if 'getDisplayTitle' in dir(mixerwidget):
302                 title = mixerwidget.getDisplayTitle()
303             else:
304                 title = mixerapp
305
306             self.tabs.addTab( w, title )
307             self.panels[guid] = w
308
309         # if there is no panel, add the no-device message
310         # else make sure it is not present
311         if self.count() == 0:
312             self.tabs.hide()
313             self.tabs.setEnabled(False)
314             self.status.lblMessage.setText("No supported device found.")
315             self.status.show()
316         else:
317             self.tabs.show()
318             self.tabs.setEnabled(True)
319             self.status.hide()
320             if use_generic:
321                 #
322                 # Show the generic (development) mixer if it is available
323                 #
324                 w = GenericMixer( devmgr.bus, FFADO_DBUS_SERVER, mw )
325                 self.tabs.addTab( w, "Generic Mixer" )
326                 self.panels[GUID_GENERIC_MIXER] = w
Note: See TracBrowser for help on using the browser.