root/trunk/libffado/support/mixer-qt4/ffado/widgets/crossbarrouter.py

Revision 2803, 9.8 kB (checked in by jwoithe, 3 years ago)

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

Line 
1 #
2 # Copyright (C) 2009 by Arnold Krille
3 #               2013 by Philippe Carriere
4 #
5 # This file is part of FFADO
6 # FFADO = Free FireWire (pro-)audio drivers for Linux
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 2 of the License, or
11 # (at your option) version 3 of the License.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21
22 # from PyQt4 import QtGui, QtCore
23 # from PyQt4.QtCore import pyqtSignal
24 # from PyQt4.QtGui import QFrame, QPainter, QGridLayout, QLabel, QComboBox
25 # from PyQt4.QtGui import QWidget, QVBoxLayout, QHBoxLayout, QPushButton
26 from ffado.import_pyqt import *
27
28 import dbus, math
29
30 import ffado.config
31
32 import logging
33 log = logging.getLogger("crossbarrouter")
34
35 class VuMeter(QFrame):
36     def __init__(self, interface, output, input=None, parent=None):
37         QFrame.__init__(self, parent)
38         self.setLineWidth(1)
39         self.setFrameStyle(QFrame.Panel|QFrame.Sunken)
40         self.setMinimumSize(20, 20)
41
42         self.level = 0
43
44         self.interface = interface
45
46         self.output = output
47
48     def updateLevel(self, value):
49         self.level = value
50         self.update()
51
52     def paintEvent(self, event):
53         p = QPainter(self)
54         value = self.level/4096
55         r = self.rect()
56         r.setHeight(r.height() * math.sqrt(value))
57         r.moveBottom(self.rect().height())
58         p.fillRect(r, self.palette().highlight())
59
60 class OutputSwitcher(QFrame):
61     """
62 The name is a bit misleading. This widget selectes sources for a specified
63 destination.
64
65 In mixer-usage this widget is at the top of the input-channel. Because the input
66 of the mixer is an available output from the routers point.
67 """
68     MixerRoutingChanged = pyqtSignal()
69     def __init__(self, interface, outname, parent):
70         QFrame.__init__(self, parent)
71         self.interface = interface
72         self.outname = outname
73         self.lastin = ""
74
75         self.setLineWidth(1)
76         self.setFrameStyle(QFrame.Sunken|QFrame.Panel)
77
78         self.layout = QGridLayout(self)
79         self.setLayout(self.layout)
80
81         self.lbl = QLabel(self.outname, self)
82         self.lbl.setToolTip("The name of the destination that is to be controlled here.")
83         self.layout.addWidget(self.lbl, 0, 0)
84
85         self.vu = VuMeter(self.interface, outname, parent=self)
86         self.layout.addWidget(self.vu, 0, 1)
87
88         sources = self.interface.getSourceNames()
89
90         self.combo = QComboBox(self)
91         self.combo.setToolTip("<qt>Select the source for this destination.<br>Each destination can only receive sound from one source at a time. But one source can send sound to multiple destinations.</qt>")
92         self.layout.addWidget(self.combo, 1, 0, 1, 2)
93         self.combo.addItem("Disconnected")
94         self.combo.addItems(sources)
95         src = self.interface.getSourceForDestination(self.outname)
96         self.lastin = str(src)
97         if src != "":
98             self.combo.setCurrentIndex(self.combo.findText(src))
99         else:
100             self.combo.setCurrentIndex(0)
101         self.combo.activated[str].connect(self.comboCurrentChanged)
102
103
104     def peakValue(self, value):
105         self.vu.updateLevel(value)
106         pass
107
108     def comboCurrentChanged(self, inname):
109         #log.debug("comboCurrentChanged( %s )" % inname)
110         if inname == self.lastin:
111             return
112         if self.lastin != "":
113             self.interface.setConnectionState(self.lastin, self.outname, False)
114
115         if inname != "Disconnected":
116             if self.interface.setConnectionState(str(inname), self.outname, True):
117                 if self.outname[:5] == "Mixer" or self.lastin[:5] == "Mixer" or str(inname)[:5] == "Mixer":
118                     self.MixerRoutingChanged.emit()
119                 self.lastin = str(inname)
120             else:
121                 log.warning(" Failed to connect %s to %s" % (inname, self.outname))
122         else:
123             self.lastin = ""
124
125
126 class CrossbarRouter(QWidget):
127     MixerRoutingChanged = pyqtSignal(name='MixerRoutingChanged')
128     def __init__(self, servername, basepath, parent=None):
129         QWidget.__init__(self, parent);
130         if not ffado.config.bypassdbus:
131             self.bus = dbus.SessionBus()
132             self.dev = self.bus.get_object(servername, basepath)
133             self.interface = dbus.Interface(self.dev, dbus_interface="org.ffado.Control.Element.CrossbarRouter")
134             self.destinations = self.interface.getDestinationNames()
135         else:
136             self.destinations = []
137
138         self.settings = QtCore.QSettings(self)
139
140         self.outgroups = []
141         for ch in self.destinations:
142             tmp = str(ch).split(":")[0]
143             if not tmp in self.outgroups:
144                 self.outgroups.append(tmp)
145
146         self.biglayout = QVBoxLayout(self)
147         self.setLayout(self.biglayout)
148
149         self.toplayout = QHBoxLayout()
150         self.biglayout.addLayout(self.toplayout)
151
152         self.vubtn = QPushButton("Switch peak meters", self)
153         self.vubtn.setCheckable(True)
154         self.vubtn.toggled.connect(self.runVu)
155         self.toplayout.addWidget(self.vubtn)
156
157         self.layout = QGridLayout()
158         self.biglayout.addLayout(self.layout)
159
160         self.switchers = {}
161         for out in self.destinations:
162             btn = OutputSwitcher(self.interface, out, self)
163             self.layout.addWidget(btn, int(out.split(":")[-1]) + 1, self.outgroups.index(out.split(":")[0]))
164             self.switchers[out] = btn
165             self.switchers[out].MixerRoutingChanged.connect(self.updateMixerRouting)
166
167         self.timer = QtCore.QTimer(self)
168         self.timer.setInterval(200)
169         self.timer.timeout.connect(self.updateLevels)
170
171         if ffado_pyqt_version == 4:
172             self.vubtn.setChecked(self.settings.value("crossbarrouter/runvu", False).toBool())
173         else:
174             self.vubtn.setChecked(self.settings.value("crossbarrouter/runvu", False) == u'true')
175
176     def __del__(self):
177         print( "CrossbarRouter.__del__()" )
178         self.settings.setValue("crossbarrouter/runvu", self.vubtn.isChecked())
179
180     def runVu(self, run=True):
181         #log.debug("CrossbarRouter.runVu( %i )" % run)
182         if run:
183             self.timer.start()
184         else:
185             self.timer.stop()
186             for sw in self.switchers:
187                 self.switchers[sw].peakValue(0)
188
189     def updateLevels(self):
190         #log.debug("CrossbarRouter.updateLevels()")
191         if ffado.config.bypassdbus:
192             return
193         peakvalues = self.interface.getPeakValues()
194         #log.debug("Got %i peaks" % len(peakvalues))
195         for peak in peakvalues:
196             #log.debug("peak = [%s,%s]" % (str(peak[0]),str(peak[1])))
197             if peak[1] >= 0:
198                 self.switchers[peak[0]].peakValue(peak[1])
199
200     def updateMixerRouting(self):
201         self.MixerRoutingChanged.emit()
202
203     def saveSettings(self, indent):
204         routerSaveString = []
205         routerSaveString.append('%s<dest_number>\n' % indent)
206         routerSaveString.append('%s  %d\n' % (indent, len(self.destinations)))
207         routerSaveString.append('%s</dest_number>\n' % indent)
208         routerSaveString.append('%s<srcperdest>\n' % indent)
209         routerSaveString.append('%s  2\n' % indent)
210         routerSaveString.append('%s</srcperdest>\n' % indent)
211         routerSaveString.append('%s<connections>\n' % indent)
212         for out in self.destinations:
213             routerSaveString.append('%s  ' % indent + out + ' ')
214             routerSaveString.append(self.interface.getSourceForDestination(out) + '\n')
215         routerSaveString.append('%s</connections>\n' % indent)
216         return routerSaveString       
217
218     def readSettings(self, routerReadString):
219         sources = str(self.interface.getSourceNames())
220         if routerReadString[0].find('<dest_number>') == -1:
221             log.debug("Number of router destinations must be specified\n")
222             return False
223         if routerReadString[2].find('</dest_number>') == -1:
224             log.debug("Incompatible xml file\n")
225             return False
226         n_dest = int(routerReadString[1])
227         if n_dest != len(self.destinations):
228             log.debug("Caution: numbers of destinations mismatch")
229         if routerReadString[3].find('<srcperdest>') == -1:
230             log.debug("Number of sources per destinations must be specified\n")
231             return False
232         if routerReadString[5].find('</srcperdest>') == -1:
233             log.debug("Incompatible xml file\n")
234             return False
235         n_spd = int(routerReadString[4])
236         if n_spd != 2:
237             log.debug("Unable to handle more than one source for each destination;")
238         try:
239             idxb = routerReadString.index('<connections>')
240             idxe = routerReadString.index('</connections>')
241         except Exception:
242             log.debug("Router connections not specified\n")
243             idxb = -1
244             idxe = -1
245             return False
246         if idxb >= 0:
247             if idxe > idxb + 1:
248                 for s in routerReadString[idxb+1:idxe]:
249                     destination = s.split()[0]
250                     if str(self.destinations).find(destination) != -1:
251                         source = s.split()[1]
252                         if sources.find(source) != -1:                       
253                             idx = self.switchers[destination].combo.findText(source)
254                             self.switchers[destination].combo.setCurrentIndex(idx)
255                             self.switchers[destination].comboCurrentChanged(source)
256         return True
257 #
258 # vim: sw=4 ts=4 et
Note: See TracBrowser for help on using the browser.