From bb3404b21cada6d8907904dd1fbaea376c171a24 Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Sun, 16 Aug 2009 00:48:33 +0000 Subject: [PATCH] catch errors on sound card starting in main dialog and show error message without the need to terminate the software immediately (as it was before) --- src/llconclientdlg.cpp | 1006 ++++++++++++++++++++-------------------- 1 file changed, 511 insertions(+), 495 deletions(-) diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp index 669ab69d..d4129129 100755 --- a/src/llconclientdlg.cpp +++ b/src/llconclientdlg.cpp @@ -1,495 +1,511 @@ -/******************************************************************************\ - * Copyright (c) 2004-2009 - * - * 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., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * -\******************************************************************************/ - -#include "llconclientdlg.h" - - -/* Implementation *************************************************************/ -CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, - const bool bNewConnectOnStartup, - const bool bNewDisalbeLEDs, - QWidget* parent, Qt::WindowFlags f ) : - pClient ( pNCliP ), QDialog ( parent, f ), - ClientSettingsDlg ( pNCliP, parent -#ifdef _WIN32 - // this somehow only works reliable on Windows - , Qt::WindowMinMaxButtonsHint -#endif - ), - ChatDlg ( parent -#ifdef _WIN32 - // this somehow only works reliable on Windows - , Qt::WindowMinMaxButtonsHint -#endif - ) -{ - setupUi ( this ); - - // add help text to controls - QString strInpLevH = tr ( "Input level meter: Shows the level of the " - "input audio signal of the sound card. Overload should be avoided." ); - TextLabelInputLevelL->setWhatsThis ( strInpLevH ); - TextLabelInputLevelR->setWhatsThis ( strInpLevH ); - MultiColorLEDBarInputLevelL->setWhatsThis ( strInpLevH ); - MultiColorLEDBarInputLevelR->setWhatsThis ( strInpLevH ); - - PushButtonConnect->setWhatsThis ( tr ( "Connect / Disconnect Button:" - " Push this button to connect the server. A valid IP address has " - "to be specified before. If the client is connected, pressing this " - "button will disconnect the connection." ) ); - - TextLabelStatus->setWhatsThis ( tr ( "Status Bar: In the status bar " - "different messages are displayed. E.g., if an error occurred or the " - "status of the connection is shown." ) ); - - QString strServAddrH = tr ( "Server Address: In this edit control, " - "the IP address of the server can be set. If an invalid address was " - "chosen, an error message is shown in the status bar." ); - TextLabelServerAddr->setWhatsThis ( strServAddrH ); - LineEditServerAddr->setWhatsThis ( strServAddrH ); - - QString strFaderTag = tr ( "Fader Tag: In this edit control, " - "the tag string of your fader can be set. This tag will appear " - "at your fader on the mixer board when connected to the server."); - TextLabelServerTag->setWhatsThis ( strFaderTag ); - LineEditFaderTag->setWhatsThis ( strFaderTag ); - - QString strAudFader = tr ( "Audio Fader: With the audio fader " - "control the level of left and right audio input channels can " - "be controlled." ); - TextAudInFader->setWhatsThis ( strAudFader ); - SliderAudInFader->setWhatsThis ( strAudFader ); - - QString strAudReverb = tr ( "Reverberation Level: The level of " - "reverberation effect can be set with this control. The channel to " - "which that reverberation effect shall be applied can be chosen " - "with the Reverberation Channel Selection radio buttons." ); - TextLabelAudReverb->setWhatsThis ( strAudReverb ); - SliderAudReverb->setWhatsThis ( strAudReverb ); - - QString strRevChanSel = tr ( "Reverberation Channel Selection: " - "With these radio buttons the audio input channel on which the " - "reverberation effect is applied can be chosen. Either the left " - "or right input channel can be selected." ); - RadioButtonRevSelL->setWhatsThis ( strRevChanSel ); - RadioButtonRevSelR->setWhatsThis ( strRevChanSel ); - - LEDOverallStatus->setWhatsThis ( tr ( "Overall Status: " - "The overall status of the software is shown. If either the " - "network or sound interface has bad status, this LED will show " - "red color." ) ); - - // init fader tag line edit - LineEditFaderTag->setText ( pClient->strName ); - - // init server address combo box (max MAX_NUM_SERVER_ADDR_ITEMS entries) - LineEditServerAddr->setMaxCount ( MAX_NUM_SERVER_ADDR_ITEMS ); - LineEditServerAddr->setInsertPolicy ( QComboBox::InsertAtTop ); - - // load data from ini file - for ( int iLEIdx = 0; iLEIdx < MAX_NUM_SERVER_ADDR_ITEMS; iLEIdx++ ) - { - if ( !pClient->vstrIPAddress[iLEIdx].isEmpty() ) - { - LineEditServerAddr->addItem ( pClient->vstrIPAddress[iLEIdx] ); - } - } - - // we want the cursor to be at IP address line edit at startup - LineEditServerAddr->setFocus(); - - // init status label - OnTimerStatus(); - - // init connection button text - PushButtonConnect->setText ( CON_BUT_CONNECTTEXT ); - - // init input level meter bars - MultiColorLEDBarInputLevelL->setValue ( 0 ); - MultiColorLEDBarInputLevelR->setValue ( 0 ); - - - // init slider controls --- - // audio in fader - SliderAudInFader->setRange ( AUD_FADER_IN_MIN, AUD_FADER_IN_MAX ); - SliderAudInFader->setTickInterval ( AUD_FADER_IN_MAX / 5 ); - UpdateAudioFaderSlider(); - - // audio reverberation - SliderAudReverb->setRange ( 0, AUD_REVERB_MAX ); - const int iCurAudReverb = pClient->GetReverbLevel(); - SliderAudReverb->setValue ( iCurAudReverb ); - SliderAudReverb->setTickInterval ( AUD_REVERB_MAX / 5 ); - - - // set radio buttons --- - // reverb channel - if ( pClient->IsReverbOnLeftChan() ) - { - RadioButtonRevSelL->setChecked ( true ); - } - else - { - RadioButtonRevSelR->setChecked ( true ); - } - - - // connect on startup --- - if ( bNewConnectOnStartup ) - { - // since the software starts up right now, the previous state was - // "not connected" so that a call to "OnConnectDisconBut()" will - // start the connection - OnConnectDisconBut(); - } - - - // disable controls on request --- - // disable LEDs in main window if requested - if ( bNewDisalbeLEDs ) - { - MultiColorLEDBarInputLevelL->setEnabled ( false ); - MultiColorLEDBarInputLevelR->setEnabled ( false ); - LEDOverallStatus->setEnabled ( false ); - PushButtonConnect->setFocus(); - } - - - // Settings menu ---------------------------------------------------------- - pSettingsMenu = new QMenu ( "&View", this ); - pSettingsMenu->addAction ( tr ( "&Chat..." ), this, - SLOT ( OnOpenChatDialog() ) ); - pSettingsMenu->addAction ( tr ( "&General Settings..." ), this, - SLOT ( OnOpenGeneralSettings() ) ); - - pSettingsMenu->addSeparator(); - pSettingsMenu->addAction ( tr ( "E&xit" ), this, - SLOT ( close() ), QKeySequence ( Qt::CTRL + Qt::Key_Q ) ); - - - // Main menu bar ----------------------------------------------------------- - pMenu = new QMenuBar ( this ); - pMenu->addMenu ( pSettingsMenu ); - pMenu->addMenu ( new CLlconHelpMenu ( this ) ); - - // Now tell the layout about the menu - layout()->setMenuBar ( pMenu ); - - - // Connections ------------------------------------------------------------- - // push-buttons - QObject::connect ( PushButtonConnect, SIGNAL ( clicked() ), - this, SLOT ( OnConnectDisconBut() ) ); - - // timers - QObject::connect ( &TimerSigMet, SIGNAL ( timeout() ), - this, SLOT ( OnTimerSigMet() ) ); - QObject::connect ( &TimerStatus, SIGNAL ( timeout() ), - this, SLOT ( OnTimerStatus() ) ); - - // sliders - QObject::connect ( SliderAudInFader, SIGNAL ( valueChanged ( int ) ), - this, SLOT ( OnSliderAudInFader ( int ) ) ); - QObject::connect ( SliderAudReverb, SIGNAL ( valueChanged ( int ) ), - this, SLOT ( OnSliderAudReverb ( int ) ) ); - - // radio buttons - QObject::connect ( RadioButtonRevSelL, SIGNAL ( clicked() ), - this, SLOT ( OnRevSelL() ) ); - QObject::connect ( RadioButtonRevSelR, SIGNAL ( clicked() ), - this, SLOT ( OnRevSelR() ) ); - - // line edits - QObject::connect ( LineEditFaderTag, SIGNAL ( textChanged ( const QString& ) ), - this, SLOT ( OnFaderTagTextChanged ( const QString& ) ) ); - QObject::connect ( LineEditServerAddr, SIGNAL ( editTextChanged ( const QString ) ), - this, SLOT ( OnLineEditServerAddrTextChanged ( const QString ) ) ); - QObject::connect ( LineEditServerAddr, SIGNAL ( activated ( int ) ), - this, SLOT ( OnLineEditServerAddrActivated ( int ) ) ); - - // other - QObject::connect ( pClient, - SIGNAL ( ConClientListMesReceived ( CVector ) ), - this, SLOT ( OnConClientListMesReceived ( CVector ) ) ); - QObject::connect ( pClient, - SIGNAL ( ChatTextReceived ( QString ) ), - this, SLOT ( OnChatTextReceived ( QString ) ) ); - QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ), - this, SLOT ( OnChangeChanGain ( int, double ) ) ); - QObject::connect ( &ChatDlg, SIGNAL ( NewLocalInputText ( QString ) ), - this, SLOT ( OnNewLocalInputText ( QString ) ) ); - - - // Timers ------------------------------------------------------------------ - // start timer for status bar - TimerStatus.start ( STATUSBAR_UPDATE_TIME ); -} - -CLlconClientDlg::~CLlconClientDlg() -{ - // if connected, terminate connection - if ( pClient->IsRunning() ) - { - pClient->Stop(); - } -} - -void CLlconClientDlg::closeEvent ( QCloseEvent * Event ) -{ - // if settings dialog or chat dialog is open, close it - ClientSettingsDlg.close(); - ChatDlg.close(); - - // store IP addresses - for ( int iLEIdx = 0; iLEIdx < LineEditServerAddr->count(); iLEIdx++ ) - { - pClient->vstrIPAddress[iLEIdx] = - LineEditServerAddr->itemText ( iLEIdx ); - } - - // store fader tag - pClient->strName = LineEditFaderTag->text(); - - // default implementation of this event handler routine - Event->accept(); -} - -void CLlconClientDlg::UpdateAudioFaderSlider() -{ - // update slider and label of audio fader - const int iCurAudInFader = pClient->GetAudioInFader(); - SliderAudInFader->setValue ( iCurAudInFader ); - - // show in label the center position and what channel is - // attenuated - if ( iCurAudInFader == AUD_FADER_IN_MIDDLE ) - { - TextLabelAudFader->setText ( "Center" ); - } - else - { - if ( iCurAudInFader > AUD_FADER_IN_MIDDLE ) - { - // attenuation on right channel - TextLabelAudFader->setText ( "R -" + - QString().setNum ( iCurAudInFader - AUD_FADER_IN_MIDDLE ) ); - } - else - { - // attenuation on left channel - TextLabelAudFader->setText ( "L -" + - QString().setNum ( AUD_FADER_IN_MIDDLE - iCurAudInFader ) ); - } - } -} - -void CLlconClientDlg::OnSliderAudInFader ( int value ) -{ - pClient->SetAudioInFader ( value ); - UpdateAudioFaderSlider(); -} - -void CLlconClientDlg::OnLineEditServerAddrTextChanged ( const QString sNewText ) -{ - // if the maximum number of items in the combo box is reached, - // delete the last item so that the new item can be added (first - // in - first out) - if ( LineEditServerAddr->count() == MAX_NUM_SERVER_ADDR_ITEMS ) - { - LineEditServerAddr->removeItem ( MAX_NUM_SERVER_ADDR_ITEMS - 1 ); - } -} - -void CLlconClientDlg::OnLineEditServerAddrActivated ( int index ) -{ - // move activated list item to the top - const QString strCurIPAddress = LineEditServerAddr->itemText ( index ); - LineEditServerAddr->removeItem ( index ); - LineEditServerAddr->insertItem ( 0, strCurIPAddress ); - LineEditServerAddr->setCurrentIndex ( 0 ); -} - -void CLlconClientDlg::OnConnectDisconBut() -{ - // start/stop client, set button text - if ( !pClient->IsRunning() ) - { - // set address and check if address is valid - if ( pClient->SetServerAddr ( LineEditServerAddr->currentText() ) ) - { - pClient->Start(); - - PushButtonConnect->setText ( CON_BUT_DISCONNECTTEXT ); - - // start timer for level meter bar - TimerSigMet.start ( LEVELMETER_UPDATE_TIME ); - } - else - { - // Restart timer to ensure that the text is visible at - // least the time for one complete interval - TimerStatus.start ( STATUSBAR_UPDATE_TIME ); - - // show the error in the status bar - TextLabelStatus->setText ( tr ( "Invalid address" ) ); - } - } - else - { - pClient->Stop(); - PushButtonConnect->setText ( CON_BUT_CONNECTTEXT ); - - // stop timer for level meter bars and reset them - TimerSigMet.stop(); - MultiColorLEDBarInputLevelL->setValue ( 0 ); - MultiColorLEDBarInputLevelR->setValue ( 0 ); - - // immediately update status bar - OnTimerStatus(); - - // clear mixer board (remove all faders) - MainMixerBoard->HideAll(); - } -} - -void CLlconClientDlg::OnOpenGeneralSettings() -{ - // open general settings dialog - ClientSettingsDlg.show(); - - // make sure dialog is upfront and has focus - ClientSettingsDlg.raise(); - ClientSettingsDlg.activateWindow(); -} - -void CLlconClientDlg::OnChatTextReceived ( QString strChatText ) -{ - ChatDlg.AddChatText ( strChatText ); - - // if requested, open window - if ( pClient->GetOpenChatOnNewMessage() ) - { - ShowChatWindow(); - } -} - -void CLlconClientDlg::ShowChatWindow() -{ - // open chat dialog - ChatDlg.show(); - - // make sure dialog is upfront and has focus - ChatDlg.raise(); - ChatDlg.activateWindow(); -} - -void CLlconClientDlg::OnFaderTagTextChanged ( const QString& strNewName ) -{ - // refresh internal name parameter - pClient->strName = strNewName; - - // update name at server - pClient->SetRemoteName(); -} - -void CLlconClientDlg::OnTimerSigMet() -{ - // get current input levels - double dCurSigLevelL = pClient->MicLevelL(); - double dCurSigLevelR = pClient->MicLevelR(); - - // linear transformation of the input level range to the progress-bar - // range - dCurSigLevelL -= LOW_BOUND_SIG_METER; - dCurSigLevelL *= NUM_STEPS_INP_LEV_METER / - ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ); - - // lower bound the signal - if ( dCurSigLevelL < 0 ) - { - dCurSigLevelL = 0; - } - - dCurSigLevelR -= LOW_BOUND_SIG_METER; - dCurSigLevelR *= NUM_STEPS_INP_LEV_METER / - ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ); - - // lower bound the signal - if ( dCurSigLevelR < 0 ) - { - dCurSigLevelR = 0; - } - - // show current level - MultiColorLEDBarInputLevelL->setValue ( (int) ceil ( dCurSigLevelL ) ); - MultiColorLEDBarInputLevelR->setValue ( (int) ceil ( dCurSigLevelR ) ); -} - -void CLlconClientDlg::UpdateDisplay() -{ - // show connection status in status bar - if ( pClient->IsConnected() && pClient->IsRunning() ) - { - TextLabelStatus->setText ( tr ( "Connected" ) ); - } - else - { - TextLabelStatus->setText ( tr ( "Disconnected" ) ); - } - -// TEST -//TextLabelStatus->setText ( QString( "Time: %1, Netw: %2" ).arg ( pClient->GetTimingStdDev() ).arg ( pClient->GetChannel()->GetTimingStdDev() ) ); - -} - -void CLlconClientDlg::customEvent ( QEvent* Event ) -{ - if ( Event->type() == QEvent::User + 11 ) - { - const int iMessType = ( (CLlconEvent*) Event )->iMessType; - const int iStatus = ( (CLlconEvent*) Event )->iStatus; - - switch ( iMessType ) - { - case MS_SOUND_IN: - case MS_SOUND_OUT: - case MS_JIT_BUF_PUT: - case MS_JIT_BUF_GET: - // show overall status -> if any LED goes red, this LED will go red - LEDOverallStatus->SetLight ( iStatus ); - break; - - case MS_RESET_ALL: - LEDOverallStatus->Reset(); - break; - - case MS_SET_JIT_BUF_SIZE: - pClient->SetSockBufNumFrames ( iStatus ); - break; - } - - // update general settings dialog, too - ClientSettingsDlg.SetStatus ( iMessType, iStatus ); - } -} +/******************************************************************************\ + * Copyright (c) 2004-2009 + * + * 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * +\******************************************************************************/ + +#include "llconclientdlg.h" + + +/* Implementation *************************************************************/ +CLlconClientDlg::CLlconClientDlg ( CClient* pNCliP, + const bool bNewConnectOnStartup, + const bool bNewDisalbeLEDs, + QWidget* parent, Qt::WindowFlags f ) : + pClient ( pNCliP ), QDialog ( parent, f ), + ClientSettingsDlg ( pNCliP, parent +#ifdef _WIN32 + // this somehow only works reliable on Windows + , Qt::WindowMinMaxButtonsHint +#endif + ), + ChatDlg ( parent +#ifdef _WIN32 + // this somehow only works reliable on Windows + , Qt::WindowMinMaxButtonsHint +#endif + ) +{ + setupUi ( this ); + + // add help text to controls + QString strInpLevH = tr ( "Input level meter: Shows the level of the " + "input audio signal of the sound card. Overload should be avoided." ); + TextLabelInputLevelL->setWhatsThis ( strInpLevH ); + TextLabelInputLevelR->setWhatsThis ( strInpLevH ); + MultiColorLEDBarInputLevelL->setWhatsThis ( strInpLevH ); + MultiColorLEDBarInputLevelR->setWhatsThis ( strInpLevH ); + + PushButtonConnect->setWhatsThis ( tr ( "Connect / Disconnect Button:" + " Push this button to connect the server. A valid IP address has " + "to be specified before. If the client is connected, pressing this " + "button will disconnect the connection." ) ); + + TextLabelStatus->setWhatsThis ( tr ( "Status Bar: In the status bar " + "different messages are displayed. E.g., if an error occurred or the " + "status of the connection is shown." ) ); + + QString strServAddrH = tr ( "Server Address: In this edit control, " + "the IP address of the server can be set. If an invalid address was " + "chosen, an error message is shown in the status bar." ); + TextLabelServerAddr->setWhatsThis ( strServAddrH ); + LineEditServerAddr->setWhatsThis ( strServAddrH ); + + QString strFaderTag = tr ( "Fader Tag: In this edit control, " + "the tag string of your fader can be set. This tag will appear " + "at your fader on the mixer board when connected to the server."); + TextLabelServerTag->setWhatsThis ( strFaderTag ); + LineEditFaderTag->setWhatsThis ( strFaderTag ); + + QString strAudFader = tr ( "Audio Fader: With the audio fader " + "control the level of left and right audio input channels can " + "be controlled." ); + TextAudInFader->setWhatsThis ( strAudFader ); + SliderAudInFader->setWhatsThis ( strAudFader ); + + QString strAudReverb = tr ( "Reverberation Level: The level of " + "reverberation effect can be set with this control. The channel to " + "which that reverberation effect shall be applied can be chosen " + "with the Reverberation Channel Selection radio buttons." ); + TextLabelAudReverb->setWhatsThis ( strAudReverb ); + SliderAudReverb->setWhatsThis ( strAudReverb ); + + QString strRevChanSel = tr ( "Reverberation Channel Selection: " + "With these radio buttons the audio input channel on which the " + "reverberation effect is applied can be chosen. Either the left " + "or right input channel can be selected." ); + RadioButtonRevSelL->setWhatsThis ( strRevChanSel ); + RadioButtonRevSelR->setWhatsThis ( strRevChanSel ); + + LEDOverallStatus->setWhatsThis ( tr ( "Overall Status: " + "The overall status of the software is shown. If either the " + "network or sound interface has bad status, this LED will show " + "red color." ) ); + + // init fader tag line edit + LineEditFaderTag->setText ( pClient->strName ); + + // init server address combo box (max MAX_NUM_SERVER_ADDR_ITEMS entries) + LineEditServerAddr->setMaxCount ( MAX_NUM_SERVER_ADDR_ITEMS ); + LineEditServerAddr->setInsertPolicy ( QComboBox::InsertAtTop ); + + // load data from ini file + for ( int iLEIdx = 0; iLEIdx < MAX_NUM_SERVER_ADDR_ITEMS; iLEIdx++ ) + { + if ( !pClient->vstrIPAddress[iLEIdx].isEmpty() ) + { + LineEditServerAddr->addItem ( pClient->vstrIPAddress[iLEIdx] ); + } + } + + // we want the cursor to be at IP address line edit at startup + LineEditServerAddr->setFocus(); + + // init status label + OnTimerStatus(); + + // init connection button text + PushButtonConnect->setText ( CON_BUT_CONNECTTEXT ); + + // init input level meter bars + MultiColorLEDBarInputLevelL->setValue ( 0 ); + MultiColorLEDBarInputLevelR->setValue ( 0 ); + + + // init slider controls --- + // audio in fader + SliderAudInFader->setRange ( AUD_FADER_IN_MIN, AUD_FADER_IN_MAX ); + SliderAudInFader->setTickInterval ( AUD_FADER_IN_MAX / 5 ); + UpdateAudioFaderSlider(); + + // audio reverberation + SliderAudReverb->setRange ( 0, AUD_REVERB_MAX ); + const int iCurAudReverb = pClient->GetReverbLevel(); + SliderAudReverb->setValue ( iCurAudReverb ); + SliderAudReverb->setTickInterval ( AUD_REVERB_MAX / 5 ); + + + // set radio buttons --- + // reverb channel + if ( pClient->IsReverbOnLeftChan() ) + { + RadioButtonRevSelL->setChecked ( true ); + } + else + { + RadioButtonRevSelR->setChecked ( true ); + } + + + // connect on startup --- + if ( bNewConnectOnStartup ) + { + // since the software starts up right now, the previous state was + // "not connected" so that a call to "OnConnectDisconBut()" will + // start the connection + OnConnectDisconBut(); + } + + + // disable controls on request --- + // disable LEDs in main window if requested + if ( bNewDisalbeLEDs ) + { + MultiColorLEDBarInputLevelL->setEnabled ( false ); + MultiColorLEDBarInputLevelR->setEnabled ( false ); + LEDOverallStatus->setEnabled ( false ); + PushButtonConnect->setFocus(); + } + + + // Settings menu ---------------------------------------------------------- + pSettingsMenu = new QMenu ( "&View", this ); + pSettingsMenu->addAction ( tr ( "&Chat..." ), this, + SLOT ( OnOpenChatDialog() ) ); + pSettingsMenu->addAction ( tr ( "&General Settings..." ), this, + SLOT ( OnOpenGeneralSettings() ) ); + + pSettingsMenu->addSeparator(); + pSettingsMenu->addAction ( tr ( "E&xit" ), this, + SLOT ( close() ), QKeySequence ( Qt::CTRL + Qt::Key_Q ) ); + + + // Main menu bar ----------------------------------------------------------- + pMenu = new QMenuBar ( this ); + pMenu->addMenu ( pSettingsMenu ); + pMenu->addMenu ( new CLlconHelpMenu ( this ) ); + + // Now tell the layout about the menu + layout()->setMenuBar ( pMenu ); + + + // Connections ------------------------------------------------------------- + // push-buttons + QObject::connect ( PushButtonConnect, SIGNAL ( clicked() ), + this, SLOT ( OnConnectDisconBut() ) ); + + // timers + QObject::connect ( &TimerSigMet, SIGNAL ( timeout() ), + this, SLOT ( OnTimerSigMet() ) ); + QObject::connect ( &TimerStatus, SIGNAL ( timeout() ), + this, SLOT ( OnTimerStatus() ) ); + + // sliders + QObject::connect ( SliderAudInFader, SIGNAL ( valueChanged ( int ) ), + this, SLOT ( OnSliderAudInFader ( int ) ) ); + QObject::connect ( SliderAudReverb, SIGNAL ( valueChanged ( int ) ), + this, SLOT ( OnSliderAudReverb ( int ) ) ); + + // radio buttons + QObject::connect ( RadioButtonRevSelL, SIGNAL ( clicked() ), + this, SLOT ( OnRevSelL() ) ); + QObject::connect ( RadioButtonRevSelR, SIGNAL ( clicked() ), + this, SLOT ( OnRevSelR() ) ); + + // line edits + QObject::connect ( LineEditFaderTag, SIGNAL ( textChanged ( const QString& ) ), + this, SLOT ( OnFaderTagTextChanged ( const QString& ) ) ); + QObject::connect ( LineEditServerAddr, SIGNAL ( editTextChanged ( const QString ) ), + this, SLOT ( OnLineEditServerAddrTextChanged ( const QString ) ) ); + QObject::connect ( LineEditServerAddr, SIGNAL ( activated ( int ) ), + this, SLOT ( OnLineEditServerAddrActivated ( int ) ) ); + + // other + QObject::connect ( pClient, + SIGNAL ( ConClientListMesReceived ( CVector ) ), + this, SLOT ( OnConClientListMesReceived ( CVector ) ) ); + QObject::connect ( pClient, + SIGNAL ( ChatTextReceived ( QString ) ), + this, SLOT ( OnChatTextReceived ( QString ) ) ); + QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ), + this, SLOT ( OnChangeChanGain ( int, double ) ) ); + QObject::connect ( &ChatDlg, SIGNAL ( NewLocalInputText ( QString ) ), + this, SLOT ( OnNewLocalInputText ( QString ) ) ); + + + // Timers ------------------------------------------------------------------ + // start timer for status bar + TimerStatus.start ( STATUSBAR_UPDATE_TIME ); +} + +CLlconClientDlg::~CLlconClientDlg() +{ + // if connected, terminate connection + if ( pClient->IsRunning() ) + { + pClient->Stop(); + } +} + +void CLlconClientDlg::closeEvent ( QCloseEvent * Event ) +{ + // if settings dialog or chat dialog is open, close it + ClientSettingsDlg.close(); + ChatDlg.close(); + + // store IP addresses + for ( int iLEIdx = 0; iLEIdx < LineEditServerAddr->count(); iLEIdx++ ) + { + pClient->vstrIPAddress[iLEIdx] = + LineEditServerAddr->itemText ( iLEIdx ); + } + + // store fader tag + pClient->strName = LineEditFaderTag->text(); + + // default implementation of this event handler routine + Event->accept(); +} + +void CLlconClientDlg::UpdateAudioFaderSlider() +{ + // update slider and label of audio fader + const int iCurAudInFader = pClient->GetAudioInFader(); + SliderAudInFader->setValue ( iCurAudInFader ); + + // show in label the center position and what channel is + // attenuated + if ( iCurAudInFader == AUD_FADER_IN_MIDDLE ) + { + TextLabelAudFader->setText ( "Center" ); + } + else + { + if ( iCurAudInFader > AUD_FADER_IN_MIDDLE ) + { + // attenuation on right channel + TextLabelAudFader->setText ( "R -" + + QString().setNum ( iCurAudInFader - AUD_FADER_IN_MIDDLE ) ); + } + else + { + // attenuation on left channel + TextLabelAudFader->setText ( "L -" + + QString().setNum ( AUD_FADER_IN_MIDDLE - iCurAudInFader ) ); + } + } +} + +void CLlconClientDlg::OnSliderAudInFader ( int value ) +{ + pClient->SetAudioInFader ( value ); + UpdateAudioFaderSlider(); +} + +void CLlconClientDlg::OnLineEditServerAddrTextChanged ( const QString sNewText ) +{ + // if the maximum number of items in the combo box is reached, + // delete the last item so that the new item can be added (first + // in - first out) + if ( LineEditServerAddr->count() == MAX_NUM_SERVER_ADDR_ITEMS ) + { + LineEditServerAddr->removeItem ( MAX_NUM_SERVER_ADDR_ITEMS - 1 ); + } +} + +void CLlconClientDlg::OnLineEditServerAddrActivated ( int index ) +{ + // move activated list item to the top + const QString strCurIPAddress = LineEditServerAddr->itemText ( index ); + LineEditServerAddr->removeItem ( index ); + LineEditServerAddr->insertItem ( 0, strCurIPAddress ); + LineEditServerAddr->setCurrentIndex ( 0 ); +} + +void CLlconClientDlg::OnConnectDisconBut() +{ + // start/stop client, set button text + if ( !pClient->IsRunning() ) + { + // set address and check if address is valid + if ( pClient->SetServerAddr ( LineEditServerAddr->currentText() ) ) + { + bool bStartOk = true; + + try + { + pClient->Start(); + } + + catch ( CGenErr generr ) + { + QMessageBox::critical ( + this, APP_NAME, generr.GetErrorText(), "Close", 0 ); + + bStartOk = false; + } + + if ( bStartOk ) + { + PushButtonConnect->setText ( CON_BUT_DISCONNECTTEXT ); + + // start timer for level meter bar + TimerSigMet.start ( LEVELMETER_UPDATE_TIME ); + } + } + else + { + // Restart timer to ensure that the text is visible at + // least the time for one complete interval + TimerStatus.start ( STATUSBAR_UPDATE_TIME ); + + // show the error in the status bar + TextLabelStatus->setText ( tr ( "Invalid address" ) ); + } + } + else + { + pClient->Stop(); + PushButtonConnect->setText ( CON_BUT_CONNECTTEXT ); + + // stop timer for level meter bars and reset them + TimerSigMet.stop(); + MultiColorLEDBarInputLevelL->setValue ( 0 ); + MultiColorLEDBarInputLevelR->setValue ( 0 ); + + // immediately update status bar + OnTimerStatus(); + + // clear mixer board (remove all faders) + MainMixerBoard->HideAll(); + } +} + +void CLlconClientDlg::OnOpenGeneralSettings() +{ + // open general settings dialog + ClientSettingsDlg.show(); + + // make sure dialog is upfront and has focus + ClientSettingsDlg.raise(); + ClientSettingsDlg.activateWindow(); +} + +void CLlconClientDlg::OnChatTextReceived ( QString strChatText ) +{ + ChatDlg.AddChatText ( strChatText ); + + // if requested, open window + if ( pClient->GetOpenChatOnNewMessage() ) + { + ShowChatWindow(); + } +} + +void CLlconClientDlg::ShowChatWindow() +{ + // open chat dialog + ChatDlg.show(); + + // make sure dialog is upfront and has focus + ChatDlg.raise(); + ChatDlg.activateWindow(); +} + +void CLlconClientDlg::OnFaderTagTextChanged ( const QString& strNewName ) +{ + // refresh internal name parameter + pClient->strName = strNewName; + + // update name at server + pClient->SetRemoteName(); +} + +void CLlconClientDlg::OnTimerSigMet() +{ + // get current input levels + double dCurSigLevelL = pClient->MicLevelL(); + double dCurSigLevelR = pClient->MicLevelR(); + + // linear transformation of the input level range to the progress-bar + // range + dCurSigLevelL -= LOW_BOUND_SIG_METER; + dCurSigLevelL *= NUM_STEPS_INP_LEV_METER / + ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ); + + // lower bound the signal + if ( dCurSigLevelL < 0 ) + { + dCurSigLevelL = 0; + } + + dCurSigLevelR -= LOW_BOUND_SIG_METER; + dCurSigLevelR *= NUM_STEPS_INP_LEV_METER / + ( UPPER_BOUND_SIG_METER - LOW_BOUND_SIG_METER ); + + // lower bound the signal + if ( dCurSigLevelR < 0 ) + { + dCurSigLevelR = 0; + } + + // show current level + MultiColorLEDBarInputLevelL->setValue ( (int) ceil ( dCurSigLevelL ) ); + MultiColorLEDBarInputLevelR->setValue ( (int) ceil ( dCurSigLevelR ) ); +} + +void CLlconClientDlg::UpdateDisplay() +{ + // show connection status in status bar + if ( pClient->IsConnected() && pClient->IsRunning() ) + { + TextLabelStatus->setText ( tr ( "Connected" ) ); + } + else + { + TextLabelStatus->setText ( tr ( "Disconnected" ) ); + } + +// TEST +//TextLabelStatus->setText ( QString( "Time: %1, Netw: %2" ).arg ( pClient->GetTimingStdDev() ).arg ( pClient->GetChannel()->GetTimingStdDev() ) ); + +} + +void CLlconClientDlg::customEvent ( QEvent* Event ) +{ + if ( Event->type() == QEvent::User + 11 ) + { + const int iMessType = ( (CLlconEvent*) Event )->iMessType; + const int iStatus = ( (CLlconEvent*) Event )->iStatus; + + switch ( iMessType ) + { + case MS_SOUND_IN: + case MS_SOUND_OUT: + case MS_JIT_BUF_PUT: + case MS_JIT_BUF_GET: + // show overall status -> if any LED goes red, this LED will go red + LEDOverallStatus->SetLight ( iStatus ); + break; + + case MS_RESET_ALL: + LEDOverallStatus->Reset(); + break; + + case MS_SET_JIT_BUF_SIZE: + pClient->SetSockBufNumFrames ( iStatus ); + break; + } + + // update general settings dialog, too + ClientSettingsDlg.SetStatus ( iMessType, iStatus ); + } +}