From: Hector M. <ma...@ma...> - 2015-05-02 17:12:54
|
Not to be confused with the older Pro 26 I/O, which ffado already supports; the PRO 26 was released in 2014. This is basically a cross between the 14, the 24, and the 40 of the same range. Two transmitters, like the 40, registers offsets that are closer to the 14, and actual capabilities are just like a 24 with two extra channels and some differences in the monitoring config. All streams and inputs have been tested, other than ADAT which I don't have a test source for. ADAT-as-SPDIF has been tested, however. I removed the mono switches in the monitoring panel, since those don't seem to do anything on this model. This model also doesn't have any soft switches for input settings, as all inputs are either fixed, auto-switching, or have dedicated front panel buttons. The only issue that I found is certain clocking instability with the S/PDIF input when used in 96kHz mode, and it seems it also interacts with ADAT-as-SPDIF in strange ways. This is likely a bug/limitation of the interface and not a problem in libffado, though. I was testing S/PDIF by looping it back, so it's also possible that the issue would not be present with external S/PDIF sources. Signed-off-by: Hector Martin <ma...@ma...> --- libffado/configuration | 8 + libffado/src/SConscript | 1 + libffado/src/dice/dice_avdevice.cpp | 16 +- libffado/src/dice/focusrite/saffire_pro26.cpp | 451 ++++++++++ libffado/src/dice/focusrite/saffire_pro26.h | 127 +++ .../ffado/mixer/Saffire_Pro26_monitoring.ui | 941 +++++++++++++++++++++ .../support/mixer-qt4/ffado/mixer/saffire_dice.py | 39 +- 7 files changed, 1564 insertions(+), 19 deletions(-) create mode 100644 libffado/src/dice/focusrite/saffire_pro26.cpp create mode 100644 libffado/src/dice/focusrite/saffire_pro26.h create mode 100644 libffado/support/mixer-qt4/ffado/mixer/Saffire_Pro26_monitoring.ui diff --git a/libffado/configuration b/libffado/configuration index 6a31ce4..b9118fd 100644 --- a/libffado/configuration +++ b/libffado/configuration @@ -620,6 +620,14 @@ device_definitions = ( mixer = "Saffire_Dice"; }, { + vendorid = 0x00130e; + modelid = 0x00000012; + vendorname = "Focusrite"; + modelname = "Saffire PRO 26"; + driver = "DICE"; + mixer = "Saffire_Dice"; +}, +{ vendorid = 0x001C6A; modelid = 0x00000001; vendorname = "Weiss Engineering Ltd."; diff --git a/libffado/src/SConscript b/libffado/src/SConscript index 4a8e20e..fa86c66 100644 --- a/libffado/src/SConscript +++ b/libffado/src/SConscript @@ -164,6 +164,7 @@ dice_source = env.Split( '\ dice/dice_eap.cpp \ dice/focusrite/focusrite_eap.cpp \ dice/focusrite/saffire_pro40.cpp \ + dice/focusrite/saffire_pro26.cpp \ dice/focusrite/saffire_pro24.cpp \ dice/focusrite/saffire_pro14.cpp \ dice/maudio/profire_2626.cpp \ diff --git a/libffado/src/dice/dice_avdevice.cpp b/libffado/src/dice/dice_avdevice.cpp index c187a4c..79f39f4 100644 --- a/libffado/src/dice/dice_avdevice.cpp +++ b/libffado/src/dice/dice_avdevice.cpp @@ -47,6 +47,7 @@ #include "devicemanager.h" #include "focusrite/saffire_pro40.h" +#include "focusrite/saffire_pro26.h" #include "focusrite/saffire_pro24.h" #include "focusrite/saffire_pro14.h" #include "maudio/profire_2626.h" @@ -137,6 +138,8 @@ Device::createDevice( DeviceManager& d, std::auto_ptr<ConfigRom>( configRom )) return new Focusrite::SaffirePro24(d, configRom); case 0x00000009: return new Focusrite::SaffirePro14(d, configRom); + case 0x00000012: + return new Focusrite::SaffirePro26(d, configRom); default: // return a plain Dice device return new Device(d, configRom); } @@ -1667,9 +1670,11 @@ Device::initIoFunctions() { } m_rx_size*=4; - // FIXME: verify this and clean it up. + // FIXME: verify this and clean it up. Maybe check the number of channels + // and ignore receivers with zero channels? /* special case for Alesis io14, which announces two receive transmitters, - * but only has one. Same is true for Alesis Multimix16. + * but only has one. Same is true for Alesis Multimix16 and Focusrite + * Saffire PRO 26. */ if (FW_VENDORID_ALESIS == getConfigRom().getNodeVendorId()) { switch (getConfigRom().getModelId()) { @@ -1679,6 +1684,13 @@ Device::initIoFunctions() { break; } } + if (FW_VENDORID_FOCUSRITE == getConfigRom().getNodeVendorId()) { + switch (getConfigRom().getModelId()) { + case 0x00000012: + m_nb_rx = 1; + break; + } + } #if USE_OLD_DEFENSIVE_STREAMING_PROTECTION // FIXME: after a crash, the device might still be streaming. We diff --git a/libffado/src/dice/focusrite/saffire_pro26.cpp b/libffado/src/dice/focusrite/saffire_pro26.cpp new file mode 100644 index 0000000..4b08409 --- /dev/null +++ b/libffado/src/dice/focusrite/saffire_pro26.cpp @@ -0,0 +1,451 @@ +/* + * Copyright (C) 2009 by Pieter Palmers + * Copyright (C) 2009 by Arnold Krille + * Copyright (C) 2015 by Hector Martin + * + * This file is part of FFADO + * FFADO = Free Firewire (pro-)audio drivers for linux + * + * FFADO is based upon FreeBoB. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "saffire_pro26.h" +#include "focusrite_eap.h" + +#include "libutil/ByteSwap.h" + +namespace Dice { +namespace Focusrite { + +void SaffirePro26::SaffirePro26EAP::setupSources_low() { + addSource("SPDIF/In", 4, 4, eRS_AES, 1); + addSource("ADAT/In", 0, 8, eRS_ADAT, 1); + addSource("Anlg/In", 0, 6, eRS_InS0, 1); + addSource("Mixer/Out", 0, 16, eRS_Mixer, 1); + addSource("1394/In", 0, 8, eRS_ARX0, 1); + addSource("Mute", 0, 1, eRS_Muted); +} +void SaffirePro26::SaffirePro26EAP::setupDestinations_low() { + addDestination("SPDIF/Out", 6, 2, eRD_AES, 1); + addDestination("Line/Out", 0, 6, eRD_InS0, 1); + addDestination("Mixer/In", 0, 16, eRD_Mixer0, 1); + addDestination("Mixer/In", 0, 2, eRD_Mixer1, 17); + addDestination("1394/Out", 0, 10, eRD_ATX0, 1); + addDestination("1394/Out", 0, 8, eRD_ATX1, 11); +// Is a Mute destination useful ? +// addDestination("Mute", 0, 1, eRD_Muted); +} + +void SaffirePro26::SaffirePro26EAP::setupSources_mid() { + addSource("SPDIF/In", 4, 4, eRS_AES, 1); + addSource("ADAT/In", 0, 4, eRS_ADAT, 1); + addSource("Anlg/In", 0, 6, eRS_InS0, 1); + addSource("Mixer/Out", 0, 16, eRS_Mixer, 1); + addSource("1394/In", 0, 8, eRS_ARX0, 1); + addSource("Mute", 0, 1, eRS_Muted); +} +void SaffirePro26::SaffirePro26EAP::setupDestinations_mid() { + addDestination("SPDIF/Out", 6, 2, eRD_AES, 1); + addDestination("Line/Out", 0, 6, eRD_InS0, 1); + addDestination("Mixer/In", 0, 16, eRD_Mixer0, 1); + addDestination("Mixer/In", 0, 2, eRD_Mixer1, 17); + addDestination("1394/Out", 0, 10, eRD_ATX0, 1); + addDestination("1394/Out", 0, 4, eRD_ATX1, 11); +// Is a Mute destination useful ? +// addDestination("Mute", 0, 1, eRD_Muted); +} + +void SaffirePro26::SaffirePro26EAP::setupSources_high() { + printMessage("High (192 kHz) sample rate not supported by Saffire Pro 26\n"); +} + +void SaffirePro26::SaffirePro26EAP::setupDestinations_high() { + printMessage("High (192 kHz) sample rate not supported by Saffire Pro 26\n"); +} + +/** + * The default configurations for the Saffire Pro 26 router. + * For coherence with hardware, destinations must follow a specific ordering + * Front LEDs are connected to the first six eRD_ATX0 entries + */ +void +SaffirePro26::SaffirePro26EAP::setupDefaultRouterConfig_low() { + unsigned int i; + // the 1394 stream receivers except the two "loops" one + for (i=0; i<6; i++) { + addRoute(eRS_InS0, i, eRD_ATX0, i); + } + for (i=0; i<2; i++) { + addRoute(eRS_AES, i+4, eRD_ATX0, i+6); + } + for (i=0; i<8; i++) { + addRoute(eRS_ADAT, i, eRD_ATX1, i); + } + // The audio ports + // Ensure that audio port are not muted + for (i=0; i<6; i++) { + addRoute(eRS_ARX0, i%2, eRD_InS0, i); + } + // the SPDIF receiver + for (i=0; i<2; i++) { + addRoute(eRS_Muted, 0, eRD_AES, i+6); + } + // the "loops" 1394 stream receivers + for (i=0; i<2; i++) { + addRoute(eRS_Muted, 0, eRD_ATX0, i+8); + } + // the Mixer inputs + for (i=0; i<6; i++) { + addRoute(eRS_InS0, i, eRD_Mixer0, i); + } + for (i=0; i<2; i++) { + addRoute(eRS_AES, i+4, eRD_Mixer0, i+6); + } + for (i=0; i<8; i++) { + addRoute(eRS_ADAT, i, eRD_Mixer0, i+8); + } + for (i=0; i<2; i++) { + addRoute(eRS_ARX0, i, eRD_Mixer1, i); + } + // The two mute destinations + // FIXME: does this do anything useful? + for (i=0; i<2; i++) { + addRoute(eRS_Mixer, i, eRD_Muted, 0); + } +} + +/** + * There must be 40 (?) destinations at mid samplerate + * Front LEDs are connected to the first six eRD_ATX0 entries + */ +void +SaffirePro26::SaffirePro26EAP::setupDefaultRouterConfig_mid() { + unsigned int i; + // the 1394 stream receivers except the two "loops" one + for (i=0; i<6; i++) { + addRoute(eRS_InS0, i, eRD_ATX0, i); + } + for (i=0; i<2; i++) { + addRoute(eRS_AES, i+4, eRD_ATX0, i+6); + } + for (i=0; i<4; i++) { + addRoute(eRS_ADAT, i, eRD_ATX1, i); + } + // The audio ports + // Ensure that audio port are not muted + for (i=0; i<6; i++) { + addRoute(eRS_ARX0, i%2, eRD_InS0, i); + } + // the SPDIF receiver + for (i=0; i<2; i++) { + addRoute(eRS_Muted, 0, eRD_AES, i+6); + } + // the "loops" 1394 stream receivers + for (i=0; i<2; i++) { + addRoute(eRS_Muted, 0, eRD_ATX0, i+8); + } + // the Mixer inputs + for (i=0; i<6; i++) { + addRoute(eRS_InS0, i, eRD_Mixer0, i); + } + for (i=0; i<2; i++) { + addRoute(eRS_AES, i+4, eRD_Mixer0, i+6); + } + for (i=0; i<4; i++) { + addRoute(eRS_ADAT, i, eRD_Mixer0, i+8); + } + for (i=0; i<4; i++) { + addRoute(eRS_Muted, i, eRD_Mixer0, i+12); + } + for (i=0; i<2; i++) { + addRoute(eRS_ARX0, i, eRD_Mixer1, i); + } + // The two mute destinations + // FIXME: does this do anything useful? + for (i=0; i<2; i++) { + addRoute(eRS_Mixer, i, eRD_Muted, 0); + } +} + +/** + * High rate not supported + */ +void +SaffirePro26::SaffirePro26EAP::setupDefaultRouterConfig_high() { + printMessage("High (192 kHz) sample rate not supported by Saffire Pro 26\n"); +} + +/** + * Pro 24 Monitor section + */ +SaffirePro26::SaffirePro26EAP::MonitorSection::MonitorSection(Dice::Focusrite::FocusriteEAP* eap, + std::string name) : Control::Container(eap, name) + , m_eap(eap) +{ + // Global Mute control + Control::Container* grp_globalmute = new Control::Container(m_eap, "GlobalMute"); + addElement(grp_globalmute); + FocusriteEAP::Switch* mute = + new FocusriteEAP::Switch(m_eap, "State", + SAFFIRE_PRO26_REGISTER_APP_GLOBAL_MUTE_SWITCH, + FOCUSRITE_EAP_GLOBAL_MUTE_SWITCH_VALUE, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_GLOBAL_DIM_MUTE_SWITCH); + grp_globalmute->addElement(mute); + + // Global Dim control + Control::Container* grp_globaldim = new Control::Container(m_eap, "GlobalDim"); + addElement(grp_globaldim); + FocusriteEAP::Switch* dim = + new FocusriteEAP::Switch(m_eap, "State", + SAFFIRE_PRO26_REGISTER_APP_GLOBAL_DIM_SWITCH, + FOCUSRITE_EAP_GLOBAL_DIM_SWITCH_VALUE, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_GLOBAL_DIM_MUTE_SWITCH); + grp_globaldim->addElement(dim); + FocusriteEAP::Poti* dimlevel = + new FocusriteEAP::Poti(m_eap, "Level", + SAFFIRE_PRO26_REGISTER_APP_GLOBAL_DIM_VOLUME, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_globaldim->addElement(dimlevel); + + // The mono switches don't seem to do anything on this device (and are not + // implemented in MixControl) + + // Independent control of each line/out + Control::Container* grp_perchannel = new Control::Container(m_eap, "LineOut"); + addElement(grp_perchannel); + FocusriteEAP::VolumeControl* vol; + + // per Line/Out monitoring + FocusriteEAP::Switch* s; + for (unsigned int i=0; i<SAFFIRE_PRO26_APP_STEREO_LINEOUT_SIZE; ++i) { + std::stringstream stream; + + // Activate/Unactivate per Line/Out volume monitoring + stream.str(std::string()); + stream << "UnActivate" << i*2+1; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_SWITCH+i*sizeof(quadlet_t), + FOCUSRITE_EAP_SWITCH_BIT_1, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_perchannel->addElement(s); + stream.str(std::string()); + stream << "UnActivate" << i*2+2; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_SWITCH+i*sizeof(quadlet_t), + FOCUSRITE_EAP_SWITCH_BIT_2, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_perchannel->addElement(s); + + // per Line/Out mute/unmute + stream.str(std::string()); + stream << "Mute" << i*2+1; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_SWITCH+i*sizeof(quadlet_t), + FOCUSRITE_EAP_SWITCH_BIT_3, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_perchannel->addElement(s); + stream.str(std::string()); + stream << "Mute" << i*2+2; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_SWITCH+i*sizeof(quadlet_t), + FOCUSRITE_EAP_SWITCH_BIT_4, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_perchannel->addElement(s); + + // per Line/Out global mute activation/unactivation + stream.str(std::string()); + stream << "GMute" << 2*i+1; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_SWITCH_CONTROL, + FOCUSRITE_EAP_SWITCH_CONTROL_VALUE + <<(FOCUSRITE_EAP_SWITCH_CONTROL_MUTE_SHIFT+2*i), + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_SWITCH_CONTROL); + grp_perchannel->addElement(s); + + stream.str(std::string()); + stream << "GMute" << 2*i+2; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_SWITCH_CONTROL, + FOCUSRITE_EAP_SWITCH_CONTROL_VALUE + <<(FOCUSRITE_EAP_SWITCH_CONTROL_MUTE_SHIFT+2*i+1), + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_SWITCH_CONTROL); + grp_perchannel->addElement(s); + + // per Line/Out global dim activation/unactivation + stream.str(std::string()); + stream << "GDim" << 2*i+1; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_SWITCH_CONTROL, + FOCUSRITE_EAP_SWITCH_CONTROL_VALUE + <<(FOCUSRITE_EAP_SWITCH_CONTROL_DIM_SHIFT+2*i), + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_SWITCH_CONTROL); + grp_perchannel->addElement(s); + + stream.str(std::string()); + stream << "GDim" << 2*i+2; + s = + new FocusriteEAP::Switch(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_SWITCH_CONTROL, + FOCUSRITE_EAP_SWITCH_CONTROL_VALUE + <<(FOCUSRITE_EAP_SWITCH_CONTROL_DIM_SHIFT+2*i+1), + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_SWITCH_CONTROL); + grp_perchannel->addElement(s); + + // per Line/Out volume control + stream.str(std::string()); + stream << "Volume" << i*2+1; + vol = + new FocusriteEAP::VolumeControl(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_VOLUME + +i*sizeof(quadlet_t), + FOCUSRITE_EAP_LINEOUT_VOLUME_SET_1, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_perchannel->addElement(vol); + stream.str(std::string()); + stream << "Volume" << i*2+2; + vol = + new FocusriteEAP::VolumeControl(m_eap, stream.str(), + SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_VOLUME + +i*sizeof(quadlet_t), + FOCUSRITE_EAP_LINEOUT_VOLUME_SET_2, + SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET, + SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME); + grp_perchannel->addElement(vol); + } + + // The Saffire PRO 26 does not have line/inst/gain controls. Instead it has + // dedicated hardware switches for inputs 1/2, auto selection for inputs 3/4, + // and no controls for inputs 5/6. + + // There is also support for ADAT-as-SPDIF, but no control is necessary. + // SPDIF inputs appear on their own dedicated routing source when present + // (labeled SPDIF 3/4). +} + +SaffirePro26::SaffirePro26( DeviceManager& d, + std::auto_ptr<ConfigRom>( configRom )) + : Dice::Device(d , configRom) +{ + debugOutput(DEBUG_LEVEL_VERBOSE, "Created Dice::Focusrite::SaffirePro26 (NodeID %d)\n", + getConfigRom().getNodeId()); +} + +SaffirePro26::~SaffirePro26() +{ + //debugOutput(DEBUG_LEVEL_VERBOSE, "Deleting the saffirePro26\n"); + /// I wonder whether we should really save only on clean exits or also each time a setting is + // changed. Or should we provide a function (and thus gui-button) to save the state of the + // device? + getEAP()->storeFlashConfig(); +} + +bool SaffirePro26::discover() { + if (Dice::Device::discover()) { + fb_quadlet_t* version = (fb_quadlet_t *)calloc(2, sizeof(fb_quadlet_t)); + getEAP()->readRegBlock(Dice::EAP::eRT_Application, SAFFIRE_PRO26_REGISTER_APP_VERSION, version, 1*sizeof(fb_quadlet_t)); + // Only known firmware for Saffire Pro 26 devices so far is 0x10000. + if (version[0] != 0x10000) { + debugError("This is a Focusrite Saffire Pro26 but not the right firmware. Better stop here before something goes wrong.\n"); + debugError("This device has firmware 0x%x while we only know about version 0x%x.\n", version[0], 0x10000); + return false; + } + + // FIXME: What is the purpose of the following commented lines at this point ? + //getEAP()->readRegBlock(Dice::EAP::eRT_Command, 0x00, tmp, 2*sizeof(fb_quadlet_t)); // DEBUG + //hexDumpQuadlets(tmp, 2); // DEBUG + + FocusriteEAP* eap = dynamic_cast<FocusriteEAP*>(getEAP()); + SaffirePro26EAP::MonitorSection* monitor = new SaffirePro26EAP::MonitorSection(eap, "Monitoring"); + getEAP()->addElement(monitor); + return true; + } + return false; +} + +void SaffirePro26::showDevice() +{ + debugOutput(DEBUG_LEVEL_VERBOSE, "This is a Dice::Focusrite::SaffirePro26\n"); + Dice::Device::showDevice(); +} +Dice::EAP* SaffirePro26::createEAP() { + return new SaffirePro26EAP(*this); +} + +bool SaffirePro26::setNickname( std::string name ) { + char nickname[SAFFIRE_PRO26_APP_NICK_NAME_SIZE+1]; + + // The device has room for SAFFIRE_PRO26_APP_NICK_NAME_SIZE characters. + // Erase supplementary characters or fill-in with NULL character if necessary + strncpy(nickname, name.c_str(), SAFFIRE_PRO26_APP_NICK_NAME_SIZE); + + // Strings from the device are always little-endian, + // so byteswap for big-endian machines + #if __BYTE_ORDER == __BIG_ENDIAN + byteSwapBlock((quadlet_t *)nickname, SAFFIRE_PRO26_APP_NICK_NAME_SIZE/4); + #endif + + if (!getEAP()->writeRegBlock(Dice::EAP::eRT_Application, SAFFIRE_PRO26_REGISTER_APP_NICK_NAME, + (quadlet_t*)nickname, SAFFIRE_PRO26_APP_NICK_NAME_SIZE)) { + debugError("Could not write nickname string \n"); + return false; + } + return true; +} + +std::string SaffirePro26::getNickname() { + char nickname[SAFFIRE_PRO26_APP_NICK_NAME_SIZE+1]; + if (!getEAP()->readRegBlock(Dice::EAP::eRT_Application, SAFFIRE_PRO26_REGISTER_APP_NICK_NAME, + (quadlet_t*)nickname, SAFFIRE_PRO26_APP_NICK_NAME_SIZE)){ + debugError("Could not read nickname string \n"); + return std::string("(unknown)"); + } + + // Strings from the device are always little-endian, + // so byteswap for big-endian machines + #if __BYTE_ORDER == __BIG_ENDIAN + byteSwapBlock((quadlet_t *)nickname, SAFFIRE_PRO26_APP_NICK_NAME_SIZE/4); + #endif + + // The device supplies at most SAFFIRE_PRO26_APP_NICK_NAME_SIZE characters. Ensure the string is + // NULL terminated. + nickname[SAFFIRE_PRO26_APP_NICK_NAME_SIZE] = 0; + return std::string(nickname); +} + +} +} + +// vim: et diff --git a/libffado/src/dice/focusrite/saffire_pro26.h b/libffado/src/dice/focusrite/saffire_pro26.h new file mode 100644 index 0000000..f43cdc8 --- /dev/null +++ b/libffado/src/dice/focusrite/saffire_pro26.h @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009 by Pieter Palmers + * Copyright (C) 2009 by Arnold Krille + * Copyright (C) 2015 by Hector Martin + * + * This file is part of FFADO + * FFADO = Free Firewire (pro-)audio drivers for linux + * + * FFADO is based upon FreeBoB. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef DICE_FOCUSRITE_SAFFIRE_PRO26_H +#define DICE_FOCUSRITE_SAFFIRE_PRO26_H + +#include "dice/dice_avdevice.h" + +#include "libieee1394/configrom.h" + +#include "focusrite_eap.h" + +/** + * Saffire Pro26 application space + */ +// Versioning registers +#define SAFFIRE_PRO26_REGISTER_APP_VERSION 0x00 +#define SAFFIRE_PRO26_REGISTER_APP_RELEASE 0x04 +#define SAFFIRE_PRO26_REGISTER_APP_BUILDNR 0x08 + +// Nickname register +#define SAFFIRE_PRO26_REGISTER_APP_NICK_NAME 0x44 +// NOTE: in bytes +#define SAFFIRE_PRO26_APP_NICK_NAME_SIZE 16 + +// Global monitor registers (application space) +#define SAFFIRE_PRO26_REGISTER_APP_GLOBAL_MUTE_SWITCH 0x10 +#define SAFFIRE_PRO26_REGISTER_APP_GLOBAL_DIM_SWITCH 0x14 +#define SAFFIRE_PRO26_REGISTER_APP_GLOBAL_DIM_VOLUME 0x58 +#define SAFFIRE_PRO26_REGISTER_APP_GLOBAL_MONITOR_VOLUME 0x28 + +// Per line/out monitor volume and switches: registers are expected to be one after the other +// each register controlling two output lines +// The whole number of physical analog output is thus 2*SAFFIRE_PRO26_APP_STEREO_LINEOUT_SIZE +#define SAFFIRE_PRO26_APP_STEREO_LINEOUT_SIZE 3 + +// Volume and switch monitor register +#define SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_VOLUME 0x18 +#define SAFFIRE_PRO26_REGISTER_APP_LINEOUT_MONITOR_SWITCH 0x2C + +// Switch control (per line/out mute, dim and mono) +#define SAFFIRE_PRO26_REGISTER_APP_LINEOUT_SWITCH_CONTROL 0x40 + +// Message set +// The location of the message register and the values for each setting +#define SAFFIRE_PRO26_REGISTER_APP_MESSAGE_SET 0x0c +#define SAFFIRE_PRO26_MESSAGE_SET_NO_MESSAGE 0 +#define SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_MONITOR_VOLUME 1 +#define SAFFIRE_PRO26_MESSAGE_SET_GLOBAL_DIM_MUTE_SWITCH 2 +#define SAFFIRE_PRO26_MESSAGE_SET_LINEOUT_SWITCH_CONTROL 3 +#define SAFFIRE_PRO26_MESSAGE_SET_INSTLINE 4 +#define SAFFIRE_PRO26_MESSAGE_SET_MESSAGE_END 5 + +namespace Dice { +namespace Focusrite { + +class SaffirePro26 : public Dice::Device { +public: + SaffirePro26( DeviceManager& d, + std::auto_ptr<ConfigRom>( configRom )); + ~SaffirePro26(); + + bool discover(); + + void showDevice(); + + bool canChangeNickname() { return true; } + bool setNickname( std::string name ); + std::string getNickname(); + +private: + + class SaffirePro26EAP : public FocusriteEAP + { + public: + SaffirePro26EAP(Dice::Device& dev) : FocusriteEAP(dev) { + } + + void setupSources_low(); + void setupDestinations_low(); + void setupSources_mid(); + void setupDestinations_mid(); + void setupSources_high(); + void setupDestinations_high(); + void setupDefaultRouterConfig_low(); + void setupDefaultRouterConfig_mid(); + void setupDefaultRouterConfig_high(); + + class MonitorSection : public Control::Container + { + public: + MonitorSection(Dice::Focusrite::FocusriteEAP*, std::string); + private: + Dice::Focusrite::FocusriteEAP* m_eap; + }; + }; + Dice::EAP* createEAP(); + +}; + +} +} + +#endif +// vim: et diff --git a/libffado/support/mixer-qt4/ffado/mixer/Saffire_Pro26_monitoring.ui b/libffado/support/mixer-qt4/ffado/mixer/Saffire_Pro26_monitoring.ui new file mode 100644 index 0000000..053a535 --- /dev/null +++ b/libffado/support/mixer-qt4/ffado/mixer/Saffire_Pro26_monitoring.ui @@ -0,0 +1,941 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SaffirePro26Monitoring</class> + <widget class="QWidget" name="SaffirePro26Monitoring"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>610</width> + <height>550</height> + </rect> + </property> + <property name="windowTitle"> + <string>Saffire Pro 26 Monitoring</string> + </property> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <widget class="QWidget" name="horizontalLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>170</x> + <y>20</y> + <width>431</width> + <height>521</height> + </rect> + </property> + <layout class="QHBoxLayout" name="LineOutMain"> + <item> + <widget class="QGroupBox" name="LineOut"> + <property name="title"> + <string>Line/Out Settings</string> + </property> + <widget class="QWidget" name="verticalLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>51</width> + <height>491</height> + </rect> + </property> + <layout class="QVBoxLayout" name="LineOutMain_1"> + <item> + <widget class="QGroupBox" name="LineOut_1"> + <property name="title"> + <string/> + </property> + <widget class="QSlider" name="LineVolume_1"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>20</width> + <height>311</height> + </rect> + </property> + <property name="locale"> + <locale language="French" country="France"/> + </property> + <property name="minimum"> + <number>-40</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>5</number> + </property> + </widget> + <widget class="QPushButton" name="LineUnActivate_1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>UA</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineMute_1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mu</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineGMute_1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>450</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="label_1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>1</string> + </property> + </widget> + <widget class="QPushButton" name="LineGDim_1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>410</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GD</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>80</x> + <y>20</y> + <width>51</width> + <height>491</height> + </rect> + </property> + <layout class="QVBoxLayout" name="LineOutMain_2"> + <item> + <widget class="QGroupBox" name="LineOut_2"> + <property name="title"> + <string/> + </property> + <widget class="QSlider" name="LineVolume_2"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>20</width> + <height>311</height> + </rect> + </property> + <property name="minimum"> + <number>-40</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>5</number> + </property> + </widget> + <widget class="QPushButton" name="LineUnActivate_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>UA</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineMute_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mu</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineGMute_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>450</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="label_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>2</string> + </property> + </widget> + <widget class="QPushButton" name="LineGDim_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>410</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GD</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <zorder>LineVolume_2</zorder> + <zorder>LineUnActivate_2</zorder> + <zorder>LineMute_2</zorder> + <zorder>LineGMute_2</zorder> + <zorder>label_2</zorder> + <zorder>LineGDim_2</zorder> + <zorder>LineOut_1</zorder> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_3"> + <property name="geometry"> + <rect> + <x>150</x> + <y>20</y> + <width>51</width> + <height>491</height> + </rect> + </property> + <layout class="QVBoxLayout" name="LineOutMain_3"> + <item> + <widget class="QGroupBox" name="LineOut_3"> + <property name="title"> + <string/> + </property> + <widget class="QSlider" name="LineVolume_3"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>20</width> + <height>311</height> + </rect> + </property> + <property name="minimum"> + <number>-40</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>5</number> + </property> + </widget> + <widget class="QPushButton" name="LineUnActivate_3"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>UA</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineMute_3"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mu</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineGMute_3"> + <property name="geometry"> + <rect> + <x>0</x> + <y>450</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="label_3"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>3</string> + </property> + </widget> + <widget class="QPushButton" name="LineGDim_3"> + <property name="geometry"> + <rect> + <x>0</x> + <y>410</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GD</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_4"> + <property name="geometry"> + <rect> + <x>220</x> + <y>20</y> + <width>51</width> + <height>491</height> + </rect> + </property> + <layout class="QVBoxLayout" name="LineOutMain_4"> + <item> + <widget class="QGroupBox" name="LineOut_4"> + <property name="title"> + <string/> + </property> + <widget class="QSlider" name="LineVolume_4"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>20</width> + <height>311</height> + </rect> + </property> + <property name="minimum"> + <number>-40</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>5</number> + </property> + </widget> + <widget class="QPushButton" name="LineUnActivate_4"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>UA</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineMute_4"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mu</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineGMute_4"> + <property name="geometry"> + <rect> + <x>0</x> + <y>450</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="label_4"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>4</string> + </property> + </widget> + <widget class="QPushButton" name="LineGDim_4"> + <property name="geometry"> + <rect> + <x>0</x> + <y>410</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GD</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_5"> + <property name="geometry"> + <rect> + <x>290</x> + <y>20</y> + <width>51</width> + <height>491</height> + </rect> + </property> + <layout class="QVBoxLayout" name="LineOutMain_5"> + <item> + <widget class="QGroupBox" name="LineOut_5"> + <property name="title"> + <string/> + </property> + <widget class="QSlider" name="LineVolume_5"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>20</width> + <height>311</height> + </rect> + </property> + <property name="minimum"> + <number>-40</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>5</number> + </property> + </widget> + <widget class="QPushButton" name="LineUnActivate_5"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>UA</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineMute_5"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mu</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineGMute_5"> + <property name="geometry"> + <rect> + <x>0</x> + <y>450</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="label_5"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>5</string> + </property> + </widget> + <widget class="QPushButton" name="LineGDim_5"> + <property name="geometry"> + <rect> + <x>0</x> + <y>410</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GD</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_6"> + <property name="geometry"> + <rect> + <x>360</x> + <y>20</y> + <width>51</width> + <height>491</height> + </rect> + </property> + <layout class="QVBoxLayout" name="LineOutMain_6"> + <item> + <widget class="QGroupBox" name="LineOut_6"> + <property name="title"> + <string/> + </property> + <widget class="QSlider" name="LineVolume_6"> + <property name="geometry"> + <rect> + <x>20</x> + <y>10</y> + <width>20</width> + <height>311</height> + </rect> + </property> + <property name="minimum"> + <number>-40</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>5</number> + </property> + </widget> + <widget class="QPushButton" name="LineUnActivate_6"> + <property name="geometry"> + <rect> + <x>0</x> + <y>330</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>UA</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineMute_6"> + <property name="geometry"> + <rect> + <x>0</x> + <y>370</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mu</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="LineGMute_6"> + <property name="geometry"> + <rect> + <x>0</x> + <y>450</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GM</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QLabel" name="label_6"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>21</width> + <height>25</height> + </rect> + </property> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>6</string> + </property> + </widget> + <widget class="QPushButton" name="LineGDim_6"> + <property name="geometry"> + <rect> + <x>0</x> + <y>410</y> + <width>41</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>GD</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + <zorder>verticalLayoutWidget</zorder> + <zorder>verticalLayoutWidget_2</zorder> + <zorder>verticalLayoutWidget_3</zorder> + <zorder>verticalLayoutWidget_4</zorder> + <zorder>verticalLayoutWidget_5</zorder> + <zorder>verticalLayoutWidget_6</zorder> + <zorder>LineOut_2</zorder> + <zorder>LineOut_1</zorder> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="horizontalLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>20</y> + <width>163</width> + <height>521</height> + </rect> + </property> + <layout class="QHBoxLayout" name="GlobalSetMain"> + <item> + <widget class="QGroupBox" name="GlobalSet"> + <property name="whatsThis"> + <string comment="Activate/Deactivate the global volume diminution" extracomment="Activate/Deactivate the global volume diminution"/> + </property> + <property name="title"> + <string>Global Settings</string> + </property> + <widget class="QSlider" name="DimLevel"> + <property name="geometry"> + <rect> + <x>60</x> + <y>100</y> + <width>19</width> + <height>311</height> + </rect> + </property> + <property name="minimum"> + <number>-87</number> + </property> + <property name="maximum"> + <number>0</number> + </property> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="invertedAppearance"> + <bool>false</bool> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBothSides</enum> + </property> + <property name="tickInterval"> + <number>10</number> + </property> + </widget> + <widget class="QLabel" name="GlobalSetLabel"> + <property name="geometry"> + <rect> + <x>40</x> + <y>60</y> + <width>77</width> + <height>25</height> + </rect> + </property> + <property name="text"> + <string>Dim level</string> + </property> + </widget> + <widget class="QPushButton" name="GlobalDim"> + <property name="geometry"> + <rect> + <x>20</x> + <y>430</y> + <width>110</width> + <height>35</height> + </rect> + </property> + <property name="whatsThis"> + <string/> + </property> + <property name="autoFillBackground"> + <bool>true</bool> + </property> + <property name="text"> + <string>Activate Dim</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="GlobalMute"> + <property name="geometry"> + <rect> + <x>20</x> + <y>470</y> + <width>110</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>Mute</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" name="HWSwitch"> + <property name="geometry"> + <rect> + <x>20</x> + <y>20</y> + <width>110</width> + <height>35</height> + </rect> + </property> + <property name="text"> + <string>H/W</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </widget> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/libffado/support/mixer-qt4/ffado/mixer/saffire_dice.py b/libffado/support/mixer-qt4/ffado/mixer/saffire_dice.py index 5501070..3c819bf 100644 --- a/libffado/support/mixer-qt4/ffado/mixer/saffire_dice.py +++ b/libffado/support/mixer-qt4/ffado/mixer/saffire_dice.py @@ -74,6 +74,8 @@ class Saffire_Dice(Generic_Dice_EAP): uicLoad("ffado/mixer/Saffire_Pro14_monitoring.ui", widget) elif ModelName == "SAFFIRE_PRO_24" or self.configrom.getModelName() == "SAFFIRE_PRO_24DSP": uicLoad("ffado/mixer/Saffire_Pro24_monitoring.ui", widget) + elif ModelName == "SAFFIRE_PRO26": + uicLoad("ffado/mixer/Saffire_Pro26_monitoring.ui", widget) elif ModelName == "SAFFIRE_PRO_40": uicLoad("ffado/mixer/Saffire_Pro40_monitoring.ui", widget) @@ -102,12 +104,14 @@ class Saffire_Dice(Generic_Dice_EAP): LineInfo = namedtuple('LineInfo', ['widget','Interface']) self.nbLines = 4 - # Mono/Stereo Switch self.LineMonos = [] - p = LineInfo(widget.Mono_12, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/Mono/Line1Line2")) - self.LineMonos.append(p) - p = LineInfo(widget.Mono_34, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/Mono/Line3Line4")) - self.LineMonos.append(p) + if ModelName != "SAFFIRE_PRO26": + # TODO: is this redundant on any other interface? + # Mono/Stereo Switch + p = LineInfo(widget.Mono_12, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/Mono/Line1Line2")) + self.LineMonos.append(p) + p = LineInfo(widget.Mono_34, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/Mono/Line3Line4")) + self.LineMonos.append(p) # Volume Unactivating self.LineUnActivates = [] @@ -166,9 +170,10 @@ class Saffire_Dice(Generic_Dice_EAP): if ModelName != "SAFFIRE_PRO_14": self.nbLines = 6 - # Mono/Stereo Switch - p = LineInfo(widget.Mono_56, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/Mono/Line5Line6")) - self.LineMonos.append(p) + if ModelName != "SAFFIRE_PRO26": + # Mono/Stereo Switch + p = LineInfo(widget.Mono_56, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/Mono/Line5Line6")) + self.LineMonos.append(p) # Volume Unactivating p = LineInfo(widget.LineUnActivate_5, BooleanControl(self.hw, self.hw.basepath+"/EAP/Monitoring/LineOut/UnActivate5")) self.LineUnActivates.append(p) @@ -253,7 +258,7 @@ class Saffire_Dice(Generic_Dice_EAP): widget.AdatSpdif.setChecked(self.adatSpdifInterface.selected()) self.connect(widget.AdatSpdif, QtCore.SIGNAL("toggled(bool)"), self.adatSpdifToggle) - else: + if ModelName in ("SAFFIRE_PRO_14", "SAFFIRE_PRO_24"): # Line/Inst and Hi/Lo switches for Pro14 and 24 widget.LineInSwitches.setVisible(True) self.LineInSwitches = [] @@ -272,12 +277,12 @@ class Saffire_Dice(Generic_Dice_EAP): widget.LineInSwitchLine_2.setChecked(not self.LineInSwitches[1].Interface.selected()) widget.LineInSwitchLo_3.setChecked(not self.LineInSwitches[2].Interface.selected()) widget.LineInSwitchLo_4.setChecked(not self.LineInSwitches[3].Interface.selected()) - - # Mono/Stereo Switch - for i in range(self.nbLines/2): - self.LineMonos[i].widget.setChecked(self.LineMonos[i].Interface.selected()) - self.connect(self.LineMonos[i].widget, QtCore.SIGNAL("toggled(bool)"), self.LineMonos[i].Interface.select) + # Mono/Stereo Switch + if ModelName != "SAFFIRE_PRO26": + for i in range(self.nbLines/2): + self.LineMonos[i].widget.setChecked(self.LineMonos[i].Interface.selected()) + self.connect(self.LineMonos[i].widget, QtCore.SIGNAL("toggled(bool)"), self.LineMonos[i].Interface.select) for i in range(self.nbLines): @@ -319,8 +324,8 @@ class Saffire_Dice(Generic_Dice_EAP): self.LineGMutes[i].widget.setChecked(True) self.L... [truncated message content] |