diff --git a/src/audiomixerboard.cpp b/src/audiomixerboard.cpp index db6cab14e4..f9ad65fb01 100644 --- a/src/audiomixerboard.cpp +++ b/src/audiomixerboard.cpp @@ -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 ) @@ -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 @@ -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(); @@ -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 ); @@ -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 ( "" ), @@ -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) @@ -1123,7 +1123,7 @@ void CAudioMixerBoard::ChangeFaderOrder ( const EChSortType eChSortType ) } break; case ST_BY_SERVER_CHANNEL: - PairList << QPair ( QString ( "%1" ).arg ( vecpChanFader[i]->GetReceivedChID(), 3, 10, QLatin1Char ( '0' ) ) + + PairList << QPair ( QString ( "%1" ).arg ( vecpChanFader[i]->GetReceivedMIDIID(), 3, 10, QLatin1Char ( '0' ) ) + vecpChanFader[i]->GetReceivedName().toLower(), i ); break; @@ -1267,7 +1267,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector& vecChanInf vecpChanFader[iChanID]->Reset(); vecAvgLevels[iChanID] = 0.0f; - if ( static_cast ( iChanID ) == iMyChannelID ) + if ( static_cast ( iChanID ) == pClient->GetMyChannelID() ) { // this is my own fader --> set fader property vecpChanFader[iChanID]->SetIsMyOwnFader(); @@ -1288,7 +1288,8 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector& 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 ( iChanID ) ) ) ) && + if ( ( !bNoFaderVisible || + ( ( pClient->GetMyChannelID() != INVALID_INDEX ) && ( pClient->GetMyChannelID() != static_cast ( iChanID ) ) ) ) && ( pSettings->iNewClientFaderLevel != 100 ) ) { // the value is in percent -> convert range @@ -1322,7 +1323,7 @@ void CAudioMixerBoard::ApplyNewConClientList ( CVector& 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 @@ -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 ( i ) != iMyChannelID ) ) + if ( vecpChanFader[i]->IsVisible() && ( static_cast ( 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 @@ -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 ( i ) != iMyChannelID ) ) + if ( vecpChanFader[i]->IsVisible() && ( static_cast ( i ) != pClient->GetMyChannelID() ) ) { // map averaged meter output level to decibels // (invert CStereoSignalLevelMeter::CalcLogResultForMeter) @@ -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 ( i ) != iMyChannelID ) ) + if ( vecpChanFader[i]->IsVisible() && ( static_cast ( i ) != pClient->GetMyChannelID() ) ) { // map averaged meter output level to decibels // (invert CStereoSignalLevelMeter::CalcLogResultForMeter) @@ -1778,4 +1779,4 @@ void CAudioMixerBoard::SetChannelLevels ( const CVector& vecChannelLev } } -void CAudioMixerBoard::MuteMyChannel() { SetFaderIsMute ( iMyChannelID, true ); } +void CAudioMixerBoard::MuteMyChannel() { SetFaderIsMute ( pClient->GetMyChannelID(), true ); } diff --git a/src/audiomixerboard.h b/src/audiomixerboard.h index 6b42d35085..9cafe4a393 100644 --- a/src/audiomixerboard.h +++ b/src/audiomixerboard.h @@ -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(); } @@ -120,6 +121,7 @@ class CChannelFader : public QObject QLabel* plblCountryFlag; CChannelInfo cReceivedChanInfo; + int cReceivedMIDIID; bool bOtherChannelIsSolo; bool bIsMyOwnFader; @@ -190,6 +192,7 @@ class CAudioMixerBoard : public QGroupBox, public CAudioMixerBoardSlots& vecChanInfo ); @@ -200,8 +203,6 @@ class CAudioMixerBoard : public QGroupBox, public CAudioMixerBoardSlots vecpChanFader; CMixerBoardScrollArea* pScrollArea; @@ -267,7 +269,6 @@ class CAudioMixerBoard : public QGroupBox, public CAudioMixerBoardSlots "false" */ + iMyChannelID ( INVALID_INDEX ), CurOpusEncoder ( nullptr ), CurOpusDecoder ( nullptr ), eAudioCompressionType ( CT_OPUS ), @@ -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 @@ -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 @@ -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 @@ -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 @@ -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) @@ -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(); diff --git a/src/client.h b/src/client.h index 3f9e30be6d..24a7977f00 100644 --- a/src/client.h +++ b/src/client.h @@ -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; } @@ -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; @@ -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; @@ -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 vecChanInfo ); diff --git a/src/clientdlg.cpp b/src/clientdlg.cpp index cb6b134bf7..1d9b5d2cc3 100644 --- a/src/clientdlg.cpp +++ b/src/clientdlg.cpp @@ -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 ); @@ -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 ); diff --git a/src/clientdlg.h b/src/clientdlg.h index 2a9062a58d..3e20b3534e 100644 --- a/src/clientdlg.h +++ b/src/clientdlg.h @@ -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 vecLevelList ) diff --git a/src/sound/soundbase.h b/src/sound/soundbase.h index 4aa6c629bc..c36205a8c9 100644 --- a/src/sound/soundbase.h +++ b/src/sound/soundbase.h @@ -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 ); };