/*
* Copyright (C) 2005-2008 by Pieter Palmers
*
* 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 .
*
*/
#include "focusrite_saffire.h"
#include "focusrite_cmd.h"
namespace BeBoB {
namespace Focusrite {
SaffireDevice::SaffireDevice( DeviceManager& d, std::auto_ptr( configRom ))
: FocusriteDevice( d, configRom)
, m_MixerContainer( NULL )
{
debugOutput( DEBUG_LEVEL_VERBOSE, "Created BeBoB::Focusrite::SaffireDevice (NodeID %d)\n",
getConfigRom().getNodeId() );
// the saffire doesn't seem to like it if the commands are too fast
if (AVC::AVCCommand::getSleepAfterAVCCommand() < 1000) {
AVC::AVCCommand::setSleepAfterAVCCommand( 1000 );
}
if(getConfigRom().getGuid() < 0x130e0100040000LL) {
m_isSaffireLE = false;
} else {
m_isSaffireLE = true;
}
}
bool
SaffireDevice::buildMixer()
{
bool result=true;
debugOutput(DEBUG_LEVEL_VERBOSE, "Building a Focusrite Saffire mixer...\n");
destroyMixer();
// create the mixer object container
m_MixerContainer = new Control::Container(this, "Mixer");
if (!m_MixerContainer) {
debugError("Could not create mixer container...\n");
return false;
}
if(m_isSaffireLE) {
// create control objects for the saffire LE
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_SPDIF_TRANSPARENT, 0,
"SpdifTransparent", "S/PDIF Transparent", "S/PDIF Transparent"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_MIDITHRU, 0,
"MidiThru", "MIDI Thru", "MIDI Thru"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_SAVE_SETTINGS, 0,
"SaveSettings", "Save Settings", "Save Settings"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_HIGH_GAIN_LINE3, 0,
"HighGainLine3", "High Gain Line-in 3", "High Gain Line-in 3"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_HIGH_GAIN_LINE4, 0,
"HighGainLine4", "High Gain Line-in 4", "High Gain Line-in 4"));
// output mute controls
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_MUTE,
"Out12Mute", "Out1/2 Mute", "Output 1/2 Mute"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_MUTE,
"Out34Mute", "Out3/4 Mute", "Output 3/4 Mute"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_MUTE,
"Out56Mute", "Out5/6 Mute", "Output 5/6 Mute"));
// output front panel hw volume control
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out12HwCtrl", "Out1/2 HwCtrl", "Output 1/2 Front Panel Hardware volume control"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out34HwCtrl", "Out3/4 HwCtrl", "Output 3/4 Front Panel Hardware volume control"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out56HwCtrl", "Out5/6 HwCtrl", "Output 5/6 Front Panel Hardware volume control"));
// dac ignore
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out12DacIgnore", "Out1/2 Dac Ignore", "Output 1/2 Dac Ignore"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out34DacIgnore", "Out3/4 Dac Ignore", "Output 3/4 Dac Ignore"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out56DacIgnore", "Out5/6 Dac Ignore", "Output 5/6 Dac Ignore"));
// output level controls
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_DAC,
"Out12Level", "Out1/2 Level", "Output 1/2 Level"));
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_DAC,
"Out34Level", "Out3/4 Level", "Output 3/4 Level"));
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRELE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRELE_CMD_ID_BITFIELD_BIT_DAC,
"Out56Level", "Out5/6 Level", "Output 5/6 Level"));
} else {
// create control objects for the saffire
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_SPDIF_SWITCH, 0,
"SpdifSwitch", "S/PDIF Switch", "S/PDIF Switch"));
// output mute controls
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_MUTE,
"Out12Mute", "Out1/2 Mute", "Output 1/2 Mute"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_MUTE,
"Out34Mute", "Out3/4 Mute", "Output 3/4 Mute"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_MUTE,
"Out56Mute", "Out5/6 Mute", "Output 5/6 Mute"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT78, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_MUTE,
"Out78Mute", "Out7/8 Mute", "Output 7/8 Mute"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT910, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_MUTE,
"Out910Mute", "Out9/10 Mute", "Output 9/10 Mute"));
// output front panel hw volume control
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out12HwCtrl", "Out1/2 HwCtrl", "Output 1/2 Front Panel Hardware volume control"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out34HwCtrl", "Out3/4 HwCtrl", "Output 3/4 Front Panel Hardware volume control"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out56HwCtrl", "Out5/6 HwCtrl", "Output 5/6 Front Panel Hardware volume control"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT78, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_HWCTRL,
"Out78HwCtrl", "Out7/8 HwCtrl", "Output 7/8 Front Panel Hardware volume control"));
// output level dim
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DIM,
"Out12Dim", "Out1/2 Dim", "Output 1/2 Level Dim"));
// dac ignore
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out12DacIgnore", "Out1/2 Dac Ignore", "Output 1/2 Dac Ignore"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out34DacIgnore", "Out3/4 Dac Ignore", "Output 3/4 Dac Ignore"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out56DacIgnore", "Out5/6 Dac Ignore", "Output 5/6 Dac Ignore"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT78, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DACIGNORE,
"Out78DacIgnore", "Out7/8 Dac Ignore", "Output 7/8 Dac Ignore"));
// output level controls
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT12, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DAC,
"Out12Level", "Out1/2 Level", "Output 1/2 Level"));
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT34, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DAC,
"Out34Level", "Out3/4 Level", "Output 3/4 Level"));
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT56, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DAC,
"Out56Level", "Out5/6 Level", "Output 5/6 Level"));
result &= m_MixerContainer->addElement(
new VolumeControlLowRes(*this,
FR_SAFFIRE_CMD_ID_BITFIELD_OUT78, FR_SAFFIRE_CMD_ID_BITFIELD_BIT_DAC,
"Out78Level", "Out7/8 Level", "Output 7/8 Level"));
}
// matrix mix controls
if(m_isSaffireLE) {
result &= m_MixerContainer->addElement(
new SaffireMatrixMixer(*this, SaffireMatrixMixer::eMMT_LEMix48, "LEMix48"));
result &= m_MixerContainer->addElement(
new SaffireMatrixMixer(*this, SaffireMatrixMixer::eMMT_LEMix96, "LEMix96"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_SWAP_OUT4_OUT1_48K, 0,
"Swap41_48", "Swap41_48", "Swap41_48"));
result &= m_MixerContainer->addElement(
new BinaryControl(*this,
FR_SAFFIRELE_CMD_ID_SWAP_OUT4_OUT1_96K, 0,
"Swap41_96", "Swap41_96", "Swap41_96"));
} else {
result &= m_MixerContainer->addElement(
new SaffireMatrixMixer(*this, SaffireMatrixMixer::eMMT_InputMix, "InputMix"));
result &= m_MixerContainer->addElement(
new SaffireMatrixMixer(*this, SaffireMatrixMixer::eMMT_PCMix, "PCMix"));
}
if (!result) {
debugWarning("One or more control elements could not be created.");
// clean up those that were created
destroyMixer();
return false;
}
if (!addElement(m_MixerContainer)) {
debugWarning("Could not register mixer to device\n");
// clean up
destroyMixer();
return false;
}
// add a direct register access element
if (!addElement(new RegisterControl(*this, "Register", "Register Access", "Direct register access"))) {
debugWarning("Could not create register control element.");
// clean up those that were created
destroyMixer();
return false;
}
return true;
}
bool
SaffireDevice::destroyMixer()
{
debugOutput(DEBUG_LEVEL_VERBOSE, "destroy mixer...\n");
if (m_MixerContainer == NULL) {
debugOutput(DEBUG_LEVEL_VERBOSE, "no mixer to destroy...\n");
return true;
}
if (!deleteElement(m_MixerContainer)) {
debugError("Mixer present but not registered to the avdevice\n");
return false;
}
// remove and delete (as in free) child control elements
m_MixerContainer->clearElements(true);
delete m_MixerContainer;
return true;
}
void
SaffireDevice::showDevice()
{
if(m_isSaffireLE) {
debugOutput(DEBUG_LEVEL_NORMAL, "This is a BeBoB::Focusrite::SaffireDevice (Saffire LE)\n");
} else {
debugOutput(DEBUG_LEVEL_NORMAL, "This is a BeBoB::Focusrite::SaffireDevice (Saffire)\n");
}
FocusriteDevice::showDevice();
}
void
SaffireDevice::setVerboseLevel(int l)
{
debugOutput( DEBUG_LEVEL_VERBOSE, "Setting verbose level to %d...\n", l );
FocusriteDevice::setVerboseLevel(l);
}
// Saffire pro matrix mixer element
SaffireMatrixMixer::SaffireMatrixMixer(SaffireDevice& p,
enum eMatrixMixerType type)
: FocusriteMatrixMixer(p, "MatrixMixer")
, m_type(type)
{
init();
}
SaffireMatrixMixer::SaffireMatrixMixer(SaffireDevice& p,
enum eMatrixMixerType type, std::string n)
: FocusriteMatrixMixer(p, n)
, m_type(type)
{
init();
}
void SaffireMatrixMixer::init()
{
if (m_type==eMMT_PCMix) {
addSignalInfo(m_RowInfo, "PC12", "PC 1/2", "PC Channel 1/2");
addSignalInfo(m_RowInfo, "PC34", "PC 3/4", "PC Channel 3/4");
addSignalInfo(m_RowInfo, "PC56", "PC 5/6", "PC Channel 5/6");
addSignalInfo(m_RowInfo, "PC78", "PC 7/8", "PC Channel 7/8");
addSignalInfo(m_RowInfo, "PC910", "PC 9/10", "PC Channel 9/10");
addSignalInfo(m_ColInfo, "OUT12", "OUT 1/2", "Output 1/2");
addSignalInfo(m_ColInfo, "OUT34", "OUT 3/4", "Output 3/4");
addSignalInfo(m_ColInfo, "OUT56", "OUT 5/6", "Output 5/6");
addSignalInfo(m_ColInfo, "OUT78", "OUT 7/8", "Output 7/8");
addSignalInfo(m_ColInfo, "OUT910", "OUT 9/10", "Output 9/10");
// init the cell matrix
#define FOCUSRITE_SAFFIRE_PCMIX_NB_COLS 5
#define FOCUSRITE_SAFFIRE_PCMIX_NB_ROWS 5
std::vector tmp_cols( FOCUSRITE_SAFFIRE_PCMIX_NB_COLS );
std::vector< std::vector > tmp_all(FOCUSRITE_SAFFIRE_PCMIX_NB_ROWS, tmp_cols);
m_CellInfo = tmp_all;
struct sCellInfo c;
c.row=-1;
c.col=-1;
c.valid=false;
c.address=0;
for (int i=0;i tmp_cols( FOCUSRITE_SAFFIRE_INPUTMIX_NB_COLS );
std::vector< std::vector > tmp_all(FOCUSRITE_SAFFIRE_INPUTMIX_NB_ROWS,tmp_cols);
m_CellInfo = tmp_all;
struct sCellInfo c;
c.row=-1;
c.col=-1;
c.valid=false;
c.address=0;
for (int i=0;i tmp_cols( FOCUSRITE_SAFFIRELE_48KMIX_NB_COLS );
std::vector< std::vector > tmp_all(FOCUSRITE_SAFFIRELE_48KMIX_NB_ROWS,tmp_cols);
m_CellInfo = tmp_all;
struct sCellInfo c;
c.row=-1;
c.col=-1;
c.valid=false;
c.address=0;
for (int i=0;i tmp_cols( FOCUSRITE_SAFFIRELE_96KMIX_NB_COLS );
std::vector< std::vector > tmp_all(FOCUSRITE_SAFFIRELE_96KMIX_NB_ROWS,tmp_cols);
m_CellInfo = tmp_all;
struct sCellInfo c;
c.row=-1;
c.col=-1;
c.valid=false;
c.address=0;
for (int i=0;i