New Select switch. All selected channels can be modified in their faders levels at the same time. Useful if channels are organized by instruments, set same level to similar instruments or to raise level of one particular set
1181 lines
44 KiB
C++
Executable File
1181 lines
44 KiB
C++
Executable File
/******************************************************************************\
|
|
* Copyright (c) 2004-2020
|
|
*
|
|
* Author(s):
|
|
* Volker Fischer
|
|
*
|
|
******************************************************************************
|
|
*
|
|
* 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) any later
|
|
* version.
|
|
*
|
|
* 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, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*
|
|
\******************************************************************************/
|
|
|
|
#include "audiomixerboard.h"
|
|
|
|
|
|
/******************************************************************************\
|
|
* CChanneFader *
|
|
\******************************************************************************/
|
|
CChannelFader::CChannelFader ( QWidget* pNW )
|
|
{
|
|
// create new GUI control objects and store pointers to them (note that
|
|
// QWidget takes the ownership of the pMainGrid so that this only has
|
|
// to be created locally in this constructor)
|
|
pFrame = new QFrame ( pNW );
|
|
|
|
pLevelsBox = new QWidget ( pFrame );
|
|
plbrChannelLevel = new CMultiColorLEDBar ( pLevelsBox );
|
|
pFader = new QSlider ( Qt::Vertical, pLevelsBox );
|
|
pPan = new QDial ( pLevelsBox );
|
|
pPanLabel = new QLabel ( tr ( "Pan" ), pLevelsBox );
|
|
pInfoLabel = new QLabel ( "", pLevelsBox );
|
|
|
|
pMuteSoloBox = new QWidget ( pFrame );
|
|
pcbMute = new QCheckBox ( tr ( "Mute" ), pMuteSoloBox );
|
|
pcbSolo = new QCheckBox ( tr ( "Solo" ), pMuteSoloBox );
|
|
pcbSelect = new QCheckBox ( tr ( "Select"), pMuteSoloBox );
|
|
|
|
pLabelInstBox = new QGroupBox ( pFrame );
|
|
plblLabel = new QLabel ( "", pFrame );
|
|
plblInstrument = new QLabel ( pFrame );
|
|
plblCountryFlag = new QLabel ( pFrame );
|
|
|
|
QVBoxLayout* pMainGrid = new QVBoxLayout ( pFrame );
|
|
QHBoxLayout* pLevelsGrid = new QHBoxLayout ( pLevelsBox );
|
|
QVBoxLayout* pMuteSoloGrid = new QVBoxLayout ( pMuteSoloBox );
|
|
pLabelGrid = new QHBoxLayout ( pLabelInstBox );
|
|
pLabelPictGrid = new QVBoxLayout ( );
|
|
QVBoxLayout* pPanGrid = new QVBoxLayout ( );
|
|
QHBoxLayout* pPanInfoGrid = new QHBoxLayout ( );
|
|
|
|
// setup channel level
|
|
plbrChannelLevel->setContentsMargins ( 0, 3, 2, 3 );
|
|
|
|
// setup slider
|
|
pFader->setPageStep ( 1 );
|
|
pFader->setRange ( 0, AUD_MIX_FADER_MAX );
|
|
pFader->setTickInterval ( AUD_MIX_FADER_MAX / 9 );
|
|
pFader->setMinimumHeight ( 85 ); // if this value is too small, the fader might not be movable with the mouse for fancy skin (#292)
|
|
|
|
// setup panning control
|
|
pPan->setRange ( 0, AUD_MIX_PAN_MAX );
|
|
pPan->setValue ( AUD_MIX_PAN_MAX / 2 );
|
|
pPan->setNotchesVisible ( true );
|
|
pPanInfoGrid->addWidget ( pPanLabel, 0, Qt::AlignLeft );
|
|
pPanInfoGrid->addWidget ( pInfoLabel );
|
|
pPanGrid->addLayout ( pPanInfoGrid );
|
|
pPanGrid->addWidget ( pPan, 0, Qt::AlignHCenter );
|
|
|
|
// setup fader tag label (black bold text which is centered)
|
|
plblLabel->setTextFormat ( Qt::PlainText );
|
|
plblLabel->setAlignment ( Qt::AlignHCenter | Qt::AlignVCenter );
|
|
plblLabel->setStyleSheet ( "QLabel { color: black; font: bold; }" );
|
|
|
|
// set margins of the layouts to zero to get maximum space for the controls
|
|
pMainGrid->setContentsMargins ( 0, 0, 0, 0 );
|
|
|
|
pPanGrid->setContentsMargins ( 0, 0, 0, 0 );
|
|
pPanGrid->setSpacing ( 0 ); // only minimal space
|
|
|
|
pLevelsGrid->setContentsMargins ( 0, 0, 0, 0 );
|
|
pLevelsGrid->setSpacing ( 0 ); // only minimal space
|
|
|
|
pMuteSoloGrid->setContentsMargins ( 0, 0, 0, 0 );
|
|
|
|
pLabelGrid->setContentsMargins ( 0, 0, 0, 0 );
|
|
pLabelGrid->setSpacing ( 2 ); // only minimal space between picture and text
|
|
|
|
// add user controls to the grids
|
|
pLabelPictGrid->addWidget ( plblCountryFlag, 0, Qt::AlignHCenter );
|
|
pLabelPictGrid->addWidget ( plblInstrument, 0, Qt::AlignHCenter );
|
|
|
|
pLabelGrid->addLayout ( pLabelPictGrid );
|
|
pLabelGrid->addWidget ( plblLabel, 0, Qt::AlignVCenter ); // note: just initial add, may be changed later
|
|
|
|
pLevelsGrid->addWidget ( plbrChannelLevel, 0, Qt::AlignRight );
|
|
pLevelsGrid->addWidget ( pFader, 0, Qt::AlignLeft );
|
|
|
|
pMuteSoloGrid->addWidget ( pcbMute, 0, Qt::AlignLeft );
|
|
pMuteSoloGrid->addWidget ( pcbSolo, 0, Qt::AlignLeft );
|
|
pMuteSoloGrid->addWidget ( pcbSelect, 0, Qt::AlignLeft );
|
|
|
|
pMainGrid->addLayout ( pPanGrid );
|
|
pMainGrid->addWidget ( pLevelsBox, 0, Qt::AlignHCenter );
|
|
pMainGrid->addWidget ( pMuteSoloBox, 0, Qt::AlignHCenter );
|
|
pMainGrid->addWidget ( pLabelInstBox );
|
|
|
|
// reset current fader
|
|
Reset();
|
|
|
|
// add help text to controls
|
|
plbrChannelLevel->setWhatsThis ( "<b>" + tr ( "Channel Level" ) + ":</b> " +
|
|
tr ( "Displays the pre-fader audio level of this channel. All clients connected to the "
|
|
"server will be assigned an audio level, the same value for every client." ) );
|
|
plbrChannelLevel->setAccessibleName ( tr ( "Input level of the current audio "
|
|
"channel at the server" ) );
|
|
|
|
pFader->setWhatsThis ( "<b>" + tr ( "Mixer Fader" ) + ":</b> " + tr (
|
|
"Adjusts the audio level of this channel. All clients connected to the server "
|
|
"will be assigned an audio fader, displayed at each client, to adjust the local mix." ) );
|
|
pFader->setAccessibleName ( tr ( "Local mix level setting of the current audio "
|
|
"channel at the server" ) );
|
|
|
|
pInfoLabel->setWhatsThis ( "<b>" + tr ( "Status Indicator" ) + ":</b> " + tr (
|
|
"Shows a status indication about the client which is assigned to this channel. "
|
|
"Supported indicators are:" ) + "<ul><li>" + tr (
|
|
"Speaker with cancellation stroke: Indicates that another client has muted you." ) +
|
|
"</li></ul>" );
|
|
pInfoLabel->setAccessibleName ( tr ( "Status indicator label" ) );
|
|
|
|
pPan->setWhatsThis ( "<b>" + tr ( "Panning" ) + ":</b> " + tr (
|
|
"Sets the pan from Left to Right of the channel. "
|
|
"Works only in stereo or preferably mono in/stereo out mode." ) );
|
|
pPan->setAccessibleName ( tr ( "Local panning position of the current audio channel at the server" ) );
|
|
|
|
pcbMute->setWhatsThis ( "<b>" + tr ( "Mute" ) + ":</b> " + tr (
|
|
"With the Mute checkbox, the audio channel can be muted." ) );
|
|
pcbMute->setAccessibleName ( tr ( "Mute button" ) );
|
|
|
|
pcbSolo->setWhatsThis ( "<b>" + tr ( "Solo" ) + ":</b> " + tr ( "With the Solo checkbox, the "
|
|
"audio channel can be set to solo which means that all other channels "
|
|
"except the soloed channel are muted. It is possible to set more than "
|
|
"one channel to solo." ) );
|
|
pcbSolo->setAccessibleName ( tr ( "Solo button" ) );
|
|
|
|
pcbSelect->setWhatsThis ( "<b>" + tr ( "Select" ) + ":</b> " + tr ( "With the Select checkbox, the "
|
|
"audio channel can be selected among others which means that all changes "
|
|
" made in any of the selected channels' fader are adjusted to the rest like all were the same "
|
|
) );
|
|
pcbSelect->setAccessibleName ( tr ( "Select button" ) );
|
|
|
|
|
|
QString strFaderText = "<b>" + tr ( "Fader Tag" ) + ":</b> " + tr ( "The fader tag "
|
|
"identifies the connected client. The tag name, a picture of your "
|
|
"instrument and the flag of your country can be set in the main window." );
|
|
|
|
plblInstrument->setWhatsThis ( strFaderText );
|
|
plblInstrument->setAccessibleName ( tr ( "Mixer channel instrument picture" ) );
|
|
plblLabel->setWhatsThis ( strFaderText );
|
|
plblLabel->setAccessibleName ( tr ( "Mixer channel label (fader tag)" ) );
|
|
plblCountryFlag->setWhatsThis ( strFaderText );
|
|
plblCountryFlag->setAccessibleName ( tr ( "Mixer channel country flag" ) );
|
|
|
|
|
|
// Connections -------------------------------------------------------------
|
|
QObject::connect ( pFader, &QSlider::valueChanged,
|
|
this, &CChannelFader::OnLevelValueChanged );
|
|
|
|
QObject::connect ( pPan, &QDial::valueChanged,
|
|
this, &CChannelFader::OnPanValueChanged );
|
|
|
|
QObject::connect ( pcbMute, &QCheckBox::stateChanged,
|
|
this, &CChannelFader::OnMuteStateChanged );
|
|
|
|
QObject::connect ( pcbSolo, &QCheckBox::stateChanged,
|
|
this, &CChannelFader::soloStateChanged );
|
|
|
|
QObject::connect ( pcbSelect, &QCheckBox::stateChanged,
|
|
this, &CChannelFader::OnSelectStateChanged );
|
|
}
|
|
|
|
void CChannelFader::SetGUIDesign ( const EGUIDesign eNewDesign )
|
|
{
|
|
switch ( eNewDesign )
|
|
{
|
|
case GD_ORIGINAL:
|
|
pFader->setStyleSheet (
|
|
"QSlider { width: 45px;"
|
|
" border-image: url(:/png/fader/res/faderbackground.png) repeat;"
|
|
" border-top: 10px transparent;"
|
|
" border-bottom: 10px transparent;"
|
|
" border-left: 20px transparent;"
|
|
" border-right: -25px transparent; }"
|
|
"QSlider::groove { image: url();"
|
|
" padding-left: -38px;"
|
|
" padding-top: -10px;"
|
|
" padding-bottom: -15px; }"
|
|
"QSlider::handle { image: url(:/png/fader/res/faderhandle.png); }" );
|
|
|
|
pLabelGrid->addWidget ( plblLabel, 0, Qt::AlignVCenter ); // label next to icons
|
|
pLabelInstBox->setMinimumHeight ( 52 ); // maximum hight of the instrument+flag pictures
|
|
pPan->setFixedSize ( 50, 50 );
|
|
pPanLabel->setText ( tr ( "PAN" ) );
|
|
pcbMute->setText ( tr ( "MUTE" ) );
|
|
pcbSolo->setText ( tr ( "SOLO" ) );
|
|
pcbSelect->setText ( tr ( "SELECT" ) );
|
|
plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_LED );
|
|
break;
|
|
|
|
case GD_SLIMFADER:
|
|
pLabelPictGrid->addWidget ( plblLabel, 0, Qt::AlignHCenter ); // label below icons
|
|
pLabelInstBox->setMinimumHeight ( 84 ); // maximum hight of the instrument+flag+label
|
|
pPan->setFixedSize ( 28, 28 );
|
|
pFader->setTickPosition ( QSlider::NoTicks );
|
|
pFader->setStyleSheet ( "" );
|
|
pPanLabel->setText ( tr ( "Pan" ) );
|
|
pcbMute->setText ( tr ( "M" ) );
|
|
pcbSolo->setText ( tr ( "S" ) );
|
|
pcbSelect->setText ( tr ( "SL" ) );
|
|
plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_SLIM_BAR );
|
|
break;
|
|
|
|
default:
|
|
// reset style sheet and set original paramters
|
|
pFader->setTickPosition ( QSlider::TicksBothSides );
|
|
pFader->setStyleSheet ( "" );
|
|
pLabelGrid->addWidget ( plblLabel, 0, Qt::AlignVCenter ); // label next to icons
|
|
pLabelInstBox->setMinimumHeight ( 52 ); // maximum hight of the instrument+flag pictures
|
|
pPan->setFixedSize ( 50, 50 );
|
|
pPanLabel->setText ( tr ( "Pan" ) );
|
|
pcbMute->setText ( tr ( "Mute" ) );
|
|
pcbSolo->setText ( tr ( "Solo" ) );
|
|
pcbSelect->setText ( tr ( "Select" ) );
|
|
plbrChannelLevel->SetLevelMeterType ( CMultiColorLEDBar::MT_BAR );
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CChannelFader::SetDisplayChannelLevel ( const bool eNDCL )
|
|
{
|
|
plbrChannelLevel->setHidden ( !eNDCL );
|
|
}
|
|
|
|
bool CChannelFader::GetDisplayChannelLevel()
|
|
{
|
|
return !plbrChannelLevel->isHidden();
|
|
}
|
|
|
|
void CChannelFader::SetDisplayPans ( const bool eNDP )
|
|
{
|
|
pInfoLabel->setHidden ( !eNDP );
|
|
pPanLabel->setHidden ( !eNDP );
|
|
pPan->setHidden ( !eNDP );
|
|
}
|
|
|
|
void CChannelFader::SetupFaderTag ( const ESkillLevel eSkillLevel )
|
|
{
|
|
// setup group box for label/instrument picture: set a thick black border
|
|
// with nice round edges
|
|
QString strStile =
|
|
"QGroupBox { border: 2px solid black;"
|
|
" border-radius: 4px;"
|
|
" padding: 3px;";
|
|
|
|
// the background color depends on the skill level
|
|
switch ( eSkillLevel )
|
|
{
|
|
case SL_BEGINNER:
|
|
strStile += QString ( "background-color: rgb(%1, %2, %3); }" ).
|
|
arg ( RGBCOL_R_SL_BEGINNER ).
|
|
arg ( RGBCOL_G_SL_BEGINNER ).
|
|
arg ( RGBCOL_B_SL_BEGINNER );
|
|
break;
|
|
|
|
case SL_INTERMEDIATE:
|
|
strStile += QString ( "background-color: rgb(%1, %2, %3); }" ).
|
|
arg ( RGBCOL_R_SL_INTERMEDIATE ).
|
|
arg ( RGBCOL_G_SL_INTERMEDIATE ).
|
|
arg ( RGBCOL_B_SL_INTERMEDIATE );
|
|
break;
|
|
|
|
case SL_PROFESSIONAL:
|
|
strStile += QString ( "background-color: rgb(%1, %2, %3); }" ).
|
|
arg ( RGBCOL_R_SL_SL_PROFESSIONAL ).
|
|
arg ( RGBCOL_G_SL_SL_PROFESSIONAL ).
|
|
arg ( RGBCOL_B_SL_SL_PROFESSIONAL );
|
|
break;
|
|
|
|
default:
|
|
strStile += QString ( "background-color: rgb(%1, %2, %3); }" ).
|
|
arg ( RGBCOL_R_SL_NOT_SET ).
|
|
arg ( RGBCOL_G_SL_NOT_SET ).
|
|
arg ( RGBCOL_B_SL_NOT_SET );
|
|
break;
|
|
}
|
|
|
|
pLabelInstBox->setStyleSheet ( strStile );
|
|
}
|
|
|
|
void CChannelFader::Reset()
|
|
{
|
|
// general initializations
|
|
SetRemoteFaderIsMute ( false );
|
|
|
|
// init gain and pan value -> maximum value as definition according to server
|
|
pFader->setValue ( AUD_MIX_FADER_MAX );
|
|
pPan->setValue ( AUD_MIX_PAN_MAX / 2 );
|
|
|
|
// reset mute/solo check boxes and level meter
|
|
pcbMute->setChecked ( false );
|
|
pcbSolo->setChecked ( false );
|
|
pcbSelect->setChecked ( false );
|
|
plbrChannelLevel->setValue ( 0 );
|
|
|
|
// clear instrument picture, country flag, tool tips and label text
|
|
plblLabel->setText ( "" );
|
|
plblLabel->setToolTip ( "" );
|
|
plblInstrument->setVisible ( false );
|
|
plblInstrument->setToolTip ( "" );
|
|
plblCountryFlag->setVisible ( false );
|
|
plblCountryFlag->setToolTip ( "" );
|
|
cReceivedChanInfo = CChannelInfo();
|
|
SetupFaderTag ( SL_NOT_SET );
|
|
|
|
// set a defined tool tip time out
|
|
const int iToolTipDurMs = 30000;
|
|
plblLabel->setToolTipDuration ( iToolTipDurMs );
|
|
plblInstrument->setToolTipDuration ( iToolTipDurMs );
|
|
plblCountryFlag->setToolTipDuration ( iToolTipDurMs );
|
|
|
|
bOtherChannelIsSolo = false;
|
|
bIsMyOwnFader = false;
|
|
bIsSelected = false;
|
|
}
|
|
|
|
void CChannelFader::SetFaderLevel ( const int iLevel )
|
|
{
|
|
// first make a range check
|
|
if ( ( iLevel >= 0 ) && ( iLevel <= AUD_MIX_FADER_MAX ) )
|
|
{
|
|
// we set the new fader level in the GUI (slider control) and also tell the
|
|
// server about the change
|
|
pFader->setValue ( iLevel );
|
|
SendFaderLevelToServer ( iLevel );
|
|
}
|
|
}
|
|
|
|
void CChannelFader::SetPanValue ( const int iPan )
|
|
{
|
|
// first make a range check
|
|
if ( ( iPan >= 0 ) && ( iPan <= AUD_MIX_PAN_MAX ) )
|
|
{
|
|
// we set the new fader level in the GUI (slider control) and also tell the
|
|
// server about the change
|
|
pPan->setValue ( iPan );
|
|
SendPanValueToServer ( iPan );
|
|
}
|
|
}
|
|
|
|
void CChannelFader::SetFaderIsSolo ( const bool bIsSolo )
|
|
{
|
|
// changing the state automatically emits the signal, too
|
|
pcbSolo->setChecked ( bIsSolo );
|
|
}
|
|
|
|
void CChannelFader::SetFaderIsMute ( const bool bIsMute )
|
|
{
|
|
// changing the state automatically emits the signal, too
|
|
pcbMute->setChecked ( bIsMute );
|
|
}
|
|
|
|
void CChannelFader::SetRemoteFaderIsMute ( const bool bIsMute )
|
|
{
|
|
if ( bIsMute )
|
|
{
|
|
// show orange utf8 SPEAKER WITH CANCELLATION STROKE (U+1F507)
|
|
pInfoLabel->setText ( "<font color=""orange"">🔇</font>" );
|
|
}
|
|
else
|
|
{
|
|
pInfoLabel->setText ( "" );
|
|
}
|
|
}
|
|
|
|
void CChannelFader::SetFaderIsSelect ( const bool bIsSelected )
|
|
{
|
|
pcbSelect->setChecked ( bIsSelected );
|
|
}
|
|
|
|
void CChannelFader::SendFaderLevelToServer ( const int iLevel )
|
|
{
|
|
// if mute flag is set or other channel is on solo, do not apply the new
|
|
// fader value (exception: we are on solo, in that case we ignore the
|
|
// "other channel is on solo" flag)
|
|
if ( ( pcbMute->checkState() == Qt::Unchecked ) &&
|
|
( !bOtherChannelIsSolo || IsSolo() ) )
|
|
{
|
|
// emit signal for new fader gain value
|
|
emit gainValueChanged ( CalcFaderGain ( iLevel ), bIsMyOwnFader );
|
|
}
|
|
}
|
|
|
|
void CChannelFader::SendPanValueToServer ( const int iPan )
|
|
{
|
|
emit panValueChanged ( static_cast<double> ( iPan ) / AUD_MIX_PAN_MAX );
|
|
}
|
|
|
|
void CChannelFader::OnMuteStateChanged ( int value )
|
|
{
|
|
// call muting function
|
|
SetMute ( static_cast<Qt::CheckState> ( value ) == Qt::Checked );
|
|
}
|
|
|
|
void CChannelFader::SetMute ( const bool bState )
|
|
{
|
|
if ( bState )
|
|
{
|
|
// mute channel -> send gain of 0
|
|
emit gainValueChanged ( 0, bIsMyOwnFader );
|
|
}
|
|
else
|
|
{
|
|
// only unmute if we are not solot but an other channel is on solo
|
|
if ( !bOtherChannelIsSolo || IsSolo() )
|
|
{
|
|
// mute was unchecked, get current fader value and apply
|
|
emit gainValueChanged ( CalcFaderGain ( GetFaderLevel() ), bIsMyOwnFader );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CChannelFader::UpdateSoloState ( const bool bNewOtherSoloState )
|
|
{
|
|
// store state (must be done before the SetMute() call!)
|
|
bOtherChannelIsSolo = bNewOtherSoloState;
|
|
|
|
// mute overwrites solo -> if mute is active, do not change anything
|
|
if ( !pcbMute->isChecked() )
|
|
{
|
|
// mute channel if we are not solo but another channel is solo
|
|
SetMute ( bOtherChannelIsSolo && !IsSolo() );
|
|
}
|
|
}
|
|
|
|
void CChannelFader::SetChannelLevel ( const uint16_t iLevel )
|
|
{
|
|
plbrChannelLevel->setValue ( iLevel );
|
|
}
|
|
|
|
void CChannelFader::SetChannelInfos ( const CChannelInfo& cChanInfo )
|
|
{
|
|
// store received channel info
|
|
cReceivedChanInfo = cChanInfo;
|
|
|
|
// init properties for the tool tip
|
|
int iTTInstrument = CInstPictures::GetNotUsedInstrument();
|
|
QLocale::Country eTTCountry = QLocale::AnyCountry;
|
|
|
|
|
|
// Label text --------------------------------------------------------------
|
|
// break text at predefined position
|
|
const int iBreakPos = MAX_LEN_FADER_TAG / 2;
|
|
|
|
QString strModText = cChanInfo.strName;
|
|
|
|
if ( strModText.length() > iBreakPos )
|
|
{
|
|
strModText.insert ( iBreakPos, QString ( "\n" ) );
|
|
}
|
|
|
|
plblLabel->setText ( strModText );
|
|
|
|
|
|
// Instrument picture ------------------------------------------------------
|
|
// get the resource reference string for this instrument
|
|
const QString strCurResourceRef =
|
|
CInstPictures::GetResourceReference ( cChanInfo.iInstrument );
|
|
|
|
// first check if instrument picture is used or not and if it is valid
|
|
if ( CInstPictures::IsNotUsedInstrument ( cChanInfo.iInstrument ) ||
|
|
strCurResourceRef.isEmpty() )
|
|
{
|
|
// disable instrument picture
|
|
plblInstrument->setVisible ( false );
|
|
}
|
|
else
|
|
{
|
|
// set correct picture
|
|
plblInstrument->setPixmap ( QPixmap ( strCurResourceRef ) );
|
|
iTTInstrument = cChanInfo.iInstrument;
|
|
|
|
// enable instrument picture
|
|
plblInstrument->setVisible ( true );
|
|
}
|
|
|
|
|
|
// Country flag icon -------------------------------------------------------
|
|
if ( cChanInfo.eCountry != QLocale::AnyCountry )
|
|
{
|
|
// try to load the country flag icon
|
|
QPixmap CountryFlagPixmap ( CLocale::GetCountryFlagIconsResourceReference ( cChanInfo.eCountry ) );
|
|
|
|
// first check if resource reference was valid
|
|
if ( CountryFlagPixmap.isNull() )
|
|
{
|
|
// disable country flag
|
|
plblCountryFlag->setVisible ( false );
|
|
}
|
|
else
|
|
{
|
|
// set correct picture
|
|
plblCountryFlag->setPixmap ( CountryFlagPixmap );
|
|
eTTCountry = cChanInfo.eCountry;
|
|
|
|
// enable country flag
|
|
plblCountryFlag->setVisible ( true );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// disable country flag
|
|
plblCountryFlag->setVisible ( false );
|
|
}
|
|
|
|
|
|
// Skill level background color --------------------------------------------
|
|
SetupFaderTag ( cChanInfo.eSkillLevel );
|
|
|
|
|
|
// Tool tip ----------------------------------------------------------------
|
|
// complete musician profile in the tool tip
|
|
QString strToolTip = "";
|
|
|
|
// alias/name
|
|
if ( !cChanInfo.strName.isEmpty() )
|
|
{
|
|
strToolTip += "<h4>" + tr ( "Alias/Name" ) + "</h4>" + cChanInfo.strName;
|
|
}
|
|
|
|
// instrument
|
|
if ( !CInstPictures::IsNotUsedInstrument ( iTTInstrument ) )
|
|
{
|
|
strToolTip += "<h4>" + tr ( "Instrument" ) + "</h4>" +
|
|
CInstPictures::GetName ( iTTInstrument );
|
|
}
|
|
|
|
// location
|
|
if ( ( eTTCountry != QLocale::AnyCountry ) ||
|
|
( !cChanInfo.strCity.isEmpty() ) )
|
|
{
|
|
strToolTip += "<h4>" + tr ( "Location" ) + "</h4>";
|
|
|
|
if ( !cChanInfo.strCity.isEmpty() )
|
|
{
|
|
strToolTip += cChanInfo.strCity;
|
|
|
|
if ( eTTCountry != QLocale::AnyCountry )
|
|
{
|
|
strToolTip += ", ";
|
|
}
|
|
}
|
|
|
|
if ( eTTCountry != QLocale::AnyCountry )
|
|
{
|
|
strToolTip += QLocale::countryToString ( eTTCountry );
|
|
}
|
|
}
|
|
|
|
// skill level
|
|
switch ( cChanInfo.eSkillLevel )
|
|
{
|
|
case SL_BEGINNER:
|
|
strToolTip += "<h4>" + tr ( "Skill Level" ) + "</h4>" + tr ( "Beginner" );
|
|
break;
|
|
|
|
case SL_INTERMEDIATE:
|
|
strToolTip += "<h4>" + tr ( "Skill Level" ) + "</h4>" + tr ( "Intermediate" );
|
|
break;
|
|
|
|
case SL_PROFESSIONAL:
|
|
strToolTip += "<h4>" + tr ( "Skill Level" ) + "</h4>" + tr ( "Expert" );
|
|
break;
|
|
|
|
case SL_NOT_SET:
|
|
// skill level not set, do not add this entry
|
|
break;
|
|
}
|
|
|
|
// if no information is given, leave the tool tip empty, otherwise add header
|
|
if ( !strToolTip.isEmpty() )
|
|
{
|
|
strToolTip.prepend ( "<h3>" + tr ( "Musician Profile" ) + "</h3>" );
|
|
}
|
|
|
|
plblCountryFlag->setToolTip ( strToolTip );
|
|
plblInstrument->setToolTip ( strToolTip );
|
|
plblLabel->setToolTip ( strToolTip );
|
|
}
|
|
|
|
double CChannelFader::CalcFaderGain ( const int value )
|
|
{
|
|
// convert actual slider range in gain values
|
|
// and normalize so that maximum gain is 1
|
|
const double dInValueRange0_1 = static_cast<double> ( value ) / AUD_MIX_FADER_MAX;
|
|
|
|
// map range from 0..1 to range -35..0 dB and calculate linear gain
|
|
if ( value == 0 )
|
|
{
|
|
return 0; // -infinity
|
|
}
|
|
else
|
|
{
|
|
return pow ( 10, ( dInValueRange0_1 * 35 - 35 ) / 20 );
|
|
}
|
|
}
|
|
|
|
void CChannelFader::OnSelectStateChanged ( int value )
|
|
{
|
|
// call selecting function
|
|
SetSelected ( static_cast<Qt::CheckState> ( value ) == Qt::Checked );
|
|
}
|
|
|
|
void CChannelFader::SetSelected ( const bool bState )
|
|
{
|
|
// Just in case we need future actions here...
|
|
bIsSelected = bState;
|
|
}
|
|
|
|
/******************************************************************************\
|
|
* CAudioMixerBoard *
|
|
\******************************************************************************/
|
|
CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent, Qt::WindowFlags ) :
|
|
QGroupBox ( parent ),
|
|
vecStoredFaderTags ( MAX_NUM_STORED_FADER_SETTINGS, "" ),
|
|
vecStoredFaderLevels ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_FADER_MAX ),
|
|
vecStoredPanValues ( MAX_NUM_STORED_FADER_SETTINGS, AUD_MIX_PAN_MAX / 2 ),
|
|
vecStoredFaderIsSolo ( MAX_NUM_STORED_FADER_SETTINGS, false ),
|
|
vecStoredFaderIsMute ( MAX_NUM_STORED_FADER_SETTINGS, false ),
|
|
vecStoredFaderIsSelect( MAX_NUM_STORED_FADER_SETTINGS, false ),
|
|
iNewClientFaderLevel ( 100 ),
|
|
bDisplayPans ( false ),
|
|
bIsPanSupported ( false ),
|
|
bNoFaderVisible ( true ),
|
|
iMyChannelID ( INVALID_INDEX ),
|
|
strServerName ( "" ),
|
|
eRecorderState ( RS_UNDEFINED )
|
|
{
|
|
// add group box and hboxlayout
|
|
QHBoxLayout* pGroupBoxLayout = new QHBoxLayout ( this );
|
|
QWidget* pMixerWidget = new QWidget(); // will be added to the scroll area which is then the parent
|
|
pScrollArea = new CMixerBoardScrollArea ( this );
|
|
pMainLayout = new QHBoxLayout ( pMixerWidget );
|
|
|
|
setAccessibleName ( "Personal Mix at the Server groupbox" );
|
|
setWhatsThis ( "<b>" + tr ( "Personal Mix at the Server" ) + "</b>: " + tr (
|
|
"When connected to a server, the controls here allow you to set your "
|
|
"local mix without affecting what others hear from you. The title shows "
|
|
"the server name and, when known, whether it is actively recording." ) );
|
|
|
|
// set title text (default: no server given)
|
|
SetServerName ( "" );
|
|
|
|
// create all mixer controls and make them invisible
|
|
vecpChanFader.Init ( MAX_NUM_CHANNELS );
|
|
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
vecpChanFader[i] = new CChannelFader ( this );
|
|
vecpChanFader[i]->Hide();
|
|
|
|
// add fader frame to audio mixer board layout
|
|
pMainLayout->addWidget ( vecpChanFader[i]->GetMainWidget() );
|
|
}
|
|
|
|
// insert horizontal spacer
|
|
pMainLayout->addItem ( new QSpacerItem ( 0, 0, QSizePolicy::Expanding ) );
|
|
|
|
// set margins of the layout to zero to get maximum space for the controls
|
|
pGroupBoxLayout->setContentsMargins ( 0, 0, 0, 1 ); // note: to avoid problems at the botton, use a small margin for that
|
|
|
|
// add the group box to the scroll area
|
|
pScrollArea->setMinimumWidth ( 200 ); // at least two faders shall be visible
|
|
pScrollArea->setWidget ( pMixerWidget );
|
|
pScrollArea->setWidgetResizable ( true ); // make sure it fills the entire scroll area
|
|
pScrollArea->setFrameShape ( QFrame::NoFrame );
|
|
pGroupBoxLayout->addWidget ( pScrollArea );
|
|
|
|
|
|
// Connections -------------------------------------------------------------
|
|
connectFaderSignalsToMixerBoardSlots<MAX_NUM_CHANNELS>();
|
|
}
|
|
|
|
template<unsigned int slotId>
|
|
inline void CAudioMixerBoard::connectFaderSignalsToMixerBoardSlots()
|
|
{
|
|
int iCurChanID = slotId - 1;
|
|
|
|
void ( CAudioMixerBoard::* pGainValueChanged )( double, bool ) =
|
|
&CAudioMixerBoardSlots<slotId>::OnChGainValueChanged;
|
|
|
|
void ( CAudioMixerBoard::* pPanValueChanged )( double ) =
|
|
&CAudioMixerBoardSlots<slotId>::OnChPanValueChanged;
|
|
|
|
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::soloStateChanged,
|
|
this, &CAudioMixerBoard::UpdateSoloStates );
|
|
|
|
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::gainValueChanged,
|
|
this, pGainValueChanged );
|
|
|
|
QObject::connect ( vecpChanFader[iCurChanID], &CChannelFader::panValueChanged,
|
|
this, pPanValueChanged );
|
|
|
|
connectFaderSignalsToMixerBoardSlots<slotId - 1>();
|
|
}
|
|
|
|
template<>
|
|
inline void CAudioMixerBoard::connectFaderSignalsToMixerBoardSlots<0>() {}
|
|
|
|
void CAudioMixerBoard::SetServerName ( const QString& strNewServerName )
|
|
{
|
|
// store the current server name
|
|
strServerName = strNewServerName;
|
|
|
|
if ( strServerName.isEmpty() )
|
|
{
|
|
// no connection or connection was reset: show default title
|
|
setTitle ( tr ( "Server" ) );
|
|
}
|
|
else
|
|
{
|
|
// Do not set the server name directly but first show a label which indicates
|
|
// that we are trying to connect the server. First if a connected client
|
|
// list was received, the connection was successful and the title is updated
|
|
// with the correct server name. Make sure to choose a "try to connect" title
|
|
// which is most striking (we use filled blocks and upper case letters).
|
|
setTitle ( u8"\u2588\u2588\u2588\u2588\u2588 " + tr ( "T R Y I N G T O C O N N E C T" ) + u8" \u2588\u2588\u2588\u2588\u2588" );
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::SetGUIDesign ( const EGUIDesign eNewDesign )
|
|
{
|
|
// move the channels tighter together in slim fader mode
|
|
if ( eNewDesign == GD_SLIMFADER )
|
|
{
|
|
pMainLayout->setSpacing ( 2 );
|
|
}
|
|
else
|
|
{
|
|
pMainLayout->setSpacing ( 6 ); // Qt default spacing value
|
|
}
|
|
|
|
// apply GUI design to child GUI controls
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
vecpChanFader[i]->SetGUIDesign ( eNewDesign );
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::SetDisplayChannelLevels ( const bool eNDCL )
|
|
{
|
|
bDisplayChannelLevels = eNDCL;
|
|
|
|
// only update hiding the levels immediately, showing the levels
|
|
// is only applied if the server actually transmits levels
|
|
if ( !bDisplayChannelLevels )
|
|
{
|
|
// hide all level meters
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
vecpChanFader[i]->SetDisplayChannelLevel ( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::SetDisplayPans ( const bool eNDP )
|
|
{
|
|
bDisplayPans = eNDP;
|
|
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
vecpChanFader[i]->SetDisplayPans ( eNDP && bIsPanSupported );
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::SetPanIsSupported()
|
|
{
|
|
bIsPanSupported = true;
|
|
SetDisplayPans ( bDisplayPans );
|
|
}
|
|
|
|
void CAudioMixerBoard::HideAll()
|
|
{
|
|
// make all controls invisible
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
// before hiding the fader, store its level (if some conditions are fullfilled)
|
|
StoreFaderSettings ( vecpChanFader[i] );
|
|
|
|
vecpChanFader[i]->SetChannelLevel ( 0 );
|
|
vecpChanFader[i]->SetDisplayChannelLevel ( false );
|
|
vecpChanFader[i]->SetDisplayPans ( false );
|
|
vecpChanFader[i]->Hide();
|
|
}
|
|
|
|
// set flags
|
|
bIsPanSupported = false;
|
|
bNoFaderVisible = true;
|
|
eRecorderState = RS_UNDEFINED;
|
|
iMyChannelID = INVALID_INDEX;
|
|
|
|
// use original order of channel (by server ID)
|
|
ChangeFaderOrder ( false, ST_BY_NAME );
|
|
|
|
// emit status of connected clients
|
|
emit NumClientsChanged ( 0 ); // -> no clients connected
|
|
}
|
|
|
|
void CAudioMixerBoard::ChangeFaderOrder ( const bool bDoSort,
|
|
const EChSortType eChSortType )
|
|
{
|
|
// create a pair list of lower strings and fader ID for each channel
|
|
QList<QPair<QString, int> > PairList;
|
|
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
if ( eChSortType == ST_BY_NAME )
|
|
{
|
|
PairList << QPair<QString, int> ( vecpChanFader[i]->GetReceivedName().toLower(), i );
|
|
}
|
|
else // ST_BY_INSTRUMENT
|
|
{
|
|
PairList << QPair<QString, int> ( CInstPictures::GetName ( vecpChanFader[i]->GetReceivedInstrument() ), i );
|
|
}
|
|
}
|
|
|
|
// if requested, sort the channels
|
|
if ( bDoSort )
|
|
{
|
|
qStableSort ( PairList.begin(), PairList.end() );
|
|
}
|
|
|
|
// add channels to the layout in the new order (since we insert on the left, we
|
|
// have to use a backwards counting loop), note that it is not required to remove
|
|
// the widget from the layout first but it is moved to the new position automatically
|
|
for ( int i = MAX_NUM_CHANNELS - 1; i >= 0; i-- )
|
|
{
|
|
pMainLayout->insertWidget ( 0, vecpChanFader[PairList[i].second]->GetMainWidget() );
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::UpdateTitle()
|
|
{
|
|
QString strTitlePrefix = "";
|
|
|
|
if ( eRecorderState == RS_RECORDING )
|
|
{
|
|
strTitlePrefix = "[" + tr ( "RECORDING ACTIVE" ) + "] ";
|
|
}
|
|
|
|
setTitle ( strTitlePrefix + tr ( "Personal Mix at: " ) + strServerName );
|
|
}
|
|
|
|
void CAudioMixerBoard::SetRecorderState ( const ERecorderState newRecorderState )
|
|
{
|
|
// store the new recorder state and update the title
|
|
eRecorderState = newRecorderState;
|
|
UpdateTitle();
|
|
}
|
|
|
|
void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInfo )
|
|
{
|
|
// we want to set the server name only if the very first faders appear
|
|
// in the audio mixer board to show a "try to connect" before
|
|
if ( bNoFaderVisible )
|
|
{
|
|
UpdateTitle();
|
|
}
|
|
|
|
// get number of connected clients
|
|
const int iNumConnectedClients = vecChanInfo.Size();
|
|
|
|
// search for channels with are already present and preserve their gain
|
|
// setting, for all other channels reset gain
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
bool bFaderIsUsed = false;
|
|
|
|
for ( int j = 0; j < iNumConnectedClients; j++ )
|
|
{
|
|
// check if current fader is used
|
|
if ( vecChanInfo[j].iChanID == i )
|
|
{
|
|
// check if fader was already in use -> preserve gain value
|
|
if ( !vecpChanFader[i]->IsVisible() )
|
|
{
|
|
// the fader was not in use, reset everything for new client
|
|
vecpChanFader[i]->Reset();
|
|
|
|
// check if this is my own fader and set fader property
|
|
if ( i == iMyChannelID )
|
|
{
|
|
vecpChanFader[i]->SetIsMyOwnFader();
|
|
}
|
|
|
|
// show fader
|
|
vecpChanFader[i]->Show();
|
|
|
|
// Set the default initial fader level. Check first that
|
|
// this is not the initialization (i.e. previously there
|
|
// were no faders visible) to avoid that our own level is
|
|
// adjusted. If we have received our own channel ID, then
|
|
// we can adjust the level even if no fader was visible.
|
|
// The fader level of 100 % is the default in the
|
|
// server, in that case we do not have to do anything here.
|
|
if ( ( !bNoFaderVisible ||
|
|
( ( iMyChannelID != INVALID_INDEX ) && ( iMyChannelID != i ) ) ) &&
|
|
( iNewClientFaderLevel != 100 ) )
|
|
{
|
|
// the value is in percent -> convert range
|
|
vecpChanFader[i]->SetFaderLevel ( static_cast<int> (
|
|
iNewClientFaderLevel / 100.0 * AUD_MIX_FADER_MAX ) );
|
|
}
|
|
}
|
|
|
|
// restore gain (if new name is different from the current one)
|
|
if ( vecpChanFader[i]->GetReceivedName().compare ( vecChanInfo[j].strName ) )
|
|
{
|
|
// the text has actually changed, search in the list of
|
|
// stored settings if we have a matching entry
|
|
int iStoredFaderLevel;
|
|
int iStoredPanValue;
|
|
bool bStoredFaderIsSolo;
|
|
bool bStoredFaderIsMute;
|
|
bool bStoredFaderIsSelect;
|
|
|
|
if ( GetStoredFaderSettings ( vecChanInfo[j],
|
|
iStoredFaderLevel,
|
|
iStoredPanValue,
|
|
bStoredFaderIsSolo,
|
|
bStoredFaderIsMute,
|
|
bStoredFaderIsSelect) )
|
|
{
|
|
vecpChanFader[i]->SetFaderLevel ( iStoredFaderLevel );
|
|
vecpChanFader[i]->SetPanValue ( iStoredPanValue );
|
|
vecpChanFader[i]->SetFaderIsSolo ( bStoredFaderIsSolo );
|
|
vecpChanFader[i]->SetFaderIsMute ( bStoredFaderIsMute );
|
|
vecpChanFader[i]->SetFaderIsSelect ( bStoredFaderIsSelect );
|
|
}
|
|
}
|
|
|
|
// set the channel infos
|
|
vecpChanFader[i]->SetChannelInfos ( vecChanInfo[j] );
|
|
|
|
bFaderIsUsed = true;
|
|
}
|
|
}
|
|
|
|
// if current fader is not used, hide it
|
|
if ( !bFaderIsUsed )
|
|
{
|
|
// before hiding the fader, store its level (if some conditions are fullfilled)
|
|
StoreFaderSettings ( vecpChanFader[i] );
|
|
|
|
vecpChanFader[i]->Hide();
|
|
}
|
|
}
|
|
|
|
// update the solo states since if any channel was on solo and a new client
|
|
// has just connected, the new channel must be muted
|
|
UpdateSoloStates();
|
|
|
|
// update flag for "all faders are invisible"
|
|
bNoFaderVisible = ( iNumConnectedClients == 0 );
|
|
|
|
// emit status of connected clients
|
|
emit NumClientsChanged ( iNumConnectedClients );
|
|
}
|
|
|
|
void CAudioMixerBoard::SetFaderLevel ( const int iChannelIdx,
|
|
const int iValue )
|
|
{
|
|
// only apply new fader level if channel index is valid and the fader is visible
|
|
if ( ( iChannelIdx >= 0 ) && ( iChannelIdx < MAX_NUM_CHANNELS ) )
|
|
{
|
|
if ( vecpChanFader[iChannelIdx]->IsVisible() )
|
|
{
|
|
vecpChanFader[iChannelIdx]->SetFaderLevel ( iValue );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::SetRemoteFaderIsMute ( const int iChannelIdx,
|
|
const bool bIsMute )
|
|
{
|
|
// only apply remote mute state if channel index is valid and the fader is visible
|
|
if ( ( iChannelIdx >= 0 ) && ( iChannelIdx < MAX_NUM_CHANNELS ) )
|
|
{
|
|
if ( vecpChanFader[iChannelIdx]->IsVisible() )
|
|
{
|
|
vecpChanFader[iChannelIdx]->SetRemoteFaderIsMute ( bIsMute );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::UpdateSoloStates()
|
|
{
|
|
// first check if any channel has a solo state active
|
|
bool bAnyChannelIsSolo = false;
|
|
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
// check if fader is in use and has solo state active
|
|
if ( vecpChanFader[i]->IsVisible() && vecpChanFader[i]->IsSolo() )
|
|
{
|
|
bAnyChannelIsSolo = true;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// now update the solo state of all active faders
|
|
for ( int i = 0; i < MAX_NUM_CHANNELS; i++ )
|
|
{
|
|
if ( vecpChanFader[i]->IsVisible() )
|
|
{
|
|
vecpChanFader[i]->UpdateSoloState ( bAnyChannelIsSolo );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CAudioMixerBoard::UpdateGainValue ( const int iChannelIdx,
|
|
const double dValue,
|
|
const bool bIsMyOwnFader )
|
|
{
|
|
if ( !vecpChanFader[iChannelIdx]->IsSelect() )
|
|
{
|
|
emit ChangeChanGain ( iChannelIdx, dValue, bIsMyOwnFader );
|
|
}
|
|
else // This is selected, so all selected must be updated as well
|
|
{
|
|
// update current, don't touch fader
|
|
emit ChangeChanGain ( iChannelIdx, dValue, bIsMyOwnFader );
|
|
for ( int i = MAX_NUM_CHANNELS - 1; i >= 0; i-- )
|
|
{
|
|
// update rest of faders selected
|
|
if ( vecpChanFader[i]->IsSelect() )
|
|
{
|
|
if ( i != iChannelIdx )
|
|
{
|
|
// temporaly unselect so it does not repeat this again and again...
|
|
vecpChanFader[i]->SetFaderIsSelect( FALSE );
|
|
// "move" faders with moving fader level
|
|
vecpChanFader[i]->SetFaderLevel( vecpChanFader[iChannelIdx]->GetFaderLevel() );
|
|
// back to selected status
|
|
vecpChanFader[i]->SetFaderIsSelect( TRUE );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CAudioMixerBoard::UpdatePanValue ( const int iChannelIdx,
|
|
const double dValue )
|
|
{
|
|
emit ChangeChanPan ( iChannelIdx, dValue );
|
|
}
|
|
|
|
void CAudioMixerBoard::StoreFaderSettings ( CChannelFader* pChanFader )
|
|
{
|
|
// if the fader was visible and the name is not empty, we store the old gain
|
|
if ( pChanFader->IsVisible() &&
|
|
!pChanFader->GetReceivedName().isEmpty() )
|
|
{
|
|
CVector<int> viOldStoredFaderLevels ( vecStoredFaderLevels );
|
|
CVector<int> viOldStoredPanValues ( vecStoredPanValues );
|
|
CVector<int> vbOldStoredFaderIsSolo ( vecStoredFaderIsSolo );
|
|
CVector<int> vbOldStoredFaderIsMute ( vecStoredFaderIsMute );
|
|
CVector<int> vbOldStoredFaderIsSelected ( vecStoredFaderIsSelect );
|
|
|
|
// init temporary list count (may be overwritten later on)
|
|
int iTempListCnt = 0;
|
|
|
|
// put new value on the top of the list
|
|
const int iOldIdx =
|
|
vecStoredFaderTags.StringFiFoWithCompare ( pChanFader->GetReceivedName(),
|
|
true );
|
|
|
|
// current fader level and solo state is at the top of the list
|
|
vecStoredFaderLevels[0] = pChanFader->GetFaderLevel();
|
|
vecStoredPanValues[0] = pChanFader->GetPanValue();
|
|
vecStoredFaderIsSolo[0] = pChanFader->IsSolo();
|
|
vecStoredFaderIsMute[0] = pChanFader->IsMute();
|
|
vecStoredFaderIsSelect[0] = pChanFader->IsSelect();
|
|
iTempListCnt = 1;
|
|
|
|
for ( int iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
|
|
{
|
|
// first check if we still have space in our data storage
|
|
if ( iTempListCnt < MAX_NUM_STORED_FADER_SETTINGS )
|
|
{
|
|
// check for the old index of the current entry (this has to be
|
|
// skipped), note that per definition: the old index is an illegal
|
|
// index in case the entry was not present in the vector before
|
|
if ( iIdx != iOldIdx )
|
|
{
|
|
vecStoredFaderLevels[iTempListCnt] = viOldStoredFaderLevels[iIdx];
|
|
vecStoredPanValues[iTempListCnt] = viOldStoredPanValues[iIdx];
|
|
vecStoredFaderIsSolo[iTempListCnt] = vbOldStoredFaderIsSolo[iIdx];
|
|
vecStoredFaderIsMute[iTempListCnt] = vbOldStoredFaderIsMute[iIdx];
|
|
|
|
iTempListCnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CAudioMixerBoard::GetStoredFaderSettings ( const CChannelInfo& ChanInfo,
|
|
int& iStoredFaderLevel,
|
|
int& iStoredPanValue,
|
|
bool& bStoredFaderIsSolo,
|
|
bool& bStoredFaderIsMute,
|
|
bool& bStoredFaderIsSelect)
|
|
{
|
|
// only do the check if the name string is not empty
|
|
if ( !ChanInfo.strName.isEmpty() )
|
|
{
|
|
for ( int iIdx = 0; iIdx < MAX_NUM_STORED_FADER_SETTINGS; iIdx++ )
|
|
{
|
|
// check if fader text is already known in the list
|
|
if ( !vecStoredFaderTags[iIdx].compare ( ChanInfo.strName ) )
|
|
{
|
|
// copy stored settings values
|
|
iStoredFaderLevel = vecStoredFaderLevels[iIdx];
|
|
iStoredPanValue = vecStoredPanValues[iIdx];
|
|
bStoredFaderIsSolo = vecStoredFaderIsSolo[iIdx] != 0;
|
|
bStoredFaderIsMute = vecStoredFaderIsMute[iIdx] != 0;
|
|
bStoredFaderIsSelect = vecStoredFaderIsSelect[iIdx] != 0;
|
|
|
|
// values found and copied, return OK
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// return "not OK" since we did not find matching fader settings
|
|
return false;
|
|
}
|
|
|
|
void CAudioMixerBoard::SetChannelLevels ( const CVector<uint16_t>& vecChannelLevel )
|
|
{
|
|
const int iNumChannelLevels = vecChannelLevel.Size();
|
|
int i = 0;
|
|
|
|
for ( int iChId = 0; iChId < MAX_NUM_CHANNELS; iChId++ )
|
|
{
|
|
if ( vecpChanFader[iChId]->IsVisible() && i < iNumChannelLevels )
|
|
{
|
|
vecpChanFader[iChId]->SetChannelLevel ( vecChannelLevel[i++] );
|
|
|
|
// show level only if we successfully received levels from the
|
|
// server (if server does not support levels, do not show levels)
|
|
if ( bDisplayChannelLevels && !vecpChanFader[iChId]->GetDisplayChannelLevel() )
|
|
{
|
|
vecpChanFader[iChId]->SetDisplayChannelLevel ( true );
|
|
}
|
|
}
|
|
}
|
|
}
|