diff --git a/src/llconclientdlg.cpp b/src/llconclientdlg.cpp
index 39ad07b6..1045d52e 100755
--- a/src/llconclientdlg.cpp
+++ b/src/llconclientdlg.cpp
@@ -1,773 +1,773 @@
-/******************************************************************************\
- * 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 ),
- 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 strInpLevHAccText = tr ( "Input level meter" );
- QString strInpLevHAccDescr = tr ( "Simulates an analog LED level meter." );
- TextLabelInputLevelL->setWhatsThis ( strInpLevH );
- TextLabelInputLevelR->setWhatsThis ( strInpLevH );
- MultiColorLEDBarInputLevelL->setWhatsThis ( strInpLevH );
- MultiColorLEDBarInputLevelL->setAccessibleName ( strInpLevHAccText );
- MultiColorLEDBarInputLevelL->setAccessibleDescription ( strInpLevHAccDescr );
- MultiColorLEDBarInputLevelR->setWhatsThis ( strInpLevH );
- MultiColorLEDBarInputLevelR->setAccessibleName ( strInpLevHAccText );
- MultiColorLEDBarInputLevelR->setAccessibleDescription ( strInpLevHAccDescr );
-
- // 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." );
- TextLabelServerTag->setWhatsThis ( strFaderTag );
- LineEditFaderTag->setWhatsThis ( strFaderTag );
- 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 );
-
-
- // 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();
- }
-
-
- // 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() ) );
-
- // 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 ( &ClientSettingsDlg, SIGNAL ( GUIDesignChanged() ),
- this, SLOT ( OnGUIDesignChanged() ) );
-
- 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::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()
-{
- // 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::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
- 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
- {
- // 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 );
-
- // 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() ) );
-
-}
-
-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 );
- }
-}
+/******************************************************************************\
+ * 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 ),
+ 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 strInpLevHAccText = tr ( "Input level meter" );
+ QString strInpLevHAccDescr = tr ( "Simulates an analog LED level meter." );
+ TextLabelInputLevelL->setWhatsThis ( strInpLevH );
+ TextLabelInputLevelR->setWhatsThis ( strInpLevH );
+ MultiColorLEDBarInputLevelL->setWhatsThis ( strInpLevH );
+ MultiColorLEDBarInputLevelL->setAccessibleName ( strInpLevHAccText );
+ MultiColorLEDBarInputLevelL->setAccessibleDescription ( strInpLevHAccDescr );
+ MultiColorLEDBarInputLevelR->setWhatsThis ( strInpLevH );
+ MultiColorLEDBarInputLevelR->setAccessibleName ( strInpLevHAccText );
+ MultiColorLEDBarInputLevelR->setAccessibleDescription ( strInpLevHAccDescr );
+
+ // 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." );
+ TextLabelServerTag->setWhatsThis ( strFaderTag );
+ LineEditFaderTag->setWhatsThis ( strFaderTag );
+ 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 );
+
+
+ // 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();
+ }
+
+
+ // 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() ) );
+
+ // 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 ( &ClientSettingsDlg, SIGNAL ( GUIDesignChanged() ),
+ this, SLOT ( OnGUIDesignChanged() ) );
+
+ 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::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()
+{
+ // 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::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
+ 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
+ {
+ // 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 );
+
+ // 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() ) );
+
+}
+
+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 95152b49..6f81a4b4 100755
--- a/src/llconclientdlg.h
+++ b/src/llconclientdlg.h
@@ -1,119 +1,119 @@
-/******************************************************************************\
- * 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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "global.h"
-#include "client.h"
-#include "multicolorled.h"
-#include "audiomixerboard.h"
-#include "clientsettingsdlg.h"
-#include "chatdlg.h"
-#ifdef _WIN32
-# include "../windows/moc/llconclientdlgbase.h"
-#else
-# include "moc/llconclientdlgbase.h"
-#endif
-
-
-/* Definitions ****************************************************************/
-// text strings for connection button for connect and disconnect
-#define CON_BUT_CONNECTTEXT "C&onnect"
-#define CON_BUT_DISCONNECTTEXT "D&isconnect"
-
-// update time for GUI controls
-#define LEVELMETER_UPDATE_TIME 100 // ms
-#define STATUSBAR_UPDATE_TIME 1000 // ms
-
-// range for signal level meter
-#define LOW_BOUND_SIG_METER ( -50.0 ) // dB
-#define UPPER_BOUND_SIG_METER ( 0.0 ) // dB
-
-
-/* Classes ********************************************************************/
-class CLlconClientDlg : public QDialog, private Ui_CLlconClientDlgBase
-{
- Q_OBJECT
-
-public:
- CLlconClientDlg ( CClient* pNCliP, const bool bNewConnectOnStartup,
- const bool bNewDisalbeLEDs,
- QWidget* parent = 0, Qt::WindowFlags f = 0 );
-
-protected:
- void SetGUIDesign ( const EGUIDesign eNewDesign );
- void SetMyWindowTitle ( const int iNumClients );
- void ShowChatWindow();
- void UpdateAudioFaderSlider();
- void ConnectDisconnect ( const bool bDoStart );
-
- CClient* pClient;
- bool bConnected;
- bool bUnreadChatMessage;
- QTimer TimerSigMet;
- QTimer TimerStatus;
-
- virtual void customEvent ( QEvent* Event );
- virtual void closeEvent ( QCloseEvent* Event );
- void UpdateDisplay();
-
- QMenu* pViewMenu;
- QMenuBar* pMenu;
-
- CClientSettingsDlg ClientSettingsDlg;
- CChatDlg ChatDlg;
-
-public slots:
- void OnConnectDisconBut();
- void OnTimerSigMet();
- void OnTimerStatus() { UpdateDisplay(); }
- void OnOpenGeneralSettings();
- void OnOpenChatDialog() { ShowChatWindow(); }
- void OnSliderAudInFader ( int value );
- void OnSliderAudReverb ( int value ) { pClient->SetReverbLevel ( value ); }
- void OnRevSelL() { pClient->SetReverbOnLeftChan ( true ); }
- void OnRevSelR() { pClient->SetReverbOnLeftChan ( false ); }
- void OnConClientListMesReceived ( CVector vecChanInfo );
- void OnChangeChanGain ( int iId, double dGain )
- { pClient->SetRemoteChanGain ( iId, dGain ); }
- void OnFaderTagTextChanged ( const QString& strNewName );
- void OnChatTextReceived ( QString strChatText );
- void OnNewLocalInputText ( QString strChatText )
- { pClient->SendTextMess ( strChatText ); }
- void OnLineEditServerAddrTextChanged ( const QString sNewText );
- void OnLineEditServerAddrActivated ( int index );
- void OnDisconnected();
- void OnStopped();
- void OnGUIDesignChanged() { SetGUIDesign ( pClient->GetGUIDesign() ); }
- void OnNumClientsChanged ( int iNewNumClients );
-};
+/******************************************************************************\
+ * 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "global.h"
+#include "client.h"
+#include "multicolorled.h"
+#include "audiomixerboard.h"
+#include "clientsettingsdlg.h"
+#include "chatdlg.h"
+#ifdef _WIN32
+# include "../windows/moc/llconclientdlgbase.h"
+#else
+# include "moc/llconclientdlgbase.h"
+#endif
+
+
+/* Definitions ****************************************************************/
+// text strings for connection button for connect and disconnect
+#define CON_BUT_CONNECTTEXT "C&onnect"
+#define CON_BUT_DISCONNECTTEXT "D&isconnect"
+
+// update time for GUI controls
+#define LEVELMETER_UPDATE_TIME 100 // ms
+#define STATUSBAR_UPDATE_TIME 1000 // ms
+
+// range for signal level meter
+#define LOW_BOUND_SIG_METER ( -50.0 ) // dB
+#define UPPER_BOUND_SIG_METER ( 0.0 ) // dB
+
+
+/* Classes ********************************************************************/
+class CLlconClientDlg : public QDialog, private Ui_CLlconClientDlgBase
+{
+ Q_OBJECT
+
+public:
+ CLlconClientDlg ( CClient* pNCliP, const bool bNewConnectOnStartup,
+ const bool bNewDisalbeLEDs,
+ QWidget* parent = 0, Qt::WindowFlags f = 0 );
+
+protected:
+ void SetGUIDesign ( const EGUIDesign eNewDesign );
+ void SetMyWindowTitle ( const int iNumClients );
+ void ShowChatWindow();
+ void UpdateAudioFaderSlider();
+ void ConnectDisconnect ( const bool bDoStart );
+
+ CClient* pClient;
+ bool bConnected;
+ bool bUnreadChatMessage;
+ QTimer TimerSigMet;
+ QTimer TimerStatus;
+
+ virtual void customEvent ( QEvent* Event );
+ virtual void closeEvent ( QCloseEvent* Event );
+ void UpdateDisplay();
+
+ QMenu* pViewMenu;
+ QMenuBar* pMenu;
+
+ CClientSettingsDlg ClientSettingsDlg;
+ CChatDlg ChatDlg;
+
+public slots:
+ void OnConnectDisconBut();
+ void OnTimerSigMet();
+ void OnTimerStatus() { UpdateDisplay(); }
+ void OnOpenGeneralSettings();
+ void OnOpenChatDialog() { ShowChatWindow(); }
+ void OnSliderAudInFader ( int value );
+ void OnSliderAudReverb ( int value ) { pClient->SetReverbLevel ( value ); }
+ void OnRevSelL() { pClient->SetReverbOnLeftChan ( true ); }
+ void OnRevSelR() { pClient->SetReverbOnLeftChan ( false ); }
+ void OnConClientListMesReceived ( CVector vecChanInfo );
+ void OnChangeChanGain ( int iId, double dGain )
+ { pClient->SetRemoteChanGain ( iId, dGain ); }
+ void OnFaderTagTextChanged ( const QString& strNewName );
+ void OnChatTextReceived ( QString strChatText );
+ void OnNewLocalInputText ( QString strChatText )
+ { pClient->SendTextMess ( strChatText ); }
+ void OnLineEditServerAddrTextChanged ( const QString sNewText );
+ void OnLineEditServerAddrActivated ( int index );
+ void OnDisconnected();
+ void OnStopped();
+ void OnGUIDesignChanged() { SetGUIDesign ( pClient->GetGUIDesign() ); }
+ void OnNumClientsChanged ( int iNewNumClients );
+};
diff --git a/src/socket.cpp b/src/socket.cpp
index 1a034621..1b61de0d 100755
--- a/src/socket.cpp
+++ b/src/socket.cpp
@@ -32,17 +32,19 @@ void CSocket::Init ( const quint16 iPortNumber )
// allocate memory for network receive and send buffer in samples
vecbyRecBuf.Init ( MAX_SIZE_BYTES_NETW_BUF );
- // initialize the listening socket
- bool bSuccess = SocketDevice.bind (
- QHostAddress ( QHostAddress::Any ), iPortNumber );
-
- // if no success, try if server is on same machine (only for client)
- if ( ( !bSuccess ) && bIsClient )
+ // initialize the listening socket, per definition use the port number plus
+ // one for the client to make it possible to run server and client on the
+ // same computer
+ bool bSuccess;
+ if ( bIsClient )
{
- // if server and client is on same machine, decrease port number by
- // one by definition
bSuccess = SocketDevice.bind (
- QHostAddress( QHostAddress::Any ), iPortNumber - 1 );
+ QHostAddress( QHostAddress::Any ), iPortNumber + 1 );
+ }
+ else
+ {
+ bSuccess = SocketDevice.bind (
+ QHostAddress ( QHostAddress::Any ), iPortNumber );
}
if ( !bSuccess )