From 0f8bb5aacb59df0b1be8e1b5335c27d4a86b0256 Mon Sep 17 00:00:00 2001 From: mocchi Date: Thu, 6 Mar 2014 10:25:08 +0000 Subject: [PATCH] bebob: improve support for PreSonus Inspire1394 This device uses AV/C Vendor Dependent commands for its mic-preamp. This commit add 'Inspire1394Device', 'Inspire1394Cmd' and 'BinaryControl' class in 'BeBoB::PreSonus' namespace and improve current python script fir ffado-mixer. git-svn-id: svn+ssh://ffado.org/ffado/trunk@2487 2be59082-3212-0410-8809-b0798e1608f0 --- libffado/src/SConscript | 1 + libffado/src/bebob/bebob_avdevice.cpp | 3 + .../src/bebob/presonus/inspire1394_avdevice.cpp | 76 ++++---- libffado/src/bebob/presonus/inspire1394_avdevice.h | 78 ++++---- .../mixer-qt4/ffado/mixer/presonus_inspire1394.py | 201 +++++++++++++++++---- 5 files changed, 257 insertions(+), 102 deletions(-) diff --git a/libffado/src/SConscript b/libffado/src/SConscript index 573f6fff..0b944313 100644 --- a/libffado/src/SConscript +++ b/libffado/src/SConscript @@ -99,6 +99,7 @@ bebob_source = env.Split( '\ bebob/yamaha/yamaha_avdevice.cpp \ bebob/maudio/maudio_normal_avdevice.cpp \ bebob/presonus/firebox_avdevice.cpp \ + bebob/presonus/inspire1394_avdevice.cpp \ ' ) bebob_pkgdata = env.Split( '\ diff --git a/libffado/src/bebob/bebob_avdevice.cpp b/libffado/src/bebob/bebob_avdevice.cpp index b6140ab7..42a6e9ce 100644 --- a/libffado/src/bebob/bebob_avdevice.cpp +++ b/libffado/src/bebob/bebob_avdevice.cpp @@ -38,6 +38,7 @@ #include "bebob/yamaha/yamaha_avdevice.h" #include "bebob/maudio/maudio_normal_avdevice.h" #include "bebob/presonus/firebox_avdevice.h" +#include "bebob/presonus/inspire1394_avdevice.h" #include "libieee1394/configrom.h" #include "libieee1394/ieee1394service.h" @@ -186,6 +187,8 @@ Device::createDevice(DeviceManager& d, std::auto_ptr( configRom )) switch (modelId) { case 0x00010000: return new Presonus::FireboxDevice(d, configRom); + case 0x00010001: + return new Presonus::Inspire1394Device(d, configRom); default: return new Device(d, configRom); } diff --git a/libffado/src/bebob/presonus/inspire1394_avdevice.cpp b/libffado/src/bebob/presonus/inspire1394_avdevice.cpp index cd7596c7..e2f50f7a 100644 --- a/libffado/src/bebob/presonus/inspire1394_avdevice.cpp +++ b/libffado/src/bebob/presonus/inspire1394_avdevice.cpp @@ -25,30 +25,32 @@ #include "./inspire1394_avdevice.h" #include "libutil/ByteSwap.h" -#include +#include "libutil/cmd_serialize.h" namespace BeBoB { namespace Presonus { -Inspire1394VendorDependentCmd::Inspire1394VendorDependentCmd(Ieee1394Service& ieee1394service) +Inspire1394Cmd::Inspire1394Cmd(Ieee1394Service& ieee1394service) : VendorDependentCmd( ieee1394service ) , m_subfunc( 0x00 ) , m_idx( 0x00 ) , m_arg( 0x00 ) { m_companyId = 0x000a92; + setSubunitType( AVC::eST_Audio ); + setSubunitId( 0x00 ); } -bool Inspire1394VendorDependentCmd::serialize( Util::Cmd::IOSSerialize& se ) +bool Inspire1394Cmd::serialize( Util::Cmd::IOSSerialize& se ) { bool result = true; result &= VendorDependentCmd::serialize( se ); - result &= se.write(m_subfunc, "Inspire1394VendorDependentCmd subfunc"); - result &= se.write(m_idx, "Inspire1394VendorDependentCmd idx"); - result &= se.write(m_arg, "Inspire1394VendorDependentCmd arg"); + result &= se.write(m_subfunc, "Inspire1394Cmd subfunc"); + result &= se.write(m_idx, "Inspire1394Cmd idx"); + result &= se.write(m_arg, "Inspire1394Cmd arg"); return result; } -bool Inspire1394VendorDependentCmd::deserialize( Util::Cmd::IOSDeserialize& de ) +bool Inspire1394Cmd::deserialize( Util::Cmd::IISDeserialize& de ) { bool result = true; result &= VendorDependentCmd::deserialize( de ); @@ -60,7 +62,7 @@ bool Inspire1394VendorDependentCmd::deserialize( Util::Cmd::IOSDeserialize& de ) } BinaryControl::BinaryControl(Inspire1394Device& parent, - EInspire1394SubFunc subfunc, + EInspire1394CmdSubfunc subfunc, std::string name, std::string label, std::string desc) : Control::Discrete(&parent) , m_Parent(parent) @@ -72,7 +74,7 @@ BinaryControl::BinaryControl(Inspire1394Device& parent, } bool BinaryControl::setValue(int idx, int v) { - uint32_t val = v; + uint8_t val = v; debugOutput(DEBUG_LEVEL_VERBOSE, "setValue for type: %d, idx: %d, val: %d\n", @@ -87,7 +89,7 @@ bool BinaryControl::setValue(int idx, int v) } int BinaryControl::getValue(int idx) { - uint32_t val; + uint8_t val; if ( !m_Parent.getSpecificValue(m_subfunc, idx, &val) ) { debugError( "getSpecificValue failed\n" ); @@ -107,42 +109,49 @@ Inspire1394Device::Inspire1394Device(DeviceManager& d, { addSpecificControls(); } +Inspire1394Device::~Inspire1394Device(void) +{ +} void Inspire1394Device::showDevice() { debugOutput(DEBUG_LEVEL_NORMAL, "This is a BeBoB::Presonus::Inspire1394Device\n"); BeBoB::Device::showDevice(); } -bool Inspire1394Device::addSpecificControls() +bool Inspire1394Device::addSpecificControls(void) { Control::Container *ctls; - BinaryControl ctl; + BinaryControl *ctl; bool result = true; debugOutput(DEBUG_LEVEL_VERBOSE, "Building a PreSonus Inspire1394 mixer...\n"); - ctls = new Control::Container(m_eap, "GlobalMute"); + ctls = new Control::Container(this, "Preamp"); if ( !addElement(ctls) ) { debugWarning("Could not register specific controls to device\n"); delete ctls; return false; } - ctl = BinaryControl(*this, Inspire1394CmdTypePhono, + // RIAA equalization curve for Analog In 3/4 + ctl = new BinaryControl(*this, EInspire1394CmdSubfuncPhono, "PhonoSwitch", "Phono Switch", "Phono Switch"); result &= ctls->addElement(ctl); - ctl = BinaryControl(*this, Inspire1394CmdTypePhantom, + // 48V for Analog In 1/2 + ctl = new BinaryControl(*this, EInspire1394CmdSubfuncPhantom, "PhantomPower", "Phantom Power", "Phantom Power"); result &= ctls->addElement(ctl); - ctl = BinaryControl(*this, Inspire1394CmdTypeBoost, + // +20dB for Analog In 1/2 + ctl = new BinaryControl(*this, EInspire1394CmdSubfuncBoost, "MicBoost", "Mic Boost", "Mic Boost"); result &= ctls->addElement(ctl); - ctl = BinaryControl(*this, Inspire1394CmdTypeLine, - "LineSwitch", "Line Switch", "Line Switch"); + // Limitter of preamp for Analog In 1/2 + ctl = new BinaryControl(*this, EInspire1394CmdSubfuncLimit, + "MicLimit", "Mic Limit", "Mic Limit"); result &= ctls->addElement(ctl); if ( !result ) { @@ -153,20 +162,23 @@ bool Inspire1394Device::addSpecificControls() return true; } -bool Inspire1394Device::getSpecificValue(EInspire1394CmdSubFunc subfunc, - int idx, uint32_t *val) +bool Inspire1394Device::getSpecificValue(EInspire1394CmdSubfunc subfunc, + int idx, uint8_t *val) { - Inspire1394VendorDependentCmd cmd( get1394Service() ); + Inspire1394Cmd cmd( get1394Service() ); cmd.setCommandType( AVC::AVCCommand::eCT_Status ); - cmd.setNodeId( getConfigRom() ); + cmd.setNodeId( getConfigRom().getNodeId() ); cmd.setVerbose( getDebugLevel() ); - cmd.setSubFunc(subfunc); + cmd.setSubfunc(subfunc); cmd.setIdx(idx); cmd.setArg(0xff); if ( !cmd.fire() ) { - debugError( "Inspire1394VendorDependentCmd failed\n" ); + debugError( "Inspire1394Cmd failed\n" ); + return false; + } else if (cmd.getResponse() != AVC::AVCCommand::eR_Implemented ) { + debugError("Inspire1394Cmd received error response\n"); return false; } @@ -174,26 +186,28 @@ bool Inspire1394Device::getSpecificValue(EInspire1394CmdSubFunc subfunc, return true; } -bool Inspire1394Device::setSpecificValue(EInspire1394CmdSubFUnc type, - int idx, uint32_t val) +bool Inspire1394Device::setSpecificValue(EInspire1394CmdSubfunc subfunc, + int idx, uint8_t val) { - Inspire1394VendorDependentCmd cmd( get1394Service() ); + Inspire1394Cmd cmd( get1394Service() ); cmd.setCommandType( AVC::AVCCommand::eCT_Control ); - cmd.setNodeId( getConfigRom() ); + cmd.setNodeId( getConfigRom().getNodeId() ); cmd.setVerbose( getDebugLevel() ); - cmd.setSubFunc(type); + cmd.setSubfunc(subfunc); cmd.setIdx(idx); cmd.setArg(val); if ( !cmd.fire() ) { - debugError( "Inspire1394VendorDependentCmd failed\n" ); + debugError( "Inspire1394Cmd failed\n" ); + return false; + } else if (cmd.getResponse() != AVC::AVCCommand::eR_Accepted) { + debugError("Inspire1394Cmd received error response\n"); return false; } return true; } -} } // namespace Presonus } // namespace BeBoB diff --git a/libffado/src/bebob/presonus/inspire1394_avdevice.h b/libffado/src/bebob/presonus/inspire1394_avdevice.h index 4818c1c6..69744acf 100644 --- a/libffado/src/bebob/presonus/inspire1394_avdevice.h +++ b/libffado/src/bebob/presonus/inspire1394_avdevice.h @@ -29,29 +29,46 @@ #include "debugmodule/debugmodule.h" #include "bebob/bebob_avdevice.h" +#include "libavc/general/avc_vendor_dependent_cmd.h" + namespace BeBoB { namespace Presonus { -enum EInspire1394CmdSubFunc { - EInspire1394CmdSubFuncPhono, - EInspire1394CmdSubFuncPhantom, - EInspire1394CmdSubFuncBoost, - EInspire1394CmdSubFuncLimit +enum EInspire1394CmdSubfunc { + EInspire1394CmdSubfuncPhono = 0, + EInspire1394CmdSubfuncPhantom, + EInspire1394CmdSubfuncBoost, + EInspire1394CmdSubfuncLimit }; -class Inspire1394VendorDependentCmd:: public AVC::VendorDependentCmd +class Inspire1394Device : public BeBoB::Device { +public: + Inspire1394Device( DeviceManager& d, std::auto_ptr( configRom )); + virtual ~Inspire1394Device(); + + virtual void showDevice(); + + bool setSpecificValue(EInspire1394CmdSubfunc subfunc, + int idx, uint8_t val); + bool getSpecificValue(EInspire1394CmdSubfunc subfunc, + int idx, uint8_t *val); +private: + bool addSpecificControls(void); +}; + +class Inspire1394Cmd : public AVC::VendorDependentCmd { public: - Inspire1394VendorDependentCmd( Ieee1394Service& ieee1394service ); - virtual ~Inspire1394VendorDependentCmd; + Inspire1394Cmd( Ieee1394Service& ieee1394service ); + virtual ~Inspire1394Cmd() {}; virtual bool serialize( Util::Cmd::IOSSerialize& se); - virtual bool deserialize( Util::Cmd::IOSDeserialize& de ); + virtual bool deserialize( Util::Cmd::IISDeserialize& de ); virtual const char* getCmdName() const - { return "Inspire1394VendorDependentCmd"; } + { return "Inspire1394Cmd"; } - virtual void setSubFunc(EInspire1394CmdSubFunc subfunc) + virtual void setSubfunc(uint8_t subfunc) { m_subfunc = subfunc; } virtual void setIdx(int idx) { m_idx = idx; } @@ -62,44 +79,31 @@ public: { return m_arg; } protected: - EInspire1394CmdSubFunc m_subfunc; - uint32_t m_idx; - uint32_t m_arg; -} + uint8_t m_subfunc; + uint8_t m_idx; + uint8_t m_arg; +}; -class BinaryControl - : public Control::Discrete +class BinaryControl : public Control::Discrete { public: BinaryControl(Inspire1394Device& parent, - EInspire1394CmdSubFunc subfunc, + EInspire1394CmdSubfunc subfunc, std::string name, std::string label, std::string desc); - virtual bool setValue(int val) { - { return setValue(0, val); } - virtual int getValue() { - { return getValue(0); } virtual bool setValue(int idx, int val); virtual int getValue(int idx); + virtual bool setValue(int val) + { return setValue(0, val); } + virtual int getValue(void) + { return getValue(0); } - virtual int getMinimum() {return 0;}; - virtual int getMaximum() {return 1;}; + virtual int getMinimum() { return 0; }; + virtual int getMaximum() { return 1; }; private: Inspire1394Device& m_Parent; - EInspire1394CmdSubFuncm_subfunc; -}; - -class Inspire1394Device : public BeBoB::Device { -public: - Inspire1394Device( DeviceManager& d, std::auto_ptr( configRom )); - virtual ~Inspire1394Device(); - - virtual void showDevice(); - -private: - bool getSpecificValue(); - bool setSpecificValue(); + EInspire1394CmdSubfunc m_subfunc; }; } // namespace Presonus diff --git a/libffado/support/mixer-qt4/ffado/mixer/presonus_inspire1394.py b/libffado/support/mixer-qt4/ffado/mixer/presonus_inspire1394.py index f11be924..e211a474 100644 --- a/libffado/support/mixer-qt4/ffado/mixer/presonus_inspire1394.py +++ b/libffado/support/mixer-qt4/ffado/mixer/presonus_inspire1394.py @@ -22,7 +22,7 @@ from PyQt4 import QtGui, QtCore from PyQt4.QtCore import QObject, Qt, SIGNAL from PyQt4.QtGui import QHBoxLayout, QVBoxLayout, QGridLayout -from PyQt4.QtGui import QGroupBox, QLabel, QSizePolicy, QSlider, QComboBox, QToolButton +from PyQt4.QtGui import QGroupBox, QLabel, QSizePolicy, QSlider, QDial, QComboBox, QToolButton from math import log10 from ffado.config import * @@ -34,7 +34,7 @@ class Presonus_Inspire1394(QtGui.QWidget): # feature_id/name mixer_src = [[3, "Analog in 1/2"], [4, "Analog in 3/4"], - [5, "Stream in 5/6"]] + [5, "Stream in 1/2"]] # feature id/name outputs = [[6, "Analog out 1/2"], @@ -52,6 +52,9 @@ class Presonus_Inspire1394(QtGui.QWidget): def buildMixer(self): self.Selectors = {} self.Volumes = {} + self.Preamps = {} + self.Pannings = {} + self.Mutes = {} plain_layout = QHBoxLayout(self) @@ -72,55 +75,94 @@ class Presonus_Inspire1394(QtGui.QWidget): box.setLayout(box_layout) box.setTitle("Analog Inputs") - grid = QGroupBox(box) - box_layout.addWidget(grid) grid_layout = QGridLayout() - grid.setLayout(grid_layout) + box_layout.addLayout(grid_layout) - self.addVolumes(self.inputs, grid, grid_layout) + self.addVolumes(self.inputs, 0, box, grid_layout) def addAnalogOutputs(self, box): box_layout = QVBoxLayout() box.setLayout(box_layout) box.setTitle("Analog Outputs") - cmb = QComboBox(box) - box_layout.addWidget(cmb) - for i in range(len(self.out_src[1])): - cmb.addItem(self.out_src[1][i], i) - self.Selectors[cmb] = ["/Mixer/Selector_%d" % self.out_src[0]] - - grid = QGroupBox(box) - box_layout.addWidget(grid) grid_layout = QGridLayout() - grid.setLayout(grid_layout) + box_layout.addLayout(grid_layout) - self.addVolumes(self.outputs, grid, grid_layout) + self.addVolumes(self.outputs, 2, box, grid_layout) def addInternalMixer(self, box): box_layout = QGridLayout() box.setLayout(box_layout) box.setTitle("Hardware Mixer") - self.addVolumes(self.mixer_src, box, box_layout) + self.addVolumes(self.mixer_src, 1, box, box_layout) + + def addVolumes(self, elms, kind, parent, layout): + def addPreampParam(label, ch, path, layout): + button = self.getThinButton(parent, label) + layout.addWidget(button) + self.Preamps[button] = ["/Preamp/%s" % path, ch] + return - def addVolumes(self, elms, parent, layout): for col in range(len(elms)): label = QLabel(parent) label.setText(elms[col][1]) - layout.addWidget(label, 0, col * 2, 1, 2, Qt.AlignHCenter) + layout.addWidget(label, 0, col * 2, 1, 2, Qt.AlignHCenter | Qt.AlignTop) + + if kind == 0: + if col == 0: + for ch in range(2): + box_layout = QVBoxLayout() + layout.addLayout(box_layout, 1, col * 2 + ch, Qt.AlignHCenter | Qt.AlignBottom) + if col == 0: + addPreampParam("+48V", ch + 1, "PhantomPower", box_layout) + addPreampParam("Boost", ch + 1, "MicBoost", box_layout) + addPreampParam("Limit", ch + 1, "MicLimit", box_layout) + else: + box_layout = QVBoxLayout() + addPreampParam("Phono", 0, "PhonoSwitch", box_layout) + layout.addLayout(box_layout, 1, col * 2, 1, 2, Qt.AlignHCenter | Qt.AlignBottom) + elif kind == 1: + l_dial = self.getDial(parent) + r_dial = self.getDial(parent) + + layout.addWidget(l_dial, 1, col * 2, Qt.AlignHCenter | Qt.AlignBottom) + layout.addWidget(r_dial, 1, col * 2 + 1, Qt.AlignHCenter | Qt.AlignBottom) + + path = "/Mixer/Feature_LRBalance_%d" % elms[col][0] + self.Pannings[l_dial] = [path, 1] + self.Pannings[r_dial] = [path, 2] + + if col == 2: + l_dial.setDisabled(True) + r_dial.setDisabled(True) + + elif col == 0: + cmb = QComboBox(parent) + layout.addWidget(cmb, 1, col * 2, 1, 4, Qt.AlignHCenter | Qt.AlignBottom) + for i in range(len(self.out_src[1])): + cmb.addItem(self.out_src[1][i], i) + self.Selectors[cmb] = ["/Mixer/Selector_%d" % self.out_src[0]] l_sld = self.getSlider(parent) r_sld = self.getSlider(parent) - layout.addWidget(l_sld, 1, col * 2, Qt.AlignHCenter) - layout.addWidget(r_sld, 1, col * 2 + 1, Qt.AlignHCenter) + layout.addWidget(l_sld, 2, col * 2, Qt.AlignHCenter) + layout.addWidget(r_sld, 2, col * 2 + 1, Qt.AlignHCenter) + + l_mute = self.getThinButton(parent, "Mute") + r_mute = self.getThinButton(parent, "Mute") + layout.addWidget(l_mute, 3, col * 2, Qt.AlignHCenter) + layout.addWidget(r_mute, 3, col * 2 + 1, Qt.AlignHCenter) - link = self.getLink(parent) - layout.addWidget(link, 2, col * 2, 1, 2, Qt.AlignHCenter) + link = self.getWideButton(parent, "Link") + layout.addWidget(link, 4, col * 2, 1, 2, Qt.AlignHCenter) path = "/Mixer/Feature_Volume_%d" % elms[col][0] - self.Volumes[l_sld] = [path, 1, r_sld, link] - self.Volumes[r_sld] = [path, 2, l_sld, link] + self.Volumes[l_sld] = [path, 1, r_sld, l_mute, link] + self.Volumes[r_sld] = [path, 2, l_sld, r_mute, link] + + self.Mutes[l_mute] = [r_mute, l_sld] + self.Mutes[r_mute] = [l_mute, r_sld] # widget helper functions def getSlider(self, parent): @@ -135,13 +177,27 @@ class Presonus_Inspire1394(QtGui.QWidget): sld.setTickPosition(QSlider.TicksBothSides) return sld - def getLink(self, parent): - link = QToolButton(parent) - link.setText("link") - link.setCheckable(True) - link.setMinimumWidth(100) - link.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) - return link + def getDial(self, parent): + dial = QDial(parent) + dial.setNotchesVisible(True) + dial.setNotchTarget(25.0) + dial.setMaximumHeight(40) + return dial; + + def getThinButton(self, parent, text): + button = QToolButton(parent) + button.setText(text) + button.setCheckable(True) + button.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + return button + + def getWideButton(self, parent, label): + button = QToolButton(parent) + button.setText(label) + button.setCheckable(True) + button.setMinimumWidth(100) + button.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) + return button def initValues(self): for ctl, params in self.Selectors.items(): @@ -154,18 +210,47 @@ class Presonus_Inspire1394(QtGui.QWidget): path = params[0] idx = params[1] pair = params[2] - link = params[3] + mute = params[3] + link = params[4] db = self.hw.getContignuous(path, idx) vol = self.db2vol(db) ctl.setValue(vol) QObject.connect(ctl, SIGNAL('valueChanged(int)'), self.updateVolume) + if vol == 0: + mute.setChecked(True) + if idx == 2: pair_db = self.hw.getContignuous(path, 1) if pair_db == db: link.setChecked(True) + for ctl, params in self.Preamps.items(): + path = params[0] + idx = params[1] + + vol = self.hw.getDiscrete(path, idx) + if vol > 0: + ctl.setChecked(True) + + QObject.connect(ctl, SIGNAL('clicked(bool)'), self.updatePreamps) + + # Right - Center - Left + # 0x8000 - 0x0000 - 0x0001 - 0x7FFE + # ..., -1, 0, +1, ... + for ctl, params in self.Pannings.items(): + path = params[0] + idx = params[1] + + val = self.hw.getContignuous(path, idx) + state = -(val / 0x7FFE) * 50 + 50 + ctl.setValue(state) + QObject.connect(ctl, SIGNAL('valueChanged(int)'), self.updatePanning) + + for ctl, params in self.Mutes.items(): + QObject.connect(ctl, SIGNAL('clicked(bool)'), self.updateMute) + # helper functions def vol2db(self, vol): return (log10(vol + 1) - 2) * 16384 @@ -178,15 +263,63 @@ class Presonus_Inspire1394(QtGui.QWidget): path = self.Selectors[sender][0] self.hw.setDiscrete(path, state) + def updatePreamps(self, state): + sender = self.sender() + path = self.Preamps[sender][0] + idx = self.Preamps[sender][1] + self.hw.setDiscrete(path, idx, state) + def updateVolume(self, vol): sender = self.sender() path = self.Volumes[sender][0] idx = self.Volumes[sender][1] pair = self.Volumes[sender][2] - link = self.Volumes[sender][3] + mute = self.Volumes[sender][3] + link = self.Volumes[sender][4] + + if mute.isChecked(): + return db = self.vol2db(vol) self.hw.setContignuous(path, db, idx) if link.isChecked(): pair.setValue(vol) + + def updatePanning(self, state): + sender = self.sender() + path = self.Pannings[sender][0] + idx = self.Pannings[sender][1] + val = (state - 50) * 0x7FFE / -50 + self.hw.setContignuous(path, idx, val) + + def updateMute(self, state): + sender = self.sender() + pair = self.Mutes[sender][0] + sld = self.Mutes[sender][1] + + path = self.Volumes[sld][0] + idx = self.Volumes[sld][1] + pair_sld = self.Volumes[sld][2] + link = self.Volumes[sld][4] + + if state: + db = 0x8000 + vol = 0 + else: + db = 0x0000 + vol = 99 + + self.hw.setContignuous(path, db, idx) + sld.setValue(vol) + sld.setDisabled(state) + + if link.isChecked(): + if idx == 1: + idx = 2 + else: + idx = 1 + self.hw.setContignuous(path, db, idx) + pair.setChecked(state) + pair_sld.setValue(vol) + pair_sld.setDisabled(state) -- 2.11.4.GIT