Skip to content

Commit

Permalink
Always give own channel MIDI number 0
Browse files Browse the repository at this point in the history
1. Moved my channel ID from the Mixer to the Client, so it is
   available when headless too.
2. Client's own channel, sent by the server, is always assigned
   to MIDI number 0, for left-most fader.
3. Translate between server channel and MIDI number at the client level.
  • Loading branch information
softins committed Nov 6, 2024
1 parent 81ec9fe commit 46f7567
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 34 deletions.
27 changes: 14 additions & 13 deletions src/audiomixerboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ void CChannelFader::SetGUIDesign ( const EGUIDesign eNewDesign )
UpdateGroupIDDependencies();

// the instrument picture might need scaling after a style change
SetChannelInfos ( cReceivedChanInfo );
SetChannelInfos ( cReceivedChanInfo, cReceivedMIDIID );
}

void CChannelFader::SetMeterStyle ( const EMeterStyle eNewMeterStyle )
Expand Down Expand Up @@ -436,6 +436,7 @@ void CChannelFader::Reset()
plblCountryFlag->setVisible ( false );
plblCountryFlag->setToolTip ( "" );
cReceivedChanInfo = CChannelInfo();
cReceivedMIDIID = INVALID_INDEX;
SetupFaderTag ( SL_NOT_SET );

// set a defined tool tip time out
Expand Down Expand Up @@ -666,10 +667,11 @@ void CChannelFader::UpdateSoloState ( const bool bNewOtherSoloState )

void CChannelFader::SetChannelLevel ( const uint16_t iLevel ) { plbrChannelLevel->SetValue ( iLevel ); }

