root/trunk/libffado/support/mixer-qt4/ffado_panelmanager.py

Revision 1298, 11.0 kB (checked in by ppalmers, 16 years ago)

add Qt4 port of the mixer (only for audiofire and saffire ATM). needed since PyQt?3 doesn't support DBUS signals.

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_mackie_generic import *
42 #from mixer_quatafire import *
43 #from mixer_motu import *
44 from mixer_dummy import *
45 from mixer_global import GlobalMixer
46
47 use_generic = False
48 try:
49     from mixer_generic import *
50     print "The generic mixer is found, seems to be a developer using ffadomixer..."
51 except ImportError:
52     pass
53 else:
54     use_generic = True
55
56 SupportedDevices=[
57     #[(0x000aac, 0x00000003),'Phase88Control'],
58     #[(0x000aac, 0x00000004),'Phase24Control'],
59     #[(0x000aac, 0x00000007),'Phase24Control'],
60     [(0x00130e, 0x00000003),'SaffireProMixer'],
61     [(0x00130e, 0x00000006),'SaffireProMixer'],
62     [(0x00130e, 0x00000000),'SaffireMixer'],
63     [(0x001486, 0x00000af2),'AudioFireMixer'],
64     [(0x001486, 0x00000af4),'AudioFireMixer'],
65     [(0x001486, 0x00000af8),'AudioFireMixer'],
66     [(0x001486, 0x0000af12),'AudioFireMixer'],
67     #[(0x0007f5, 0x00010049),'BCoAudio5Control'],
68     #[(0x0040AB, 0x00010049),'EdirolFa66Control'],
69     #[(0x00000f, 0x00010067),'MackieGenericControl'],
70     #[(0x000f1b, 0x00010064),'QuataFireMixer'],
71     #[(0x0001f2, 0x00000000),'MotuMixer'],
72     ]
73
74 # pseudo-guid
75 GUID_GENERIC_MIXER = 0
76
77
78 class HLine( QFrame ):
79     def __init__( self, parent ):
80         QFrame.__init__( self, parent )
81         self.setFrameShape( QFrame.HLine )
82         self.setLineWidth( 2 )
83         self.setMinimumHeight( 10 )
84
85 class PanelManagerStatus(QWidget, Ui_PanelManagerStatusUI):
86     def __init__(self, parent):
87         QWidget.__init__(self,parent)
88         self.setupUi(self)
89
90 class PanelManager(QWidget):
91     def __init__(self, parent, devmgr):
92         QWidget.__init__(self, parent)
93         self.devmgr = devmgr
94         self.devmgr.registerPreUpdateCallback(self.devlistPreUpdate)
95         self.devmgr.registerPostUpdateCallback(self.devlistPostUpdate)
96         self.devmgr.registerUpdateCallback(self.devlistUpdate)
97         self.devmgr.registerDestroyedCallback(self.devmgrDestroyed)
98
99         # maps a device GUID to a QT panel
100         self.panels = {}
101
102         # a layout for ourselves
103         self.layout = QVBoxLayout( self )
104
105         # the tabs
106         self.tabs = QTabWidget(self)
107         self.tabs.hide()
108         self.layout.addWidget(self.tabs)
109
110         # a dialog that is shown during update
111         self.status = PanelManagerStatus(self)
112         self.status.lblMessage.setText("Initializing...")
113         self.layout.addWidget(self.status)
114         self.status.show()
115
116         # live check timer
117         self.alivetimer = QTimer()
118         QObject.connect( self.alivetimer, SIGNAL('timeout()'), self.commCheck )
119         self.alivetimer.start( 2000 )
120
121     def count(self):
122         return self.tabs.count()
123
124     def pollPanels(self):
125         # only when not modifying the tabs
126         if self.tabs.isEnabled():
127             for guid in self.panels.keys():
128                 w = self.panels[guid]
129                 if 'polledUpdate' in dir(w):
130                     try:
131                         w.polledUpdate()
132                     except:
133                         print "error in polled update"
134
135     def devlistPreUpdate(self):
136         print "devlistPreUpdate"
137         self.tabs.setEnabled(False)
138         self.tabs.hide()
139         self.status.lblMessage.setText("Bus reconfiguration in progress, please wait...")
140         self.status.show()
141
142     def devlistPostUpdate(self):
143         print "devlistPostUpdate"
144         self.updatePanels()
145
146     def devlistUpdate(self):
147         print "devlistUpdate"
148
149     def devmgrDestroyed(self):
150         print "devmgrDestroyed"
151         self.alivetimer.stop()
152         self.tabs.setEnabled(False)
153         self.tabs.hide()
154         self.status.lblMessage.setText("DBUS server was shut down, please restart it and restart ffadomixer...")
155         self.status.show()
156
157     def commCheck(self):
158         try:
159             nbDevices = self.devmgr.getNbDevices()
160         except:
161             print "comms lost"
162             self.tabs.setEnabled(False)
163             self.tabs.hide()
164             self.status.lblMessage.setText("Failed to communicate with DBUS server. Please restart it and restart ffadomixer...")
165             self.status.show()
166             self.alivetimer.stop()
167
168     def updatePanels(self):
169         nbDevices = self.devmgr.getNbDevices()
170
171         # list of panels present
172         guids_with_tabs = self.panels.keys()
173
174         # build list of guids on the bus now
175         guids_present = []
176         guid_indexes = {}
177         for idx in range(nbDevices):
178             path = self.devmgr.getDeviceName(idx)
179             cfgrom = ConfigRomInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path)
180             guid = cfgrom.getGUID()
181             guids_present.append(guid)
182             guid_indexes[guid] = idx
183
184         # figure out what to remove
185         # the special panel (generic)
186         # that has (pseudo-)GUID 0
187         # is also automatically removed
188         to_remove = []
189         for guid in guids_with_tabs:
190             if not guid in guids_present:
191                 to_remove.append(guid)
192                 print "going to remove %s" % str(guid)
193             else:
194                 print "going to keep %s" % str(guid)
195
196         # figure out what to add
197         to_add = []
198         for guid in guids_present:
199             if not guid in guids_with_tabs:
200                 to_add.append(guid)
201                 print "going to add %s" % str(guid)
202
203         # update the widget
204         for guid in to_remove:
205             w = self.panels[guid]
206             del self.panels[guid] # remove from the list
207             idx = self.tabs.indexOf(w)
208             self.tabs.removeTab(idx)
209             del w # GC might also take care of that
210
211         for guid in to_add:
212             # retrieve the device manager index
213             idx = guid_indexes[guid]
214             path = self.devmgr.getDeviceName(idx)
215             print "Adding device %d: %s" % (idx, path)
216
217             cfgrom = ConfigRomInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path)
218             vendorId = cfgrom.getVendorId()
219             modelId = cfgrom.getModelId()
220             unitVersion = cfgrom.getUnitVersion()
221             guid = cfgrom.getGUID()
222             vendorName = cfgrom.getVendorName()
223             modelName = cfgrom.getModelName()
224             print " Found (%s, %X, %X) %s %s" % (str(guid), vendorId, modelId, vendorName, modelName)
225
226             # check whether this has already been registered at ffado.org
227             reg = ffado_registration(FFADO_VERSION, int(guid, 16),
228                                      vendorId, modelId,
229                                      vendorName, modelName)
230             reg.check_for_registration()
231
232             thisdev = (vendorId, modelId);
233             # The MOTU devices use unitVersion to differentiate models.  For the
234             # moment thought we don't need to know precisely which model we're
235             # using.
236             if vendorId == 0x1f2:
237                 thisdev = (vendorId, 0x00000000)
238
239             dev = None
240             for d in SupportedDevices:
241                 if d[0] == thisdev:
242                     dev = d
243
244             w = QWidget( self.tabs )
245             l = QVBoxLayout( w )
246
247             # create a control object
248             hw = ControlInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path)
249             clockselect = ClockSelectInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path )
250             samplerateselect = SamplerateSelectInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path )
251             nickname = TextInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path+"/Generic/Nickname" )
252
253             #
254             # Generic elements for all mixers follow here:
255             #
256             tmp = GlobalMixer( w )
257             tmp.configrom = cfgrom
258             tmp.clockselect = clockselect
259             tmp.samplerateselect = samplerateselect
260             tmp.nickname = nickname
261             tmp.hw = hw
262             tmp.initValues()
263             l.addWidget( tmp, 1 )
264
265             #
266             # Line to separate
267             #
268             l.addWidget( HLine( w ) )
269
270             #
271             # Specific (or dummy) mixer widgets get loaded in the following
272             #
273             if dev != None:
274                 mixerapp = dev[1]
275                 exec( "mixerwidget = "+mixerapp+"( w )" )
276             else:
277                 mixerwidget = DummyMixer( w )
278                 mixerapp = modelName+" (Dummy)"
279
280             #
281             # The same for all mixers
282             #
283             l.addWidget( mixerwidget, 10 )
284             mixerwidget.configrom = cfgrom
285             mixerwidget.clockselect = clockselect
286             mixerwidget.samplerateselect = samplerateselect
287             mixerwidget.nickname = nickname
288             mixerwidget.hw = hw
289             if 'buildMixer' in dir(mixerwidget):
290                 mixerwidget.buildMixer()
291             if 'initValues' in dir(mixerwidget):
292                 mixerwidget.initValues()
293             if 'getDisplayTitle' in dir(mixerwidget):
294                 title = mixerwidget.getDisplayTitle()
295             else:
296                 title = mixerapp
297
298             self.tabs.addTab( w, title )
299             self.panels[guid] = w
300
301         # if there is no panel, add the no-device message
302         # else make sure it is not present
303         if self.count() == 0:
304             self.tabs.hide()
305             self.tabs.setEnabled(False)
306             self.status.lblMessage.setText("No supported device found.")
307             self.status.show()
308         else:
309             self.tabs.show()
310             self.tabs.setEnabled(True)
311             self.status.hide()
312             if use_generic:
313                 #
314                 # Show the generic (development) mixer if it is available
315                 #
316                 w = GenericMixer( devmgr.bus, FFADO_DBUS_SERVER, mw )
317                 self.tabs.addTab( w, "Generic Mixer" )
318                 self.panels[GUID_GENERIC_MIXER] = w
Note: See TracBrowser for help on using the browser.