diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp
index a21da3de..4f43918b 100755
--- a/src/llconclientdlg.cpp
+++ b/src/llconclientdlg.cpp
@@ -1,662 +1,666 @@
-/******************************************************************************\
- * Copyright (c) 2004-2010
- *
- * 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 ),
- bUnreadChatMessage ( false ),
- 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 -----------------------------------------------
- // input level meter
- QString strInpLevH = tr ( "Input Level Meter: The input level "
- "indicators show the current input level of the two stereo channels "
- "of the current selected audio input. The upper level display belongs "
- "to the left channel and the lower level display to the right channel "
- "of the audio input.
"
- "Make sure not to clip the input signal to avoid distortions of the "
- "audio signal." );
-
- QString strInpLevHTT = tr ( "If the llcon software is connected and "
- "you play your instrument/sing in the microphone, the LED level "
- "meter should flicker. If this is not the case, you have "
- "probably selected the wrong input channel (e.g. line in instead "
- "of the microphone input) or set the input gain too low in the "
- "(Windows) audio mixer.
For a proper usage of the llcon software, "
- "you should not hear your singing/instrument in the loudspeaker or "
- "your headphone when the llcon software is not connected. This can "
- "be achieved by muting your input audio channel in the Playback "
- "mixer (not the Recording mixer!)." ) + TOOLTIP_COM_END_TEXT;
-
- QString strInpLevHAccText = tr ( "Input level meter" );
- QString strInpLevHAccDescr = tr ( "Simulates an analog LED level meter." );
-
- TextLabelInputLevelL->setWhatsThis ( strInpLevH );
- TextLabelInputLevelL->setToolTip ( strInpLevHTT );
- TextLabelInputLevelR->setWhatsThis ( strInpLevH );
- TextLabelInputLevelR->setToolTip ( strInpLevHTT );
- MultiColorLEDBarInputLevelL->setWhatsThis ( strInpLevH );
- MultiColorLEDBarInputLevelL->setAccessibleName ( strInpLevHAccText );
- MultiColorLEDBarInputLevelL->setAccessibleDescription ( strInpLevHAccDescr );
- MultiColorLEDBarInputLevelL->setToolTip ( strInpLevHTT );
- MultiColorLEDBarInputLevelR->setWhatsThis ( strInpLevH );
- MultiColorLEDBarInputLevelR->setAccessibleName ( strInpLevHAccText );
- MultiColorLEDBarInputLevelR->setAccessibleDescription ( strInpLevHAccDescr );
- MultiColorLEDBarInputLevelR->setToolTip ( strInpLevHTT );
-
- // connect/disconnect button
- 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." ) );
-
- PushButtonConnect->setAccessibleName (
- tr ( "Connect and disconnect toggle button" ) );
-
- PushButtonConnect->setAccessibleDescription ( tr ( "Clicking on this "
- "button changes the caption of the button from Connect to "
- "Disconnect, i.e., it implements a toggle functionality for connecting "
- "and disconnecting the llcon software." ) );
-
- // status bar
- 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." ) );
-
- TextLabelStatus->setAccessibleName ( tr ( "Status bar" ) );
-
- // server address
- QString strServAddrH = tr ( "Server Address: The IP address or URL "
- "of the server running the llcon server software must be set here. "
- "A list of the most recent used server URLs is available for "
- "selection. If an invalid address was chosen, an error message is "
- "shown in the status bar." );
-
- TextLabelServerAddr->setWhatsThis ( strServAddrH );
- LineEditServerAddr->setWhatsThis ( strServAddrH );
-
- LineEditServerAddr->setAccessibleName ( tr ( "Server address edit box" ) );
- LineEditServerAddr->setAccessibleDescription ( tr ( "Holds the current server "
- "URL. It also stores old URLs in the combo box list." ) );
-
- // fader tag
- QString strFaderTag = tr ( "Fader Tag: The fader tag of the local "
- "client is set in the fader tag edit box. This tag will appear "
- "at your fader on the mixer board when you are connected to a llcon "
- "server. This tag will also show up at each client which is connected "
- "to the same server as the local client. If the fader tag is empty, "
- "the IP address of the client is displayed instead." );
-
- QString strFaderTagTT = tr ( "Set your name and/or instrument and/or "
- "pseoudonym here so that the other musicians can identify you." ) +
- TOOLTIP_COM_END_TEXT;
-
- TextLabelServerTag->setWhatsThis ( strFaderTag );
- TextLabelServerTag->setToolTip ( strFaderTagTT );
- LineEditFaderTag->setWhatsThis ( strFaderTag );
- LineEditFaderTag->setToolTip ( strFaderTagTT );
-
- LineEditFaderTag->setAccessibleName ( tr ( "Fader tag edit box" ) );
-
- // local audio input fader
- QString strAudFader = tr ( "Local Audio Input Fader: With the "
- "audio fader, the relative levels of the left and right local audio "
- "channels can be changed. It acts like a panning between the two "
- "channels. If, e.g., a microphone is connected to the right input "
- "channel and an instrument is connected to the left input channel "
- "which is much louder than the microphone, move the audio fader in "
- "a direction where the label above the fader shows L -x, where "
- "x is the current attenuation indication. " );
-
- TextAudInFader->setWhatsThis ( strAudFader );
- SliderAudInFader->setWhatsThis ( strAudFader );
-
- SliderAudInFader->setAccessibleName ( tr ( "Local audio input fader (left/right)" ) );
-
- // reverberation level
- QString strAudReverb = tr ( "Reverberation Level: A reverberation "
- "effect can be applied to one local audio channel. The channel "
- "selection and the reverberation level can be modified. If, e.g., "
- "the microphone signal is fed into the right audio channel of the "
- "sound card and a reverberation effect shall be applied, set the "
- "channel selector to right and move the fader upwards until the "
- "desired reverberation level is reached.
"
- "The reverberation effect requires significant CPU so that it should "
- "only be used on fast PCs. If the reverberation level fader is set to "
- "minimum (which is the default setting), the reverberation effect is "
- "switched off and does not cause any additional CPU usage." );
-
- TextLabelAudReverb->setWhatsThis ( strAudReverb );
- SliderAudReverb->setWhatsThis ( strAudReverb );
-
- SliderAudReverb->setAccessibleName ( tr ( "Reverberation effect level setting" ) );
-
- // reverberation channel selection
- 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 );
- RadioButtonRevSelL->setAccessibleName ( tr ( "Left channel selection for reverberation" ) );
- RadioButtonRevSelR->setWhatsThis ( strRevChanSel );
- RadioButtonRevSelR->setAccessibleName ( tr ( "Right channel selection for reverberation" ) );
-
- // overall status
- LEDOverallStatus->setWhatsThis ( tr ( "Overall Status: "
- "The light next to the status bar shows the current audio/streaming "
- "status. If the light is green, there are no buffer overruns/underruns "
- "and the audio stream is not interrupted. If the light is red, the "
- "audio stream is interrupted caused by one of the following problems:"
- "
"
- "- The network jitter buffer is not large enough for the current "
- "network/audio interface jitter.
"
- "- The sound card buffer delay (buffer size) is set to a too small "
- "value.
"
- "- The upload or download stream rate is too high for the current "
- "available internet bandwidth.
"
- "- The CPU of the client or server is at 100%.
"
- "
" ) );
-
- LEDOverallStatus->setAccessibleName ( tr ( "Overall status LED indicator" ) );
-
-
- // init GUI design
- SetGUIDesign ( pClient->GetGUIDesign() );
-
- // reset mixer board
- MainMixerBoard->HideAll();
-
- // 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 );
-
- // init reverb channel
- UpdateRevSelection();
-
-
- // 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();
- }
-
-
- // Mac Workaround:
- // If the connect button is the default button, on Mac it is highlighted
- // by fading in and out a blue backgroud color. This operation consumes so
- // much CPU that we get audio interruptions.
- // Better solution: increase thread priority of worker thread (since the
- // user can always highlight the button manually, too) -> TODO
-#if defined ( __APPLE__ ) || defined ( __MACOSX )
- PushButtonConnect->setDefault ( false );
-#endif
-
-
- // View menu --------------------------------------------------------------
- pViewMenu = new QMenu ( "&View", this );
-
- pViewMenu->addAction ( tr ( "&Chat..." ), this,
- SLOT ( OnOpenChatDialog() ) );
-
- pViewMenu->addAction ( tr ( "&General Settings..." ), this,
- SLOT ( OnOpenGeneralSettings() ) );
-
- pViewMenu->addSeparator();
-
- pViewMenu->addAction ( tr ( "E&xit" ), this,
- SLOT ( close() ), QKeySequence ( Qt::CTRL + Qt::Key_Q ) );
-
-
- // Main menu bar -----------------------------------------------------------
- pMenu = new QMenuBar ( this );
-
- pMenu->addMenu ( pViewMenu );
- 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() ) );
-
+/******************************************************************************\
+ * Copyright (c) 2004-2010
+ *
+ * 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 ),
+ bUnreadChatMessage ( false ),
+ iErrorStatusCounter ( 0 ),
+ 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 -----------------------------------------------
+ // input level meter
+ QString strInpLevH = tr ( "Input Level Meter: The input level "
+ "indicators show the current input level of the two stereo channels "
+ "of the current selected audio input. The upper level display belongs "
+ "to the left channel and the lower level display to the right channel "
+ "of the audio input.
"
+ "Make sure not to clip the input signal to avoid distortions of the "
+ "audio signal." );
+
+ QString strInpLevHTT = tr ( "If the llcon software is connected and "
+ "you play your instrument/sing in the microphone, the LED level "
+ "meter should flicker. If this is not the case, you have "
+ "probably selected the wrong input channel (e.g. line in instead "
+ "of the microphone input) or set the input gain too low in the "
+ "(Windows) audio mixer.
For a proper usage of the llcon software, "
+ "you should not hear your singing/instrument in the loudspeaker or "
+ "your headphone when the llcon software is not connected. This can "
+ "be achieved by muting your input audio channel in the Playback "
+ "mixer (not the Recording mixer!)." ) + TOOLTIP_COM_END_TEXT;
+
+ QString strInpLevHAccText = tr ( "Input level meter" );
+ QString strInpLevHAccDescr = tr ( "Simulates an analog LED level meter." );
+
+ TextLabelInputLevelL->setWhatsThis ( strInpLevH );
+ TextLabelInputLevelL->setToolTip ( strInpLevHTT );
+ TextLabelInputLevelR->setWhatsThis ( strInpLevH );
+ TextLabelInputLevelR->setToolTip ( strInpLevHTT );
+ MultiColorLEDBarInputLevelL->setWhatsThis ( strInpLevH );
+ MultiColorLEDBarInputLevelL->setAccessibleName ( strInpLevHAccText );
+ MultiColorLEDBarInputLevelL->setAccessibleDescription ( strInpLevHAccDescr );
+ MultiColorLEDBarInputLevelL->setToolTip ( strInpLevHTT );
+ MultiColorLEDBarInputLevelR->setWhatsThis ( strInpLevH );
+ MultiColorLEDBarInputLevelR->setAccessibleName ( strInpLevHAccText );
+ MultiColorLEDBarInputLevelR->setAccessibleDescription ( strInpLevHAccDescr );
+ MultiColorLEDBarInputLevelR->setToolTip ( strInpLevHTT );
+
+ // connect/disconnect button
+ 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." ) );
+
+ PushButtonConnect->setAccessibleName (
+ tr ( "Connect and disconnect toggle button" ) );
+
+ PushButtonConnect->setAccessibleDescription ( tr ( "Clicking on this "
+ "button changes the caption of the button from Connect to "
+ "Disconnect, i.e., it implements a toggle functionality for connecting "
+ "and disconnecting the llcon software." ) );
+
+ // status bar
+ 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." ) );
+
+ TextLabelStatus->setAccessibleName ( tr ( "Status bar" ) );
+
+ // server address
+ QString strServAddrH = tr ( "Server Address: The IP address or URL "
+ "of the server running the llcon server software must be set here. "
+ "A list of the most recent used server URLs is available for "
+ "selection. If an invalid address was chosen, an error message is "
+ "shown in the status bar." );
+
+ TextLabelServerAddr->setWhatsThis ( strServAddrH );
+ LineEditServerAddr->setWhatsThis ( strServAddrH );
+
+ LineEditServerAddr->setAccessibleName ( tr ( "Server address edit box" ) );
+ LineEditServerAddr->setAccessibleDescription ( tr ( "Holds the current server "
+ "URL. It also stores old URLs in the combo box list." ) );
+
+ // fader tag
+ QString strFaderTag = tr ( "Fader Tag: The fader tag of the local "
+ "client is set in the fader tag edit box. This tag will appear "
+ "at your fader on the mixer board when you are connected to a llcon "
+ "server. This tag will also show up at each client which is connected "
+ "to the same server as the local client. If the fader tag is empty, "
+ "the IP address of the client is displayed instead." );
+
+ QString strFaderTagTT = tr ( "Set your name and/or instrument and/or "
+ "pseoudonym here so that the other musicians can identify you." ) +
+ TOOLTIP_COM_END_TEXT;
+
+ TextLabelServerTag->setWhatsThis ( strFaderTag );
+ TextLabelServerTag->setToolTip ( strFaderTagTT );
+ LineEditFaderTag->setWhatsThis ( strFaderTag );
+ LineEditFaderTag->setToolTip ( strFaderTagTT );
+
+ LineEditFaderTag->setAccessibleName ( tr ( "Fader tag edit box" ) );
+
+ // local audio input fader
+ QString strAudFader = tr ( "Local Audio Input Fader: With the "
+ "audio fader, the relative levels of the left and right local audio "
+ "channels can be changed. It acts like a panning between the two "
+ "channels. If, e.g., a microphone is connected to the right input "
+ "channel and an instrument is connected to the left input channel "
+ "which is much louder than the microphone, move the audio fader in "
+ "a direction where the label above the fader shows L -x, where "
+ "x is the current attenuation indication. " );
+
+ TextAudInFader->setWhatsThis ( strAudFader );
+ SliderAudInFader->setWhatsThis ( strAudFader );
+
+ SliderAudInFader->setAccessibleName ( tr ( "Local audio input fader (left/right)" ) );
+
+ // reverberation level
+ QString strAudReverb = tr ( "Reverberation Level: A reverberation "
+ "effect can be applied to one local audio channel. The channel "
+ "selection and the reverberation level can be modified. If, e.g., "
+ "the microphone signal is fed into the right audio channel of the "
+ "sound card and a reverberation effect shall be applied, set the "
+ "channel selector to right and move the fader upwards until the "
+ "desired reverberation level is reached.
"
+ "The reverberation effect requires significant CPU so that it should "
+ "only be used on fast PCs. If the reverberation level fader is set to "
+ "minimum (which is the default setting), the reverberation effect is "
+ "switched off and does not cause any additional CPU usage." );
+
+ TextLabelAudReverb->setWhatsThis ( strAudReverb );
+ SliderAudReverb->setWhatsThis ( strAudReverb );
+
+ SliderAudReverb->setAccessibleName ( tr ( "Reverberation effect level setting" ) );
+
+ // reverberation channel selection
+ 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 );
+ RadioButtonRevSelL->setAccessibleName ( tr ( "Left channel selection for reverberation" ) );
+ RadioButtonRevSelR->setWhatsThis ( strRevChanSel );
+ RadioButtonRevSelR->setAccessibleName ( tr ( "Right channel selection for reverberation" ) );
+
+ // overall status
+ LEDOverallStatus->setWhatsThis ( tr ( "Overall Status: "
+ "The light next to the status bar shows the current audio/streaming "
+ "status. If the light is green, there are no buffer overruns/underruns "
+ "and the audio stream is not interrupted. If the light is red, the "
+ "audio stream is interrupted caused by one of the following problems:"
+ ""
+ "- The network jitter buffer is not large enough for the current "
+ "network/audio interface jitter.
"
+ "- The sound card buffer delay (buffer size) is set to a too small "
+ "value.
"
+ "- The upload or download stream rate is too high for the current "
+ "available internet bandwidth.
"
+ "- The CPU of the client or server is at 100%.
"
+ "
" ) );
+
+ LEDOverallStatus->setAccessibleName ( tr ( "Overall status LED indicator" ) );
+
+
+ // init GUI design
+ SetGUIDesign ( pClient->GetGUIDesign() );
+
+ // reset mixer board
+ MainMixerBoard->HideAll();
+
+ // 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 );
+
+ // init reverb channel
+ UpdateRevSelection();
+
+
+ // 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();
+ }
+
+
+ // Mac Workaround:
+ // If the connect button is the default button, on Mac it is highlighted
+ // by fading in and out a blue backgroud color. This operation consumes so
+ // much CPU that we get audio interruptions.
+ // Better solution: increase thread priority of worker thread (since the
+ // user can always highlight the button manually, too) -> TODO
+#if defined ( __APPLE__ ) || defined ( __MACOSX )
+ PushButtonConnect->setDefault ( false );
+#endif
+
+
+ // View menu --------------------------------------------------------------
+ pViewMenu = new QMenu ( "&View", this );
+
+ pViewMenu->addAction ( tr ( "&Chat..." ), this,
+ SLOT ( OnOpenChatDialog() ) );
+
+ pViewMenu->addAction ( tr ( "&General Settings..." ), this,
+ SLOT ( OnOpenGeneralSettings() ) );
+
+ pViewMenu->addSeparator();
+
+ pViewMenu->addAction ( tr ( "E&xit" ), this,
+ SLOT ( close() ), QKeySequence ( Qt::CTRL + Qt::Key_Q ) );
+
+
+ // Main menu bar -----------------------------------------------------------
+ pMenu = new QMenuBar ( this );
+
+ pMenu->addMenu ( pViewMenu );
+ 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() ) );
+
QObject::connect ( &TimerPing, SIGNAL ( timeout() ),
- this, SLOT ( OnTimerPing() ) );
-
- // 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 ( Disconnected() ),
- this, SLOT ( OnDisconnected() ) );
-
- QObject::connect ( pClient,
- SIGNAL ( Stopped() ),
- this, SLOT ( OnStopped() ) );
-
- QObject::connect ( pClient,
- SIGNAL ( ChatTextReceived ( QString ) ),
- this, SLOT ( OnChatTextReceived ( QString ) ) );
-
+ this, SLOT ( OnTimerPing() ) );
+
+ // 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 ( Disconnected() ),
+ this, SLOT ( OnDisconnected() ) );
+
+ QObject::connect ( pClient,
+ SIGNAL ( Stopped() ),
+ this, SLOT ( OnStopped() ) );
+
+ QObject::connect ( pClient,
+ SIGNAL ( ChatTextReceived ( QString ) ),
+ this, SLOT ( OnChatTextReceived ( QString ) ) );
+
QObject::connect ( pClient, SIGNAL ( PingTimeReceived ( int ) ),
- this, SLOT ( OnPingTimeResult ( int ) ) );
-
- QObject::connect ( &ClientSettingsDlg, SIGNAL ( GUIDesignChanged() ),
- this, SLOT ( OnGUIDesignChanged() ) );
-
- QObject::connect ( &ClientSettingsDlg, SIGNAL ( StereoCheckBoxChanged() ),
- this, SLOT ( OnStereoCheckBoxChanged() ) );
-
- QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ),
- this, SLOT ( OnChangeChanGain ( int, double ) ) );
-
- QObject::connect ( MainMixerBoard, SIGNAL ( NumClientsChanged ( int ) ),
- this, SLOT ( OnNumClientsChanged ( int ) ) );
-
- QObject::connect ( &ChatDlg, SIGNAL ( NewLocalInputText ( QString ) ),
- this, SLOT ( OnNewLocalInputText ( QString ) ) );
-
-
- // Timers ------------------------------------------------------------------
- // start timer for status bar
- TimerStatus.start ( STATUSBAR_UPDATE_TIME );
-}
-
-void CLlconClientDlg::closeEvent ( QCloseEvent* Event )
-{
- // if settings dialog or chat dialog is open, close it
- ClientSettingsDlg.close();
- ChatDlg.close();
-
- // if connected, terminate connection
- if ( pClient->IsRunning() )
- {
- pClient->Stop();
- }
-
- // 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::UpdateRevSelection()
-{
- if ( pClient->GetUseStereo() )
- {
- // for stereo make channel selection invisible since
- // reverberation effect is always applied to both channels
- RadioButtonRevSelL->setVisible ( false );
- RadioButtonRevSelR->setVisible ( false );
- }
- else
- {
- // make radio buttons visible
- RadioButtonRevSelL->setVisible ( true );
- RadioButtonRevSelR->setVisible ( true );
-
- // update value
- if ( pClient->IsReverbOnLeftChan() )
- {
- RadioButtonRevSelL->setChecked ( true );
- }
- else
- {
- RadioButtonRevSelR->setChecked ( true );
- }
- }
-}
-
-void CLlconClientDlg::OnSliderAudInFader ( int value )
-{
- pClient->SetAudioInFader ( value );
- UpdateAudioFaderSlider();
-}
-
-void CLlconClientDlg::OnLineEditServerAddrTextChanged ( const QString )
-{
- // 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()
-{
- // the connect/disconnect button implements a toggle functionality
- // -> apply inverted running state
- ConnectDisconnect ( !pClient->IsRunning() );
-}
-
-void CLlconClientDlg::OnStopped()
-{
- ConnectDisconnect ( false );
-}
-
-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 )
-{
- // init flag (will maybe overwritten later in this function)
- bUnreadChatMessage = false;
-
- ChatDlg.AddChatText ( strChatText );
-
- // if requested, open window
- if ( pClient->GetOpenChatOnNewMessage() )
- {
- ShowChatWindow();
- }
- else
- {
- if ( !ChatDlg.isVisible() )
- {
- bUnreadChatMessage = true;
- }
- }
-
- UpdateDisplay();
-}
-
-void CLlconClientDlg::OnDisconnected()
-{
- // channel is now disconnected, clear mixer board (remove all faders)
- MainMixerBoard->HideAll();
-}
-
-void CLlconClientDlg::OnConClientListMesReceived ( CVector vecChanInfo )
-{
- // update mixer board
- MainMixerBoard->ApplyNewConClientList ( vecChanInfo );
-}
-
-void CLlconClientDlg::OnNumClientsChanged ( int iNewNumClients )
-{
- // update window title
- SetMyWindowTitle ( iNewNumClients );
-}
-
-void CLlconClientDlg::SetMyWindowTitle ( const int iNumClients )
-{
- // show number of connected clients in window title (and therefore also in
- // the task bar of the OS)
- if ( iNumClients == 0 )
- {
- // only application name
- setWindowTitle ( APP_NAME );
- }
- else
- {
- if ( iNumClients == 1 )
- {
- setWindowTitle ( QString ( APP_NAME ) + " (1 user)" );
- }
- else
- {
- setWindowTitle ( QString ( APP_NAME ) +
- QString ( " (%1 users)" ).arg ( iNumClients ) );
- }
- }
-}
-
-void CLlconClientDlg::ShowChatWindow()
-{
- // open chat dialog
- ChatDlg.show();
-
- // make sure dialog is upfront and has focus
- ChatDlg.raise();
- ChatDlg.activateWindow();
-
- // chat dialog is opened, reset unread message flag
- bUnreadChatMessage = false;
-
- UpdateDisplay();
-}
-
-void CLlconClientDlg::OnFaderTagTextChanged ( const QString& strNewName )
-{
- // check length
- if ( strNewName.length() <= MAX_LEN_FADER_TAG )
- {
- // refresh internal name parameter
- pClient->strName = strNewName;
-
- // update name at server
- pClient->SetRemoteName();
- }
- else
- {
- // text is too long, update control with shortend text
- LineEditFaderTag->setText ( strNewName.left ( MAX_LEN_FADER_TAG ) );
- }
-}
-
-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 ) );
-}
-
+ this, SLOT ( OnPingTimeResult ( int ) ) );
+
+ QObject::connect ( &ClientSettingsDlg, SIGNAL ( GUIDesignChanged() ),
+ this, SLOT ( OnGUIDesignChanged() ) );
+
+ QObject::connect ( &ClientSettingsDlg, SIGNAL ( StereoCheckBoxChanged() ),
+ this, SLOT ( OnStereoCheckBoxChanged() ) );
+
+ QObject::connect ( MainMixerBoard, SIGNAL ( ChangeChanGain ( int, double ) ),
+ this, SLOT ( OnChangeChanGain ( int, double ) ) );
+
+ QObject::connect ( MainMixerBoard, SIGNAL ( NumClientsChanged ( int ) ),
+ this, SLOT ( OnNumClientsChanged ( int ) ) );
+
+ QObject::connect ( &ChatDlg, SIGNAL ( NewLocalInputText ( QString ) ),
+ this, SLOT ( OnNewLocalInputText ( QString ) ) );
+
+
+ // Timers ------------------------------------------------------------------
+ // set error status timer to a single shot timer
+ TimerErrorStatus.setSingleShot ( true );
+
+ // start timer for status bar
+ TimerStatus.start ( STATUSBAR_UPDATE_TIME );
+}
+
+void CLlconClientDlg::closeEvent ( QCloseEvent* Event )
+{
+ // if settings dialog or chat dialog is open, close it
+ ClientSettingsDlg.close();
+ ChatDlg.close();
+
+ // if connected, terminate connection
+ if ( pClient->IsRunning() )
+ {
+ pClient->Stop();
+ }
+
+ // 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::UpdateRevSelection()
+{
+ if ( pClient->GetUseStereo() )
+ {
+ // for stereo make channel selection invisible since
+ // reverberation effect is always applied to both channels
+ RadioButtonRevSelL->setVisible ( false );
+ RadioButtonRevSelR->setVisible ( false );
+ }
+ else
+ {
+ // make radio buttons visible
+ RadioButtonRevSelL->setVisible ( true );
+ RadioButtonRevSelR->setVisible ( true );
+
+ // update value
+ if ( pClient->IsReverbOnLeftChan() )
+ {
+ RadioButtonRevSelL->setChecked ( true );
+ }
+ else
+ {
+ RadioButtonRevSelR->setChecked ( true );
+ }
+ }
+}
+
+void CLlconClientDlg::OnSliderAudInFader ( int value )
+{
+ pClient->SetAudioInFader ( value );
+ UpdateAudioFaderSlider();
+}
+
+void CLlconClientDlg::OnLineEditServerAddrTextChanged ( const QString )
+{
+ // 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()
+{
+ // the connect/disconnect button implements a toggle functionality
+ // -> apply inverted running state
+ ConnectDisconnect ( !pClient->IsRunning() );
+}
+
+void CLlconClientDlg::OnStopped()
+{
+ ConnectDisconnect ( false );
+}
+
+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 )
+{
+ // init flag (will maybe overwritten later in this function)
+ bUnreadChatMessage = false;
+
+ ChatDlg.AddChatText ( strChatText );
+
+ // if requested, open window
+ if ( pClient->GetOpenChatOnNewMessage() )
+ {
+ ShowChatWindow();
+ }
+ else
+ {
+ if ( !ChatDlg.isVisible() )
+ {
+ bUnreadChatMessage = true;
+ }
+ }
+
+ UpdateDisplay();
+}
+
+void CLlconClientDlg::OnDisconnected()
+{
+ // channel is now disconnected, clear mixer board (remove all faders)
+ MainMixerBoard->HideAll();
+}
+
+void CLlconClientDlg::OnConClientListMesReceived ( CVector vecChanInfo )
+{
+ // update mixer board
+ MainMixerBoard->ApplyNewConClientList ( vecChanInfo );
+}
+
+void CLlconClientDlg::OnNumClientsChanged ( int iNewNumClients )
+{
+ // update window title
+ SetMyWindowTitle ( iNewNumClients );
+}
+
+void CLlconClientDlg::SetMyWindowTitle ( const int iNumClients )
+{
+ // show number of connected clients in window title (and therefore also in
+ // the task bar of the OS)
+ if ( iNumClients == 0 )
+ {
+ // only application name
+ setWindowTitle ( APP_NAME );
+ }
+ else
+ {
+ if ( iNumClients == 1 )
+ {
+ setWindowTitle ( QString ( APP_NAME ) + " (1 user)" );
+ }
+ else
+ {
+ setWindowTitle ( QString ( APP_NAME ) +
+ QString ( " (%1 users)" ).arg ( iNumClients ) );
+ }
+ }
+}
+
+void CLlconClientDlg::ShowChatWindow()
+{
+ // open chat dialog
+ ChatDlg.show();
+
+ // make sure dialog is upfront and has focus
+ ChatDlg.raise();
+ ChatDlg.activateWindow();
+
+ // chat dialog is opened, reset unread message flag
+ bUnreadChatMessage = false;
+
+ UpdateDisplay();
+}
+
+void CLlconClientDlg::OnFaderTagTextChanged ( const QString& strNewName )
+{
+ // check length
+ if ( strNewName.length() <= MAX_LEN_FADER_TAG )
+ {
+ // refresh internal name parameter
+ pClient->strName = strNewName;
+
+ // update name at server
+ pClient->SetRemoteName();
+ }
+ else
+ {
+ // text is too long, update control with shortend text
+ LineEditFaderTag->setText ( strNewName.left ( MAX_LEN_FADER_TAG ) );
+ }
+}
+
+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::OnTimerPing()
{
// send ping message to server
pClient->SendPingMess();
-}
+}
void CLlconClientDlg::OnPingTimeResult ( int iPingTime )
{
@@ -668,221 +672,256 @@ void CLlconClientDlg::OnPingTimeResult ( int iPingTime )
if ( iOverallDelayMs <= 40 )
{
iOverallDelayLEDColor = MUL_COL_LED_GREEN;
+
+ // reset ping error counter
+ iErrorStatusCounter = 0;
}
else
{
if ( iOverallDelayMs <= 65 )
{
iOverallDelayLEDColor = MUL_COL_LED_YELLOW;
+
+ // reset ping error counter
+ iErrorStatusCounter = 0;
}
else
{
iOverallDelayLEDColor = MUL_COL_LED_RED;
+
+ iErrorStatusCounter++;
+ if ( iErrorStatusCounter >= NUM_HIGH_PINGS_UNTIL_ERROR )
+ {
+ // delay too long, show error status in main window
+ TimerErrorStatus.start ( ERROR_STATUS_DISPLAY_TIME );
+
+ // avoid integer overrun of error state but keep
+ // error state valid
+ iErrorStatusCounter = NUM_HIGH_PINGS_UNTIL_ERROR;
+ }
}
}
- // set ping time result to general settings dialog
- ClientSettingsDlg.SetPingTimeResult ( iPingTime,
- iOverallDelayMs,
- iOverallDelayLEDColor );
-}
-
-void CLlconClientDlg::ConnectDisconnect ( const bool bDoStart )
-{
- // start/stop client, set button text
- if ( bDoStart )
- {
- // set address and check if address is valid
- if ( pClient->SetServerAddr ( LineEditServerAddr->currentText() ) )
- {
- bool bStartOk = true;
-
- // try to start client, if error occurred, do not go in
- // running state but show error message
- 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 and ping time measurement
- TimerSigMet.start ( LEVELMETER_UPDATE_TIME );
- TimerPing.start ( PING_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
- {
- // only stop client if currently running, in case we received
- // the stopped message, the client is already stopped but the
- // connect/disconnect button and other GUI controls must be
- // updated
- if ( pClient->IsRunning() )
- {
- pClient->Stop();
- }
-
- PushButtonConnect->setText ( CON_BUT_CONNECTTEXT );
-
- // stop timer for level meter bars and reset them
- TimerSigMet.stop();
- MultiColorLEDBarInputLevelL->setValue ( 0 );
- MultiColorLEDBarInputLevelR->setValue ( 0 );
-
- // stop ping time measurement timer
- TimerPing.stop();
-
- // immediately update status bar
- OnTimerStatus();
-
- // clear mixer board (remove all faders)
- MainMixerBoard->HideAll();
- }
-}
-
-void CLlconClientDlg::UpdateDisplay()
-{
- // show connection status in status bar
- if ( pClient->IsConnected() && pClient->IsRunning() )
- {
- QString strStatus = tr ( "Connected" );
-
- if ( bUnreadChatMessage )
- {
- strStatus += ", New Chat";
- }
-
- TextLabelStatus->setText ( strStatus );
- }
- else
- {
- TextLabelStatus->setText ( tr ( "Disconnected" ) );
- }
-
-// TEST
-//TextLabelStatus->setText ( QString( "Time: %1, Netw: %2" ).arg ( pClient->GetTimingStdDev() ).arg ( pClient->GetChannel()->GetTimingStdDev() ) );
-//TextLabelStatus->setText ( QString( "Buf. Err. Rate: %1 %" ).arg ( pClient->GetChannel()->GetJitterBufferErrorRate() * 100.0 ) );
-
-}
-
-void CLlconClientDlg::SetGUIDesign ( const EGUIDesign eNewDesign )
-{
- // apply GUI design to current window
- switch ( eNewDesign )
- {
- case GD_ORIGINAL:
- // group box
- groupBoxLocal->setStyleSheet (
- "QGroupBox { border-image: url(:/png/fader/res/mixerboardbackground.png) 34px 30px 40px 40px;"
- " border-top: 34px transparent;"
- " border-bottom: 40px transparent;"
- " border-left: 30px transparent;"
- " border-right: 40px transparent;"
- " padding: -5px;"
- " margin: -5px, -5px, 0px, 0px; }"
- "QGroupBox::title { margin-top: 13px;"
- " margin-left: 35px;"
- " background-color: transparent;"
- " color: rgb(148, 148, 148); }" );
- groupBoxLocal->layout()->setMargin ( 3 );
-
- // audio fader
- SliderAudInFader->setStyleSheet (
- "QSlider { background-image: url(:/png/fader/res/faderbackground.png);"
- " width: 45px; }"
- "QSlider::groove { image: url(); }"
- "QSlider::handle { image: url(:/png/fader/res/faderhandlesmall.png); }" );
- TextLabelAudFader->setStyleSheet (
- "QLabel { color: rgb(148, 148, 148);"
- " font: bold; }" );
- TextAudInFader->setStyleSheet (
- "QLabel { color: rgb(148, 148, 148);"
- " font: bold; }" );
-
- // Reverberation
- SliderAudReverb->setStyleSheet (
- "QSlider { background-image: url(:/png/fader/res/faderbackground.png);"
- " width: 45px; }"
- "QSlider::groove { image: url(); }"
- "QSlider::handle { image: url(:/png/fader/res/faderhandlesmall.png); }" );
-
- RadioButtonRevSelL->setStyleSheet (
- "QRadioButton { color: rgb(148, 148, 148);"
- " font: bold; }" );
- RadioButtonRevSelR->setStyleSheet (
- "QRadioButton { color: rgb(148, 148, 148);"
- " font: bold; }" );
-
- TextLabelAudReverb->setStyleSheet (
- "QLabel { color: rgb(148, 148, 148);"
- " font: bold; }" );
- break;
-
- default:
- // reset style sheet and set original paramters
- groupBoxLocal->setStyleSheet ( "" );
- groupBoxLocal->layout()->setMargin ( 9 );
- SliderAudInFader->setStyleSheet ( "" );
- SliderAudReverb->setStyleSheet ( "" );
- RadioButtonRevSelL->setStyleSheet ( "" );
- RadioButtonRevSelR->setStyleSheet ( "" );
- TextLabelAudReverb->setStyleSheet ( "" );
- TextLabelAudFader->setStyleSheet ( "" );
- TextAudInFader->setStyleSheet ( "" );
- break;
- }
-
- // also apply GUI design to child GUI controls
- MainMixerBoard->SetGUIDesign ( eNewDesign );
-}
-
-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 );
- }
-}
+ // only update delay information on settings dialog if it is visible to
+ // avoid CPU load on working thread if not necessary
+ if ( ClientSettingsDlg.isVisible() )
+ {
+ // set ping time result to general settings dialog
+ ClientSettingsDlg.SetPingTimeResult ( iPingTime,
+ iOverallDelayMs,
+ iOverallDelayLEDColor );
+ }
+}
+
+void CLlconClientDlg::ConnectDisconnect ( const bool bDoStart )
+{
+ // start/stop client, set button text
+ if ( bDoStart )
+ {
+ // set address and check if address is valid
+ if ( pClient->SetServerAddr ( LineEditServerAddr->currentText() ) )
+ {
+ bool bStartOk = true;
+
+ // try to start client, if error occurred, do not go in
+ // running state but show error message
+ try
+ {
+ pClient->Start();
+ }
+
+ catch ( CGenErr generr )
+ {
+ QMessageBox::critical (
+ this, APP_NAME, generr.GetErrorText(), "Close", 0 );
+
+ bStartOk = false;
+ }
+
+ if ( bStartOk )
+ {
+ PushButtonConnect->setText ( CON_BUT_DISCONNECTTEXT );
+
+ // reset ping error counter and timer
+ iErrorStatusCounter = 0;
+ TimerErrorStatus.stop();
+
+ // start timer for level meter bar and ping time measurement
+ TimerSigMet.start ( LEVELMETER_UPDATE_TIME );
+ TimerPing.start ( PING_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
+ {
+ // only stop client if currently running, in case we received
+ // the stopped message, the client is already stopped but the
+ // connect/disconnect button and other GUI controls must be
+ // updated
+ if ( pClient->IsRunning() )
+ {
+ pClient->Stop();
+ }
+
+ PushButtonConnect->setText ( CON_BUT_CONNECTTEXT );
+
+ // stop timer for level meter bars and reset them
+ TimerSigMet.stop();
+ MultiColorLEDBarInputLevelL->setValue ( 0 );
+ MultiColorLEDBarInputLevelR->setValue ( 0 );
+
+ // stop ping time measurement timer
+ TimerPing.stop();
+
+ // immediately update status bar
+ OnTimerStatus();
+
+ // clear mixer board (remove all faders)
+ MainMixerBoard->HideAll();
+ }
+}
+
+void CLlconClientDlg::UpdateDisplay()
+{
+ // show connection status in status bar
+ if ( pClient->IsConnected() && pClient->IsRunning() )
+ {
+ QString strStatus;
+ if ( TimerErrorStatus.isActive() )
+ {
+ // right now we only have one error case: delay too high
+ strStatus = tr ( "Audio delay too long" );
+ }
+ else
+ {
+ strStatus = tr ( "Connected" );
+ }
+
+ if ( bUnreadChatMessage )
+ {
+ strStatus += ", New chat";
+ }
+
+ TextLabelStatus->setText ( strStatus );
+ }
+ else
+ {
+ TextLabelStatus->setText ( tr ( "Disconnected" ) );
+ }
+
+// TEST
+//TextLabelStatus->setText ( QString( "Time: %1, Netw: %2" ).arg ( pClient->GetTimingStdDev() ).arg ( pClient->GetChannel()->GetTimingStdDev() ) );
+//TextLabelStatus->setText ( QString( "Buf. Err. Rate: %1 %" ).arg ( pClient->GetChannel()->GetJitterBufferErrorRate() * 100.0 ) );
+
+}
+
+void CLlconClientDlg::SetGUIDesign ( const EGUIDesign eNewDesign )
+{
+ // apply GUI design to current window
+ switch ( eNewDesign )
+ {
+ case GD_ORIGINAL:
+ // group box
+ groupBoxLocal->setStyleSheet (
+ "QGroupBox { border-image: url(:/png/fader/res/mixerboardbackground.png) 34px 30px 40px 40px;"
+ " border-top: 34px transparent;"
+ " border-bottom: 40px transparent;"
+ " border-left: 30px transparent;"
+ " border-right: 40px transparent;"
+ " padding: -5px;"
+ " margin: -5px, -5px, 0px, 0px; }"
+ "QGroupBox::title { margin-top: 13px;"
+ " margin-left: 35px;"
+ " background-color: transparent;"
+ " color: rgb(148, 148, 148); }" );
+ groupBoxLocal->layout()->setMargin ( 3 );
+
+ // audio fader
+ SliderAudInFader->setStyleSheet (
+ "QSlider { background-image: url(:/png/fader/res/faderbackground.png);"
+ " width: 45px; }"
+ "QSlider::groove { image: url(); }"
+ "QSlider::handle { image: url(:/png/fader/res/faderhandlesmall.png); }" );
+ TextLabelAudFader->setStyleSheet (
+ "QLabel { color: rgb(148, 148, 148);"
+ " font: bold; }" );
+ TextAudInFader->setStyleSheet (
+ "QLabel { color: rgb(148, 148, 148);"
+ " font: bold; }" );
+
+ // Reverberation
+ SliderAudReverb->setStyleSheet (
+ "QSlider { background-image: url(:/png/fader/res/faderbackground.png);"
+ " width: 45px; }"
+ "QSlider::groove { image: url(); }"
+ "QSlider::handle { image: url(:/png/fader/res/faderhandlesmall.png); }" );
+
+ RadioButtonRevSelL->setStyleSheet (
+ "QRadioButton { color: rgb(148, 148, 148);"
+ " font: bold; }" );
+ RadioButtonRevSelR->setStyleSheet (
+ "QRadioButton { color: rgb(148, 148, 148);"
+ " font: bold; }" );
+
+ TextLabelAudReverb->setStyleSheet (
+ "QLabel { color: rgb(148, 148, 148);"
+ " font: bold; }" );
+ break;
+
+ default:
+ // reset style sheet and set original paramters
+ groupBoxLocal->setStyleSheet ( "" );
+ groupBoxLocal->layout()->setMargin ( 9 );
+ SliderAudInFader->setStyleSheet ( "" );
+ SliderAudReverb->setStyleSheet ( "" );
+ RadioButtonRevSelL->setStyleSheet ( "" );
+ RadioButtonRevSelR->setStyleSheet ( "" );
+ TextLabelAudReverb->setStyleSheet ( "" );
+ TextLabelAudFader->setStyleSheet ( "" );
+ TextAudInFader->setStyleSheet ( "" );
+ break;
+ }
+
+ // also apply GUI design to child GUI controls
+ MainMixerBoard->SetGUIDesign ( eNewDesign );
+}
+
+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 );
+ }
+}
diff --git a/src/llconclientdlg.h b/src/llconclientdlg.h
index 839b973f..e224604c 100755
--- a/src/llconclientdlg.h
+++ b/src/llconclientdlg.h
@@ -58,11 +58,15 @@
// update time for GUI controls
#define LEVELMETER_UPDATE_TIME 100 // ms
#define STATUSBAR_UPDATE_TIME 1000 // ms
+#define ERROR_STATUS_DISPLAY_TIME 3000 // ms
// range for signal level meter
#define LOW_BOUND_SIG_METER ( -50.0 ) // dB
#define UPPER_BOUND_SIG_METER ( 0.0 ) // dB
+// number of ping times > upper bound until error message is shown
+#define NUM_HIGH_PINGS_UNTIL_ERROR 5
+
/* Classes ********************************************************************/
class CLlconClientDlg : public QDialog, private Ui_CLlconClientDlgBase
@@ -85,9 +89,11 @@ protected:
CClient* pClient;
bool bConnected;
bool bUnreadChatMessage;
+ int iErrorStatusCounter;
QTimer TimerSigMet;
QTimer TimerStatus;
QTimer TimerPing;
+ QTimer TimerErrorStatus;
virtual void customEvent ( QEvent* Event );
virtual void closeEvent ( QCloseEvent* Event );