void CChannelFader::SetChannelInfos ( const CChannelInfo& cChanInfo )
void CChannelFader::SetChannelInfos ( const CChannelInfo& cChanInfo, int iMIDIID )
{
// store received channel info
cReceivedChanInfo = cChanInfo;
cReceivedMIDIID = iMIDIID;

// init properties for the tool tip
int iTTInstrument = CInstPictures::GetNotUsedInstrument();
Expand All @@ -682,7 +684,7 @@ void CChannelFader::SetChannelInfos ( const CChannelInfo& cChanInfo )
// show channel numbers if --ctrlmidich is used (#241, #95)
if ( bMIDICtrlUsed )
{
strModText.prepend ( QString().setNum ( cChanInfo.iChanID ) + ":" );
strModText.prepend ( QString().setNum ( iMIDIID ) + ":" );
}

QTextBoundaryFinder tbfName ( QTextBoundaryFinder::Grapheme, cChanInfo.strName );
Expand Down Expand Up @@ -886,7 +888,6 @@ CAudioMixerBoard::CAudioMixerBoard ( QWidget* parent ) :
bDisplayPans ( false ),
bIsPanSupported ( false ),
bNoFaderVisible ( true ),
iMyChannelID ( INVALID_INDEX ),
iRunningNewClientCnt ( 0 ),
iNumMixerPanelRows ( 1 ), // pSettings->iNumMixerPanelRows is not yet available
strServerName ( "" ),
Expand Down Expand Up @@ -1049,7 +1050,6 @@ void CAudioMixerBoard::HideAll()
bIsPanSupported = false;
bNoFaderVisible = true;
eRecorderState = RS_UNDEFINED;
iMyChannelID = INVALID_INDEX;
iRunningNewClientCnt = 0; // reset running counter on new server connection

// use original order of channel (by server ID)
Expand Down Expand Up @@ -1123,7 +1123,7 @@ void CAudioMixerBoard::ChangeFaderOrder ( const EChSortType eChSortType )
}
break;
case ST_BY_SERVER_CHANNEL:
PairList << QPair<QString, size_t> ( QString ( "%1" ).arg ( vecpChanFader[i]->GetReceivedChID(), 3, 10, QLatin1Char ( '0' ) ) +
PairList << QPair<QString, size_t> ( QString ( "%1" ).arg ( vecpChanFader[i]->GetReceivedMIDIID(), 3, 10, QLatin1Char ( '0' ) ) +
vecpChanFader[i]->GetReceivedName().toLower(),
i );
break;
Expand Down Expand Up @@ -1267,7 +1267,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
vecpChanFader[iChanID]->Reset();
vecAvgLevels[iChanID] = 0.0f;

if ( static_cast<int> ( iChanID ) == iMyChannelID )
if ( static_cast<int> ( iChanID ) == pClient->GetMyChannelID() )
{
// this is my own fader --> set fader property
vecpChanFader[iChanID]->SetIsMyOwnFader();
Expand All @@ -1288,7 +1288,8 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
// 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 != static_cast<int> ( iChanID ) ) ) ) &&
if ( ( !bNoFaderVisible ||
( ( pClient->GetMyChannelID() != INVALID_INDEX ) && ( pClient->GetMyChannelID() != static_cast<int> ( iChanID ) ) ) ) &&
( pSettings->iNewClientFaderLevel != 100 ) )
{
// the value is in percent -> convert range
Expand Down Expand Up @@ -1322,7 +1323,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInf
}

// set the channel infos
vecpChanFader[iChanID]->SetChannelInfos ( vecChanInfo[idxVecpChan] );
vecpChanFader[iChanID]->SetChannelInfos ( vecChanInfo[idxVecpChan], pClient->ChanToMIDI ( iChanID ) );
}

// update the solo states since if any channel was on solo and a new client
Expand Down Expand Up @@ -1397,7 +1398,7 @@ void CAudioMixerBoard::SetAllFaderLevelsToNewClientLevel()
for ( size_t i = 0; i < MAX_NUM_CHANNELS; i++ )
{
// only apply to visible faders and not to my own channel fader
if ( vecpChanFader[i]->IsVisible() && ( static_cast<int> ( i ) != iMyChannelID ) )
if ( vecpChanFader[i]->IsVisible() && ( static_cast<int> ( i ) != pClient->GetMyChannelID() ) )
{
// the value is in percent -> convert range, also use the group
// update flag to make sure the group values are all set to the
Expand Down Expand Up @@ -1426,7 +1427,7 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels()
for ( size_t i = 0; i < MAX_NUM_CHANNELS; ++i )
{
// only apply to visible faders (and not to my own channel fader)
if ( vecpChanFader[i]->IsVisible() && ( static_cast<int> ( i ) != iMyChannelID ) )
if ( vecpChanFader[i]->IsVisible() && ( static_cast<int> ( i ) != pClient->GetMyChannelID() ) )
{
// map averaged meter output level to decibels
// (invert CStereoSignalLevelMeter::CalcLogResultForMeter)
Expand Down Expand Up @@ -1516,7 +1517,7 @@ void CAudioMixerBoard::AutoAdjustAllFaderLevels()
for ( size_t i = 0; i < MAX_NUM_CHANNELS; ++i )
{
// only apply to visible faders (and not to my own channel fader)
if ( vecpChanFader[i]->IsVisible() && ( static_cast<int> ( i ) != iMyChannelID ) )
if ( vecpChanFader[i]->IsVisible() && ( static_cast<int> ( i ) != pClient->GetMyChannelID() ) )
{
// map averaged meter output level to decibels
// (invert CStereoSignalLevelMeter::CalcLogResultForMeter)
Expand Down Expand Up @@ -1778,4 +1779,4 @@ void CAudioMixerBoard::SetChannelLevels ( const CVector<uint16_t>& vecChannelLev
}
}

void CAudioMixerBoard::MuteMyChannel() { SetFaderIsMute ( iMyChannelID, true ); }
void CAudioMixerBoard::MuteMyChannel() { SetFaderIsMute ( pClient->GetMyChannelID(), true ); }
9 changes: 5 additions & 4 deletions src/audiomixerboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class CChannelFader : public QObject
int GetReceivedInstrument() { return cReceivedChanInfo.iInstrument; }
QString GetReceivedCity() { return cReceivedChanInfo.strCity; }
int GetReceivedChID() { return cReceivedChanInfo.iChanID; }
void SetChannelInfos ( const CChannelInfo& cChanInfo );
int GetReceivedMIDIID() { return cReceivedMIDIID; }
void SetChannelInfos ( const CChannelInfo& cChanInfo, int iMIDIID );
void Show() { pFrame->show(); }
void Hide() { pFrame->hide(); }
bool IsVisible() { return !pFrame->isHidden(); }
Expand Down Expand Up @@ -120,6 +121,7 @@ class CChannelFader : public QObject
QLabel* plblCountryFlag;

CChannelInfo cReceivedChanInfo;
int cReceivedMIDIID;

bool bOtherChannelIsSolo;
bool bIsMyOwnFader;
Expand Down Expand Up @@ -190,6 +192,7 @@ class CAudioMixerBoard : public QGroupBox, public CAudioMixerBoardSlots<MAX_NUM_

virtual ~CAudioMixerBoard();

void SetClientPointer ( CClient* pNClient ) { pClient = pNClient; }
void SetSettingsPointer ( CClientSettings* pNSet ) { pSettings = pNSet; }
void HideAll();
void ApplyNewConClientList ( CVector<CChannelInfo>& vecChanInfo );
Expand All @@ -200,8 +203,6 @@ class CAudioMixerBoard : public QGroupBox, public CAudioMixerBoardSlots<MAX_NUM_
void SetDisplayPans ( const bool eNDP );
void SetPanIsSupported();
void SetRemoteFaderIsMute ( const int iChannelIdx, const bool bIsMute );
void SetMyChannelID ( const int iChannelIdx ) { iMyChannelID = iChannelIdx; }
int GetMyChannelID() const { return iMyChannelID; }

void SetFaderLevel ( const int iChannelIdx, const int iValue );

Expand Down Expand Up @@ -260,14 +261,14 @@ class CAudioMixerBoard : public QGroupBox, public CAudioMixerBoardSlots<MAX_NUM_
void UpdateSoloStates();
void UpdateTitle();

CClient* pClient;
CClientSettings* pSettings;
CVector<CChannelFader*> vecpChanFader;
CMixerBoardScrollArea* pScrollArea;
QGridLayout* pMainLayout;
bool bDisplayPans;
bool bIsPanSupported;
bool bNoFaderVisible;
int iMyChannelID; // must use int (not size_t) so INVALID_INDEX can be stored
int iRunningNewClientCnt; // integer type is sufficient, will never overrun for its purpose
int iNumMixerPanelRows;
QString strServerName;
Expand Down
60 changes: 56 additions & 4 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ CClient::CClient ( const quint16 iPortNumber,
ChannelInfo(),
strClientName ( strNClientName ),
Channel ( false ), /* we need a client channel -> "false" */
iMyChannelID ( INVALID_INDEX ),
CurOpusEncoder ( nullptr ),
CurOpusDecoder ( nullptr ),
eAudioCompressionType ( CT_OPUS ),
Expand Down Expand Up @@ -789,8 +790,44 @@ void CClient::OnHandledSignal ( int sigNum )
#endif
}

void CClient::OnControllerInFaderLevel ( int iChannelIdx, int iValue )
// Ensure user's own channel is always given MIDI offset 0, so it is the first physical fader
// All channels with a client ID less than user's own will use ID+1 as their MIDI offset

int CClient::ChanToMIDI ( const int iChannelIdx )
{
if ( iMyChannelID == INVALID_INDEX )
return iChannelIdx;

if ( iChannelIdx == iMyChannelID )
return 0;

if ( iChannelIdx < iMyChannelID )
return iChannelIdx + 1;

return iChannelIdx;
}

int CClient::MIDIToChan ( const int iMIDIIdx )
{
if ( iMyChannelID == INVALID_INDEX )
return iMIDIIdx;

if ( iMIDIIdx == 0 )
return iMyChannelID;

if ( iMIDIIdx <= iMyChannelID )
return iMIDIIdx - 1;

return iMIDIIdx;
}

// Handle received MIDI controls

void CClient::OnControllerInFaderLevel ( int iMIDIIdx, int iValue )
{
// map the MIDI index to the real channel number
const int iChannelIdx = MIDIToChan ( iMIDIIdx );

// in case of a headless client the faders cannot be moved so we need
// to send the controller information directly to the server
#ifdef HEADLESS
Expand All @@ -804,8 +841,11 @@ void CClient::OnControllerInFaderLevel ( int iChannelIdx, int iValue )
emit ControllerInFaderLevel ( iChannelIdx, iValue );
}

void CClient::OnControllerInPanValue ( int iChannelIdx, int iValue )
void CClient::OnControllerInPanValue ( int iMIDIIdx, int iValue )
{
// map the MIDI index to the real channel number
const int iChannelIdx = MIDIToChan ( iMIDIIdx );

// in case of a headless client the panners cannot be moved so we need
// to send the controller information directly to the server
#ifdef HEADLESS
Expand All @@ -816,8 +856,11 @@ void CClient::OnControllerInPanValue ( int iChannelIdx, int iValue )
emit ControllerInPanValue ( iChannelIdx, iValue );
}

void CClient::OnControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo )
void CClient::OnControllerInFaderIsSolo ( int iMIDIIdx, bool bIsSolo )
{
// map the MIDI index to the real channel number
const int iChannelIdx = MIDIToChan ( iMIDIIdx );

// in case of a headless client the buttons are not displayed so we need
// to send the controller information directly to the server
#ifdef HEADLESS
Expand All @@ -827,8 +870,11 @@ void CClient::OnControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo )
emit ControllerInFaderIsSolo ( iChannelIdx, bIsSolo );
}

void CClient::OnControllerInFaderIsMute ( int iChannelIdx, bool bIsMute )
void CClient::OnControllerInFaderIsMute ( int iMIDIIdx, bool bIsMute )
{
// map the MIDI index to the real channel number
const int iChannelIdx = MIDIToChan ( iMIDIIdx );

// in case of a headless client the buttons are not displayed so we need
// to send the controller information directly to the server
#ifdef HEADLESS
Expand All @@ -851,6 +897,9 @@ void CClient::OnControllerInMuteMyself ( bool bMute )

void CClient::OnClientIDReceived ( int iChanID )
{
// remember our client ID received from the server
iMyChannelID = iChanID;

// for headless mode we support to mute our own signal in the personal mix
// (note that the check for headless is done in the main.cpp and must not
// be checked here)
Expand Down Expand Up @@ -903,6 +952,9 @@ void CClient::Stop()
// disconnects the connection anyway).
ConnLessProtocol.CreateCLDisconnection ( Channel.GetAddress() );

// forget our own channel ID
iMyChannelID = INVALID_INDEX;

// reset current signal level and LEDs
bJitterBufferOK = true;
SignalLevelMeter.Reset();
Expand Down
18 changes: 14 additions & 4 deletions src/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class CClient : public QObject

bool IsConnected() { return Channel.IsConnected(); }

int GetMyChannelID() { return iMyChannelID; }

EGUIDesign GetGUIDesign() const { return eGUIDesign; }
void SetGUIDesign ( const EGUIDesign eNGD ) { eGUIDesign = eNGD; }

Expand Down Expand Up @@ -272,6 +274,10 @@ class CClient : public QObject
Channel.GetBufErrorRates ( vecErrRates, dLimit, dMaxUpLimit );
}

// convert between MIDI index and real channel index
int ChanToMIDI ( const int iChanIdx );
int MIDIToChan ( const int iMIDIIdx );

// settings
CChannelCoreInfo ChannelInfo;
QString strClientName;
Expand All @@ -292,6 +298,9 @@ class CClient : public QObject
CChannel Channel;
CProtocol ConnLessProtocol;

// this client's channel ID sent by the server
int iMyChannelID; // must use int (not size_t) so INVALID_INDEX can be stored

// audio encoder/decoder
OpusCustomMode* Opus64Mode;
OpusCustomEncoder* Opus64EncoderMono;
Expand Down Expand Up @@ -398,10 +407,11 @@ protected slots:
void OnCLPingWithNumClientsReceived ( CHostAddress InetAddr, int iMs, int iNumClients );

void OnSndCrdReinitRequest ( int iSndCrdResetType );
void OnControllerInFaderLevel ( int iChannelIdx, int iValue );
void OnControllerInPanValue ( int iChannelIdx, int iValue );
void OnControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo );
void OnControllerInFaderIsMute ( int iChannelIdx, bool bIsMute );

void OnControllerInFaderLevel ( int iMIDIIdx, int iValue );
void OnControllerInPanValue ( int iMIDIIdx, int iValue );
void OnControllerInFaderIsSolo ( int iMIDIIdx, bool bIsSolo );
void OnControllerInFaderIsMute ( int iMIDIIdx, bool bIsMute );
void OnControllerInMuteMyself ( bool bMute );
void OnClientIDReceived ( int iChanID );
void OnConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo );
Expand Down
5 changes: 2 additions & 3 deletions src/clientdlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,8 @@ CClientDlg::CClientDlg ( CClient* pNCliP,
// MeterStyle init
SetMeterStyle ( pClient->GetMeterStyle() );

// set the settings pointer to the mixer board (must be done early)
// pass the client and settings pointers to the mixer board (must be done early)
MainMixerBoard->SetClientPointer ( pClient );
MainMixerBoard->SetSettingsPointer ( pSettings );
MainMixerBoard->SetNumMixerPanelRows ( pSettings->iNumMixerPanelRows );

Expand Down Expand Up @@ -487,8 +488,6 @@ CClientDlg::CClientDlg ( CClient* pNCliP,

QObject::connect ( pClient, &CClient::ChatTextReceived, this, &CClientDlg::OnChatTextReceived );

QObject::connect ( pClient, &CClient::ClientIDReceived, this, &CClientDlg::OnClientIDReceived );

QObject::connect ( pClient, &CClient::MuteStateHasChangedReceived, this, &CClientDlg::OnMuteStateHasChangedReceived );

QObject::connect ( pClient, &CClient::RecorderStateReceived, this, &CClientDlg::OnRecorderStateReceived );
Expand Down
2 changes: 0 additions & 2 deletions src/clientdlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,6 @@ public slots:
ConnectDlg.SetConnClientsList ( InetAddr, vecChanInfo );
}

void OnClientIDReceived ( int iChanID ) { MainMixerBoard->SetMyChannelID ( iChanID ); }

void OnMuteStateHasChangedReceived ( int iChanID, bool bIsMuted ) { MainMixerBoard->SetRemoteFaderIsMute ( iChanID, bIsMuted ); }

void OnCLChannelLevelListReceived ( CHostAddress /* unused */, CVector<uint16_t> vecLevelList )
Expand Down
8 changes: 4 additions & 4 deletions src/sound/soundbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ class CSoundBase : public QThread

signals:
void ReinitRequest ( int iSndCrdResetType );
void ControllerInFaderLevel ( int iChannelIdx, int iValue );
void ControllerInPanValue ( int iChannelIdx, int iValue );
void ControllerInFaderIsSolo ( int iChannelIdx, bool bIsSolo );
void ControllerInFaderIsMute ( int iChannelIdx, bool bIsMute );
void ControllerInFaderLevel ( int iMIDIIdx, int iValue );
void ControllerInPanValue ( int iMIDIIdx, int iValue );
void ControllerInFaderIsSolo ( int iMIDIIdx, bool bIsSolo );
void ControllerInFaderIsMute ( int iMIDIIdx, bool bIsMute );
void ControllerInMuteMyself ( bool bMute );
};

0 comments on commit 46f7567

Please sign in to comment.