root/trunk/libffado/support/mixer/ffadomixer.in

Revision 1217, 17.1 kB (checked in by ppalmers, 16 years ago)

merge libffado-2.0 changes r1213:1216 to trunk (svn merge -r 1213:HEAD svn+ssh://ffadosvn@ffado.org/ffado/branches/libffado-2.0)

  • Property svn:executable set to *
Line 
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2005-2007 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
25 import sys
26
27 # Add the path of the installed ffado-mixer-modules
28 sys.path.append( "$PYTHONDIR" )
29
30 from ffadomixer_config import FFADO_VERSION
31
32 import os
33 import time
34 import dbus
35
36 from qt import *
37
38 from ffado_registration import *
39
40 from mixer_phase88 import *
41 from mixer_phase24 import *
42 from mixer_saffire import *
43 from mixer_saffirele import *
44 from mixer_saffirepro import *
45 from mixer_af2 import *
46 from mixer_bcoaudio5 import *
47 from mixer_edirolfa66 import *
48 from mixer_mackie_generic import *
49 from mixer_quatafire import *
50 from mixer_motu import *
51 from mixer_dummy import *
52 from mixer_global import *
53
54 use_generic = False
55 try:
56     from mixer_generic import *
57     print "The generic mixer is found, seems to be a developer using ffadomixer..."
58 except ImportError:
59     pass
60 else:
61     use_generic = True
62
63 SupportedDevices=[
64     [(0x000aac, 0x00000003),'Phase88Control'],
65     [(0x000aac, 0x00000004),'PhaseX24Control'],
66     [(0x000aac, 0x00000007),'PhaseX24Control'],
67     [(0x00130e, 0x00000003),'SaffireProMixer'],
68     [(0x00130e, 0x00000006),'SaffireProMixer'],
69     [(0x00130e, 0x00000000),'SaffireMixer'],
70     [(0x001486, 0x00000af2),'AudioFire2Mixer'],
71     [(0x0007f5, 0x00010049),'BCoAudio5Control'],
72     [(0x0040AB, 0x00010049),'EdirolFa66Control'],
73     [(0x00000f, 0x00010067),'MackieGenericControl'],
74     [(0x000f1b, 0x00010064),'QuataFireMixer'],
75     [(0x0001f2, 0x00000000),'MotuMixer'],
76     ]
77
78 class ControlInterface:
79     def __init__(self, servername, basepath):
80         self.basepath=basepath
81         self.servername=servername
82         self.bus=dbus.SessionBus()
83
84     def setContignuous(self, subpath, v, idx=None):
85         try:
86             path = self.basepath + subpath
87             dev = self.bus.get_object(self.servername, path)
88             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Continuous')
89             if idx == None:
90                 dev_cont.setValue(v)
91             else:
92                 dev_cont.setValueIdx(idx,v)
93         except:
94             print "Failed to set Continuous %s on server %s" % (path, self.servername)
95
96     def getContignuous(self, subpath, idx=None):
97         try:
98             path = self.basepath + subpath
99             dev = self.bus.get_object(self.servername, path)
100             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Continuous')
101             if idx == None:
102                 return dev_cont.getValue()
103             else:
104                 return dev_cont.getValueIdx(idx)
105         except:
106             print "Failed to get Continuous %s on server %s" % (path, self.servername)
107             return 0
108
109     def setDiscrete(self, subpath, v):
110         try:
111             path = self.basepath + subpath
112             dev = self.bus.get_object(self.servername, path)
113             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Discrete')
114             dev_cont.setValue(v)
115         except:
116             print "Failed to set Discrete %s on server %s" % (path, self.servername)
117
118     def getDiscrete(self, subpath):
119         try:
120             path = self.basepath + subpath
121             dev = self.bus.get_object(self.servername, path)
122             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Discrete')
123             return dev_cont.getValue()
124         except:
125             print "Failed to get Discrete %s on server %s" % (path, self.servername)
126             return 0
127
128     def setText(self, subpath, v):
129         try:
130             path = self.basepath + subpath
131             dev = self.bus.get_object(self.servername, path)
132             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Text')
133             dev_cont.setValue(v)
134         except:
135             print "Failed to set Text %s on server %s" % (path, self.servername)
136
137     def getText(self, subpath):
138         try:
139             path = self.basepath + subpath
140             dev = self.bus.get_object(self.servername, path)
141             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Text')
142             return dev_cont.getValue()
143         except:
144             print "Failed to get Text %s on server %s" % (path, self.servername)
145             return 0
146
147     def setMatrixMixerValue(self, subpath, row, col, v):
148         try:
149             path = self.basepath + subpath
150             dev = self.bus.get_object(self.servername, path)
151             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.MatrixMixer')
152             dev_cont.setValue(row, col, v)
153         except:
154             print "Failed to set MatrixMixer %s on server %s" % (path, self.servername)
155
156     def getMatrixMixerValue(self, subpath, row, col):
157         try:
158             path = self.basepath + subpath
159             dev = self.bus.get_object(self.servername, path)
160             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.MatrixMixer')
161             return dev_cont.getValue(row, col)
162         except:
163             print "Failed to get MatrixMixer %s on server %s" % (path, self.servername)
164             return 0
165
166     def enumSelect(self, subpath, v):
167         try:
168             path = self.basepath + subpath
169             dev = self.bus.get_object(self.servername, path)
170             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Enum')
171             dev_cont.select(v)
172         except:
173             print "Failed to select %s on server %s" % (path, self.servername)
174
175     def enumSelected(self, subpath):
176         try:
177             path = self.basepath + subpath
178             dev = self.bus.get_object(self.servername, path)
179             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Enum')
180             return dev_cont.selected()
181         except:
182             print "Failed to get selected enum %s on server %s" % (path, self.servername)
183             return 0
184
185     def enumGetLabel(self, subpath, v):
186         try:
187             path = self.basepath + subpath
188             dev = self.bus.get_object(self.servername, path)
189             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Enum')
190             return dev_cont.getEnumLabel(v)
191         except:
192             print "Failed to get enum label %s on server %s" % (path, self.servername)
193             return 0
194
195     def enumCount(self, subpath):
196         try:
197             path = self.basepath + subpath
198             dev = self.bus.get_object(self.servername, path)
199             dev_cont = dbus.Interface(dev, dbus_interface='org.ffado.Control.Element.Enum')
200             return dev_cont.count()
201         except:
202             print "Failed to get enum count %s on server %s" % (path, self.servername)
203             return 0
204
205 class DeviceManagerInterface:
206     def __init__(self, servername, basepath):
207         self.basepath=basepath + '/DeviceManager'
208         self.servername=servername
209         self.bus=dbus.SessionBus()
210         self.dev = self.bus.get_object(self.servername, self.basepath)
211         self.iface = dbus.Interface(self.dev, dbus_interface='org.ffado.Control.Element.Container')
212         # signal reception does not work yet since we need a mainloop for that
213         # and qt3 doesn't provide one for python/dbus
214         #try:
215             #self.dev.connect_to_signal("Updated", self.updateSignal, \
216                                        #dbus_interface="org.ffado.Control.Element.Container", arg0=self)
217         #except dbus.DBusException:
218             #traceback.print_exc()
219
220     #def updateSignal(self):
221         #print ("Received update signal")
222
223     def getNbDevices(self):
224         return self.iface.getNbElements()
225     def getDeviceName(self, idx):
226         return self.iface.getElementName(idx)
227
228
229 class ConfigRomInterface:
230     def __init__(self, servername, devicepath):
231         self.basepath=devicepath + '/ConfigRom'
232         self.servername=servername
233         self.bus=dbus.SessionBus()
234         self.dev = self.bus.get_object(self.servername, self.basepath)
235         self.iface = dbus.Interface(self.dev, dbus_interface='org.ffado.Control.Element.ConfigRomX')
236     def getGUID(self):
237         return self.iface.getGUID()
238     def getVendorName(self):
239         return self.iface.getVendorName()
240     def getModelName(self):
241         return self.iface.getModelName()
242     def getVendorId(self):
243         return self.iface.getVendorId()
244     def getModelId(self):
245         return self.iface.getModelId()
246     def getUnitVersion(self):
247         return self.iface.getUnitVersion()
248
249 class ClockSelectInterface:
250     def __init__(self, servername, devicepath):
251         self.basepath=devicepath + '/Generic/ClockSelect'
252         self.servername=servername
253         self.bus=dbus.SessionBus()
254         self.dev = self.bus.get_object(self.servername, self.basepath)
255         self.iface = dbus.Interface(self.dev, dbus_interface='org.ffado.Control.Element.AttributeEnum')
256     def count(self):
257         return self.iface.count()
258     def select(self, idx):
259         return self.iface.select(idx)
260     def selected(self):
261         return self.iface.selected()
262     def getEnumLabel(self, idx):
263         return self.iface.getEnumLabel(idx)
264     def attributeCount(self):
265         return self.iface.attributeCount()
266     def getAttributeValue(self, idx):
267         return self.iface.getAttributeValue(idx)
268     def getAttributeName(self, idx):
269         return self.iface.getAttributeName(idx)
270
271 class TextInterface:
272     def __init__(self, servername, basepath):
273         self.basepath=basepath
274         self.servername=servername
275         self.bus=dbus.SessionBus()
276         self.dev = self.bus.get_object( self.servername, self.basepath )
277         self.iface = dbus.Interface( self.dev, dbus_interface="org.ffado.Control.Element.Text" )
278
279     def text(self):
280         return self.iface.getValue()
281
282     def setText(self,text):
283         self.iface.setValue(text)
284
285 class HLine( QFrame ):
286     def __init__( self, parent ):
287         QFrame.__init__( self, parent )
288         self.setFrameShape( QFrame.HLine )
289         self.setLineWidth( 2 )
290         self.setMinimumHeight( 10 )
291
292 if __name__ == "__main__":
293
294     server='org.ffado.Control'
295     basepath='/org/ffado/Control'
296
297     app = QApplication(sys.argv)
298
299     msg = QMessageBox()
300
301     repeat = 1
302     while repeat > 0:
303         try:
304             devmgr=DeviceManagerInterface(server, basepath)
305             nbDevices=devmgr.getNbDevices()
306             repeat -= 1
307         except dbus.DBusException, ex:
308             print "\n"
309             print "==========================================================="
310             print "ERROR: Could not communicate with the FFADO DBus service..."
311             print "==========================================================="
312             print "\n"
313             tmp = msg.question( msg, "FFADO-DBus not found", "<qt><b>The connection to FFADOs DBus service could not be established.</b><p>Probably you didn't start the ffado-dbus-server. Should I try this now?</qt>", QMessageBox.Yes, QMessageBox.No )
314             if tmp == 4:
315                 sys.exit(-1)
316             else:
317                 os.spawnlp( os.P_NOWAIT, "ffado-dbus-server" )
318                 nb_checks = 20
319                 while nb_checks > 0:
320                     nb_checks = nb_checks - 1
321                     try:
322                         devmgr=DeviceManagerInterface(server, basepath)
323                         nbDevices=devmgr.getNbDevices()
324                         nb_checks = 0
325                         repeat = 0
326                     except dbus.DBusException, ex:
327                         time.sleep( 2 )
328
329     if nbDevices == 0:
330         print "No supported device found..."
331         msg.information( msg, "No mixer found", "No devices with mixer support discovered." )
332         sys.exit( -1 )
333
334     mw = QTabWidget()
335
336     for idx in range(nbDevices):
337         path=devmgr.getDeviceName(idx)
338         print "Found device %d: %s" % (idx, path)
339
340         cfgrom = ConfigRomInterface(server, basepath+'/DeviceManager/'+path)
341         vendorId = cfgrom.getVendorId()
342         modelId = cfgrom.getModelId()
343         unitVersion = cfgrom.getUnitVersion()
344         GUID = cfgrom.getGUID()
345         vendorName = cfgrom.getVendorName()
346         modelName = cfgrom.getModelName()
347         print " Found (%s, %X, %X) %s %s" % (str(GUID), vendorId, modelId, vendorName, modelName)
348
349         # check whether this has already been registered at ffado.org
350         reg = ffado_registration(FFADO_VERSION, int(GUID, 16),
351                                  vendorId, modelId,
352                                  vendorName, modelName)
353         reg.check_for_registration()
354
355         thisdev=(vendorId, modelId);
356         # The MOTU devices use unitVersion to differentiate models.  For the
357         # moment thought we don't need to know precisely which model we're
358         # using.
359         if vendorId == 0x1f2:
360             thisdev=(vendorId, 0x00000000)
361
362         dev = None
363         for d in SupportedDevices:
364             if d[0] == thisdev:
365                 dev = d
366
367         w = QWidget( mw )
368         l = QVBoxLayout( w )
369
370         # create a control object
371         hw = ControlInterface(server, basepath+'/DeviceManager/'+path)
372
373         #
374         # Generic elements for all mixers follow here:
375         #
376         tmp = GlobalMixer( w )
377         tmp.clockselect = ClockSelectInterface( server, basepath+"/DeviceManager/"+path )
378         tmp.nickname = TextInterface( server, basepath+"/DeviceManager/"+path+"/Generic/Nickname" )
379         tmp.hw = hw
380         tmp.initValues()
381         l.addWidget( tmp, 1 )
382
383         #
384         # Line to separate
385         #
386         l.addWidget( HLine( w ) )
387
388         #
389         # Specific (or dummy) mixer widgets get loaded in the following
390         #
391         if dev != None:
392             mixerapp = dev[1]
393             if vendorId == 0x00130e:
394                 is_saffirele = False
395                 is_saffirepro = False
396
397                 # hack for the focusrite devices
398                 # Saffire:        0x130e010001????
399                 # SaffireLE:    0x130e010004????
400                 if modelId == 0x00000000:
401                     if int(GUID, 16) >= 0x130e0100040000:
402                         is_saffirele = True
403                         print "Found SaffireLE GUID"
404                     else:
405                         is_saffirele = False
406                         print "Found Saffire GUID"
407
408                 # different panel for different clock frequency
409                 samplerate = hw.getDiscrete('/Generic/SamplerateSelect')
410
411                 # adat on PRO26 makes a difference
412                 have_adat = False
413                 if modelId == 0x00000003: # PRO26
414                     is_saffirepro = True
415                     state = hw.getDiscrete('/Control/ADATDisable')
416                     if state:
417                         have_adat = False
418                         print "detected PRO26, ADAT disabled"
419                     else:
420                         have_adat = True
421                         print "detected PRO26, ADAT enabled"
422                 elif modelId == 0x00000006: # PRO10
423                     is_saffirepro = True
424
425                 suffix = ''
426                 if samplerate <= 48000:
427                     suffix = "Large"
428                 # on the saffire pro 26, the large panel can be used
429                 # at 96k when adat is disabled. pro10 = pro26 w/o ADAT
430                 elif samplerate <= 96000 and is_saffirepro and have_adat:
431                     suffix = "Small"
432                 elif samplerate <= 96000 and is_saffirepro:
433                     suffix = "Large"
434                 # higher samplerates need the small panel
435                 else:
436                     suffix = "Small"
437
438                 if is_saffirepro:
439                     mixerapp = "SaffireProMixer" + suffix
440                 elif is_saffirele:
441                     mixerapp = "SaffireLEMixer" + suffix
442                 else:
443                     mixerapp = "SaffireMixer"
444
445             exec( "mixerwidget = "+mixerapp+"( w )" )
446
447         else:
448             mixerwidget = DummyMixer( w )
449             mixerapp = modelName+" (Dummy)"
450
451         #
452         # The same for all mixers
453         #
454         l.addWidget( mixerwidget, 10 )
455         mixerwidget.hw = hw
456         mixerwidget.configrom = cfgrom
457         mixerwidget.clockselect = ClockSelectInterface(server, basepath+'/DeviceManager/'+path)
458         mixerwidget.initValues()
459         mw.addTab( w, mixerapp )
460
461     #
462     # Show the generic (development) mixer if it is available
463     #
464     if nbDevices > 0 and use_generic:
465         mw.addTab( GenericMixer( devmgr.bus, server, mw ), "Generic Mixer" )
466
467     #
468     # Only really show the mainwindow and start the mixer when at least on mixer is shown
469     #
470     if mw.count() > 0:
471         mw.show()
472
473         QObject.connect(app,SIGNAL("lastWindowClosed()"),app,SLOT("quit()"))
474
475         app.exec_loop()
476
Note: See TracBrowser for help on using the browser.